(index<- ) ./libsyntax/ext/quote.rs
git branch: * master 5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
modified: Fri May 9 13:02:28 2014
1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use ast;
12 use codemap::Span;
13 use ext::base::ExtCtxt;
14 use ext::base;
15 use ext::build::AstBuilder;
16 use parse::token::*;
17 use parse::token;
18 use parse;
19
20
21 /**
22 *
23 * Quasiquoting works via token trees.
24 *
25 * This is registered as a set of expression syntax extension called quote!
26 * that lifts its argument token-tree to an AST representing the
27 * construction of the same token tree, with ast::TTNonterminal nodes
28 * interpreted as antiquotes (splices).
29 *
30 */
31
32 pub mod rt {
33 use ast;
34 use ext::base::ExtCtxt;
35 use parse::token;
36 use parse;
37 use print::pprust;
38
39 pub use ast::*;
40 pub use parse::token::*;
41 pub use parse::new_parser_from_tts;
42 pub use codemap::{BytePos, Span, dummy_spanned};
43
44 pub trait ToTokens {
45 fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> ;
46 }
47
48 impl ToTokens for Vec<TokenTree> {
49 fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
50 (*self).clone()
51 }
52 }
53
54 /* Should be (when bugs in default methods are fixed):
55
56 trait ToSource : ToTokens {
57 // Takes a thing and generates a string containing rust code for it.
58 pub fn to_source() -> StrBuf;
59
60 // If you can make source, you can definitely make tokens.
61 pub fn to_tokens(cx: &ExtCtxt) -> ~[TokenTree] {
62 cx.parse_tts(self.to_source())
63 }
64 }
65
66 */
67
68 pub trait ToSource {
69 // Takes a thing and generates a string containing rust code for it.
70 fn to_source(&self) -> StrBuf;
71 }
72
73 impl ToSource for ast::Ident {
74 fn to_source(&self) -> StrBuf {
75 get_ident(*self).get().to_strbuf()
76 }
77 }
78
79 impl ToSource for @ast::Item {
80 fn to_source(&self) -> StrBuf {
81 pprust::item_to_str(*self)
82 }
83 }
84
85 impl<'a> ToSource for &'a [@ast::Item] {
86 fn to_source(&self) -> StrBuf {
87 self.iter()
88 .map(|i| i.to_source())
89 .collect::<Vec<StrBuf>>()
90 .connect("\n\n")
91 .to_strbuf()
92 }
93 }
94
95 impl ToSource for ast::Ty {
96 fn to_source(&self) -> StrBuf {
97 pprust::ty_to_str(self)
98 }
99 }
100
101 impl<'a> ToSource for &'a [ast::Ty] {
102 fn to_source(&self) -> StrBuf {
103 self.iter()
104 .map(|i| i.to_source())
105 .collect::<Vec<StrBuf>>()
106 .connect(", ")
107 .to_strbuf()
108 }
109 }
110
111 impl ToSource for Generics {
112 fn to_source(&self) -> StrBuf {
113 pprust::generics_to_str(self)
114 }
115 }
116
117 impl ToSource for @ast::Expr {
118 fn to_source(&self) -> StrBuf {
119 pprust::expr_to_str(*self)
120 }
121 }
122
123 impl ToSource for ast::Block {
124 fn to_source(&self) -> StrBuf {
125 pprust::block_to_str(self)
126 }
127 }
128
129 impl<'a> ToSource for &'a str {
130 fn to_source(&self) -> StrBuf {
131 let lit = dummy_spanned(ast::LitStr(
132 token::intern_and_get_ident(*self), ast::CookedStr));
133 pprust::lit_to_str(&lit)
134 }
135 }
136
137 impl ToSource for () {
138 fn to_source(&self) -> StrBuf {
139 "()".to_strbuf()
140 }
141 }
142
143 impl ToSource for bool {
144 fn to_source(&self) -> StrBuf {
145 let lit = dummy_spanned(ast::LitBool(*self));
146 pprust::lit_to_str(&lit)
147 }
148 }
149
150 impl ToSource for char {
151 fn to_source(&self) -> StrBuf {
152 let lit = dummy_spanned(ast::LitChar(*self));
153 pprust::lit_to_str(&lit)
154 }
155 }
156
157 impl ToSource for int {
158 fn to_source(&self) -> StrBuf {
159 let lit = dummy_spanned(ast::LitInt(*self as i64, ast::TyI));
160 pprust::lit_to_str(&lit)
161 }
162 }
163
164 impl ToSource for i8 {
165 fn to_source(&self) -> StrBuf {
166 let lit = dummy_spanned(ast::LitInt(*self as i64, ast::TyI8));
167 pprust::lit_to_str(&lit)
168 }
169 }
170
171 impl ToSource for i16 {
172 fn to_source(&self) -> StrBuf {
173 let lit = dummy_spanned(ast::LitInt(*self as i64, ast::TyI16));
174 pprust::lit_to_str(&lit)
175 }
176 }
177
178
179 impl ToSource for i32 {
180 fn to_source(&self) -> StrBuf {
181 let lit = dummy_spanned(ast::LitInt(*self as i64, ast::TyI32));
182 pprust::lit_to_str(&lit)
183 }
184 }
185
186 impl ToSource for i64 {
187 fn to_source(&self) -> StrBuf {
188 let lit = dummy_spanned(ast::LitInt(*self as i64, ast::TyI64));
189 pprust::lit_to_str(&lit)
190 }
191 }
192
193 impl ToSource for uint {
194 fn to_source(&self) -> StrBuf {
195 let lit = dummy_spanned(ast::LitUint(*self as u64, ast::TyU));
196 pprust::lit_to_str(&lit)
197 }
198 }
199
200 impl ToSource for u8 {
201 fn to_source(&self) -> StrBuf {
202 let lit = dummy_spanned(ast::LitUint(*self as u64, ast::TyU8));
203 pprust::lit_to_str(&lit)
204 }
205 }
206
207 impl ToSource for u16 {
208 fn to_source(&self) -> StrBuf {
209 let lit = dummy_spanned(ast::LitUint(*self as u64, ast::TyU16));
210 pprust::lit_to_str(&lit)
211 }
212 }
213
214 impl ToSource for u32 {
215 fn to_source(&self) -> StrBuf {
216 let lit = dummy_spanned(ast::LitUint(*self as u64, ast::TyU32));
217 pprust::lit_to_str(&lit)
218 }
219 }
220
221 impl ToSource for u64 {
222 fn to_source(&self) -> StrBuf {
223 let lit = dummy_spanned(ast::LitUint(*self as u64, ast::TyU64));
224 pprust::lit_to_str(&lit)
225 }
226 }
227
228 // Alas ... we write these out instead. All redundant.
229
230 macro_rules! impl_to_tokens(
231 ($t:ty) => (
232 impl ToTokens for $t {
233 fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
234 cx.parse_tts(self.to_source())
235 }
236 }
237 )
238 )
239
240 macro_rules! impl_to_tokens_self(
241 ($t:ty) => (
242 impl<'a> ToTokens for $t {
243 fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
244 cx.parse_tts(self.to_source())
245 }
246 }
247 )
248 )
249
250 impl_to_tokens!(ast::Ident)
251 impl_to_tokens!(@ast::Item)
252 impl_to_tokens_self!(&'a [@ast::Item])
253 impl_to_tokens!(ast::Ty)
254 impl_to_tokens_self!(&'a [ast::Ty])
255 impl_to_tokens!(Generics)
256 impl_to_tokens!(@ast::Expr)
257 impl_to_tokens!(ast::Block)
258 impl_to_tokens_self!(&'a str)
259 impl_to_tokens!(())
260 impl_to_tokens!(char)
261 impl_to_tokens!(bool)
262 impl_to_tokens!(int)
263 impl_to_tokens!(i8)
264 impl_to_tokens!(i16)
265 impl_to_tokens!(i32)
266 impl_to_tokens!(i64)
267 impl_to_tokens!(uint)
268 impl_to_tokens!(u8)
269 impl_to_tokens!(u16)
270 impl_to_tokens!(u32)
271 impl_to_tokens!(u64)
272
273 pub trait ExtParseUtils {
274 fn parse_item(&self, s: StrBuf) -> @ast::Item;
275 fn parse_expr(&self, s: StrBuf) -> @ast::Expr;
276 fn parse_stmt(&self, s: StrBuf) -> @ast::Stmt;
277 fn parse_tts(&self, s: StrBuf) -> Vec<ast::TokenTree> ;
278 }
279
280 impl<'a> ExtParseUtils for ExtCtxt<'a> {
281
282 fn parse_item(&self, s: StrBuf) -> @ast::Item {
283 let res = parse::parse_item_from_source_str(
284 "<quote expansion>".to_strbuf(),
285 s,
286 self.cfg(),
287 self.parse_sess());
288 match res {
289 Some(ast) => ast,
290 None => {
291 error!("parse error");
292 fail!()
293 }
294 }
295 }
296
297 fn parse_stmt(&self, s: StrBuf) -> @ast::Stmt {
298 parse::parse_stmt_from_source_str("<quote expansion>".to_strbuf(),
299 s,
300 self.cfg(),
301 Vec::new(),
302 self.parse_sess())
303 }
304
305 fn parse_expr(&self, s: StrBuf) -> @ast::Expr {
306 parse::parse_expr_from_source_str("<quote expansion>".to_strbuf(),
307 s,
308 self.cfg(),
309 self.parse_sess())
310 }
311
312 fn parse_tts(&self, s: StrBuf) -> Vec<ast::TokenTree> {
313 parse::parse_tts_from_source_str("<quote expansion>".to_strbuf(),
314 s,
315 self.cfg(),
316 self.parse_sess())
317 }
318 }
319
320 }
321
322 pub fn expand_quote_tokens(cx: &mut ExtCtxt,
323 sp: Span,
324 tts: &[ast::TokenTree])
325 -> Box<base::MacResult> {
326 let (cx_expr, expr) = expand_tts(cx, sp, tts);
327 let expanded = expand_wrapper(cx, sp, cx_expr, expr);
328 base::MacExpr::new(expanded)
329 }
330
331 pub fn expand_quote_expr(cx: &mut ExtCtxt,
332 sp: Span,
333 tts: &[ast::TokenTree]) -> Box<base::MacResult> {
334 let expanded = expand_parse_call(cx, sp, "parse_expr", Vec::new(), tts);
335 base::MacExpr::new(expanded)
336 }
337
338 pub fn expand_quote_item(cx: &mut ExtCtxt,
339 sp: Span,
340 tts: &[ast::TokenTree])
341 -> Box<base::MacResult> {
342 let e_attrs = cx.expr_vec_ng(sp);
343 let expanded = expand_parse_call(cx, sp, "parse_item",
344 vec!(e_attrs), tts);
345 base::MacExpr::new(expanded)
346 }
347
348 pub fn expand_quote_pat(cx: &mut ExtCtxt,
349 sp: Span,
350 tts: &[ast::TokenTree])
351 -> Box<base::MacResult> {
352 let e_refutable = cx.expr_lit(sp, ast::LitBool(true));
353 let expanded = expand_parse_call(cx, sp, "parse_pat",
354 vec!(e_refutable), tts);
355 base::MacExpr::new(expanded)
356 }
357
358 pub fn expand_quote_ty(cx: &mut ExtCtxt,
359 sp: Span,
360 tts: &[ast::TokenTree])
361 -> Box<base::MacResult> {
362 let e_param_colons = cx.expr_lit(sp, ast::LitBool(false));
363 let expanded = expand_parse_call(cx, sp, "parse_ty",
364 vec!(e_param_colons), tts);
365 base::MacExpr::new(expanded)
366 }
367
368 pub fn expand_quote_stmt(cx: &mut ExtCtxt,
369 sp: Span,
370 tts: &[ast::TokenTree])
371 -> Box<base::MacResult> {
372 let e_attrs = cx.expr_vec_ng(sp);
373 let expanded = expand_parse_call(cx, sp, "parse_stmt",
374 vec!(e_attrs), tts);
375 base::MacExpr::new(expanded)
376 }
377
378 fn ids_ext(strs: Vec<StrBuf> ) -> Vec<ast::Ident> {
379 strs.iter().map(|str| str_to_ident((*str).as_slice())).collect()
380 }
381
382 fn id_ext(str: &str) -> ast::Ident {
383 str_to_ident(str)
384 }
385
386 // Lift an ident to the expr that evaluates to that ident.
387 fn mk_ident(cx: &ExtCtxt, sp: Span, ident: ast::Ident) -> @ast::Expr {
388 let e_str = cx.expr_str(sp, token::get_ident(ident));
389 cx.expr_method_call(sp,
390 cx.expr_ident(sp, id_ext("ext_cx")),
391 id_ext("ident_of"),
392 vec!(e_str))
393 }
394
395 fn mk_binop(cx: &ExtCtxt, sp: Span, bop: token::BinOp) -> @ast::Expr {
396 let name = match bop {
397 PLUS => "PLUS",
398 MINUS => "MINUS",
399 STAR => "STAR",
400 SLASH => "SLASH",
401 PERCENT => "PERCENT",
402 CARET => "CARET",
403 AND => "AND",
404 OR => "OR",
405 SHL => "SHL",
406 SHR => "SHR"
407 };
408 cx.expr_ident(sp, id_ext(name))
409 }
410
411 fn mk_token(cx: &ExtCtxt, sp: Span, tok: &token::Token) -> @ast::Expr {
412
413 match *tok {
414 BINOP(binop) => {
415 return cx.expr_call_ident(sp,
416 id_ext("BINOP"),
417 vec!(mk_binop(cx, sp, binop)));
418 }
419 BINOPEQ(binop) => {
420 return cx.expr_call_ident(sp,
421 id_ext("BINOPEQ"),
422 vec!(mk_binop(cx, sp, binop)));
423 }
424
425 LIT_CHAR(i) => {
426 let e_char = cx.expr_lit(sp, ast::LitChar(i));
427
428 return cx.expr_call_ident(sp, id_ext("LIT_CHAR"), vec!(e_char));
429 }
430
431 LIT_INT(i, ity) => {
432 let s_ity = match ity {
433 ast::TyI => "TyI".to_owned(),
434 ast::TyI8 => "TyI8".to_owned(),
435 ast::TyI16 => "TyI16".to_owned(),
436 ast::TyI32 => "TyI32".to_owned(),
437 ast::TyI64 => "TyI64".to_owned()
438 };
439 let e_ity = cx.expr_ident(sp, id_ext(s_ity));
440
441 let e_i64 = cx.expr_lit(sp, ast::LitInt(i, ast::TyI64));
442
443 return cx.expr_call_ident(sp,
444 id_ext("LIT_INT"),
445 vec!(e_i64, e_ity));
446 }
447
448 LIT_UINT(u, uty) => {
449 let s_uty = match uty {
450 ast::TyU => "TyU".to_owned(),
451 ast::TyU8 => "TyU8".to_owned(),
452 ast::TyU16 => "TyU16".to_owned(),
453 ast::TyU32 => "TyU32".to_owned(),
454 ast::TyU64 => "TyU64".to_owned()
455 };
456 let e_uty = cx.expr_ident(sp, id_ext(s_uty));
457
458 let e_u64 = cx.expr_lit(sp, ast::LitUint(u, ast::TyU64));
459
460 return cx.expr_call_ident(sp,
461 id_ext("LIT_UINT"),
462 vec!(e_u64, e_uty));
463 }
464
465 LIT_INT_UNSUFFIXED(i) => {
466 let e_i64 = cx.expr_lit(sp, ast::LitInt(i, ast::TyI64));
467
468 return cx.expr_call_ident(sp,
469 id_ext("LIT_INT_UNSUFFIXED"),
470 vec!(e_i64));
471 }
472
473 LIT_FLOAT(fident, fty) => {
474 let s_fty = match fty {
475 ast::TyF32 => "TyF32".to_owned(),
476 ast::TyF64 => "TyF64".to_owned(),
477 ast::TyF128 => "TyF128".to_owned()
478 };
479 let e_fty = cx.expr_ident(sp, id_ext(s_fty));
480
481 let e_fident = mk_ident(cx, sp, fident);
482
483 return cx.expr_call_ident(sp,
484 id_ext("LIT_FLOAT"),
485 vec!(e_fident, e_fty));
486 }
487
488 LIT_STR(ident) => {
489 return cx.expr_call_ident(sp,
490 id_ext("LIT_STR"),
491 vec!(mk_ident(cx, sp, ident)));
492 }
493
494 LIT_STR_RAW(ident, n) => {
495 return cx.expr_call_ident(sp,
496 id_ext("LIT_STR_RAW"),
497 vec!(mk_ident(cx, sp, ident),
498 cx.expr_uint(sp, n)));
499 }
500
501 IDENT(ident, b) => {
502 return cx.expr_call_ident(sp,
503 id_ext("IDENT"),
504 vec!(mk_ident(cx, sp, ident),
505 cx.expr_bool(sp, b)));
506 }
507
508 LIFETIME(ident) => {
509 return cx.expr_call_ident(sp,
510 id_ext("LIFETIME"),
511 vec!(mk_ident(cx, sp, ident)));
512 }
513
514 DOC_COMMENT(ident) => {
515 return cx.expr_call_ident(sp,
516 id_ext("DOC_COMMENT"),
517 vec!(mk_ident(cx, sp, ident)));
518 }
519
520 INTERPOLATED(_) => fail!("quote! with interpolated token"),
521
522 _ => ()
523 }
524
525 let name = match *tok {
526 EQ => "EQ",
527 LT => "LT",
528 LE => "LE",
529 EQEQ => "EQEQ",
530 NE => "NE",
531 GE => "GE",
532 GT => "GT",
533 ANDAND => "ANDAND",
534 OROR => "OROR",
535 NOT => "NOT",
536 TILDE => "TILDE",
537 AT => "AT",
538 DOT => "DOT",
539 DOTDOT => "DOTDOT",
540 COMMA => "COMMA",
541 SEMI => "SEMI",
542 COLON => "COLON",
543 MOD_SEP => "MOD_SEP",
544 RARROW => "RARROW",
545 LARROW => "LARROW",
546 DARROW => "DARROW",
547 FAT_ARROW => "FAT_ARROW",
548 LPAREN => "LPAREN",
549 RPAREN => "RPAREN",
550 LBRACKET => "LBRACKET",
551 RBRACKET => "RBRACKET",
552 LBRACE => "LBRACE",
553 RBRACE => "RBRACE",
554 POUND => "POUND",
555 DOLLAR => "DOLLAR",
556 UNDERSCORE => "UNDERSCORE",
557 EOF => "EOF",
558 _ => fail!()
559 };
560 cx.expr_ident(sp, id_ext(name))
561 }
562
563
564 fn mk_tt(cx: &ExtCtxt, sp: Span, tt: &ast::TokenTree) -> Vec<@ast::Stmt> {
565
566 match *tt {
567
568 ast::TTTok(sp, ref tok) => {
569 let e_sp = cx.expr_ident(sp, id_ext("_sp"));
570 let e_tok = cx.expr_call_ident(sp,
571 id_ext("TTTok"),
572 vec!(e_sp, mk_token(cx, sp, tok)));
573 let e_push =
574 cx.expr_method_call(sp,
575 cx.expr_ident(sp, id_ext("tt")),
576 id_ext("push"),
577 vec!(e_tok));
578 vec!(cx.stmt_expr(e_push))
579 }
580
581 ast::TTDelim(ref tts) => mk_tts(cx, sp, tts.as_slice()),
582 ast::TTSeq(..) => fail!("TTSeq in quote!"),
583
584 ast::TTNonterminal(sp, ident) => {
585
586 // tt.push_all_move($ident.to_tokens(ext_cx))
587
588 let e_to_toks =
589 cx.expr_method_call(sp,
590 cx.expr_ident(sp, ident),
591 id_ext("to_tokens"),
592 vec!(cx.expr_ident(sp, id_ext("ext_cx"))));
593
594 let e_push =
595 cx.expr_method_call(sp,
596 cx.expr_ident(sp, id_ext("tt")),
597 id_ext("push_all_move"),
598 vec!(e_to_toks));
599
600 vec!(cx.stmt_expr(e_push))
601 }
602 }
603 }
604
605 fn mk_tts(cx: &ExtCtxt, sp: Span, tts: &[ast::TokenTree])
606 -> Vec<@ast::Stmt> {
607 let mut ss = Vec::new();
608 for tt in tts.iter() {
609 ss.push_all_move(mk_tt(cx, sp, tt));
610 }
611 ss
612 }
613
614 fn expand_tts(cx: &ExtCtxt, sp: Span, tts: &[ast::TokenTree])
615 -> (@ast::Expr, @ast::Expr) {
616 // NB: It appears that the main parser loses its mind if we consider
617 // $foo as a TTNonterminal during the main parse, so we have to re-parse
618 // under quote_depth > 0. This is silly and should go away; the _guess_ is
619 // it has to do with transition away from supporting old-style macros, so
620 // try removing it when enough of them are gone.
621
622 let mut p = parse::new_parser_from_tts(cx.parse_sess(),
623 cx.cfg(),
624 tts.iter()
625 .map(|x| (*x).clone())
626 .collect());
627 p.quote_depth += 1u;
628
629 let cx_expr = p.parse_expr();
630 if !p.eat(&token::COMMA) {
631 p.fatal("expected token `,`");
632 }
633
634 let tts = p.parse_all_token_trees();
635 p.abort_if_errors();
636
637 // We also bind a single value, sp, to ext_cx.call_site()
638 //
639 // This causes every span in a token-tree quote to be attributed to the
640 // call site of the extension using the quote. We can't really do much
641 // better since the source of the quote may well be in a library that
642 // was not even parsed by this compilation run, that the user has no
643 // source code for (eg. in libsyntax, which they're just _using_).
644 //
645 // The old quasiquoter had an elaborate mechanism for denoting input
646 // file locations from which quotes originated; unfortunately this
647 // relied on feeding the source string of the quote back into the
648 // compiler (which we don't really want to do) and, in any case, only
649 // pushed the problem a very small step further back: an error
650 // resulting from a parse of the resulting quote is still attributed to
651 // the site the string literal occurred, which was in a source file
652 // _other_ than the one the user has control over. For example, an
653 // error in a quote from the protocol compiler, invoked in user code
654 // using macro_rules! for example, will be attributed to the macro_rules.rs
655 // file in libsyntax, which the user might not even have source to (unless
656 // they happen to have a compiler on hand). Over all, the phase distinction
657 // just makes quotes "hard to attribute". Possibly this could be fixed
658 // by recreating some of the original qq machinery in the tt regime
659 // (pushing fake FileMaps onto the parser to account for original sites
660 // of quotes, for example) but at this point it seems not likely to be
661 // worth the hassle.
662
663 let e_sp = cx.expr_method_call(sp,
664 cx.expr_ident(sp, id_ext("ext_cx")),
665 id_ext("call_site"),
666 Vec::new());
667
668 let stmt_let_sp = cx.stmt_let(sp, false,
669 id_ext("_sp"),
670 e_sp);
671
672 let stmt_let_tt = cx.stmt_let(sp, true, id_ext("tt"), cx.expr_vec_ng(sp));
673
674 let mut vector = vec!(stmt_let_sp, stmt_let_tt);
675 vector.push_all_move(mk_tts(cx, sp, tts.as_slice()));
676 let block = cx.expr_block(
677 cx.block_all(sp,
678 Vec::new(),
679 vector,
680 Some(cx.expr_ident(sp, id_ext("tt")))));
681
682 (cx_expr, block)
683 }
684
685 fn expand_wrapper(cx: &ExtCtxt,
686 sp: Span,
687 cx_expr: @ast::Expr,
688 expr: @ast::Expr) -> @ast::Expr {
689 let uses = vec![ cx.view_use_glob(sp, ast::Inherited,
690 ids_ext(vec!["syntax".to_strbuf(),
691 "ext".to_strbuf(),
692 "quote".to_strbuf(),
693 "rt".to_strbuf()])) ];
694
695 let stmt_let_ext_cx = cx.stmt_let(sp, false, id_ext("ext_cx"), cx_expr);
696
697 cx.expr_block(cx.block_all(sp, uses, vec!(stmt_let_ext_cx), Some(expr)))
698 }
699
700 fn expand_parse_call(cx: &ExtCtxt,
701 sp: Span,
702 parse_method: &str,
703 arg_exprs: Vec<@ast::Expr> ,
704 tts: &[ast::TokenTree]) -> @ast::Expr {
705 let (cx_expr, tts_expr) = expand_tts(cx, sp, tts);
706
707 let cfg_call = || cx.expr_method_call(
708 sp, cx.expr_ident(sp, id_ext("ext_cx")),
709 id_ext("cfg"), Vec::new());
710
711 let parse_sess_call = || cx.expr_method_call(
712 sp, cx.expr_ident(sp, id_ext("ext_cx")),
713 id_ext("parse_sess"), Vec::new());
714
715 let new_parser_call =
716 cx.expr_call(sp,
717 cx.expr_ident(sp, id_ext("new_parser_from_tts")),
718 vec!(parse_sess_call(), cfg_call(), tts_expr));
719
720 let expr = cx.expr_method_call(sp, new_parser_call, id_ext(parse_method),
721 arg_exprs);
722
723 expand_wrapper(cx, sp, cx_expr, expr)
724 }
libsyntax/ext/quote.rs:68:4-68:4 -trait- definition:
pub trait ToSource {
// Takes a thing and generates a string containing rust code for it.
fn to_source(&self) -> StrBuf;
references:- 22123: impl ToSource for ast::Block {
124: fn to_source(&self) -> StrBuf {
--
179: impl ToSource for i32 {
180: fn to_source(&self) -> StrBuf {
--
186: impl ToSource for i64 {
187: fn to_source(&self) -> StrBuf {
--
193: impl ToSource for uint {
194: fn to_source(&self) -> StrBuf {
--
200: impl ToSource for u8 {
201: fn to_source(&self) -> StrBuf {
--
214: impl ToSource for u32 {
215: fn to_source(&self) -> StrBuf {
--
221: impl ToSource for u64 {
222: fn to_source(&self) -> StrBuf {
libsyntax/ext/quote.rs:386:59-386:59 -fn- definition:
// Lift an ident to the expr that evaluates to that ident.
fn mk_ident(cx: &ExtCtxt, sp: Span, ident: ast::Ident) -> @ast::Expr {
let e_str = cx.expr_str(sp, token::get_ident(ident));
references:- 6510: id_ext("LIFETIME"),
511: vec!(mk_ident(cx, sp, ident)));
512: }
--
516: id_ext("DOC_COMMENT"),
517: vec!(mk_ident(cx, sp, ident)));
518: }
libsyntax/ext/quote.rs:684:1-684:1 -fn- definition:
fn expand_wrapper(cx: &ExtCtxt,
sp: Span,
cx_expr: @ast::Expr,
references:- 2326: let (cx_expr, expr) = expand_tts(cx, sp, tts);
327: let expanded = expand_wrapper(cx, sp, cx_expr, expr);
328: base::MacExpr::new(expanded)
--
723: expand_wrapper(cx, sp, cx_expr, expr)
724: }
libsyntax/ext/quote.rs:699:1-699:1 -fn- definition:
fn expand_parse_call(cx: &ExtCtxt,
sp: Span,
parse_method: &str,
references:- 5333: tts: &[ast::TokenTree]) -> Box<base::MacResult> {
334: let expanded = expand_parse_call(cx, sp, "parse_expr", Vec::new(), tts);
335: base::MacExpr::new(expanded)
--
362: let e_param_colons = cx.expr_lit(sp, ast::LitBool(false));
363: let expanded = expand_parse_call(cx, sp, "parse_ty",
364: vec!(e_param_colons), tts);
--
372: let e_attrs = cx.expr_vec_ng(sp);
373: let expanded = expand_parse_call(cx, sp, "parse_stmt",
374: vec!(e_attrs), tts);
libsyntax/ext/quote.rs:44:4-44:4 -trait- definition:
pub trait ToTokens {
fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> ;
}
references:- 23231: ($t:ty) => (
232: impl ToTokens for $t {
233: fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
--
241: ($t:ty) => (
242: impl<'a> ToTokens for $t {
243: fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
libsyntax/ext/quote.rs:613:1-613:1 -fn- definition:
fn expand_tts(cx: &ExtCtxt, sp: Span, tts: &[ast::TokenTree])
-> (@ast::Expr, @ast::Expr) {
// NB: It appears that the main parser loses its mind if we consider
references:- 2325: -> Box<base::MacResult> {
326: let (cx_expr, expr) = expand_tts(cx, sp, tts);
327: let expanded = expand_wrapper(cx, sp, cx_expr, expr);
--
704: tts: &[ast::TokenTree]) -> @ast::Expr {
705: let (cx_expr, tts_expr) = expand_tts(cx, sp, tts);
libsyntax/ext/quote.rs:604:1-604:1 -fn- definition:
fn mk_tts(cx: &ExtCtxt, sp: Span, tts: &[ast::TokenTree])
-> Vec<@ast::Stmt> {
let mut ss = Vec::new();
references:- 2674: let mut vector = vec!(stmt_let_sp, stmt_let_tt);
675: vector.push_all_move(mk_tts(cx, sp, tts.as_slice()));
676: let block = cx.expr_block(
libsyntax/ext/quote.rs:381:1-381:1 -fn- definition:
fn id_ext(str: &str) -> ast::Ident {
str_to_ident(str)
}
references:- 39libsyntax/ext/quote.rs:394:1-394:1 -fn- definition:
fn mk_binop(cx: &ExtCtxt, sp: Span, bop: token::BinOp) -> @ast::Expr {
let name = match bop {
PLUS => "PLUS",
references:- 2416: id_ext("BINOP"),
417: vec!(mk_binop(cx, sp, binop)));
418: }
--
421: id_ext("BINOPEQ"),
422: vec!(mk_binop(cx, sp, binop)));
423: }