@@ -86,65 +86,6 @@ fn id_ext(cx: ext_ctxt, str: ~str) -> ast::ident {
86
86
cx. parse_sess ( ) . interner . intern ( @str)
87
87
}
88
88
89
- fn mk_option_span ( cx : ext_ctxt ,
90
- qsp : span ,
91
- sp : Option < span > ) -> @ast:: expr {
92
- match sp {
93
- None => build:: mk_path ( cx, qsp, ids_ext ( cx, ~[ ~"None "] ) ) ,
94
- Some ( sp) => {
95
- build:: mk_call ( cx, qsp,
96
- ids_ext ( cx, ~[ ~"Some "] ) ,
97
- ~[ build:: mk_managed ( cx, qsp,
98
- mk_span ( cx, qsp, sp) ) ] )
99
- }
100
- }
101
- }
102
-
103
- fn mk_span ( cx : ext_ctxt , qsp : span , sp : span ) -> @ast:: expr {
104
-
105
- let e_expn_info = match sp. expn_info {
106
- None => build:: mk_path ( cx, qsp, ids_ext ( cx, ~[ ~"None "] ) ) ,
107
- Some ( @codemap:: ExpandedFrom ( ref cr) ) => {
108
- let e_callee =
109
- build:: mk_rec_e (
110
- cx, qsp,
111
- ~[ { ident: id_ext ( cx, ~"name") ,
112
- ex: build:: mk_uniq_str ( cx, qsp,
113
- ( * cr) . callie . name ) } ,
114
- { ident: id_ext ( cx, ~"span") ,
115
- ex: mk_option_span ( cx, qsp, ( * cr) . callie . span ) } ] ) ;
116
-
117
- let e_expn_info_ =
118
- build:: mk_call (
119
- cx, qsp,
120
- ids_ext ( cx, ~[ ~"expanded_from"] ) ,
121
- ~[ build:: mk_rec_e (
122
- cx, qsp,
123
- ~[ { ident: id_ext ( cx, ~"call_site") ,
124
- ex: mk_span ( cx, qsp, ( * cr) . call_site ) } ,
125
- { ident: id_ext ( cx, ~"callie") ,
126
- ex: e_callee} ] ) ] ) ;
127
-
128
- build:: mk_call ( cx, qsp,
129
- ids_ext ( cx, ~[ ~"Some "] ) ,
130
- ~[ build:: mk_managed ( cx, qsp, e_expn_info_) ] )
131
- }
132
- } ;
133
-
134
- let span_path = ids_ext ( cx, ~[ ~"span"] ) ;
135
-
136
- build:: mk_struct_e ( cx, qsp,
137
- span_path,
138
- ~[ { ident: id_ext ( cx, ~"lo") ,
139
- ex: mk_bytepos ( cx, qsp, sp. lo ) } ,
140
-
141
- { ident: id_ext ( cx, ~"hi") ,
142
- ex: mk_bytepos ( cx, qsp, sp. hi ) } ,
143
-
144
- { ident: id_ext ( cx, ~"expn_info") ,
145
- ex: e_expn_info} ] )
146
- }
147
-
148
89
// Lift an ident to the expr that evaluates to that ident.
149
90
fn mk_ident ( cx : ext_ctxt , sp : span , ident : ast:: ident ) -> @ast:: expr {
150
91
let e_meth = build:: mk_access ( cx, sp,
@@ -321,59 +262,121 @@ fn mk_token(cx: ext_ctxt, sp: span, tok: token::Token) -> @ast::expr {
321
262
}
322
263
323
264
324
- fn mk_tt( cx : ext_ctxt , sp : span , tt : & ast:: token_tree ) -> @ast:: expr {
265
+ fn mk_tt ( cx : ext_ctxt , sp : span , tt : & ast:: token_tree )
266
+ -> ~[ @ast:: stmt ] {
267
+
325
268
match * tt {
269
+
326
270
ast:: tt_tok( sp, ref tok) => {
271
+ let e_sp = build:: mk_path ( cx, sp,
272
+ ids_ext ( cx, ~[ ~"sp"] ) ) ;
327
273
let e_tok =
328
274
build:: mk_call ( cx, sp,
329
275
ids_ext ( cx, ~[ ~"tt_tok"] ) ,
330
- ~[ mk_span ( cx, sp, sp) ,
331
- mk_token ( cx, sp, ( * tok) ) ] ) ;
332
- build:: mk_uniq_vec_e ( cx, sp, ~[ e_tok] )
333
- }
276
+ ~[ e_sp, mk_token ( cx, sp, * tok) ] ) ;
277
+ let e_push =
278
+ build:: mk_call_ ( cx, sp,
279
+ build:: mk_access ( cx, sp,
280
+ ids_ext ( cx, ~[ ~"tt"] ) ,
281
+ id_ext ( cx, ~"push") ) ,
282
+ ~[ e_tok] ) ;
283
+ ~[ build:: mk_stmt ( cx, sp, e_push) ]
334
284
335
- ast:: tt_delim( ref tts) => {
336
- let e_delim =
337
- build:: mk_call ( cx, sp,
338
- ids_ext ( cx, ~[ ~"tt_delim"] ) ,
339
- ~[ mk_tts ( cx, sp, ( * tts) ) ] ) ;
340
- build:: mk_uniq_vec_e ( cx, sp, ~[ e_delim] )
341
285
}
342
286
287
+ ast:: tt_delim( ref tts) => mk_tts ( cx, sp, * tts) ,
343
288
ast:: tt_seq( * ) => fail ~"tt_seq in quote!",
344
289
345
- ast::tt_nonterminal(sp, ident) =>
346
- build::mk_copy(cx, sp, build::mk_path(cx, sp, ~[ident]))
290
+ ast::tt_nonterminal(sp, ident) => {
291
+ let e_push =
292
+ build::mk_call_(cx, sp,
293
+ build::mk_access
294
+ (cx, sp,
295
+ ids_ext(cx, ~[~" tt"] ) ,
296
+ id_ext( cx, ~"push_all_move") ) ,
297
+ ~[ build:: mk_path( cx, sp, ~[ ident] ) ] ) ;
298
+ ~[ build:: mk_stmt( cx, sp, e_push) ]
299
+ }
347
300
}
348
301
}
349
302
350
- fn mk_tts(cx: ext_ctxt, sp: span, tts: &[ast::token_tree]) -> @ast::expr {
351
- let e_tts = tts.map(|tt| mk_tt(cx, sp, tt));
352
- build::mk_call(cx, sp,
353
- ids_ext(cx, ~[~" vec", ~"concat"] ) ,
354
- ~[ build:: mk_slice_vec_e( cx, sp, e_tts) ] )
303
+ fn mk_tts( cx: ext_ctxt, sp: span, tts: & [ ast:: token_tree] )
304
+ -> ~[ @ast:: stmt] {
305
+ let mut ss = ~[ ] ;
306
+ for tts. each |tt| {
307
+ ss. push_all_move( mk_tt( cx, sp, tt) ) ;
308
+ }
309
+ ss
355
310
}
356
311
357
312
fn expand_tts( cx: ext_ctxt,
358
313
sp: span,
359
314
tts: ~[ ast:: token_tree] ) -> @ast:: expr {
315
+
360
316
// NB: It appears that the main parser loses its mind if we consider
361
317
// $foo as a tt_nonterminal during the main parse, so we have to re-parse
362
318
// under quote_depth > 0. This is silly and should go away; the _guess_ is
363
319
// it has to do with transition away from supporting old-style macros, so
364
320
// try removing it when enough of them are gone.
321
+
365
322
let p = parse : : new_parser_from_tts( cx. parse_sess( ) , cx. cfg( ) , tts) ;
366
323
p. quote_depth += 1 u;
367
324
let tts = p. parse_all_token_trees( ) ;
368
325
p. abort_if_errors( ) ;
369
326
370
327
// We want to emit a block expression that does a sequence of 'use's to
371
- // import the runtime module, followed by a tt expression.
328
+ // import the runtime module, followed by a tt-building expression.
329
+
372
330
let uses = ~[ build:: mk_glob_use( cx, sp, ids_ext( cx, ~[ ~"syntax",
373
331
~"ext",
374
332
~"quote",
375
333
~"rt"] ) ) ] ;
376
- build:: mk_block( cx, sp, uses, ~[ ] , Some ( mk_tts( cx, sp, tts) ) )
334
+
335
+ // We also bind a single value, sp, to ext_cx.call_site()
336
+ //
337
+ // This causes every span in a token-tree quote to be attributed to the
338
+ // call site of the extension using the quote. We can't really do much
339
+ // better since the source of the quote may well be in a library that
340
+ // was not even parsed by this compilation run, that the user has no
341
+ // source code for (eg. in libsyntax, which they're just _using_).
342
+ //
343
+ // The old quasiquoter had an elaborate mechanism for denoting input
344
+ // file locations from which quotes originated; unfortunately this
345
+ // relied on feeding the source string of the quote back into the
346
+ // compiler (which we don't really want to do) and, in any case, only
347
+ // pushed the problem a very small step further back: an error
348
+ // resulting from a parse of the resulting quote is still attributed to
349
+ // the site the string literal occured, which was in a source file
350
+ // _other_ than the one the user has control over. For example, an
351
+ // error in a quote from the protocol compiler, invoked in user code
352
+ // using proto! for example, will be attributed to the pipec.rs file in
353
+ // libsyntax, which the user might not even have source to (unless they
354
+ // happen to have a compiler on hand). Over all, the phase distinction
355
+ // just makes quotes "hard to attribute". Possibly this could be fixed
356
+ // by recreating some of the original qq machinery in the tt regime
357
+ // (pushing fake FileMaps onto the parser to account for original sites
358
+ // of quotes, for example) but at this point it seems not likely to be
359
+ // worth the hassle.
360
+
361
+ let e_sp = build:: mk_call_ ( cx, sp,
362
+ build:: mk_access ( cx, sp,
363
+ ids_ext ( cx, ~[ ~"ext_cx"] ) ,
364
+ id_ext ( cx, ~"call_site") ) ,
365
+ ~[ ] ) ;
366
+
367
+ let stmt_let_sp = build:: mk_local ( cx, sp, false ,
368
+ id_ext ( cx, ~"sp") ,
369
+ e_sp) ;
370
+
371
+ let stmt_let_tt = build:: mk_local ( cx, sp, true ,
372
+ id_ext ( cx, ~"tt") ,
373
+ build:: mk_uniq_vec_e ( cx, sp, ~[ ] ) ) ;
374
+
375
+ build:: mk_block ( cx, sp, uses,
376
+ ~[ stmt_let_sp,
377
+ stmt_let_tt] + mk_tts ( cx, sp, tts) ,
378
+ Some ( build:: mk_path ( cx, sp,
379
+ ids_ext ( cx, ~[ ~"tt"] ) ) ) )
377
380
}
378
381
379
382
fn expand_parse_call ( cx : ext_ctxt ,
0 commit comments