@@ -315,20 +315,13 @@ pub enum Edge {
315315 EnterNovelDelimiterRHS {
316316 contiguous : bool ,
317317 } ,
318- ExitDelimiter ,
319318}
320319
321320const NOT_CONTIGUOUS_PENALTY : u64 = 50 ;
322321
323322impl Edge {
324323 pub fn cost ( self ) -> u64 {
325324 match self {
326- // When we're at the end of a list, there's only one exit
327- // delimiter possibility, so the cost doesn't matter. We
328- // choose a non-zero number as it's easier to reason
329- // about.
330- ExitDelimiter => 1 ,
331-
332325 // Matching nodes is always best.
333326 UnchangedNode { depth_difference } => min ( 40 , u64:: from ( depth_difference) + 1 ) ,
334327 // Matching an outer delimiter is good.
@@ -383,7 +376,6 @@ pub type SeenMap<'syn, 'b> = hashbrown::HashMap<
383376 BuildHasherDefault < FxHasher > ,
384377> ;
385378
386- #[ inline( never) ]
387379fn allocate_if_new < ' syn , ' b > (
388380 v : Vertex < ' syn , ' b > ,
389381 alloc : & ' b Bump ,
@@ -417,15 +409,46 @@ fn looks_like_punctuation(content: &str) -> bool {
417409 content == "," || content == ";" || content == "."
418410}
419411
420- fn skip_pop_either < ' a > (
421- mut syntax : & ' a Syntax < ' a > ,
422- mut stack : BitStack ,
423- ) -> ( SideSyntax < ' a > , BitStack ) {
424- while let ( None , Some ( PopEither ) ) = ( syntax. next_sibling ( ) , stack. peek ( ) ) {
425- syntax = syntax. parent ( ) . unwrap ( ) ;
426- stack = stack. pop ( ) ;
412+ #[ inline( always) ]
413+ fn next_vertex < ' a , ' b > (
414+ mut lhs_syntax : SideSyntax < ' a > ,
415+ mut rhs_syntax : SideSyntax < ' a > ,
416+ mut lhs_parent_stack : BitStack ,
417+ mut rhs_parent_stack : BitStack ,
418+ ) -> Vertex < ' a , ' b > {
419+ loop {
420+ while let ( None , Some ( PopEither ) ) = ( lhs_syntax. get_side ( ) , lhs_parent_stack. peek ( ) ) {
421+ lhs_syntax = next_sibling ( lhs_syntax. parent ( ) . unwrap ( ) ) ;
422+ lhs_parent_stack = lhs_parent_stack. pop ( ) ;
423+ }
424+
425+ while let ( None , Some ( PopEither ) ) = ( rhs_syntax. get_side ( ) , rhs_parent_stack. peek ( ) ) {
426+ rhs_syntax = next_sibling ( rhs_syntax. parent ( ) . unwrap ( ) ) ;
427+ rhs_parent_stack = rhs_parent_stack. pop ( ) ;
428+ }
429+
430+ if let ( None , None , Some ( PopBoth ) , Some ( PopBoth ) ) = (
431+ lhs_syntax. get_side ( ) ,
432+ rhs_syntax. get_side ( ) ,
433+ lhs_parent_stack. peek ( ) ,
434+ rhs_parent_stack. peek ( ) ,
435+ ) {
436+ lhs_syntax = next_sibling ( lhs_syntax. parent ( ) . unwrap ( ) ) ;
437+ rhs_syntax = next_sibling ( rhs_syntax. parent ( ) . unwrap ( ) ) ;
438+ lhs_parent_stack = lhs_parent_stack. pop ( ) ;
439+ rhs_parent_stack = rhs_parent_stack. pop ( ) ;
440+ } else {
441+ break ;
442+ }
443+ }
444+
445+ Vertex {
446+ lhs_syntax,
447+ rhs_syntax,
448+ lhs_parent_stack,
449+ rhs_parent_stack,
450+ ..Default :: default ( )
427451 }
428- ( next_sibling ( syntax) , stack)
429452}
430453
431454/// Compute the neighbours of `v`.
@@ -445,49 +468,23 @@ pub fn get_neighbours<'syn, 'b>(
445468 } ,
446469 ) ;
447470
448- let v_info = (
449- v. lhs_syntax . get_side ( ) ,
450- v. rhs_syntax . get_side ( ) ,
451- v. lhs_parent_stack . peek ( ) ,
452- v. rhs_parent_stack . peek ( ) ,
453- ) ;
454-
455- if let ( None , None , Some ( PopBoth ) , Some ( PopBoth ) ) = v_info {
456- // We have exhausted all the nodes on both lists, so we can
457- // move up to the parent node.
458-
459- // Continue from sibling of parent.
460- add_neighbor (
461- ExitDelimiter ,
462- Vertex {
463- lhs_syntax : next_sibling ( v. lhs_syntax . parent ( ) . unwrap ( ) ) ,
464- rhs_syntax : next_sibling ( v. rhs_syntax . parent ( ) . unwrap ( ) ) ,
465- lhs_parent_stack : v. lhs_parent_stack . pop ( ) ,
466- rhs_parent_stack : v. rhs_parent_stack . pop ( ) ,
467- ..Vertex :: default ( )
468- } ,
469- ) ;
470- }
471+ let v_info = ( v. lhs_syntax . get_side ( ) , v. rhs_syntax . get_side ( ) ) ;
471472
472- if let ( Some ( lhs_syntax) , Some ( rhs_syntax) , _ , _ ) = v_info {
473+ if let ( Some ( lhs_syntax) , Some ( rhs_syntax) ) = v_info {
473474 if lhs_syntax == rhs_syntax {
474475 let depth_difference = ( lhs_syntax. num_ancestors ( ) as i32
475476 - rhs_syntax. num_ancestors ( ) as i32 )
476477 . unsigned_abs ( ) ;
477478
478- let ( next_lhs_syntax, next_lhs_stack) = skip_pop_either ( lhs_syntax, v. lhs_parent_stack ) ;
479- let ( next_rhs_syntax, next_rhs_stack) = skip_pop_either ( rhs_syntax, v. rhs_parent_stack ) ;
480-
481479 // Both nodes are equal, the happy case.
482480 add_neighbor (
483481 UnchangedNode { depth_difference } ,
484- Vertex {
485- lhs_syntax : next_lhs_syntax,
486- rhs_syntax : next_rhs_syntax,
487- lhs_parent_stack : next_lhs_stack,
488- rhs_parent_stack : next_rhs_stack,
489- ..Vertex :: default ( )
490- } ,
482+ next_vertex (
483+ next_sibling ( lhs_syntax) ,
484+ next_sibling ( rhs_syntax) ,
485+ v. lhs_parent_stack ,
486+ v. rhs_parent_stack ,
487+ ) ,
491488 ) ;
492489 }
493490
@@ -515,13 +512,12 @@ pub fn get_neighbours<'syn, 'b>(
515512
516513 add_neighbor (
517514 EnterUnchangedDelimiter { depth_difference } ,
518- Vertex {
519- lhs_syntax : next_child ( lhs_syntax, lhs_children) ,
520- rhs_syntax : next_child ( rhs_syntax, rhs_children) ,
521- lhs_parent_stack : v. lhs_parent_stack . push ( PopBoth ) ,
522- rhs_parent_stack : v. rhs_parent_stack . push ( PopBoth ) ,
523- ..Vertex :: default ( )
524- } ,
515+ next_vertex (
516+ next_child ( lhs_syntax, lhs_children) ,
517+ next_child ( rhs_syntax, rhs_children) ,
518+ v. lhs_parent_stack . push ( PopBoth ) ,
519+ v. rhs_parent_stack . push ( PopBoth ) ,
520+ ) ,
525521 ) ;
526522 }
527523 }
@@ -545,101 +541,83 @@ pub fn get_neighbours<'syn, 'b>(
545541 let levenshtein_pct =
546542 ( normalized_levenshtein ( lhs_content, rhs_content) * 100.0 ) . round ( ) as u8 ;
547543
548- let ( next_lhs_syntax, next_lhs_stack) =
549- skip_pop_either ( lhs_syntax, v. lhs_parent_stack ) ;
550- let ( next_rhs_syntax, next_rhs_stack) =
551- skip_pop_either ( rhs_syntax, v. rhs_parent_stack ) ;
552-
553544 add_neighbor (
554545 ReplacedComment { levenshtein_pct } ,
555- Vertex {
556- lhs_syntax : next_lhs_syntax,
557- rhs_syntax : next_rhs_syntax,
558- lhs_parent_stack : next_lhs_stack,
559- rhs_parent_stack : next_rhs_stack,
560- ..Vertex :: default ( )
561- } ,
546+ next_vertex (
547+ next_sibling ( lhs_syntax) ,
548+ next_sibling ( rhs_syntax) ,
549+ v. lhs_parent_stack ,
550+ v. rhs_parent_stack ,
551+ ) ,
562552 ) ;
563553 }
564554 }
565555 }
566556
567- if let ( Some ( lhs_syntax) , _, _, _) = v_info {
568- let ( edge, child) = match lhs_syntax {
569- Syntax :: Atom { content, .. } => (
570- NovelAtomLHS {
571- // TODO: should this apply if prev is a parent
572- // node rather than a sibling?
573- contiguous : lhs_syntax. prev_is_contiguous ( ) ,
574- probably_punctuation : looks_like_punctuation ( content) ,
575- } ,
576- None ,
577- ) ,
578- Syntax :: List { children, .. } => (
579- EnterNovelDelimiterLHS {
580- contiguous : lhs_syntax. prev_is_contiguous ( ) ,
581- } ,
582- children. get ( 0 ) . copied ( ) ,
583- ) ,
584- } ;
585-
586- let ( next_syntax, next_stack) = if let Some ( child) = child {
587- (
588- SideSyntax :: from_side ( child) ,
589- v. lhs_parent_stack . push ( PopEither ) ,
590- )
591- } else {
592- skip_pop_either ( lhs_syntax, v. lhs_parent_stack )
557+ if let ( Some ( lhs_syntax) , _) = v_info {
558+ match lhs_syntax {
559+ Syntax :: Atom { content, .. } => {
560+ add_neighbor (
561+ NovelAtomLHS {
562+ // TODO: should this apply if prev is a parent
563+ // node rather than a sibling?
564+ contiguous : lhs_syntax. prev_is_contiguous ( ) ,
565+ probably_punctuation : looks_like_punctuation ( content) ,
566+ } ,
567+ next_vertex (
568+ next_sibling ( lhs_syntax) ,
569+ v. rhs_syntax ,
570+ v. lhs_parent_stack ,
571+ v. rhs_parent_stack ,
572+ ) ,
573+ ) ;
574+ }
575+ Syntax :: List { children, .. } => {
576+ add_neighbor (
577+ EnterNovelDelimiterLHS {
578+ contiguous : lhs_syntax. prev_is_contiguous ( ) ,
579+ } ,
580+ next_vertex (
581+ next_child ( lhs_syntax, children) ,
582+ v. rhs_syntax ,
583+ v. lhs_parent_stack . push ( PopEither ) ,
584+ v. rhs_parent_stack ,
585+ ) ,
586+ ) ;
587+ }
593588 } ;
594-
595- add_neighbor (
596- edge,
597- Vertex {
598- lhs_syntax : next_syntax,
599- rhs_syntax : v. rhs_syntax ,
600- lhs_parent_stack : next_stack,
601- rhs_parent_stack : v. rhs_parent_stack ,
602- ..Vertex :: default ( )
603- } ,
604- ) ;
605589 }
606590
607- if let ( _, Some ( rhs_syntax) , _, _) = v_info {
608- let ( edge, child) = match rhs_syntax {
609- Syntax :: Atom { content, .. } => (
610- NovelAtomRHS {
611- contiguous : rhs_syntax. prev_is_contiguous ( ) ,
612- probably_punctuation : looks_like_punctuation ( content) ,
613- } ,
614- None ,
615- ) ,
616- Syntax :: List { children, .. } => (
617- EnterNovelDelimiterRHS {
618- contiguous : rhs_syntax. prev_is_contiguous ( ) ,
619- } ,
620- children. get ( 0 ) . copied ( ) ,
621- ) ,
622- } ;
623-
624- let ( next_syntax, next_stack) = if let Some ( child) = child {
625- (
626- SideSyntax :: from_side ( child) ,
627- v. rhs_parent_stack . push ( PopEither ) ,
628- )
629- } else {
630- skip_pop_either ( rhs_syntax, v. rhs_parent_stack )
591+ if let ( _, Some ( rhs_syntax) ) = v_info {
592+ match rhs_syntax {
593+ Syntax :: Atom { content, .. } => {
594+ add_neighbor (
595+ NovelAtomRHS {
596+ contiguous : rhs_syntax. prev_is_contiguous ( ) ,
597+ probably_punctuation : looks_like_punctuation ( content) ,
598+ } ,
599+ next_vertex (
600+ v. lhs_syntax ,
601+ next_sibling ( rhs_syntax) ,
602+ v. lhs_parent_stack ,
603+ v. rhs_parent_stack ,
604+ ) ,
605+ ) ;
606+ }
607+ Syntax :: List { children, .. } => {
608+ add_neighbor (
609+ EnterNovelDelimiterRHS {
610+ contiguous : rhs_syntax. prev_is_contiguous ( ) ,
611+ } ,
612+ next_vertex (
613+ v. lhs_syntax ,
614+ next_child ( rhs_syntax, children) ,
615+ v. lhs_parent_stack ,
616+ v. rhs_parent_stack . push ( PopEither ) ,
617+ ) ,
618+ ) ;
619+ }
631620 } ;
632-
633- add_neighbor (
634- edge,
635- Vertex {
636- lhs_syntax : v. lhs_syntax ,
637- rhs_syntax : next_syntax,
638- lhs_parent_stack : v. lhs_parent_stack ,
639- rhs_parent_stack : next_stack,
640- ..Vertex :: default ( )
641- } ,
642- ) ;
643621 }
644622}
645623
@@ -651,9 +629,6 @@ pub fn populate_change_map<'a, 'b>(
651629
652630 for ( e, v) in route {
653631 match e {
654- ExitDelimiter => {
655- // Nothing to do: we have already marked this node when we entered it.
656- }
657632 UnchangedNode { .. } => {
658633 // No change on this node or its children.
659634 let lhs = v. lhs_syntax . get_side ( ) . unwrap ( ) ;
0 commit comments