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