(index<- )        ./libsyntax/ext/base.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-2014 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 ast::Name;
  13  use codemap;
  14  use codemap::{CodeMap, Span, ExpnInfo};
  15  use ext;
  16  use ext::expand;
  17  use parse;
  18  use parse::token;
  19  use parse::token::{InternedString, intern, str_to_ident};
  20  use util::small_vector::SmallVector;
  21  
  22  use collections::HashMap;
  23  
  24  // new-style macro! tt code:
  25  //
  26  //    MacResult, NormalTT, IdentTT
  27  //
  28  // also note that ast::Mac used to have a bunch of extraneous cases and
  29  // is now probably a redundant AST node, can be merged with
  30  // ast::MacInvocTT.
  31  
  32  pub struct MacroDef {
  33      pub name: StrBuf,
  34      pub ext: SyntaxExtension
  35  }
  36  
  37  pub type ItemDecorator =
  38      fn(&mut ExtCtxt, Span, @ast::MetaItem, @ast::Item, |@ast::Item|);
  39  
  40  pub type ItemModifier =
  41      fn(&mut ExtCtxt, Span, @ast::MetaItem, @ast::Item) -> @ast::Item;
  42  
  43  pub struct BasicMacroExpander {
  44      pub expander: MacroExpanderFn,
  45      pub span: Option<Span>
  46  }
  47  
  48  pub trait MacroExpander {
  49      fn expand(&self,
  50                ecx: &mut ExtCtxt,
  51                span: Span,
  52                token_tree: &[ast::TokenTree])
  53                -> Box<MacResult>;
  54  }
  55  
  56  pub type MacroExpanderFn =
  57      fn(ecx: &mut ExtCtxt, span: codemap::Span, token_tree: &[ast::TokenTree])
  58         -> Box<MacResult>;
  59  
  60  impl MacroExpander for BasicMacroExpander {
  61      fn expand(&self,
  62                ecx&mut ExtCtxt,
  63                spanSpan,
  64                token_tree&[ast::TokenTree])
  65                -> Box<MacResult> {
  66          (self.expander)(ecx, span, token_tree)
  67      }
  68  }
  69  
  70  pub struct BasicIdentMacroExpander {
  71      pub expander: IdentMacroExpanderFn,
  72      pub span: Option<Span>
  73  }
  74  
  75  pub trait IdentMacroExpander {
  76      fn expand(&self,
  77                cx: &mut ExtCtxt,
  78                sp: Span,
  79                ident: ast::Ident,
  80                token_tree: Vec<ast::TokenTree> )
  81                -> Box<MacResult>;
  82  }
  83  
  84  impl IdentMacroExpander for BasicIdentMacroExpander {
  85      fn expand(&self,
  86                cx&mut ExtCtxt,
  87                spSpan,
  88                identast::Ident,
  89                token_treeVec<ast::TokenTree> )
  90                -> Box<MacResult> {
  91          (self.expander)(cx, sp, ident, token_tree)
  92      }
  93  }
  94  
  95  pub type IdentMacroExpanderFn =
  96      fn(&mut ExtCtxt, Span, ast::Ident, Vec<ast::TokenTree>) -> Box<MacResult>;
  97  
  98  pub type MacroCrateRegistrationFun =
  99      fn(|ast::Name, SyntaxExtension|);
 100  
 101  /// The result of a macro expansion. The return values of the various
 102  /// methods are spliced into the AST at the callsite of the macro (or
 103  /// just into the compiler's internal macro table, for `make_def`).
 104  pub trait MacResult {
 105      /// Define a new macro.
 106      fn make_def(&self) -> Option<MacroDef> {
 107          None
 108      }
 109      /// Create an expression.
 110      fn make_expr(&self) -> Option<@ast::Expr> {
 111          None
 112      }
 113      /// Create zero or more items.
 114      fn make_items(&self) -> Option<SmallVector<@ast::Item>> {
 115          None
 116      }
 117  
 118      /// Create a statement.
 119      ///
 120      /// By default this attempts to create an expression statement,
 121      /// returning None if that fails.
 122      fn make_stmt(&self) -> Option<@ast::Stmt> {
 123          self.make_expr()
 124              .map(|e| @codemap::respan(e.span, ast::StmtExpr(e, ast::DUMMY_NODE_ID)))
 125      }
 126  }
 127  
 128  /// A convenience type for macros that return a single expression.
 129  pub struct MacExpr {
 130      e: @ast::Expr
 131  }
 132  impl MacExpr {
 133      pub fn new(e@ast::Expr) -> Box<MacResult> {
 134          box MacExpr { e: e } as Box<MacResult>
 135      }
 136  }
 137  impl MacResult for MacExpr {
 138      fn make_expr(&self) -> Option<@ast::Expr> {
 139          Some(self.e)
 140      }
 141  }
 142  /// A convenience type for macros that return a single item.
 143  pub struct MacItem {
 144      i: @ast::Item
 145  }
 146  impl MacItem {
 147      pub fn new(i@ast::Item) -> Box<MacResult> {
 148          box MacItem { i: i } as Box<MacResult>
 149      }
 150  }
 151  impl MacResult for MacItem {
 152      fn make_items(&self) -> Option<SmallVector<@ast::Item>> {
 153          Some(SmallVector::one(self.i))
 154      }
 155      fn make_stmt(&self) -> Option<@ast::Stmt> {
 156          Some(@codemap::respan(
 157              self.i.span,
 158              ast::StmtDecl(
 159                  @codemap::respan(self.i.span, ast::DeclItem(self.i)),
 160                  ast::DUMMY_NODE_ID)))
 161      }
 162  }
 163  
 164  /// Fill-in macro expansion result, to allow compilation to continue
 165  /// after hitting errors.
 166  pub struct DummyResult {
 167      expr_only: bool,
 168      span: Span
 169  }
 170  
 171  impl DummyResult {
 172      /// Create a default MacResult that can be anything.
 173      ///
 174      /// Use this as a return value after hitting any errors and
 175      /// calling `span_err`.
 176      pub fn any(spSpan) -> Box<MacResult> {
 177          box DummyResult { expr_only: false, span: sp } as Box<MacResult>
 178      }
 179  
 180      /// Create a default MacResult that can only be an expression.
 181      ///
 182      /// Use this for macros that must expand to an expression, so even
 183      /// if an error is encountered internally, the user will recieve
 184      /// an error that they also used it in the wrong place.
 185      pub fn expr(spSpan) -> Box<MacResult> {
 186          box DummyResult { expr_only: true, span: sp } as Box<MacResult>
 187      }
 188  
 189      /// A plain dummy expression.
 190      pub fn raw_expr(spSpan) -> @ast::Expr {
 191          @ast::Expr {
 192              id: ast::DUMMY_NODE_ID,
 193              node: ast::ExprLit(@codemap::respan(sp, ast::LitNil)),
 194              span: sp,
 195          }
 196      }
 197  }
 198  
 199  impl MacResult for DummyResult {
 200      fn make_expr(&self) -> Option<@ast::Expr> {
 201          Some(DummyResult::raw_expr(self.span))
 202      }
 203      fn make_items(&self) -> Option<SmallVector<@ast::Item>> {
 204          if self.expr_only {
 205              None
 206          } else {
 207              Some(SmallVector::zero())
 208          }
 209      }
 210      fn make_stmt(&self) -> Option<@ast::Stmt> {
 211          Some(@codemap::respan(self.span,
 212                                ast::StmtExpr(DummyResult::raw_expr(self.span),
 213                                              ast::DUMMY_NODE_ID)))
 214      }
 215  }
 216  
 217  /// An enum representing the different kinds of syntax extensions.
 218  pub enum SyntaxExtension {
 219      /// A syntax extension that is attached to an item and creates new items
 220      /// based upon it.
 221      ///
 222      /// `#[deriving(...)]` is an `ItemDecorator`.
 223      ItemDecorator(ItemDecorator),
 224  
 225      /// A syntax extension that is attached to an item and modifies it
 226      /// in-place.
 227      ItemModifier(ItemModifier),
 228  
 229      /// A normal, function-like syntax extension.
 230      ///
 231      /// `bytes!` is a `NormalTT`.
 232      NormalTT(Box<MacroExpander:'static>, Option<Span>),
 233  
 234      /// A function-like syntax extension that has an extra ident before
 235      /// the block.
 236      ///
 237      /// `macro_rules!` is an `IdentTT`.
 238      IdentTT(Box<IdentMacroExpander:'static>, Option<Span>),
 239  }
 240  
 241  pub struct BlockInfo {
 242      // should macros escape from this scope?
 243      pub macros_escape: bool,
 244      // what are the pending renames?
 245      pub pending_renames: RenameList,
 246  }
 247  
 248  impl BlockInfo {
 249      pub fn new() -> BlockInfo {
 250          BlockInfo {
 251              macros_escape: false,
 252              pending_renames: Vec::new(),
 253          }
 254      }
 255  }
 256  
 257  // a list of ident->name renamings
 258  pub type RenameList = Vec<(ast::Ident, Name)>;
 259  
 260  // The base map of methods for expanding syntax extension
 261  // AST nodes into full ASTs
 262  pub fn syntax_expander_table() -> SyntaxEnv {
 263      // utility function to simplify creating NormalTT syntax extensions
 264      fn builtin_normal_expander(fMacroExpanderFn) -> SyntaxExtension {
 265          NormalTT(box BasicMacroExpander {
 266                  expander: f,
 267                  span: None,
 268              },
 269              None)
 270      }
 271  
 272      let mut syntax_expanders = SyntaxEnv::new();
 273      syntax_expanders.insert(intern("macro_rules"),
 274                              IdentTT(box BasicIdentMacroExpander {
 275                                  expander: ext::tt::macro_rules::add_new_extension,
 276                                  span: None,
 277                              },
 278                              None));
 279      syntax_expanders.insert(intern("fmt"),
 280                              builtin_normal_expander(
 281                                  ext::fmt::expand_syntax_ext));
 282      syntax_expanders.insert(intern("format_args"),
 283                              builtin_normal_expander(
 284                                  ext::format::expand_args));
 285      syntax_expanders.insert(intern("env"),
 286                              builtin_normal_expander(
 287                                      ext::env::expand_env));
 288      syntax_expanders.insert(intern("option_env"),
 289                              builtin_normal_expander(
 290                                      ext::env::expand_option_env));
 291      syntax_expanders.insert(intern("bytes"),
 292                              builtin_normal_expander(
 293                                      ext::bytes::expand_syntax_ext));
 294      syntax_expanders.insert(intern("concat_idents"),
 295                              builtin_normal_expander(
 296                                      ext::concat_idents::expand_syntax_ext));
 297      syntax_expanders.insert(intern("concat"),
 298                              builtin_normal_expander(
 299                                      ext::concat::expand_syntax_ext));
 300      syntax_expanders.insert(intern("log_syntax"),
 301                              builtin_normal_expander(
 302                                      ext::log_syntax::expand_syntax_ext));
 303      syntax_expanders.insert(intern("deriving"),
 304                              ItemDecorator(ext::deriving::expand_meta_deriving));
 305  
 306      // Quasi-quoting expanders
 307      syntax_expanders.insert(intern("quote_tokens"),
 308                         builtin_normal_expander(
 309                              ext::quote::expand_quote_tokens));
 310      syntax_expanders.insert(intern("quote_expr"),
 311                         builtin_normal_expander(
 312                              ext::quote::expand_quote_expr));
 313      syntax_expanders.insert(intern("quote_ty"),
 314                         builtin_normal_expander(
 315                              ext::quote::expand_quote_ty));
 316      syntax_expanders.insert(intern("quote_item"),
 317                         builtin_normal_expander(
 318                              ext::quote::expand_quote_item));
 319      syntax_expanders.insert(intern("quote_pat"),
 320                         builtin_normal_expander(
 321                              ext::quote::expand_quote_pat));
 322      syntax_expanders.insert(intern("quote_stmt"),
 323                         builtin_normal_expander(
 324                              ext::quote::expand_quote_stmt));
 325  
 326      syntax_expanders.insert(intern("line"),
 327                              builtin_normal_expander(
 328                                      ext::source_util::expand_line));
 329      syntax_expanders.insert(intern("col"),
 330                              builtin_normal_expander(
 331                                      ext::source_util::expand_col));
 332      syntax_expanders.insert(intern("file"),
 333                              builtin_normal_expander(
 334                                      ext::source_util::expand_file));
 335      syntax_expanders.insert(intern("stringify"),
 336                              builtin_normal_expander(
 337                                      ext::source_util::expand_stringify));
 338      syntax_expanders.insert(intern("include"),
 339                              builtin_normal_expander(
 340                                      ext::source_util::expand_include));
 341      syntax_expanders.insert(intern("include_str"),
 342                              builtin_normal_expander(
 343                                      ext::source_util::expand_include_str));
 344      syntax_expanders.insert(intern("include_bin"),
 345                              builtin_normal_expander(
 346                                      ext::source_util::expand_include_bin));
 347      syntax_expanders.insert(intern("module_path"),
 348                              builtin_normal_expander(
 349                                      ext::source_util::expand_mod));
 350      syntax_expanders.insert(intern("asm"),
 351                              builtin_normal_expander(
 352                                      ext::asm::expand_asm));
 353      syntax_expanders.insert(intern("cfg"),
 354                              builtin_normal_expander(
 355                                      ext::cfg::expand_cfg));
 356      syntax_expanders.insert(intern("trace_macros"),
 357                              builtin_normal_expander(
 358                                      ext::trace_macros::expand_trace_macros));
 359      syntax_expanders
 360  }
 361  
 362  pub struct MacroCrate {
 363      pub lib: Option<Path>,
 364      pub macros: Vec<StrBuf>,
 365      pub registrar_symbol: Option<StrBuf>,
 366  }
 367  
 368  pub trait CrateLoader {
 369      fn load_crate(&mut self, krate: &ast::ViewItem) -> MacroCrate;
 370  }
 371  
 372  // One of these is made during expansion and incrementally updated as we go;
 373  // when a macro expansion occurs, the resulting nodes have the backtrace()
 374  // -> expn_info of their expansion context stored into their span.
 375  pub struct ExtCtxt<'a> {
 376      pub parse_sess: &'a parse::ParseSess,
 377      pub cfg: ast::CrateConfig,
 378      pub backtrace: Option<@ExpnInfo>,
 379      pub ecfg: expand::ExpansionConfig<'a>,
 380  
 381      pub mod_path: Vec<ast::Ident> ,
 382      pub trace_mac: bool,
 383  }
 384  
 385  impl<'a> ExtCtxt<'a> {
 386      pub fn new<'a>(parse_sess&'a parse::ParseSess, cfgast::CrateConfig,
 387                     ecfgexpand::ExpansionConfig<'a>) -> ExtCtxt<'a> {
 388          ExtCtxt {
 389              parse_sess: parse_sess,
 390              cfg: cfg,
 391              backtrace: None,
 392              mod_path: Vec::new(),
 393              ecfg: ecfg,
 394              trace_mac: false
 395          }
 396      }
 397  
 398      pub fn expand_expr(&mut self, mut e@ast::Expr) -> @ast::Expr {
 399          loop {
 400              match e.node {
 401                  ast::ExprMac(..) => {
 402                      let mut expander = expand::MacroExpander {
 403                          extsbox: syntax_expander_table(),
 404                          cx: self,
 405                      };
 406                      e = expand::expand_expr(e, &mut expander);
 407                  }
 408                  _ => return e
 409              }
 410          }
 411      }
 412  
 413      pub fn codemap(&self) -> &'a CodeMap { &self.parse_sess.span_diagnostic.cm }
 414      pub fn parse_sess(&self) -> &'a parse::ParseSess { self.parse_sess }
 415      pub fn cfg(&self) -> ast::CrateConfig { self.cfg.clone() }
 416      pub fn call_site(&self) -> Span {
 417          match self.backtrace {
 418              Some(expn_info) => expn_info.call_site,
 419              None => self.bug("missing top span")
 420          }
 421      }
 422      pub fn print_backtrace(&self) { }
 423      pub fn backtrace(&self) -> Option<@ExpnInfo> { self.backtrace }
 424      pub fn mod_push(&mut self, iast::Ident) { self.mod_path.push(i); }
 425      pub fn mod_pop(&mut self) { self.mod_path.pop().unwrap(); }
 426      pub fn mod_path(&self) -> Vec<ast::Ident> {
 427          let mut v = Vec::new();
 428          v.push(token::str_to_ident(self.ecfg.crate_id.name.as_slice()));
 429          v.extend(self.mod_path.iter().map(|a| *a));
 430          return v;
 431      }
 432      pub fn bt_push(&mut self, eicodemap::ExpnInfo) {
 433          match ei {
 434              ExpnInfo {call_site: cs, callee: ref callee} => {
 435                  self.backtrace =
 436                      Some(@ExpnInfo {
 437                          call_site: Span {lo: cs.lo, hi: cs.hi,
 438                                           expn_info: self.backtrace},
 439                          callee: (*callee).clone()
 440                      });
 441              }
 442          }
 443      }
 444      pub fn bt_pop(&mut self) {
 445          match self.backtrace {
 446              Some(expn_info) => self.backtrace = expn_info.call_site.expn_info,
 447              _ => self.bug("tried to pop without a push")
 448          }
 449      }
 450      /// Emit `msg` attached to `sp`, and stop compilation immediately.
 451      ///
 452      /// `span_err` should be strongly prefered where-ever possible:
 453      /// this should *only* be used when
 454      /// - continuing has a high risk of flow-on errors (e.g. errors in
 455      ///   declaring a macro would cause all uses of that macro to
 456      ///   complain about "undefined macro"), or
 457      /// - there is literally nothing else that can be done (however,
 458      ///   in most cases one can construct a dummy expression/item to
 459      ///   substitute; we never hit resolve/type-checking so the dummy
 460      ///   value doesn't have to match anything)
 461      pub fn span_fatal(&self, spSpan, msg&str) -> ! {
 462          self.print_backtrace();
 463          self.parse_sess.span_diagnostic.span_fatal(sp, msg);
 464      }
 465  
 466      /// Emit `msg` attached to `sp`, without immediately stopping
 467      /// compilation.
 468      ///
 469      /// Compilation will be stopped in the near future (at the end of
 470      /// the macro expansion phase).
 471      pub fn span_err(&self, spSpan, msg&str) {
 472          self.print_backtrace();
 473          self.parse_sess.span_diagnostic.span_err(sp, msg);
 474      }
 475      pub fn span_warn(&self, spSpan, msg&str) {
 476          self.print_backtrace();
 477          self.parse_sess.span_diagnostic.span_warn(sp, msg);
 478      }
 479      pub fn span_unimpl(&self, spSpan, msg&str) -> ! {
 480          self.print_backtrace();
 481          self.parse_sess.span_diagnostic.span_unimpl(sp, msg);
 482      }
 483      pub fn span_bug(&self, spSpan, msg&str) -> ! {
 484          self.print_backtrace();
 485          self.parse_sess.span_diagnostic.span_bug(sp, msg);
 486      }
 487      pub fn span_note(&self, spSpan, msg&str) {
 488          self.print_backtrace();
 489          self.parse_sess.span_diagnostic.span_note(sp, msg);
 490      }
 491      pub fn bug(&self, msg&str) -> ! {
 492          self.print_backtrace();
 493          self.parse_sess.span_diagnostic.handler().bug(msg);
 494      }
 495      pub fn trace_macros(&self) -> bool {
 496          self.trace_mac
 497      }
 498      pub fn set_trace_macros(&mut self, xbool) {
 499          self.trace_mac = x
 500      }
 501      pub fn ident_of(&self, st&str) -> ast::Ident {
 502          str_to_ident(st)
 503      }
 504  }
 505  
 506  /// Extract a string literal from the macro expanded version of `expr`,
 507  /// emitting `err_msg` if `expr` is not a string literal. This does not stop
 508  /// compilation on error, merely emits a non-fatal error and returns None.
 509  pub fn expr_to_str(cx: &mut ExtCtxt, expr: @ast::Expr, err_msg: &str)
 510                     -> Option<(InternedString, ast::StrStyle)> {
 511      // we want to be able to handle e.g. concat("foo", "bar")
 512      let expr = cx.expand_expr(expr);
 513      match expr.node {
 514          ast::ExprLit(l) => match l.node {
 515              ast::LitStr(ref s, style) => return Some(((*s).clone(), style)),
 516              _ => cx.span_err(l.span, err_msg)
 517          },
 518          _ => cx.span_err(expr.span, err_msg)
 519      }
 520      None
 521  }
 522  
 523  /// Non-fatally assert that `tts` is empty. Note that this function
 524  /// returns even when `tts` is non-empty, macros that *need* to stop
 525  /// compilation should call
 526  /// `cx.parse_sess.span_diagnostic.abort_if_errors()` (this should be
 527  /// done as rarely as possible).
 528  pub fn check_zero_tts(cx: &ExtCtxt,
 529                        spSpan,
 530                        tts: &[ast::TokenTree],
 531                        name: &str) {
 532      if tts.len() != 0 {
 533          cx.span_err(sp, format!("{} takes no arguments", name));
 534      }
 535  }
 536  
 537  /// Extract the string literal from the first token of `tts`. If this
 538  /// is not a string literal, emit an error and return None.
 539  pub fn get_single_str_from_tts(cx: &ExtCtxt,
 540                                 spSpan,
 541                                 tts: &[ast::TokenTree],
 542                                 name: &str)
 543                                 -> Option<StrBuf> {
 544      if tts.len() != 1 {
 545          cx.span_err(sp, format!("{} takes 1 argument.", name));
 546      } else {
 547          match tts[0] {
 548              ast::TTTok(_, token::LIT_STR(ident))
 549              | ast::TTTok(_, token::LIT_STR_RAW(ident, _)) => {
 550                  return Some(token::get_ident(ident).get().to_strbuf())
 551              }
 552              _ => cx.span_err(sp, format!("{} requires a string.", name)),
 553          }
 554      }
 555      None
 556  }
 557  
 558  /// Extract comma-separated expressions from `tts`. If there is a
 559  /// parsing error, emit a non-fatal error and return None.
 560  pub fn get_exprs_from_tts(cx: &mut ExtCtxt,
 561                            spSpan,
 562                            tts: &[ast::TokenTree]) -> Option<Vec<@ast::Expr> > {
 563      let mut p = parse::new_parser_from_tts(cx.parse_sess(),
 564                                             cx.cfg(),
 565                                             tts.iter()
 566                                                .map(|x| (*x).clone())
 567                                                .collect());
 568      let mut es = Vec::new();
 569      while p.token != token::EOF {
 570          if es.len() != 0 && !p.eat(&token::COMMA) {
 571              cx.span_err(sp, "expected token: `,`");
 572              return None;
 573          }
 574          es.push(cx.expand_expr(p.parse_expr()));
 575      }
 576      Some(es)
 577  }
 578  
 579  // in order to have some notion of scoping for macros,
 580  // we want to implement the notion of a transformation
 581  // environment.
 582  
 583  // This environment maps Names to SyntaxExtensions.
 584  
 585  //impl question: how to implement it? Initially, the
 586  // env will contain only macros, so it might be painful
 587  // to add an empty frame for every context. Let's just
 588  // get it working, first....
 589  
 590  // NB! the mutability of the underlying maps means that
 591  // if expansion is out-of-order, a deeper scope may be
 592  // able to refer to a macro that was added to an enclosing
 593  // scope lexically later than the deeper scope.
 594  
 595  struct MapChainFrame {
 596      info: BlockInfo,
 597      map: HashMap<Name, SyntaxExtension>,
 598  }
 599  
 600  // Only generic to make it easy to test
 601  pub struct SyntaxEnv {
 602      chain: Vec<MapChainFrame> ,
 603  }
 604  
 605  impl SyntaxEnv {
 606      pub fn new() -> SyntaxEnv {
 607          let mut map = SyntaxEnv { chain: Vec::new() };
 608          map.push_frame();
 609          map
 610      }
 611  
 612      pub fn push_frame(&mut self) {
 613          self.chain.push(MapChainFrame {
 614              info: BlockInfo::new(),
 615              map: HashMap::new(),
 616          });
 617      }
 618  
 619      pub fn pop_frame(&mut self) {
 620          assert!(self.chain.len() > 1, "too many pops on MapChain!");
 621          self.chain.pop();
 622      }
 623  
 624      fn find_escape_frame<'a>(&'a mut self) -> &'a mut MapChainFrame {
 625          for (i, frame) in self.chain.mut_iter().enumerate().rev() {
 626              if !frame.info.macros_escape || i == 0 {
 627                  return frame
 628              }
 629          }
 630          unreachable!()
 631      }
 632  
 633      pub fn find<'a>(&'a self, k&Name) -> Option<&'a SyntaxExtension> {
 634          for frame in self.chain.iter().rev() {
 635              match frame.map.find(k) {
 636                  Some(v) => return Some(v),
 637                  None => {}
 638              }
 639          }
 640          None
 641      }
 642  
 643      pub fn insert(&mut self, kName, vSyntaxExtension) {
 644          self.find_escape_frame().map.insert(k, v);
 645      }
 646  
 647      pub fn info<'a>(&'a mut self) -> &'a mut BlockInfo {
 648          let last_chain_index = self.chain.len() - 1;
 649          &mut self.chain.get_mut(last_chain_index).info
 650      }
 651  }


