@@ -14,21 +14,24 @@ impl Bindings {
14
14
self . inner . contains_key ( name)
15
15
}
16
16
17
- fn get ( & self , name : & str , nesting : & [ usize ] ) -> Result < & Fragment , ExpandError > {
17
+ fn get ( & self , name : & str , nesting : & mut [ NestingState ] ) -> Result < & Fragment , ExpandError > {
18
18
let mut b = self . inner . get ( name) . ok_or_else ( || {
19
19
ExpandError :: BindingError ( format ! ( "could not find binding `{}`" , name) )
20
20
} ) ?;
21
- for & idx in nesting. iter ( ) {
21
+ for nesting_state in nesting. iter_mut ( ) {
22
+ nesting_state. hit = true ;
22
23
b = match b {
23
24
Binding :: Fragment ( _) => break ,
24
- Binding :: Nested ( bs) => bs. get ( idx) . ok_or_else ( || {
25
+ Binding :: Nested ( bs) => bs. get ( nesting_state. idx ) . ok_or_else ( || {
26
+ nesting_state. at_end = true ;
25
27
ExpandError :: BindingError ( format ! ( "could not find nested binding `{}`" , name) )
26
28
} ) ?,
27
29
Binding :: Empty => {
30
+ nesting_state. at_end = true ;
28
31
return Err ( ExpandError :: BindingError ( format ! (
29
32
"could not find empty binding `{}`" ,
30
33
name
31
- ) ) )
34
+ ) ) ) ;
32
35
}
33
36
} ;
34
37
}
@@ -51,15 +54,25 @@ pub(super) fn transcribe(
51
54
bindings : & Bindings ,
52
55
) -> Result < tt:: Subtree , ExpandError > {
53
56
assert ! ( template. delimiter == None ) ;
54
- let mut ctx = ExpandCtx { bindings : & bindings, nesting : Vec :: new ( ) , var_expanded : false } ;
57
+ let mut ctx = ExpandCtx { bindings : & bindings, nesting : Vec :: new ( ) } ;
55
58
expand_subtree ( & mut ctx, template)
56
59
}
57
60
61
+ #[ derive( Debug ) ]
62
+ struct NestingState {
63
+ idx : usize ,
64
+ /// `hit` is currently necessary to tell `expand_repeat` if it should stop
65
+ /// because there is no variable in use by the current repetition
66
+ hit : bool ,
67
+ /// `at_end` is currently necessary to tell `expand_repeat` if it should stop
68
+ /// because there is no more value avaible for the current repetition
69
+ at_end : bool ,
70
+ }
71
+
58
72
#[ derive( Debug ) ]
59
73
struct ExpandCtx < ' a > {
60
74
bindings : & ' a Bindings ,
61
- nesting : Vec < usize > ,
62
- var_expanded : bool ,
75
+ nesting : Vec < NestingState > ,
63
76
}
64
77
65
78
fn expand_subtree ( ctx : & mut ExpandCtx , template : & tt:: Subtree ) -> Result < tt:: Subtree , ExpandError > {
@@ -121,9 +134,7 @@ fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> Result<Fragment, ExpandError>
121
134
. into ( ) ;
122
135
Fragment :: Tokens ( tt)
123
136
} else {
124
- let fragment = ctx. bindings . get ( & v, & ctx. nesting ) ?. clone ( ) ;
125
- ctx. var_expanded = true ;
126
- fragment
137
+ ctx. bindings . get ( & v, & mut ctx. nesting ) ?. clone ( )
127
138
} ;
128
139
Ok ( res)
129
140
}
@@ -135,37 +146,24 @@ fn expand_repeat(
135
146
separator : Option < Separator > ,
136
147
) -> Result < Fragment , ExpandError > {
137
148
let mut buf: Vec < tt:: TokenTree > = Vec :: new ( ) ;
138
- ctx. nesting . push ( 0 ) ;
149
+ ctx. nesting . push ( NestingState { idx : 0 , at_end : false , hit : false } ) ;
139
150
// Dirty hack to make macro-expansion terminate.
140
151
// This should be replaced by a propper macro-by-example implementation
141
- let mut limit = 65536 ;
152
+ let limit = 65536 ;
142
153
let mut has_seps = 0 ;
143
154
let mut counter = 0 ;
144
155
145
- // We store the old var expanded value, and restore it later
146
- // It is because before this `$repeat`,
147
- // it is possible some variables already expanad in the same subtree
148
- //
149
- // `some_var_expanded` keep check if the deeper subtree has expanded variables
150
- let mut some_var_expanded = false ;
151
- let old_var_expanded = ctx. var_expanded ;
152
- ctx. var_expanded = false ;
153
-
154
- while let Ok ( mut t) = expand_subtree ( ctx, template) {
155
- t. delimiter = None ;
156
- // if no var expanded in the child, we count it as a fail
157
- if !ctx. var_expanded {
156
+ loop {
157
+ let res = expand_subtree ( ctx, template) ;
158
+ let nesting_state = ctx. nesting . last_mut ( ) . unwrap ( ) ;
159
+ if nesting_state. at_end || !nesting_state. hit {
158
160
break ;
159
161
}
160
-
161
- // Reset `ctx.var_expandeded` to see if there is other expanded variable
162
- // in the next matching
163
- some_var_expanded = true ;
164
- ctx. var_expanded = false ;
162
+ nesting_state. idx += 1 ;
163
+ nesting_state. hit = false ;
165
164
166
165
counter += 1 ;
167
- limit -= 1 ;
168
- if limit == 0 {
166
+ if counter == limit {
169
167
log:: warn!(
170
168
"expand_tt excced in repeat pattern exceed limit => {:#?}\n {:#?}" ,
171
169
template,
@@ -174,8 +172,11 @@ fn expand_repeat(
174
172
break ;
175
173
}
176
174
177
- let idx = ctx. nesting . pop ( ) . unwrap ( ) ;
178
- ctx. nesting . push ( idx + 1 ) ;
175
+ let mut t = match res {
176
+ Ok ( t) => t,
177
+ Err ( _) => continue ,
178
+ } ;
179
+ t. delimiter = None ;
179
180
push_subtree ( & mut buf, t) ;
180
181
181
182
if let Some ( ref sep) = separator {
@@ -203,9 +204,6 @@ fn expand_repeat(
203
204
}
204
205
}
205
206
206
- // Restore the `var_expanded` by combining old one and the new one
207
- ctx. var_expanded = some_var_expanded || old_var_expanded;
208
-
209
207
ctx. nesting . pop ( ) . unwrap ( ) ;
210
208
for _ in 0 ..has_seps {
211
209
buf. pop ( ) ;
0 commit comments