1- //! Transcraber takes a template, like `fn $ident() {}`, a set of bindings like
1+ //! Transcriber takes a template, like `fn $ident() {}`, a set of bindings like
22//! `$ident => foo`, interpolates variables in the template, to get `fn foo() {}`
33
44use ra_syntax:: SmolStr ;
@@ -53,7 +53,8 @@ impl Bindings {
5353pub ( super ) fn transcribe ( template : & tt:: Subtree , bindings : & Bindings ) -> ExpandResult < tt:: Subtree > {
5454 assert ! ( template. delimiter == None ) ;
5555 let mut ctx = ExpandCtx { bindings : & bindings, nesting : Vec :: new ( ) } ;
56- expand_subtree ( & mut ctx, template)
56+ let mut arena: Vec < tt:: TokenTree > = Vec :: new ( ) ;
57+ expand_subtree ( & mut ctx, template, & mut arena)
5758}
5859
5960#[ derive( Debug ) ]
@@ -73,8 +74,13 @@ struct ExpandCtx<'a> {
7374 nesting : Vec < NestingState > ,
7475}
7576
76- fn expand_subtree ( ctx : & mut ExpandCtx , template : & tt:: Subtree ) -> ExpandResult < tt:: Subtree > {
77- let mut buf: Vec < tt:: TokenTree > = Vec :: new ( ) ;
77+ fn expand_subtree (
78+ ctx : & mut ExpandCtx ,
79+ template : & tt:: Subtree ,
80+ arena : & mut Vec < tt:: TokenTree > ,
81+ ) -> ExpandResult < tt:: Subtree > {
82+ // remember how many elements are in the arena now - when returning, we want to drain exactly how many elements we added. This way, the recursive uses of the arena get their own "view" of the arena, but will reuse the allocation
83+ let start_elements = arena. len ( ) ;
7884 let mut err = None ;
7985 for op in parse_template ( template) {
8086 let op = match op {
@@ -85,25 +91,27 @@ fn expand_subtree(ctx: &mut ExpandCtx, template: &tt::Subtree) -> ExpandResult<t
8591 }
8692 } ;
8793 match op {
88- Op :: TokenTree ( tt @ tt:: TokenTree :: Leaf ( ..) ) => buf . push ( tt. clone ( ) ) ,
94+ Op :: TokenTree ( tt @ tt:: TokenTree :: Leaf ( ..) ) => arena . push ( tt. clone ( ) ) ,
8995 Op :: TokenTree ( tt:: TokenTree :: Subtree ( tt) ) => {
90- let ExpandResult ( tt, e) = expand_subtree ( ctx, tt) ;
96+ let ExpandResult ( tt, e) = expand_subtree ( ctx, tt, arena ) ;
9197 err = err. or ( e) ;
92- buf . push ( tt. into ( ) ) ;
98+ arena . push ( tt. into ( ) ) ;
9399 }
94100 Op :: Var { name, kind : _ } => {
95101 let ExpandResult ( fragment, e) = expand_var ( ctx, name) ;
96102 err = err. or ( e) ;
97- push_fragment ( & mut buf , fragment) ;
103+ push_fragment ( arena , fragment) ;
98104 }
99105 Op :: Repeat { subtree, kind, separator } => {
100- let ExpandResult ( fragment, e) = expand_repeat ( ctx, subtree, kind, separator) ;
106+ let ExpandResult ( fragment, e) = expand_repeat ( ctx, subtree, kind, separator, arena ) ;
101107 err = err. or ( e) ;
102- push_fragment ( & mut buf , fragment)
108+ push_fragment ( arena , fragment)
103109 }
104110 }
105111 }
106- ExpandResult ( tt:: Subtree { delimiter : template. delimiter , token_trees : buf } , err)
112+ // drain the elements added in this instance of expand_subtree
113+ let tts = arena. drain ( start_elements..arena. len ( ) ) . collect ( ) ;
114+ ExpandResult ( tt:: Subtree { delimiter : template. delimiter , token_trees : tts } , err)
107115}
108116
109117fn expand_var ( ctx : & mut ExpandCtx , v : & SmolStr ) -> ExpandResult < Fragment > {
@@ -155,6 +163,7 @@ fn expand_repeat(
155163 template : & tt:: Subtree ,
156164 kind : RepeatKind ,
157165 separator : Option < Separator > ,
166+ arena : & mut Vec < tt:: TokenTree > ,
158167) -> ExpandResult < Fragment > {
159168 let mut buf: Vec < tt:: TokenTree > = Vec :: new ( ) ;
160169 ctx. nesting . push ( NestingState { idx : 0 , at_end : false , hit : false } ) ;
@@ -165,7 +174,7 @@ fn expand_repeat(
165174 let mut counter = 0 ;
166175
167176 loop {
168- let ExpandResult ( mut t, e) = expand_subtree ( ctx, template) ;
177+ let ExpandResult ( mut t, e) = expand_subtree ( ctx, template, arena ) ;
169178 let nesting_state = ctx. nesting . last_mut ( ) . unwrap ( ) ;
170179 if nesting_state. at_end || !nesting_state. hit {
171180 break ;
0 commit comments