(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, sStrBuf) -> @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, sStrBuf) -> @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, sStrBuf) -> @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, sStrBuf) -> 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                             spSpan,
 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                           spSpan,
 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                           spSpan,
 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                          spSpan,
 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                         spSpan,
 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                           spSpan,
 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(strsVec<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, spSpan, identast::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, spSpan, boptoken::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, spSpan, 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, spSpan, 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, spSpan, 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, spSpan, 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                    spSpan,
 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                       spSpan,
 702                       parse_method: &str,
 703                       arg_exprsVec<@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:- 22
123:     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:- 6
510:                                       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:- 2
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)
--
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:- 5
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)
--
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:- 23
231:         ($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:- 2
325:                            -> 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:- 2
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(


libsyntax/ext/quote.rs:381:1-381:1 -fn- definition:
fn id_ext(str: &str) -> ast::Ident {
    str_to_ident(str)
}
references:- 39


libsyntax/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:- 2
416:                                       id_ext("BINOP"),
417:                                       vec!(mk_binop(cx, sp, binop)));
418:         }
--
421:                                       id_ext("BINOPEQ"),
422:                                       vec!(mk_binop(cx, sp, binop)));
423:         }