@@ -60,14 +60,14 @@ pub fn qquote<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[TokenTree])
60
60
struct QDelimited {
61
61
delim : token:: DelimToken ,
62
62
open_span : Span ,
63
- tts : Vec < QTT > ,
63
+ tts : Vec < Qtt > ,
64
64
close_span : Span ,
65
65
}
66
66
67
67
#[ derive( Debug ) ]
68
- enum QTT {
68
+ enum Qtt {
69
69
TT ( TokenTree ) ,
70
- QDL ( QDelimited ) ,
70
+ Delimited ( QDelimited ) ,
71
71
QIdent ( TokenTree ) ,
72
72
}
73
73
@@ -103,10 +103,10 @@ fn qquoter<'cx>(cx: &'cx mut ExtCtxt, ts: TokenStream) -> TokenStream {
103
103
}
104
104
}
105
105
106
- fn qquote_iter < ' cx > ( cx : & ' cx mut ExtCtxt , depth : i64 , ts : TokenStream ) -> ( Bindings , Vec < QTT > ) {
106
+ fn qquote_iter < ' cx > ( cx : & ' cx mut ExtCtxt , depth : i64 , ts : TokenStream ) -> ( Bindings , Vec < Qtt > ) {
107
107
let mut depth = depth;
108
108
let mut bindings: Bindings = Vec :: new ( ) ;
109
- let mut output: Vec < QTT > = Vec :: new ( ) ;
109
+ let mut output: Vec < Qtt > = Vec :: new ( ) ;
110
110
111
111
let mut iter = ts. iter ( ) ;
112
112
@@ -133,32 +133,32 @@ fn qquote_iter<'cx>(cx: &'cx mut ExtCtxt, depth: i64, ts: TokenStream) -> (Bindi
133
133
for b in bindings. clone ( ) {
134
134
debug ! ( "{:?} = {}" , b. 0 , pprust:: tts_to_string( & b. 1 . to_tts( ) [ ..] ) ) ;
135
135
}
136
- output. push ( QTT :: QIdent ( as_tt ( Token :: Ident ( new_id. clone ( ) ) ) ) ) ;
136
+ output. push ( Qtt :: QIdent ( as_tt ( Token :: Ident ( new_id. clone ( ) ) ) ) ) ;
137
137
} else {
138
138
depth = depth - 1 ;
139
- output. push ( QTT :: TT ( next. clone ( ) ) ) ;
139
+ output. push ( Qtt :: TT ( next. clone ( ) ) ) ;
140
140
}
141
141
}
142
142
TokenTree :: Token ( _, Token :: Ident ( id) ) if is_qquote ( id) => {
143
143
depth = depth + 1 ;
144
144
}
145
145
TokenTree :: Delimited ( _, ref dl) => {
146
146
let br = qquote_iter ( cx, depth, TokenStream :: from_tts ( dl. tts . clone ( ) . to_owned ( ) ) ) ;
147
- let mut bind_ = br. 0 ;
148
- let res_ = br. 1 ;
149
- bindings. append ( & mut bind_ ) ;
147
+ let mut nested_bindings = br. 0 ;
148
+ let nested = br. 1 ;
149
+ bindings. append ( & mut nested_bindings ) ;
150
150
151
151
let new_dl = QDelimited {
152
152
delim : dl. delim ,
153
153
open_span : dl. open_span ,
154
- tts : res_ ,
154
+ tts : nested ,
155
155
close_span : dl. close_span ,
156
156
} ;
157
157
158
- output. push ( QTT :: QDL ( new_dl) ) ;
158
+ output. push ( Qtt :: Delimited ( new_dl) ) ;
159
159
}
160
160
t => {
161
- output. push ( QTT :: TT ( t) ) ;
161
+ output. push ( Qtt :: TT ( t) ) ;
162
162
}
163
163
}
164
164
}
@@ -188,9 +188,9 @@ fn unravel_concats(tss: Vec<TokenStream>) -> TokenStream {
188
188
output
189
189
}
190
190
191
- /// This converts the vector of QTTs into a seet of Bindings for construction and the main
191
+ /// This converts the vector of Qtts into a set of Bindings for construction and the main
192
192
/// body as a TokenStream.
193
- fn convert_complex_tts < ' cx > ( cx : & ' cx mut ExtCtxt , tts : Vec < QTT > ) -> ( Bindings , TokenStream ) {
193
+ fn convert_complex_tts < ' cx > ( cx : & ' cx mut ExtCtxt , tts : Vec < Qtt > ) -> ( Bindings , TokenStream ) {
194
194
let mut pushes: Vec < TokenStream > = Vec :: new ( ) ;
195
195
let mut bindings: Bindings = Vec :: new ( ) ;
196
196
@@ -203,28 +203,37 @@ fn convert_complex_tts<'cx>(cx: &'cx mut ExtCtxt, tts: Vec<QTT>) -> (Bindings, T
203
203
}
204
204
let next = next. unwrap ( ) ;
205
205
match next {
206
- QTT :: TT ( TokenTree :: Token ( _, t) ) => {
206
+ Qtt :: TT ( TokenTree :: Token ( _, t) ) => {
207
207
let token_out = emit_token ( t) ;
208
208
pushes. push ( token_out) ;
209
209
}
210
210
// FIXME handle sequence repetition tokens
211
- QTT :: QDL ( qdl) => {
212
- debug ! ( " QDL: {:?} " , qdl. tts) ;
213
- let new_id = Ident :: with_empty_ctxt ( Symbol :: gensym ( "qdl_tmp" ) ) ;
214
- let mut cct_rec = convert_complex_tts ( cx, qdl. tts ) ;
215
- bindings. append ( & mut cct_rec. 0 ) ;
216
- bindings. push ( ( new_id, cct_rec. 1 ) ) ;
217
-
218
- let sep = build_delim_tok ( qdl. delim ) ;
219
-
220
- pushes. push ( build_mod_call (
221
- vec ! [ Ident :: from_str( "proc_macro_tokens" ) ,
222
- Ident :: from_str( "build" ) ,
223
- Ident :: from_str( "build_delimited" ) ] ,
224
- concat ( from_tokens ( vec ! [ Token :: Ident ( new_id) ] ) , concat ( lex ( "," ) , sep) ) ,
225
- ) ) ;
211
+ Qtt :: Delimited ( qdl) => {
212
+ debug ! ( " Delimited: {:?} " , qdl. tts) ;
213
+ let fresh_id = Ident :: with_empty_ctxt ( Symbol :: gensym ( "qdl_tmp" ) ) ;
214
+ let ( mut nested_bindings, nested_toks) = convert_complex_tts ( cx, qdl. tts ) ;
215
+
216
+ let body = if nested_toks. is_empty ( ) {
217
+ assert ! ( nested_bindings. is_empty( ) ) ;
218
+ build_mod_call ( vec ! [ Ident :: from_str( "TokenStream" ) ,
219
+ Ident :: from_str( "mk_empty" ) ] ,
220
+ TokenStream :: mk_empty ( ) )
221
+ } else {
222
+ bindings. append ( & mut nested_bindings) ;
223
+ bindings. push ( ( fresh_id, nested_toks) ) ;
224
+ TokenStream :: from_tokens ( vec ! [ Token :: Ident ( fresh_id) ] )
225
+ } ;
226
+
227
+ let delimitiers = build_delim_tok ( qdl. delim ) ;
228
+
229
+ pushes. push ( build_mod_call ( vec ! [ Ident :: from_str( "proc_macro_tokens" ) ,
230
+ Ident :: from_str( "build" ) ,
231
+ Ident :: from_str( "build_delimited" ) ] ,
232
+ flatten ( vec ! [ body,
233
+ lex( "," ) ,
234
+ delimitiers] . into_iter ( ) ) ) ) ;
226
235
}
227
- QTT :: QIdent ( t) => {
236
+ Qtt :: QIdent ( t) => {
228
237
pushes. push ( TokenStream :: from_tts ( vec ! [ t] ) ) ;
229
238
pushes. push ( TokenStream :: mk_empty ( ) ) ;
230
239
}
@@ -240,14 +249,8 @@ fn convert_complex_tts<'cx>(cx: &'cx mut ExtCtxt, tts: Vec<QTT>) -> (Bindings, T
240
249
// Utilities
241
250
242
251
/// Unravels Bindings into a TokenStream of `let` declarations.
243
- fn unravel ( binds : Bindings ) -> TokenStream {
244
- let mut output = TokenStream :: mk_empty ( ) ;
245
-
246
- for b in binds {
247
- output = concat ( output, build_let ( b. 0 , b. 1 ) ) ;
248
- }
249
-
250
- output
252
+ fn unravel ( bindings : Bindings ) -> TokenStream {
253
+ flatten ( bindings. into_iter ( ) . map ( |( a, b) | build_let ( a, b) ) )
251
254
}
252
255
253
256
/// Checks if the Ident is `unquote`.
0 commit comments