about summary refs log tree commit diff
path: root/src/libsyntax/ext
diff options
context:
space:
mode:
authorKeegan McAllister <kmcallister@mozilla.com>2014-09-15 18:27:28 -0700
committerKeegan McAllister <kmcallister@mozilla.com>2015-01-05 11:38:12 -0800
commitad7c64777380a780b42028855ad0d09932a11623 (patch)
treee07587239681150b7c9a9d4464411d18eed31714 /src/libsyntax/ext
parent5e5924b79915326d81db2aebfe73d2a20b8506f1 (diff)
downloadrust-ad7c64777380a780b42028855ad0d09932a11623.tar.gz
rust-ad7c64777380a780b42028855ad0d09932a11623.zip
Add a special macro nonterminal $crate
Diffstat (limited to 'src/libsyntax/ext')
-rw-r--r--src/libsyntax/ext/expand.rs12
-rw-r--r--src/libsyntax/ext/tt/macro_rules.rs8
-rw-r--r--src/libsyntax/ext/tt/transcribe.rs29
3 files changed, 43 insertions, 6 deletions
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index a1a13f23064..325d8aa594a 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -432,7 +432,7 @@ pub fn expand_item(it: P<ast::Item>, fld: &mut MacroExpander)
     }
 
     let mut new_items = match it.node {
-        ast::ItemMac(..) => expand_item_mac(it, fld),
+        ast::ItemMac(..) => expand_item_mac(it, None, fld),
         ast::ItemMod(_) | ast::ItemForeignMod(_) => {
             let valid_ident =
                 it.ident.name != parse::token::special_idents::invalid.name;
@@ -529,8 +529,9 @@ fn contains_macro_escape(attrs: &[ast::Attribute]) -> bool {
 
 // Support for item-position macro invocations, exactly the same
 // logic as for expression-position macro invocations.
-pub fn expand_item_mac(it: P<ast::Item>, fld: &mut MacroExpander)
-                       -> SmallVector<P<ast::Item>> {
+pub fn expand_item_mac(it: P<ast::Item>,
+                       imported_from: Option<ast::Ident>,
+                       fld: &mut MacroExpander) -> SmallVector<P<ast::Item>> {
     let (extname, path_span, tts) = match it.node {
         ItemMac(codemap::Spanned {
             node: MacInvocTT(ref pth, ref tts, _),
@@ -611,7 +612,8 @@ pub fn expand_item_mac(it: P<ast::Item>, fld: &mut MacroExpander)
                     });
                     // DON'T mark before expansion.
                     let MacroDef { name, ext }
-                        = macro_rules::add_new_extension(fld.cx, it.span, it.ident, tts);
+                        = macro_rules::add_new_extension(fld.cx, it.span, it.ident,
+                                                         imported_from, tts);
 
                     fld.cx.syntax_env.insert(intern(name.as_slice()), ext);
                     if attr::contains_name(it.attrs.as_slice(), "macro_export") {
@@ -1190,7 +1192,7 @@ pub fn expand_crate(parse_sess: &parse::ParseSess,
                                                          expander.cx.cfg(),
                                                          expander.cx.parse_sess())
                     .expect("expected a serialized item");
-            expand_item_mac(item, &mut expander);
+            expand_item_mac(item, Some(crate_name), &mut expander);
         }
     }
 
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index 15b75442ca2..a278604b167 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -110,6 +110,7 @@ impl<'a> MacResult for ParserAnyMacro<'a> {
 
 struct MacroRulesMacroExpander {
     name: Ident,
+    imported_from: Option<Ident>,
     lhses: Vec<Rc<NamedMatch>>,
     rhses: Vec<Rc<NamedMatch>>,
 }
@@ -123,6 +124,7 @@ impl TTMacroExpander for MacroRulesMacroExpander {
         generic_extension(cx,
                           sp,
                           self.name,
+                          self.imported_from,
                           arg,
                           self.lhses[],
                           self.rhses[])
@@ -133,6 +135,7 @@ impl TTMacroExpander for MacroRulesMacroExpander {
 fn generic_extension<'cx>(cx: &'cx ExtCtxt,
                           sp: Span,
                           name: Ident,
+                          imported_from: Option<Ident>,
                           arg: &[ast::TokenTree],
                           lhses: &[Rc<NamedMatch>],
                           rhses: &[Rc<NamedMatch>])
@@ -157,6 +160,7 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt,
             // `None` is because we're not interpolating
             let mut arg_rdr = new_tt_reader(&cx.parse_sess().span_diagnostic,
                                             None,
+                                            None,
                                             arg.iter()
                                                .map(|x| (*x).clone())
                                                .collect());
@@ -177,6 +181,7 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt,
                 // rhs has holes ( `$id` and `$(...)` that need filled)
                 let trncbr = new_tt_reader(&cx.parse_sess().span_diagnostic,
                                            Some(named_matches),
+                                           imported_from,
                                            rhs);
                 let p = Parser::new(cx.parse_sess(), cx.cfg(), box trncbr);
                 // Let the context choose how to interpret the result.
@@ -209,6 +214,7 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt,
 pub fn add_new_extension<'cx>(cx: &'cx mut ExtCtxt,
                               sp: Span,
                               name: Ident,
+                              imported_from: Option<Ident>,
                               arg: Vec<ast::TokenTree> )
                               -> MacroDef {
 
@@ -247,6 +253,7 @@ pub fn add_new_extension<'cx>(cx: &'cx mut ExtCtxt,
     // Parse the macro_rules! invocation (`none` is for no interpolations):
     let arg_reader = new_tt_reader(&cx.parse_sess().span_diagnostic,
                                    None,
+                                   None,
                                    arg.clone());
     let argument_map = parse_or_else(cx.parse_sess(),
                                      cx.cfg(),
@@ -266,6 +273,7 @@ pub fn add_new_extension<'cx>(cx: &'cx mut ExtCtxt,
 
     let exp = box MacroRulesMacroExpander {
         name: name,
+        imported_from: imported_from,
         lhses: lhses,
         rhses: rhses,
     };
diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs
index 86e81ede8b0..e4e6f5ac6b0 100644
--- a/src/libsyntax/ext/tt/transcribe.rs
+++ b/src/libsyntax/ext/tt/transcribe.rs
@@ -15,7 +15,7 @@ use codemap::{Span, DUMMY_SP};
 use diagnostic::SpanHandler;
 use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal};
 use parse::token::{Eof, DocComment, Interpolated, MatchNt, SubstNt};
-use parse::token::{Token, NtIdent};
+use parse::token::{Token, NtIdent, SpecialMacroVar};
 use parse::token;
 use parse::lexer::TokenAndSpan;
 
@@ -39,6 +39,10 @@ pub struct TtReader<'a> {
     stack: Vec<TtFrame>,
     /* for MBE-style macro transcription */
     interpolations: HashMap<Ident, Rc<NamedMatch>>,
+    imported_from: Option<Ident>,
+
+    // Some => return imported_from as the next token
+    crate_name_next: Option<Span>,
     repeat_idx: Vec<uint>,
     repeat_len: Vec<uint>,
     /* cached: */
@@ -53,6 +57,7 @@ pub struct TtReader<'a> {
 /// should) be none.
 pub fn new_tt_reader<'a>(sp_diag: &'a SpanHandler,
                          interp: Option<HashMap<Ident, Rc<NamedMatch>>>,
+                         imported_from: Option<Ident>,
                          src: Vec<ast::TokenTree> )
                          -> TtReader<'a> {
     let mut r = TtReader {
@@ -71,6 +76,8 @@ pub fn new_tt_reader<'a>(sp_diag: &'a SpanHandler,
             None => HashMap::new(),
             Some(x) => x,
         },
+        imported_from: imported_from,
+        crate_name_next: None,
         repeat_idx: Vec::new(),
         repeat_len: Vec::new(),
         desugar_doc_comments: false,
@@ -162,6 +169,14 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan {
         sp: r.cur_span.clone(),
     };
     loop {
+        match r.crate_name_next.take() {
+            None => (),
+            Some(sp) => {
+                r.cur_span = sp;
+                r.cur_tok = token::Ident(r.imported_from.unwrap(), token::Plain);
+                return ret_val;
+            },
+        }
         let should_pop = match r.stack.last() {
             None => {
                 assert_eq!(ret_val.tok, token::Eof);
@@ -307,6 +322,18 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan {
                    sep: None
                 });
             }
+            TtToken(sp, token::SpecialVarNt(SpecialMacroVar::CrateMacroVar)) => {
+                r.stack.last_mut().unwrap().idx += 1;
+
+                if r.imported_from.is_some() {
+                    r.cur_span = sp;
+                    r.cur_tok = token::ModSep;
+                    r.crate_name_next = Some(sp);
+                    return ret_val;
+                }
+
+                // otherwise emit nothing and proceed to the next token
+            }
             TtToken(sp, tok) => {
                 r.cur_span = sp;
                 r.cur_tok = tok;