libsyntax/ext/base.rs:31:1-31:1 -struct- definition:
pub struct MacroDef {
    pub name: StrBuf,
    pub ext: SyntaxExtension
references:- 5
libsyntax/ext/tt/macro_rules.rs:
248:     box MacroRulesDefiner {
249:         def: RefCell::new(Some(MacroDef {
250:             name: token::get_ident(name).to_str().to_strbuf(),
libsyntax/ext/base.rs:
105:     /// Define a new macro.
106:     fn make_def(&self) -> Option<MacroDef> {
107:         None
libsyntax/ext/tt/macro_rules.rs:
108: struct MacroRulesDefiner {
109:     def: RefCell<Option<MacroDef>>
110: }
111: impl MacResult for MacroRulesDefiner {
112:     fn make_def(&self) -> Option<MacroDef> {
113:         Some(self.def.borrow_mut().take().expect("MacroRulesDefiner expanded twice"))
libsyntax/ext/expand.rs:
432:     let items = match expanded.make_def() {
433:         Some(MacroDef { name, ext }) => {
434:             // yikes... no idea how to apply the mark to this. I'm afraid


libsyntax/ext/base.rs:538:60-538:60 -fn- definition:
/// is not a string literal, emit an error and return None.
pub fn get_single_str_from_tts(cx: &ExtCtxt,
                               sp: Span,
references:- 4
libsyntax/ext/source_util.rs:
104:                           -> Box<base::MacResult> {
105:     let file = match get_single_str_from_tts(cx, sp, tts, "include_str!") {
106:         Some(f) => f,
--
135:                           -> Box<base::MacResult> {
136:     let file = match get_single_str_from_tts(cx, sp, tts, "include_bin!") {
137:         Some(f) => f,
libsyntax/ext/env.rs:
27:                          -> Box<base::MacResult> {
28:     let var = match get_single_str_from_tts(cx, sp, tts, "option_env!") {
29:         None => return DummyResult::expr(sp),


libsyntax/ext/base.rs:217:67-217:67 -enum- definition:
/// An enum representing the different kinds of syntax extensions.
pub enum SyntaxExtension {
    /// A syntax extension that is attached to an item and creates new items
references:- 6
98: pub type MacroCrateRegistrationFun =
99:     fn(|ast::Name, SyntaxExtension|);
--
633:     pub fn find<'a>(&'a self, k: &Name) -> Option<&'a SyntaxExtension> {
634:         for frame in self.chain.iter().rev() {
--
643:     pub fn insert(&mut self, k: Name, v: SyntaxExtension) {
644:         self.find_escape_frame().map.insert(k, v);


libsyntax/ext/base.rs:240:1-240:1 -struct- definition:
pub struct BlockInfo {
    // should macros escape from this scope?
    pub macros_escape: bool,
references:- 5
249:     pub fn new() -> BlockInfo {
250:         BlockInfo {
251:             macros_escape: false,
--
647:     pub fn info<'a>(&'a mut self) -> &'a mut BlockInfo {
648:         let last_chain_index = self.chain.len() - 1;


libsyntax/ext/base.rs:594:1-594:1 -struct- definition:
struct MapChainFrame {
    info: BlockInfo,
    map: HashMap<Name, SyntaxExtension>,
references:- 3
612:     pub fn push_frame(&mut self) {
613:         self.chain.push(MapChainFrame {
614:             info: BlockInfo::new(),
--
624:     fn find_escape_frame<'a>(&'a mut self) -> &'a mut MapChainFrame {
625:         for (i, frame) in self.chain.mut_iter().enumerate().rev() {


libsyntax/ext/base.rs:600:40-600:40 -struct- definition:
// Only generic to make it easy to test
pub struct SyntaxEnv {
    chain: Vec<MapChainFrame> ,
references:- 5
606:     pub fn new() -> SyntaxEnv {
607:         let mut map = SyntaxEnv { chain: Vec::new() };
608:         map.push_frame();
libsyntax/ext/expand.rs:
834: pub struct MacroExpander<'a, 'b> {
835:     pub extsbox: SyntaxEnv,
836:     pub cx: &'a mut ExtCtxt<'b>,


libsyntax/ext/base.rs:74:1-74:1 -trait- definition:
pub trait IdentMacroExpander {
    fn expand(&self,
              cx: &mut ExtCtxt,
references:- 2
84: impl IdentMacroExpander for BasicIdentMacroExpander {
85:     fn expand(&self,
--
237:     /// `macro_rules!` is an `IdentTT`.
238:     IdentTT(Box<IdentMacroExpander:'static>, Option<Span>),
239: }


libsyntax/ext/base.rs:142:61-142:61 -struct- definition:
/// A convenience type for macros that return a single item.
pub struct MacItem {
    i: @ast::Item
references:- 3
150: }
151: impl MacResult for MacItem {
152:     fn make_items(&self) -> Option<SmallVector<@ast::Item>> {


libsyntax/ext/base.rs:47:1-47:1 -trait- definition:
pub trait MacroExpander {
    fn expand(&self,
              ecx: &mut ExtCtxt,
references:- 3
60: impl MacroExpander for BasicMacroExpander {
61:     fn expand(&self,
libsyntax/ext/tt/macro_rules.rs:
93: impl MacroExpander for MacroRulesMacroExpander {
94:     fn expand(&self,
libsyntax/ext/base.rs:
231:     /// `bytes!` is a `NormalTT`.
232:     NormalTT(Box<MacroExpander:'static>, Option<Span>),


libsyntax/ext/base.rs:361:1-361:1 -struct- definition:
pub struct MacroCrate {
    pub lib: Option<Path>,
    pub macros: Vec<StrBuf>,
references:- 2
368: pub trait CrateLoader {
369:     fn load_crate(&mut self, krate: &ast::ViewItem) -> MacroCrate;
370: }
libsyntax/ext/expand.rs:
487: fn load_extern_macros(krate: &ast::ViewItem, fld: &mut MacroExpander) {
488:     let MacroCrate { lib, macros, registrar_symbol } =
489:         fld.cx.ecfg.loader.load_crate(krate);


libsyntax/ext/base.rs:261:28-261:28 -fn- definition:
// AST nodes into full ASTs
pub fn syntax_expander_table() -> SyntaxEnv {
    // utility function to simplify creating NormalTT syntax extensions
references:- 2
libsyntax/ext/expand.rs:
875:     let mut expander = MacroExpander {
876:         extsbox: syntax_expander_table(),
877:         cx: &mut cx,
libsyntax/ext/base.rs:
402:                     let mut expander = expand::MacroExpander {
403:                         extsbox: syntax_expander_table(),
404:                         cx: self,


libsyntax/ext/base.rs:42:1-42:1 -struct- definition:
pub struct BasicMacroExpander {
    pub expander: MacroExpanderFn,
    pub span: Option<Span>
references:- 2
264:     fn builtin_normal_expander(f: MacroExpanderFn) -> SyntaxExtension {
265:         NormalTT(box BasicMacroExpander {
266:                 expander: f,


libsyntax/ext/base.rs:128:67-128:67 -struct- definition:
/// A convenience type for macros that return a single expression.
pub struct MacExpr {
    e: @ast::Expr
references:- 3
136: }
137: impl MacResult for MacExpr {
138:     fn make_expr(&self) -> Option<@ast::Expr> {


libsyntax/ext/base.rs:559:59-559:59 -fn- definition:
/// parsing error, emit a non-fatal error and return None.
pub fn get_exprs_from_tts(cx: &mut ExtCtxt,
                          sp: Span,
references:- 3
libsyntax/ext/env.rs:
63:                   -> Box<base::MacResult> {
64:     let exprs = match get_exprs_from_tts(cx, sp, tts) {
65:         Some(ref exprs) if exprs.len() == 0 => {
libsyntax/ext/bytes.rs:
22:     // Gather all argument expressions
23:     let exprs = match get_exprs_from_tts(cx, sp, tts) {
24:         None => return DummyResult::expr(sp),
libsyntax/ext/concat.rs:
22:                          -> Box<base::MacResult> {
23:     let es = match base::get_exprs_from_tts(cx, sp, tts) {
24:         Some(e) => e,


libsyntax/ext/base.rs:55:1-55:1 -NK_AS_STR_TODO- definition:
pub type MacroExpanderFn =
    fn(ecx: &mut ExtCtxt, span: codemap::Span, token_tree: &[ast::TokenTree])
       -> Box<MacResult>;
references:- 2
43: pub struct BasicMacroExpander {
44:     pub expander: MacroExpanderFn,
45:     pub span: Option<Span>
--
263:     // utility function to simplify creating NormalTT syntax extensions
264:     fn builtin_normal_expander(f: MacroExpanderFn) -> SyntaxExtension {
265:         NormalTT(box BasicMacroExpander {


libsyntax/ext/base.rs:165:26-165:26 -struct- definition:
/// after hitting errors.
pub struct DummyResult {
    expr_only: bool,
references:- 4
176:     pub fn any(sp: Span) -> Box<MacResult> {
177:         box DummyResult { expr_only: false, span: sp } as Box<MacResult>
178:     }
--
185:     pub fn expr(sp: Span) -> Box<MacResult> {
186:         box DummyResult { expr_only: true, span: sp } as Box<MacResult>
187:     }
--
199: impl MacResult for DummyResult {
200:     fn make_expr(&self) -> Option<@ast::Expr> {


libsyntax/ext/base.rs:527:33-527:33 -fn- definition:
/// done as rarely as possible).
pub fn check_zero_tts(cx: &ExtCtxt,
                      sp: Span,
references:- 4
libsyntax/ext/source_util.rs:
55:                    -> Box<base::MacResult> {
56:     base::check_zero_tts(cx, sp, tts, "file!");
--
72:                   -> Box<base::MacResult> {
73:     base::check_zero_tts(cx, sp, tts, "module_path!");
74:     let string = cx.mod_path()


libsyntax/ext/base.rs:69:1-69:1 -struct- definition:
pub struct BasicIdentMacroExpander {
    pub expander: IdentMacroExpanderFn,
    pub span: Option<Span>
references:- 2
84: impl IdentMacroExpander for BasicIdentMacroExpander {
85:     fn expand(&self,
--
273:     syntax_expanders.insert(intern("macro_rules"),
274:                             IdentTT(box BasicIdentMacroExpander {
275:                                 expander: ext::tt::macro_rules::add_new_extension,


libsyntax/ext/base.rs:264:4-264:4 -fn- definition:
    fn builtin_normal_expander(f: MacroExpanderFn) -> SyntaxExtension {
        NormalTT(box BasicMacroExpander {
                expander: f,
references:- 25
297:     syntax_expanders.insert(intern("concat"),
298:                             builtin_normal_expander(
299:                                     ext::concat::expand_syntax_ext));
--
356:     syntax_expanders.insert(intern("trace_macros"),
357:                             builtin_normal_expander(
358:                                     ext::trace_macros::expand_trace_macros));


libsyntax/ext/base.rs:374:67-374:67 -struct- definition:
// -> expn_info of their expansion context stored into their span.
pub struct ExtCtxt<'a> {
    pub parse_sess: &'a parse::ParseSess,
references:- 160
libsyntax/ext/expand.rs:
libsyntax/ext/quote.rs:
libsyntax/ext/deriving/mod.rs:
libsyntax/ext/deriving/bounds.rs:
libsyntax/ext/deriving/clone.rs:
libsyntax/ext/deriving/encodable.rs:
libsyntax/ext/deriving/decodable.rs:
libsyntax/ext/deriving/hash.rs:
libsyntax/ext/deriving/rand.rs:
libsyntax/ext/deriving/show.rs:
libsyntax/ext/deriving/zero.rs:
libsyntax/ext/deriving/default.rs:
libsyntax/ext/deriving/primitive.rs:
libsyntax/ext/deriving/cmp/eq.rs:
libsyntax/ext/deriving/cmp/totaleq.rs:
libsyntax/ext/deriving/cmp/ord.rs:
libsyntax/ext/deriving/cmp/totalord.rs:
libsyntax/ext/deriving/generic.rs:
libsyntax/ext/deriving/ty.rs:
libsyntax/ext/build.rs:
libsyntax/ext/tt/macro_rules.rs:
libsyntax/ext/cfg.rs:
libsyntax/ext/fmt.rs:
libsyntax/ext/format.rs:
libsyntax/ext/env.rs:
libsyntax/ext/bytes.rs:
libsyntax/ext/concat.rs:
libsyntax/ext/concat_idents.rs:
libsyntax/ext/log_syntax.rs:
libsyntax/ext/source_util.rs:
libsyntax/ext/trace_macros.rs:
libsyntax/ext/asm.rs:
libsyntax/ext/base.rs:


libsyntax/ext/base.rs:103:68-103:68 -trait- definition:
/// just into the compiler's internal macro table, for `make_def`).
pub trait MacResult {
    /// Define a new macro.
references:- 49
libsyntax/ext/quote.rs:
libsyntax/ext/tt/macro_rules.rs:
libsyntax/ext/cfg.rs:
libsyntax/ext/fmt.rs:
libsyntax/ext/format.rs:
libsyntax/ext/env.rs:
libsyntax/ext/bytes.rs:
libsyntax/ext/concat.rs:
libsyntax/ext/concat_idents.rs:
libsyntax/ext/log_syntax.rs:
libsyntax/ext/source_util.rs:
libsyntax/ext/trace_macros.rs:
libsyntax/ext/asm.rs:
libsyntax/ext/source_util.rs:


libsyntax/ext/base.rs:508:75-508:75 -fn- definition:
/// compilation on error, merely emits a non-fatal error and returns None.
pub fn expr_to_str(cx: &mut ExtCtxt, expr: @ast::Expr, err_msg: &str)
                   -> Option<(InternedString, ast::StrStyle)> {
references:- 4
libsyntax/ext/format.rs:
832:     cx.fmtsp = efmt.span;
833:     let fmt = match expr_to_str(cx.ecx,
834:                                 efmt,
libsyntax/ext/env.rs:
73:     let var = match expr_to_str(cx,
74:                                 *exprs.get(0),
libsyntax/ext/asm.rs:
71:             Asm => {
72:                 let (s, style) = match expr_to_str(cx, p.parse_expr(),
73:                                                    "inline assembly must be a string literal.") {
libsyntax/ext/env.rs:
85:         2 => {
86:             match expr_to_str(cx, *exprs.get(1), "expected string literal") {
87:                 None => return DummyResult::expr(sp),


libsyntax/ext/base.rs:257:35-257:35 -NK_AS_STR_TODO- definition:
// a list of ident->name renamings
pub type RenameList = Vec<(ast::Ident, Name)>;
// The base map of methods for expanding syntax extension
references:- 3
244:     // what are the pending renames?
245:     pub pending_renames: RenameList,
246: }
libsyntax/ext/expand.rs:
801: pub struct IdentRenamer<'a> {
802:     renames: &'a mut RenameList,
803: }
--
818: // renames.
819: pub fn renames_to_fold<'a>(renames: &'a mut RenameList) -> IdentRenamer<'a> {
820:     IdentRenamer {