]> git.lizzy.rs Git - rust.git/blob - src/libsyntax/ext/base.rs
Rollup merge of #34403 - jonathandturner:move_liberror, r=alexcrichton
[rust.git] / src / libsyntax / ext / base.rs
1 // Copyright 2015 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 pub use self::SyntaxExtension::*;
12
13 use ast;
14 use ast::{Name, PatKind};
15 use attr::HasAttrs;
16 use codemap::{self, CodeMap, ExpnInfo};
17 use syntax_pos::{Span, ExpnId, NO_EXPANSION};
18 use errors::DiagnosticBuilder;
19 use ext;
20 use ext::expand;
21 use ext::tt::macro_rules;
22 use parse;
23 use parse::parser;
24 use parse::token;
25 use parse::token::{InternedString, intern, str_to_ident};
26 use ptr::P;
27 use util::small_vector::SmallVector;
28 use util::lev_distance::find_best_match_for_name;
29 use ext::mtwt;
30 use fold::Folder;
31
32 use std::collections::{HashMap, HashSet};
33 use std::rc::Rc;
34 use std::default::Default;
35
36
37 #[derive(Debug,Clone)]
38 pub enum Annotatable {
39     Item(P<ast::Item>),
40     TraitItem(P<ast::TraitItem>),
41     ImplItem(P<ast::ImplItem>),
42 }
43
44 impl HasAttrs for Annotatable {
45     fn attrs(&self) -> &[ast::Attribute] {
46         match *self {
47             Annotatable::Item(ref item) => &item.attrs,
48             Annotatable::TraitItem(ref trait_item) => &trait_item.attrs,
49             Annotatable::ImplItem(ref impl_item) => &impl_item.attrs,
50         }
51     }
52
53     fn map_attrs<F: FnOnce(Vec<ast::Attribute>) -> Vec<ast::Attribute>>(self, f: F) -> Self {
54         match self {
55             Annotatable::Item(item) => Annotatable::Item(item.map_attrs(f)),
56             Annotatable::TraitItem(trait_item) => Annotatable::TraitItem(trait_item.map_attrs(f)),
57             Annotatable::ImplItem(impl_item) => Annotatable::ImplItem(impl_item.map_attrs(f)),
58         }
59     }
60 }
61
62 impl Annotatable {
63     pub fn attrs(&self) -> &[ast::Attribute] {
64         HasAttrs::attrs(self)
65     }
66     pub fn fold_attrs(self, attrs: Vec<ast::Attribute>) -> Annotatable {
67         self.map_attrs(|_| attrs)
68     }
69
70     pub fn expect_item(self) -> P<ast::Item> {
71         match self {
72             Annotatable::Item(i) => i,
73             _ => panic!("expected Item")
74         }
75     }
76
77     pub fn map_item_or<F, G>(self, mut f: F, mut or: G) -> Annotatable
78         where F: FnMut(P<ast::Item>) -> P<ast::Item>,
79               G: FnMut(Annotatable) -> Annotatable
80     {
81         match self {
82             Annotatable::Item(i) => Annotatable::Item(f(i)),
83             _ => or(self)
84         }
85     }
86
87     pub fn expect_trait_item(self) -> ast::TraitItem {
88         match self {
89             Annotatable::TraitItem(i) => i.unwrap(),
90             _ => panic!("expected Item")
91         }
92     }
93
94     pub fn expect_impl_item(self) -> ast::ImplItem {
95         match self {
96             Annotatable::ImplItem(i) => i.unwrap(),
97             _ => panic!("expected Item")
98         }
99     }
100
101     pub fn fold_with<F: Folder>(self, folder: &mut F) -> SmallVector<Self> {
102         match self {
103             Annotatable::Item(item) => folder.fold_item(item).map(Annotatable::Item),
104             Annotatable::ImplItem(item) =>
105                 folder.fold_impl_item(item.unwrap()).map(|item| Annotatable::ImplItem(P(item))),
106             Annotatable::TraitItem(item) =>
107                 folder.fold_trait_item(item.unwrap()).map(|item| Annotatable::TraitItem(P(item))),
108         }
109     }
110 }
111
112 // A more flexible ItemDecorator.
113 pub trait MultiItemDecorator {
114     fn expand(&self,
115               ecx: &mut ExtCtxt,
116               sp: Span,
117               meta_item: &ast::MetaItem,
118               item: &Annotatable,
119               push: &mut FnMut(Annotatable));
120 }
121
122 impl<F> MultiItemDecorator for F
123     where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, &Annotatable, &mut FnMut(Annotatable))
124 {
125     fn expand(&self,
126               ecx: &mut ExtCtxt,
127               sp: Span,
128               meta_item: &ast::MetaItem,
129               item: &Annotatable,
130               push: &mut FnMut(Annotatable)) {
131         (*self)(ecx, sp, meta_item, item, push)
132     }
133 }
134
135 // `meta_item` is the annotation, and `item` is the item being modified.
136 // FIXME Decorators should follow the same pattern too.
137 pub trait MultiItemModifier {
138     fn expand(&self,
139               ecx: &mut ExtCtxt,
140               span: Span,
141               meta_item: &ast::MetaItem,
142               item: Annotatable)
143               -> Vec<Annotatable>;
144 }
145
146 impl<F, T> MultiItemModifier for F
147     where F: Fn(&mut ExtCtxt, Span, &ast::MetaItem, Annotatable) -> T,
148           T: Into<Vec<Annotatable>>,
149 {
150     fn expand(&self,
151               ecx: &mut ExtCtxt,
152               span: Span,
153               meta_item: &ast::MetaItem,
154               item: Annotatable)
155               -> Vec<Annotatable> {
156         (*self)(ecx, span, meta_item, item).into()
157     }
158 }
159
160 impl Into<Vec<Annotatable>> for Annotatable {
161     fn into(self) -> Vec<Annotatable> {
162         vec![self]
163     }
164 }
165
166 /// Represents a thing that maps token trees to Macro Results
167 pub trait TTMacroExpander {
168     fn expand<'cx>(&self,
169                    ecx: &'cx mut ExtCtxt,
170                    span: Span,
171                    token_tree: &[ast::TokenTree])
172                    -> Box<MacResult+'cx>;
173 }
174
175 pub type MacroExpanderFn =
176     for<'cx> fn(&'cx mut ExtCtxt, Span, &[ast::TokenTree]) -> Box<MacResult+'cx>;
177
178 impl<F> TTMacroExpander for F
179     where F : for<'cx> Fn(&'cx mut ExtCtxt, Span, &[ast::TokenTree]) -> Box<MacResult+'cx>
180 {
181     fn expand<'cx>(&self,
182                    ecx: &'cx mut ExtCtxt,
183                    span: Span,
184                    token_tree: &[ast::TokenTree])
185                    -> Box<MacResult+'cx> {
186         (*self)(ecx, span, token_tree)
187     }
188 }
189
190 pub trait IdentMacroExpander {
191     fn expand<'cx>(&self,
192                    cx: &'cx mut ExtCtxt,
193                    sp: Span,
194                    ident: ast::Ident,
195                    token_tree: Vec<ast::TokenTree> )
196                    -> Box<MacResult+'cx>;
197 }
198
199 pub type IdentMacroExpanderFn =
200     for<'cx> fn(&'cx mut ExtCtxt, Span, ast::Ident, Vec<ast::TokenTree>) -> Box<MacResult+'cx>;
201
202 impl<F> IdentMacroExpander for F
203     where F : for<'cx> Fn(&'cx mut ExtCtxt, Span, ast::Ident,
204                           Vec<ast::TokenTree>) -> Box<MacResult+'cx>
205 {
206     fn expand<'cx>(&self,
207                    cx: &'cx mut ExtCtxt,
208                    sp: Span,
209                    ident: ast::Ident,
210                    token_tree: Vec<ast::TokenTree> )
211                    -> Box<MacResult+'cx>
212     {
213         (*self)(cx, sp, ident, token_tree)
214     }
215 }
216
217 // Use a macro because forwarding to a simple function has type system issues
218 macro_rules! make_stmts_default {
219     ($me:expr) => {
220         $me.make_expr().map(|e| {
221             SmallVector::one(codemap::respan(
222                 e.span, ast::StmtKind::Expr(e, ast::DUMMY_NODE_ID)))
223         })
224     }
225 }
226
227 /// The result of a macro expansion. The return values of the various
228 /// methods are spliced into the AST at the callsite of the macro.
229 pub trait MacResult {
230     /// Create an expression.
231     fn make_expr(self: Box<Self>) -> Option<P<ast::Expr>> {
232         None
233     }
234     /// Create zero or more items.
235     fn make_items(self: Box<Self>) -> Option<SmallVector<P<ast::Item>>> {
236         None
237     }
238
239     /// Create zero or more impl items.
240     fn make_impl_items(self: Box<Self>) -> Option<SmallVector<ast::ImplItem>> {
241         None
242     }
243
244     /// Create zero or more trait items.
245     fn make_trait_items(self: Box<Self>) -> Option<SmallVector<ast::TraitItem>> {
246         None
247     }
248
249     /// Create a pattern.
250     fn make_pat(self: Box<Self>) -> Option<P<ast::Pat>> {
251         None
252     }
253
254     /// Create zero or more statements.
255     ///
256     /// By default this attempts to create an expression statement,
257     /// returning None if that fails.
258     fn make_stmts(self: Box<Self>) -> Option<SmallVector<ast::Stmt>> {
259         make_stmts_default!(self)
260     }
261
262     fn make_ty(self: Box<Self>) -> Option<P<ast::Ty>> {
263         None
264     }
265 }
266
267 macro_rules! make_MacEager {
268     ( $( $fld:ident: $t:ty, )* ) => {
269         /// `MacResult` implementation for the common case where you've already
270         /// built each form of AST that you might return.
271         #[derive(Default)]
272         pub struct MacEager {
273             $(
274                 pub $fld: Option<$t>,
275             )*
276         }
277
278         impl MacEager {
279             $(
280                 pub fn $fld(v: $t) -> Box<MacResult> {
281                     Box::new(MacEager {
282                         $fld: Some(v),
283                         ..Default::default()
284                     })
285                 }
286             )*
287         }
288     }
289 }
290
291 make_MacEager! {
292     expr: P<ast::Expr>,
293     pat: P<ast::Pat>,
294     items: SmallVector<P<ast::Item>>,
295     impl_items: SmallVector<ast::ImplItem>,
296     trait_items: SmallVector<ast::TraitItem>,
297     stmts: SmallVector<ast::Stmt>,
298     ty: P<ast::Ty>,
299 }
300
301 impl MacResult for MacEager {
302     fn make_expr(self: Box<Self>) -> Option<P<ast::Expr>> {
303         self.expr
304     }
305
306     fn make_items(self: Box<Self>) -> Option<SmallVector<P<ast::Item>>> {
307         self.items
308     }
309
310     fn make_impl_items(self: Box<Self>) -> Option<SmallVector<ast::ImplItem>> {
311         self.impl_items
312     }
313
314     fn make_trait_items(self: Box<Self>) -> Option<SmallVector<ast::TraitItem>> {
315         self.trait_items
316     }
317
318     fn make_stmts(self: Box<Self>) -> Option<SmallVector<ast::Stmt>> {
319         match self.stmts.as_ref().map_or(0, |s| s.len()) {
320             0 => make_stmts_default!(self),
321             _ => self.stmts,
322         }
323     }
324
325     fn make_pat(self: Box<Self>) -> Option<P<ast::Pat>> {
326         if let Some(p) = self.pat {
327             return Some(p);
328         }
329         if let Some(e) = self.expr {
330             if let ast::ExprKind::Lit(_) = e.node {
331                 return Some(P(ast::Pat {
332                     id: ast::DUMMY_NODE_ID,
333                     span: e.span,
334                     node: PatKind::Lit(e),
335                 }));
336             }
337         }
338         None
339     }
340
341     fn make_ty(self: Box<Self>) -> Option<P<ast::Ty>> {
342         self.ty
343     }
344 }
345
346 /// Fill-in macro expansion result, to allow compilation to continue
347 /// after hitting errors.
348 #[derive(Copy, Clone)]
349 pub struct DummyResult {
350     expr_only: bool,
351     span: Span
352 }
353
354 impl DummyResult {
355     /// Create a default MacResult that can be anything.
356     ///
357     /// Use this as a return value after hitting any errors and
358     /// calling `span_err`.
359     pub fn any(sp: Span) -> Box<MacResult+'static> {
360         Box::new(DummyResult { expr_only: false, span: sp })
361     }
362
363     /// Create a default MacResult that can only be an expression.
364     ///
365     /// Use this for macros that must expand to an expression, so even
366     /// if an error is encountered internally, the user will receive
367     /// an error that they also used it in the wrong place.
368     pub fn expr(sp: Span) -> Box<MacResult+'static> {
369         Box::new(DummyResult { expr_only: true, span: sp })
370     }
371
372     /// A plain dummy expression.
373     pub fn raw_expr(sp: Span) -> P<ast::Expr> {
374         P(ast::Expr {
375             id: ast::DUMMY_NODE_ID,
376             node: ast::ExprKind::Lit(P(codemap::respan(sp, ast::LitKind::Bool(false)))),
377             span: sp,
378             attrs: None,
379         })
380     }
381
382     /// A plain dummy pattern.
383     pub fn raw_pat(sp: Span) -> ast::Pat {
384         ast::Pat {
385             id: ast::DUMMY_NODE_ID,
386             node: PatKind::Wild,
387             span: sp,
388         }
389     }
390
391     pub fn raw_ty(sp: Span) -> P<ast::Ty> {
392         P(ast::Ty {
393             id: ast::DUMMY_NODE_ID,
394             node: ast::TyKind::Infer,
395             span: sp
396         })
397     }
398 }
399
400 impl MacResult for DummyResult {
401     fn make_expr(self: Box<DummyResult>) -> Option<P<ast::Expr>> {
402         Some(DummyResult::raw_expr(self.span))
403     }
404
405     fn make_pat(self: Box<DummyResult>) -> Option<P<ast::Pat>> {
406         Some(P(DummyResult::raw_pat(self.span)))
407     }
408
409     fn make_items(self: Box<DummyResult>) -> Option<SmallVector<P<ast::Item>>> {
410         // this code needs a comment... why not always just return the Some() ?
411         if self.expr_only {
412             None
413         } else {
414             Some(SmallVector::zero())
415         }
416     }
417
418     fn make_impl_items(self: Box<DummyResult>) -> Option<SmallVector<ast::ImplItem>> {
419         if self.expr_only {
420             None
421         } else {
422             Some(SmallVector::zero())
423         }
424     }
425
426     fn make_trait_items(self: Box<DummyResult>) -> Option<SmallVector<ast::TraitItem>> {
427         if self.expr_only {
428             None
429         } else {
430             Some(SmallVector::zero())
431         }
432     }
433
434     fn make_stmts(self: Box<DummyResult>) -> Option<SmallVector<ast::Stmt>> {
435         Some(SmallVector::one(
436             codemap::respan(self.span,
437                             ast::StmtKind::Expr(DummyResult::raw_expr(self.span),
438                                                 ast::DUMMY_NODE_ID))))
439     }
440 }
441
442 /// An enum representing the different kinds of syntax extensions.
443 pub enum SyntaxExtension {
444     /// A syntax extension that is attached to an item and creates new items
445     /// based upon it.
446     ///
447     /// `#[derive(...)]` is a `MultiItemDecorator`.
448     MultiDecorator(Box<MultiItemDecorator + 'static>),
449
450     /// A syntax extension that is attached to an item and modifies it
451     /// in-place. More flexible version than Modifier.
452     MultiModifier(Box<MultiItemModifier + 'static>),
453
454     /// A normal, function-like syntax extension.
455     ///
456     /// `bytes!` is a `NormalTT`.
457     ///
458     /// The `bool` dictates whether the contents of the macro can
459     /// directly use `#[unstable]` things (true == yes).
460     NormalTT(Box<TTMacroExpander + 'static>, Option<Span>, bool),
461
462     /// A function-like syntax extension that has an extra ident before
463     /// the block.
464     ///
465     IdentTT(Box<IdentMacroExpander + 'static>, Option<Span>, bool),
466
467     /// Represents `macro_rules!` itself.
468     MacroRulesTT,
469 }
470
471 pub type NamedSyntaxExtension = (Name, SyntaxExtension);
472
473 pub struct BlockInfo {
474     /// Should macros escape from this scope?
475     pub macros_escape: bool,
476     /// What are the pending renames?
477     pub pending_renames: mtwt::RenameList,
478 }
479
480 impl BlockInfo {
481     pub fn new() -> BlockInfo {
482         BlockInfo {
483             macros_escape: false,
484             pending_renames: Vec::new(),
485         }
486     }
487 }
488
489 /// The base map of methods for expanding syntax extension
490 /// AST nodes into full ASTs
491 fn initial_syntax_expander_table<'feat>(ecfg: &expand::ExpansionConfig<'feat>)
492                                         -> SyntaxEnv {
493     // utility function to simplify creating NormalTT syntax extensions
494     fn builtin_normal_expander(f: MacroExpanderFn) -> SyntaxExtension {
495         NormalTT(Box::new(f), None, false)
496     }
497
498     let mut syntax_expanders = SyntaxEnv::new();
499     syntax_expanders.insert(intern("macro_rules"), MacroRulesTT);
500
501     if ecfg.enable_quotes() {
502         // Quasi-quoting expanders
503         syntax_expanders.insert(intern("quote_tokens"),
504                            builtin_normal_expander(
505                                 ext::quote::expand_quote_tokens));
506         syntax_expanders.insert(intern("quote_expr"),
507                            builtin_normal_expander(
508                                 ext::quote::expand_quote_expr));
509         syntax_expanders.insert(intern("quote_ty"),
510                            builtin_normal_expander(
511                                 ext::quote::expand_quote_ty));
512         syntax_expanders.insert(intern("quote_item"),
513                            builtin_normal_expander(
514                                 ext::quote::expand_quote_item));
515         syntax_expanders.insert(intern("quote_pat"),
516                            builtin_normal_expander(
517                                 ext::quote::expand_quote_pat));
518         syntax_expanders.insert(intern("quote_arm"),
519                            builtin_normal_expander(
520                                 ext::quote::expand_quote_arm));
521         syntax_expanders.insert(intern("quote_stmt"),
522                            builtin_normal_expander(
523                                 ext::quote::expand_quote_stmt));
524         syntax_expanders.insert(intern("quote_matcher"),
525                            builtin_normal_expander(
526                                 ext::quote::expand_quote_matcher));
527         syntax_expanders.insert(intern("quote_attr"),
528                            builtin_normal_expander(
529                                 ext::quote::expand_quote_attr));
530         syntax_expanders.insert(intern("quote_arg"),
531                            builtin_normal_expander(
532                                 ext::quote::expand_quote_arg));
533         syntax_expanders.insert(intern("quote_block"),
534                            builtin_normal_expander(
535                                 ext::quote::expand_quote_block));
536         syntax_expanders.insert(intern("quote_meta_item"),
537                            builtin_normal_expander(
538                                 ext::quote::expand_quote_meta_item));
539         syntax_expanders.insert(intern("quote_path"),
540                            builtin_normal_expander(
541                                 ext::quote::expand_quote_path));
542     }
543
544     syntax_expanders.insert(intern("line"),
545                             builtin_normal_expander(
546                                     ext::source_util::expand_line));
547     syntax_expanders.insert(intern("column"),
548                             builtin_normal_expander(
549                                     ext::source_util::expand_column));
550     syntax_expanders.insert(intern("file"),
551                             builtin_normal_expander(
552                                     ext::source_util::expand_file));
553     syntax_expanders.insert(intern("stringify"),
554                             builtin_normal_expander(
555                                     ext::source_util::expand_stringify));
556     syntax_expanders.insert(intern("include"),
557                             builtin_normal_expander(
558                                     ext::source_util::expand_include));
559     syntax_expanders.insert(intern("include_str"),
560                             builtin_normal_expander(
561                                     ext::source_util::expand_include_str));
562     syntax_expanders.insert(intern("include_bytes"),
563                             builtin_normal_expander(
564                                     ext::source_util::expand_include_bytes));
565     syntax_expanders.insert(intern("module_path"),
566                             builtin_normal_expander(
567                                     ext::source_util::expand_mod));
568     syntax_expanders
569 }
570
571 pub trait MacroLoader {
572     fn load_crate(&mut self, extern_crate: &ast::Item, allows_macros: bool) -> Vec<ast::MacroDef>;
573 }
574
575 pub struct DummyMacroLoader;
576 impl MacroLoader for DummyMacroLoader {
577     fn load_crate(&mut self, _: &ast::Item, _: bool) -> Vec<ast::MacroDef> {
578         Vec::new()
579     }
580 }
581
582 /// One of these is made during expansion and incrementally updated as we go;
583 /// when a macro expansion occurs, the resulting nodes have the backtrace()
584 /// -> expn_info of their expansion context stored into their span.
585 pub struct ExtCtxt<'a> {
586     pub parse_sess: &'a parse::ParseSess,
587     pub cfg: ast::CrateConfig,
588     pub backtrace: ExpnId,
589     pub ecfg: expand::ExpansionConfig<'a>,
590     pub crate_root: Option<&'static str>,
591     pub loader: &'a mut MacroLoader,
592
593     pub mod_path: Vec<ast::Ident> ,
594     pub exported_macros: Vec<ast::MacroDef>,
595
596     pub syntax_env: SyntaxEnv,
597     pub recursion_count: usize,
598
599     pub filename: Option<String>,
600     pub mod_path_stack: Vec<InternedString>,
601     pub in_block: bool,
602 }
603
604 impl<'a> ExtCtxt<'a> {
605     pub fn new(parse_sess: &'a parse::ParseSess, cfg: ast::CrateConfig,
606                ecfg: expand::ExpansionConfig<'a>,
607                loader: &'a mut MacroLoader)
608                -> ExtCtxt<'a> {
609         let env = initial_syntax_expander_table(&ecfg);
610         ExtCtxt {
611             parse_sess: parse_sess,
612             cfg: cfg,
613             backtrace: NO_EXPANSION,
614             mod_path: Vec::new(),
615             ecfg: ecfg,
616             crate_root: None,
617             exported_macros: Vec::new(),
618             loader: loader,
619             syntax_env: env,
620             recursion_count: 0,
621
622             filename: None,
623             mod_path_stack: Vec::new(),
624             in_block: false,
625         }
626     }
627
628     /// Returns a `Folder` for deeply expanding all macros in an AST node.
629     pub fn expander<'b>(&'b mut self) -> expand::MacroExpander<'b, 'a> {
630         expand::MacroExpander::new(self)
631     }
632
633     pub fn new_parser_from_tts(&self, tts: &[ast::TokenTree])
634         -> parser::Parser<'a> {
635         parse::tts_to_parser(self.parse_sess, tts.to_vec(), self.cfg())
636     }
637
638     pub fn codemap(&self) -> &'a CodeMap { self.parse_sess.codemap() }
639     pub fn parse_sess(&self) -> &'a parse::ParseSess { self.parse_sess }
640     pub fn cfg(&self) -> ast::CrateConfig { self.cfg.clone() }
641     pub fn call_site(&self) -> Span {
642         self.codemap().with_expn_info(self.backtrace, |ei| match ei {
643             Some(expn_info) => expn_info.call_site,
644             None => self.bug("missing top span")
645         })
646     }
647     pub fn backtrace(&self) -> ExpnId { self.backtrace }
648
649     /// Returns span for the macro which originally caused the current expansion to happen.
650     ///
651     /// Stops backtracing at include! boundary.
652     pub fn expansion_cause(&self) -> Span {
653         let mut expn_id = self.backtrace;
654         let mut last_macro = None;
655         loop {
656             if self.codemap().with_expn_info(expn_id, |info| {
657                 info.map_or(None, |i| {
658                     if i.callee.name().as_str() == "include" {
659                         // Stop going up the backtrace once include! is encountered
660                         return None;
661                     }
662                     expn_id = i.call_site.expn_id;
663                     last_macro = Some(i.call_site);
664                     return Some(());
665                 })
666             }).is_none() {
667                 break
668             }
669         }
670         last_macro.expect("missing expansion backtrace")
671     }
672
673     pub fn mod_push(&mut self, i: ast::Ident) { self.mod_path.push(i); }
674     pub fn mod_pop(&mut self) { self.mod_path.pop().unwrap(); }
675     pub fn mod_path(&self) -> Vec<ast::Ident> {
676         let mut v = Vec::new();
677         v.push(token::str_to_ident(&self.ecfg.crate_name));
678         v.extend(self.mod_path.iter().cloned());
679         return v;
680     }
681     pub fn bt_push(&mut self, ei: ExpnInfo) {
682         self.recursion_count += 1;
683         if self.recursion_count > self.ecfg.recursion_limit {
684             self.span_fatal(ei.call_site,
685                             &format!("recursion limit reached while expanding the macro `{}`",
686                                     ei.callee.name()));
687         }
688
689         let mut call_site = ei.call_site;
690         call_site.expn_id = self.backtrace;
691         self.backtrace = self.codemap().record_expansion(ExpnInfo {
692             call_site: call_site,
693             callee: ei.callee
694         });
695     }
696     pub fn bt_pop(&mut self) {
697         match self.backtrace {
698             NO_EXPANSION => self.bug("tried to pop without a push"),
699             expn_id => {
700                 self.recursion_count -= 1;
701                 self.backtrace = self.codemap().with_expn_info(expn_id, |expn_info| {
702                     expn_info.map_or(NO_EXPANSION, |ei| ei.call_site.expn_id)
703                 });
704             }
705         }
706     }
707
708     pub fn insert_macro(&mut self, def: ast::MacroDef) {
709         if def.export {
710             self.exported_macros.push(def.clone());
711         }
712         if def.use_locally {
713             let ext = macro_rules::compile(self, &def);
714             self.syntax_env.insert(def.ident.name, ext);
715         }
716     }
717
718     pub fn struct_span_warn(&self,
719                             sp: Span,
720                             msg: &str)
721                             -> DiagnosticBuilder<'a> {
722         self.parse_sess.span_diagnostic.struct_span_warn(sp, msg)
723     }
724     pub fn struct_span_err(&self,
725                            sp: Span,
726                            msg: &str)
727                            -> DiagnosticBuilder<'a> {
728         self.parse_sess.span_diagnostic.struct_span_err(sp, msg)
729     }
730     pub fn struct_span_fatal(&self,
731                              sp: Span,
732                              msg: &str)
733                              -> DiagnosticBuilder<'a> {
734         self.parse_sess.span_diagnostic.struct_span_fatal(sp, msg)
735     }
736
737     /// Emit `msg` attached to `sp`, and stop compilation immediately.
738     ///
739     /// `span_err` should be strongly preferred where-ever possible:
740     /// this should *only* be used when
741     /// - continuing has a high risk of flow-on errors (e.g. errors in
742     ///   declaring a macro would cause all uses of that macro to
743     ///   complain about "undefined macro"), or
744     /// - there is literally nothing else that can be done (however,
745     ///   in most cases one can construct a dummy expression/item to
746     ///   substitute; we never hit resolve/type-checking so the dummy
747     ///   value doesn't have to match anything)
748     pub fn span_fatal(&self, sp: Span, msg: &str) -> ! {
749         panic!(self.parse_sess.span_diagnostic.span_fatal(sp, msg));
750     }
751
752     /// Emit `msg` attached to `sp`, without immediately stopping
753     /// compilation.
754     ///
755     /// Compilation will be stopped in the near future (at the end of
756     /// the macro expansion phase).
757     pub fn span_err(&self, sp: Span, msg: &str) {
758         self.parse_sess.span_diagnostic.span_err(sp, msg);
759     }
760     pub fn span_warn(&self, sp: Span, msg: &str) {
761         self.parse_sess.span_diagnostic.span_warn(sp, msg);
762     }
763     pub fn span_unimpl(&self, sp: Span, msg: &str) -> ! {
764         self.parse_sess.span_diagnostic.span_unimpl(sp, msg);
765     }
766     pub fn span_bug(&self, sp: Span, msg: &str) -> ! {
767         self.parse_sess.span_diagnostic.span_bug(sp, msg);
768     }
769     pub fn bug(&self, msg: &str) -> ! {
770         self.parse_sess.span_diagnostic.bug(msg);
771     }
772     pub fn trace_macros(&self) -> bool {
773         self.ecfg.trace_mac
774     }
775     pub fn set_trace_macros(&mut self, x: bool) {
776         self.ecfg.trace_mac = x
777     }
778     pub fn ident_of(&self, st: &str) -> ast::Ident {
779         str_to_ident(st)
780     }
781     pub fn std_path(&self, components: &[&str]) -> Vec<ast::Ident> {
782         let mut v = Vec::new();
783         if let Some(s) = self.crate_root {
784             v.push(self.ident_of(s));
785         }
786         v.extend(components.iter().map(|s| self.ident_of(s)));
787         return v
788     }
789     pub fn name_of(&self, st: &str) -> ast::Name {
790         token::intern(st)
791     }
792
793     pub fn suggest_macro_name(&mut self,
794                               name: &str,
795                               err: &mut DiagnosticBuilder<'a>) {
796         let names = &self.syntax_env.names;
797         if let Some(suggestion) = find_best_match_for_name(names.iter(), name, None) {
798             if suggestion != name {
799                 err.help(&format!("did you mean `{}!`?", suggestion));
800             } else {
801                 err.help(&format!("have you added the `#[macro_use]` on the \
802                                    module/import?"));
803             }
804         }
805     }
806 }
807
808 /// Extract a string literal from the macro expanded version of `expr`,
809 /// emitting `err_msg` if `expr` is not a string literal. This does not stop
810 /// compilation on error, merely emits a non-fatal error and returns None.
811 pub fn expr_to_string(cx: &mut ExtCtxt, expr: P<ast::Expr>, err_msg: &str)
812                       -> Option<(InternedString, ast::StrStyle)> {
813     // we want to be able to handle e.g. concat("foo", "bar")
814     let expr = cx.expander().fold_expr(expr);
815     match expr.node {
816         ast::ExprKind::Lit(ref l) => match l.node {
817             ast::LitKind::Str(ref s, style) => return Some(((*s).clone(), style)),
818             _ => cx.span_err(l.span, err_msg)
819         },
820         _ => cx.span_err(expr.span, err_msg)
821     }
822     None
823 }
824
825 /// Non-fatally assert that `tts` is empty. Note that this function
826 /// returns even when `tts` is non-empty, macros that *need* to stop
827 /// compilation should call
828 /// `cx.parse_sess.span_diagnostic.abort_if_errors()` (this should be
829 /// done as rarely as possible).
830 pub fn check_zero_tts(cx: &ExtCtxt,
831                       sp: Span,
832                       tts: &[ast::TokenTree],
833                       name: &str) {
834     if !tts.is_empty() {
835         cx.span_err(sp, &format!("{} takes no arguments", name));
836     }
837 }
838
839 /// Extract the string literal from the first token of `tts`. If this
840 /// is not a string literal, emit an error and return None.
841 pub fn get_single_str_from_tts(cx: &mut ExtCtxt,
842                                sp: Span,
843                                tts: &[ast::TokenTree],
844                                name: &str)
845                                -> Option<String> {
846     let mut p = cx.new_parser_from_tts(tts);
847     if p.token == token::Eof {
848         cx.span_err(sp, &format!("{} takes 1 argument", name));
849         return None
850     }
851     let ret = cx.expander().fold_expr(panictry!(p.parse_expr()));
852     if p.token != token::Eof {
853         cx.span_err(sp, &format!("{} takes 1 argument", name));
854     }
855     expr_to_string(cx, ret, "argument must be a string literal").map(|(s, _)| {
856         s.to_string()
857     })
858 }
859
860 /// Extract comma-separated expressions from `tts`. If there is a
861 /// parsing error, emit a non-fatal error and return None.
862 pub fn get_exprs_from_tts(cx: &mut ExtCtxt,
863                           sp: Span,
864                           tts: &[ast::TokenTree]) -> Option<Vec<P<ast::Expr>>> {
865     let mut p = cx.new_parser_from_tts(tts);
866     let mut es = Vec::new();
867     while p.token != token::Eof {
868         es.push(cx.expander().fold_expr(panictry!(p.parse_expr())));
869         if p.eat(&token::Comma) {
870             continue;
871         }
872         if p.token != token::Eof {
873             cx.span_err(sp, "expected token: `,`");
874             return None;
875         }
876     }
877     Some(es)
878 }
879
880 /// In order to have some notion of scoping for macros,
881 /// we want to implement the notion of a transformation
882 /// environment.
883 ///
884 /// This environment maps Names to SyntaxExtensions.
885 pub struct SyntaxEnv {
886     chain: Vec<MapChainFrame>,
887     /// All bang-style macro/extension names
888     /// encountered so far; to be used for diagnostics in resolve
889     pub names: HashSet<Name>,
890 }
891
892 // impl question: how to implement it? Initially, the
893 // env will contain only macros, so it might be painful
894 // to add an empty frame for every context. Let's just
895 // get it working, first....
896
897 // NB! the mutability of the underlying maps means that
898 // if expansion is out-of-order, a deeper scope may be
899 // able to refer to a macro that was added to an enclosing
900 // scope lexically later than the deeper scope.
901
902 struct MapChainFrame {
903     info: BlockInfo,
904     map: HashMap<Name, Rc<SyntaxExtension>>,
905 }
906
907 impl SyntaxEnv {
908     fn new() -> SyntaxEnv {
909         let mut map = SyntaxEnv { chain: Vec::new() , names: HashSet::new()};
910         map.push_frame();
911         map
912     }
913
914     pub fn push_frame(&mut self) {
915         self.chain.push(MapChainFrame {
916             info: BlockInfo::new(),
917             map: HashMap::new(),
918         });
919     }
920
921     pub fn pop_frame(&mut self) {
922         assert!(self.chain.len() > 1, "too many pops on MapChain!");
923         self.chain.pop();
924     }
925
926     fn find_escape_frame(&mut self) -> &mut MapChainFrame {
927         for (i, frame) in self.chain.iter_mut().enumerate().rev() {
928             if !frame.info.macros_escape || i == 0 {
929                 return frame
930             }
931         }
932         unreachable!()
933     }
934
935     pub fn find(&self, k: Name) -> Option<Rc<SyntaxExtension>> {
936         for frame in self.chain.iter().rev() {
937             match frame.map.get(&k) {
938                 Some(v) => return Some(v.clone()),
939                 None => {}
940             }
941         }
942         None
943     }
944
945     pub fn insert(&mut self, k: Name, v: SyntaxExtension) {
946         if let NormalTT(..) = v {
947             self.names.insert(k);
948         }
949         self.find_escape_frame().map.insert(k, Rc::new(v));
950     }
951
952     pub fn info(&mut self) -> &mut BlockInfo {
953         let last_chain_index = self.chain.len() - 1;
954         &mut self.chain[last_chain_index].info
955     }
956
957     pub fn is_crate_root(&mut self) -> bool {
958         // The first frame is pushed in `SyntaxEnv::new()` and the second frame is
959         // pushed when folding the crate root pseudo-module (c.f. noop_fold_crate).
960         self.chain.len() <= 2
961     }
962 }