@@ -340,6 +340,11 @@ pub struct TokenStream {
340340 ts : InternalTS ,
341341}
342342
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+
343348// NB If Leaf access proves to be slow, inroducing a secondary Leaf without the bounds
344349// for unsliced Leafs may lead to some performance improvemenet.
345350#[ derive( Clone , PartialEq , Eq , Hash , RustcEncodable , RustcDecodable ) ]
@@ -483,6 +488,37 @@ impl InternalTS {
483488 }
484489 }
485490 }
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+ }
486522}
487523
488524/// TokenStream operators include basic destructuring, boolean operations, `maybe_...`
@@ -496,14 +532,17 @@ impl InternalTS {
496532///
497533/// `maybe_path_prefix("a::b::c(a,b,c).foo()") -> (a::b::c, "(a,b,c).foo()")`
498534impl TokenStream {
535+ // Construct an empty node with a dummy span.
499536 pub fn mk_empty ( ) -> TokenStream {
500537 TokenStream { ts : InternalTS :: Empty ( DUMMY_SP ) }
501538 }
502539
540+ // Construct an empty node with the provided span.
503541 fn mk_spanned_empty ( sp : Span ) -> TokenStream {
504542 TokenStream { ts : InternalTS :: Empty ( sp) }
505543 }
506544
545+ // Construct a leaf node with a 0 offset and length equivalent to the input.
507546 fn mk_leaf ( tts : Rc < Vec < TokenTree > > , sp : Span ) -> TokenStream {
508547 let len = tts. len ( ) ;
509548 TokenStream {
@@ -516,6 +555,7 @@ impl TokenStream {
516555 }
517556 }
518557
558+ // Construct a leaf node with the provided values.
519559 fn mk_sub_leaf ( tts : Rc < Vec < TokenTree > > , offset : usize , len : usize , sp : Span ) -> TokenStream {
520560 TokenStream {
521561 ts : InternalTS :: Leaf {
@@ -527,6 +567,7 @@ impl TokenStream {
527567 }
528568 }
529569
570+ // Construct an internal node with the provided values.
530571 fn mk_int_node ( left : Rc < InternalTS > ,
531572 right : Rc < InternalTS > ,
532573 len : usize ,
@@ -561,11 +602,56 @@ impl TokenStream {
561602 }
562603 }
563604
564- /// Concatenates two TokenStreams into a new TokenStream
605+ /// Concatenates two TokenStreams into a new TokenStream.
565606 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+ }
569655 }
570656
571657 /// Indicate if the TokenStream is empty.
@@ -580,27 +666,13 @@ impl TokenStream {
580666
581667 /// Convert a TokenStream into a vector of borrowed TokenTrees.
582668 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 ( )
598670 }
599671
600672 /// Convert a TokenStream into a vector of TokenTrees (by cloning the TokenTrees).
601673 /// (This operation is an O(n) deep copy of the underlying structure.)
602674 pub fn to_tts ( & self ) -> Vec < TokenTree > {
603- self . to_vec ( ) . into_iter ( ) . cloned ( ) . collect :: < Vec < TokenTree > > ( )
675+ self . ts . to_tts ( )
604676 }
605677
606678 /// Return the TokenStream's span.
0 commit comments