@@ -340,6 +340,11 @@ pub struct TokenStream {
340
340
ts : InternalTS ,
341
341
}
342
342
343
+ // This indicates the maximum size for a leaf in the concatenation algorithm.
344
+ // If two leafs will be collectively smaller than this, they will be merged.
345
+ // If a leaf is larger than this, it will be concatenated at the top.
346
+ const LEAF_SIZE : usize = 32 ;
347
+
343
348
// NB If Leaf access proves to be slow, inroducing a secondary Leaf without the bounds
344
349
// for unsliced Leafs may lead to some performance improvemenet.
345
350
#[ derive( Clone , PartialEq , Eq , Hash , RustcEncodable , RustcDecodable ) ]
@@ -483,6 +488,37 @@ impl InternalTS {
483
488
}
484
489
}
485
490
}
491
+
492
+ fn to_vec ( & self ) -> Vec < & TokenTree > {
493
+ let mut res = Vec :: with_capacity ( self . len ( ) ) ;
494
+ fn traverse_and_append < ' a > ( res : & mut Vec < & ' a TokenTree > , ts : & ' a InternalTS ) {
495
+ match * ts {
496
+ InternalTS :: Empty ( ..) => { } ,
497
+ InternalTS :: Leaf { ref tts, offset, len, .. } => {
498
+ let mut to_app = tts[ offset..offset + len] . iter ( ) . collect ( ) ;
499
+ res. append ( & mut to_app) ;
500
+ }
501
+ InternalTS :: Node { ref left, ref right, .. } => {
502
+ traverse_and_append ( res, left) ;
503
+ traverse_and_append ( res, right) ;
504
+ }
505
+ }
506
+ }
507
+ traverse_and_append ( & mut res, self ) ;
508
+ res
509
+ }
510
+
511
+ fn to_tts ( & self ) -> Vec < TokenTree > {
512
+ self . to_vec ( ) . into_iter ( ) . cloned ( ) . collect :: < Vec < TokenTree > > ( )
513
+ }
514
+
515
+ // Returns an internal node's children.
516
+ fn children ( & self ) -> Option < ( Rc < InternalTS > , Rc < InternalTS > ) > {
517
+ match * self {
518
+ InternalTS :: Node { ref left, ref right, .. } => Some ( ( left. clone ( ) , right. clone ( ) ) ) ,
519
+ _ => None ,
520
+ }
521
+ }
486
522
}
487
523
488
524
/// TokenStream operators include basic destructuring, boolean operations, `maybe_...`
@@ -496,14 +532,17 @@ impl InternalTS {
496
532
///
497
533
/// `maybe_path_prefix("a::b::c(a,b,c).foo()") -> (a::b::c, "(a,b,c).foo()")`
498
534
impl TokenStream {
535
+ // Construct an empty node with a dummy span.
499
536
pub fn mk_empty ( ) -> TokenStream {
500
537
TokenStream { ts : InternalTS :: Empty ( DUMMY_SP ) }
501
538
}
502
539
540
+ // Construct an empty node with the provided span.
503
541
fn mk_spanned_empty ( sp : Span ) -> TokenStream {
504
542
TokenStream { ts : InternalTS :: Empty ( sp) }
505
543
}
506
544
545
+ // Construct a leaf node with a 0 offset and length equivalent to the input.
507
546
fn mk_leaf ( tts : Rc < Vec < TokenTree > > , sp : Span ) -> TokenStream {
508
547
let len = tts. len ( ) ;
509
548
TokenStream {
@@ -516,6 +555,7 @@ impl TokenStream {
516
555
}
517
556
}
518
557
558
+ // Construct a leaf node with the provided values.
519
559
fn mk_sub_leaf ( tts : Rc < Vec < TokenTree > > , offset : usize , len : usize , sp : Span ) -> TokenStream {
520
560
TokenStream {
521
561
ts : InternalTS :: Leaf {
@@ -527,6 +567,7 @@ impl TokenStream {
527
567
}
528
568
}
529
569
570
+ // Construct an internal node with the provided values.
530
571
fn mk_int_node ( left : Rc < InternalTS > ,
531
572
right : Rc < InternalTS > ,
532
573
len : usize ,
@@ -561,11 +602,56 @@ impl TokenStream {
561
602
}
562
603
}
563
604
564
- /// Concatenates two TokenStreams into a new TokenStream
605
+ /// Concatenates two TokenStreams into a new TokenStream.
565
606
pub fn concat ( left : TokenStream , right : TokenStream ) -> TokenStream {
566
- let new_len = left. len ( ) + right. len ( ) ;
567
- let new_span = combine_spans ( left. span ( ) , right. span ( ) ) ;
568
- TokenStream :: mk_int_node ( Rc :: new ( left. ts ) , Rc :: new ( right. ts ) , new_len, new_span)
607
+ // This internal procedure performs 'aggressive compacting' during concatenation as
608
+ // follows:
609
+ // - If the nodes' combined total total length is less than 32, we copy both of
610
+ // them into a new vector and build a new leaf node.
611
+ // - If one node is an internal node and the other is a 'small' leaf (length<32),
612
+ // we recur down the internal node on the appropriate side.
613
+ // - Otherwise, we construct a new internal node that points to them as left and
614
+ // right.
615
+ fn concat_internal ( left : Rc < InternalTS > , right : Rc < InternalTS > ) -> TokenStream {
616
+ let llen = left. len ( ) ;
617
+ let rlen = right. len ( ) ;
618
+ let len = llen + rlen;
619
+ let span = combine_spans ( left. span ( ) , right. span ( ) ) ;
620
+ if len <= LEAF_SIZE {
621
+ let mut new_vec = left. to_tts ( ) ;
622
+ let mut rvec = right. to_tts ( ) ;
623
+ new_vec. append ( & mut rvec) ;
624
+ return TokenStream :: mk_leaf ( Rc :: new ( new_vec) , span) ;
625
+ }
626
+
627
+ match ( left. children ( ) , right. children ( ) ) {
628
+ ( Some ( ( lleft, lright) ) , None ) => {
629
+ if rlen <= LEAF_SIZE {
630
+ let new_right = concat_internal ( lright, right) ;
631
+ TokenStream :: mk_int_node ( lleft, Rc :: new ( new_right. ts ) , len, span)
632
+ } else {
633
+ TokenStream :: mk_int_node ( left, right, len, span)
634
+ }
635
+ }
636
+ ( None , Some ( ( rleft, rright) ) ) => {
637
+ if rlen <= LEAF_SIZE {
638
+ let new_left = concat_internal ( left, rleft) ;
639
+ TokenStream :: mk_int_node ( Rc :: new ( new_left. ts ) , rright, len, span)
640
+ } else {
641
+ TokenStream :: mk_int_node ( left, right, len, span)
642
+ }
643
+ }
644
+ ( _, _) => TokenStream :: mk_int_node ( left, right, len, span) ,
645
+ }
646
+ }
647
+
648
+ if left. is_empty ( ) {
649
+ right
650
+ } else if right. is_empty ( ) {
651
+ left
652
+ } else {
653
+ concat_internal ( Rc :: new ( left. ts ) , Rc :: new ( right. ts ) )
654
+ }
569
655
}
570
656
571
657
/// Indicate if the TokenStream is empty.
@@ -580,27 +666,13 @@ impl TokenStream {
580
666
581
667
/// Convert a TokenStream into a vector of borrowed TokenTrees.
582
668
pub fn to_vec ( & self ) -> Vec < & TokenTree > {
583
- fn internal_to_vec ( ts : & InternalTS ) -> Vec < & TokenTree > {
584
- match * ts {
585
- InternalTS :: Empty ( ..) => Vec :: new ( ) ,
586
- InternalTS :: Leaf { ref tts, offset, len, .. } => {
587
- tts[ offset..offset + len] . iter ( ) . collect ( )
588
- }
589
- InternalTS :: Node { ref left, ref right, .. } => {
590
- let mut v1 = internal_to_vec ( left) ;
591
- let mut v2 = internal_to_vec ( right) ;
592
- v1. append ( & mut v2) ;
593
- v1
594
- }
595
- }
596
- }
597
- internal_to_vec ( & self . ts )
669
+ self . ts . to_vec ( )
598
670
}
599
671
600
672
/// Convert a TokenStream into a vector of TokenTrees (by cloning the TokenTrees).
601
673
/// (This operation is an O(n) deep copy of the underlying structure.)
602
674
pub fn to_tts ( & self ) -> Vec < TokenTree > {
603
- self . to_vec ( ) . into_iter ( ) . cloned ( ) . collect :: < Vec < TokenTree > > ( )
675
+ self . ts . to_tts ( )
604
676
}
605
677
606
678
/// Return the TokenStream's span.
0 commit comments