@@ -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 s in nesting. iter_mut ( ) {
22
+ s. 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 ( s. idx ) . ok_or_else ( || {
26
+ s. at_end = true ;
25
27
ExpandError :: BindingError ( format ! ( "could not find nested binding `{}`" , name) )
26
28
} ) ?,
27
29
Binding :: Empty => {
30
+ s. 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,21 @@ 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 : bool ,
65
+ at_end : bool ,
66
+ }
67
+
58
68
#[ derive( Debug ) ]
59
69
struct ExpandCtx < ' a > {
60
70
bindings : & ' a Bindings ,
61
- nesting : Vec < usize > ,
62
- var_expanded : bool ,
71
+ nesting : Vec < NestingState > ,
63
72
}
64
73
65
74
fn expand_subtree ( ctx : & mut ExpandCtx , template : & tt:: Subtree ) -> Result < tt:: Subtree , ExpandError > {
@@ -121,8 +130,7 @@ fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> Result<Fragment, ExpandError>
121
130
. into ( ) ;
122
131
Fragment :: Tokens ( tt)
123
132
} else {
124
- let fragment = ctx. bindings . get ( & v, & ctx. nesting ) ?. clone ( ) ;
125
- ctx. var_expanded = true ;
133
+ let fragment = ctx. bindings . get ( & v, & mut ctx. nesting ) ?. clone ( ) ;
126
134
fragment
127
135
} ;
128
136
Ok ( res)
@@ -135,37 +143,24 @@ fn expand_repeat(
135
143
separator : Option < Separator > ,
136
144
) -> Result < Fragment , ExpandError > {
137
145
let mut buf: Vec < tt:: TokenTree > = Vec :: new ( ) ;
138
- ctx. nesting . push ( 0 ) ;
146
+ ctx. nesting . push ( NestingState { idx : 0 , at_end : false , hit : false } ) ;
139
147
// Dirty hack to make macro-expansion terminate.
140
148
// This should be replaced by a propper macro-by-example implementation
141
- let mut limit = 65536 ;
149
+ let limit = 65536 ;
142
150
let mut has_seps = 0 ;
143
151
let mut counter = 0 ;
144
152
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 {
153
+ loop {
154
+ let res = expand_subtree ( ctx, template) ;
155
+ let nesting_state = ctx. nesting . last_mut ( ) . unwrap ( ) ;
156
+ if nesting_state. at_end || !nesting_state. hit {
158
157
break ;
159
158
}
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 ;
159
+ nesting_state. idx += 1 ;
160
+ nesting_state. hit = false ;
165
161
166
162
counter += 1 ;
167
- limit -= 1 ;
168
- if limit == 0 {
163
+ if counter == limit {
169
164
log:: warn!(
170
165
"expand_tt excced in repeat pattern exceed limit => {:#?}\n {:#?}" ,
171
166
template,
@@ -174,8 +169,11 @@ fn expand_repeat(
174
169
break ;
175
170
}
176
171
177
- let idx = ctx. nesting . pop ( ) . unwrap ( ) ;
178
- ctx. nesting . push ( idx + 1 ) ;
172
+ let mut t = match res {
173
+ Ok ( t) => t,
174
+ Err ( _) => continue ,
175
+ } ;
176
+ t. delimiter = None ;
179
177
push_subtree ( & mut buf, t) ;
180
178
181
179
if let Some ( ref sep) = separator {
@@ -203,9 +201,6 @@ fn expand_repeat(
203
201
}
204
202
}
205
203
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
204
ctx. nesting . pop ( ) . unwrap ( ) ;
210
205
for _ in 0 ..has_seps {
211
206
buf. pop ( ) ;
0 commit comments