]> git.lizzy.rs Git - rust.git/commitdiff
Replace LetSyntaxTT with MacroRulesTT
authorKeegan McAllister <kmcallister@mozilla.com>
Mon, 15 Sep 2014 23:09:09 +0000 (16:09 -0700)
committerKeegan McAllister <kmcallister@mozilla.com>
Mon, 5 Jan 2015 19:38:12 +0000 (11:38 -0800)
The implementation of LetSyntaxTT was specialized to macro_rules! in various
ways. This gets rid of the false generality and simplifies the code.

src/librustc/plugin/registry.rs
src/librustc_driver/driver.rs
src/libsyntax/ext/base.rs
src/libsyntax/ext/expand.rs
src/libsyntax/ext/tt/macro_rules.rs
src/test/auxiliary/macro_crate_MacroRulesTT.rs [new file with mode: 0644]
src/test/compile-fail-fulldeps/plugin-MacroRulesTT.rs [new file with mode: 0644]

index 99e870a901e0893240a9acb87a6ccf4559d041f4..c5550902f19895aba6efdd5f8254fbef3503a93a 100644 (file)
 //! Used by plugin crates to tell `rustc` about the plugins they provide.
 
 use lint::{LintPassObject, LintId, Lint};
+use session::Session;
 
 use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT};
-use syntax::ext::base::{IdentTT, LetSyntaxTT, Decorator, Modifier};
+use syntax::ext::base::{IdentTT, Decorator, Modifier, MacroRulesTT};
 use syntax::ext::base::{MacroExpanderFn};
 use syntax::codemap::Span;
 use syntax::parse::token;
 /// This struct has public fields and other methods for use by `rustc`
 /// itself. They are not documented here, and plugin authors should
 /// not use them.
-pub struct Registry {
+pub struct Registry<'a> {
+    /// Compiler session. Useful if you want to emit diagnostic messages
+    /// from the plugin registrar.
+    pub sess: &'a Session,
+
     #[doc(hidden)]
     pub krate_span: Span,
 
@@ -43,10 +48,11 @@ pub struct Registry {
     pub lint_groups: HashMap<&'static str, Vec<LintId>>,
 }
 
-impl Registry {
+impl<'a> Registry<'a> {
     #[doc(hidden)]
-    pub fn new(krate: &ast::Crate) -> Registry {
+    pub fn new(sess: &'a Session, krate: &ast::Crate) -> Registry<'a> {
         Registry {
+            sess: sess,
             krate_span: krate.span,
             syntax_exts: vec!(),
             lint_passes: vec!(),
@@ -63,8 +69,11 @@ pub fn register_syntax_extension(&mut self, name: ast::Name, extension: SyntaxEx
             IdentTT(ext, _) => IdentTT(ext, Some(self.krate_span)),
             Decorator(ext) => Decorator(ext),
             Modifier(ext) => Modifier(ext),
-            // there's probably a nicer way to signal this:
-            LetSyntaxTT(_, _) => panic!("can't register a new LetSyntax!"),
+
+            MacroRulesTT => {
+                self.sess.err("plugin tried to register a new MacroRulesTT");
+                return;
+            }
         }));
     }
 
index 1455aa3c99bb3680403e7a33897672319d1187cf..0d9736a82736fb206477fc655c18d0bf1e6647ed 100644 (file)
@@ -216,7 +216,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
         = time(time_passes, "plugin loading", (), |_|
                plugin::load::load_plugins(sess, &krate, addl_plugins.take().unwrap()));
 
-    let mut registry = Registry::new(&krate);
+    let mut registry = Registry::new(sess, &krate);
 
     time(time_passes, "plugin registration", (), |_| {
         if sess.features.borrow().rustc_diagnostic_macros {
index 91cc8a24622054ceeb29af05662c51e0eea16ab2..4b38e6c0cb231374cb822bc51a2c03df502e6118 100644 (file)
@@ -328,13 +328,8 @@ pub enum SyntaxExtension {
     ///
     IdentTT(Box<IdentMacroExpander + 'static>, Option<Span>),
 
-    /// An ident macro that has two properties:
-    /// - it adds a macro definition to the environment, and
-    /// - the definition it adds doesn't introduce any new
-    ///   identifiers.
-    ///
-    /// `macro_rules!` is a LetSyntaxTT
-    LetSyntaxTT(Box<IdentMacroExpander + 'static>, Option<Span>),
+    /// Represents `macro_rules!` itself.
+    MacroRulesTT,
 }
 
 pub type NamedSyntaxExtension = (Name, SyntaxExtension);
@@ -364,8 +359,7 @@ fn builtin_normal_expander(f: MacroExpanderFn) -> SyntaxExtension {
     }
 
     let mut syntax_expanders = SyntaxEnv::new();
-    syntax_expanders.insert(intern("macro_rules"),
-                            LetSyntaxTT(box ext::tt::macro_rules::add_new_extension, None));
+    syntax_expanders.insert(intern("macro_rules"), MacroRulesTT);
     syntax_expanders.insert(intern("fmt"),
                             builtin_normal_expander(
                                 ext::fmt::expand_syntax_ext));
index b3f30dd4581c9ed6edd5453a7621df805fc61cc7..a1a13f2306477ca7ef3414bf8c5f30bdff5ce7f8 100644 (file)
@@ -7,7 +7,6 @@
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
-use self::Either::*;
 
 use ast::{Block, Crate, DeclLocal, ExprMac, PatMac};
 use ast::{Local, Ident, MacInvocTT};
@@ -18,6 +17,7 @@
 use ast_util::path_to_ident;
 use ext::mtwt;
 use ext::build::AstBuilder;
+use ext::tt::macro_rules;
 use attr;
 use attr::AttrMetaMethods;
 use codemap;
 use visit;
 use visit::Visitor;
 
-enum Either<L,R> {
-    Left(L),
-    Right(R)
-}
-
 pub fn expand_type(t: P<ast::Ty>,
                    fld: &mut MacroExpander,
                    impl_ty: Option<P<ast::Ty>>)
@@ -548,8 +543,8 @@ pub fn expand_item_mac(it: P<ast::Item>, fld: &mut MacroExpander)
 
     let extnamestr = token::get_ident(extname);
     let fm = fresh_mark();
-    let def_or_items = {
-        let mut expanded = match fld.cx.syntax_env.find(&extname.name) {
+    let items = {
+        let expanded = match fld.cx.syntax_env.find(&extname.name) {
             None => {
                 fld.cx.span_err(path_span,
                                 format!("macro undefined: '{}!'",
@@ -600,11 +595,10 @@ pub fn expand_item_mac(it: P<ast::Item>, fld: &mut MacroExpander)
                     let marked_tts = mark_tts(tts[], fm);
                     expander.expand(fld.cx, it.span, it.ident, marked_tts)
                 }
-                LetSyntaxTT(ref expander, span) => {
+                MacroRulesTT => {
                     if it.ident.name == parse::token::special_idents::invalid.name {
                         fld.cx.span_err(path_span,
-                                        format!("macro {}! expects an ident argument",
-                                                extnamestr.get())[]);
+                                        format!("macro_rules! expects an ident argument")[]);
                         return SmallVector::zero();
                     }
                     fld.cx.bt_push(ExpnInfo {
@@ -612,11 +606,21 @@ pub fn expand_item_mac(it: P<ast::Item>, fld: &mut MacroExpander)
                         callee: NameAndSpan {
                             name: extnamestr.get().to_string(),
                             format: MacroBang,
-                            span: span
+                            span: None,
                         }
                     });
-                    // DON'T mark before expansion:
-                    expander.expand(fld.cx, it.span, it.ident, tts)
+                    // DON'T mark before expansion.
+                    let MacroDef { name, ext }
+                        = macro_rules::add_new_extension(fld.cx, it.span, it.ident, tts);
+
+                    fld.cx.syntax_env.insert(intern(name.as_slice()), ext);
+                    if attr::contains_name(it.attrs.as_slice(), "macro_export") {
+                        fld.cx.exported_macros.push(it);
+                    }
+
+                    // macro_rules! has a side effect but expands to nothing.
+                    fld.cx.bt_pop();
+                    return SmallVector::zero();
                 }
                 _ => {
                     fld.cx.span_err(it.span,
@@ -627,31 +631,17 @@ pub fn expand_item_mac(it: P<ast::Item>, fld: &mut MacroExpander)
             }
         };
 
-        match expanded.make_def() {
-            Some(def) => Left(def),
-            None => Right(expanded.make_items())
-        }
+        expanded.make_items()
     };
 
-    let items = match def_or_items {
-        Left(MacroDef { name, ext }) => {
-            // hidden invariant: this should only be possible as the
-            // result of expanding a LetSyntaxTT, and thus doesn't
-            // need to be marked. Not that it could be marked anyway.
-            // create issue to recommend refactoring here?
-            fld.cx.syntax_env.insert(intern(name[]), ext);
-            if attr::contains_name(it.attrs[], "macro_export") {
-                fld.cx.exported_macros.push(it);
-            }
-            SmallVector::zero()
-        }
-        Right(Some(items)) => {
+    let items = match items {
+        Some(items) => {
             items.into_iter()
                 .map(|i| mark_item(i, fm))
                 .flat_map(|i| fld.fold_item(i).into_iter())
                 .collect()
         }
-        Right(None) => {
+        None => {
             fld.cx.span_err(path_span,
                             format!("non-item macro in item position: {}",
                                     extnamestr.get())[]);
index 08014dc13383f99d822b815a781ffe55bdccf5c6..15b75442ca2cb049d016cd0c263100cee469eee2 100644 (file)
@@ -129,15 +129,6 @@ fn expand<'cx>(&self,
     }
 }
 
-struct MacroRulesDefiner {
-    def: Option<MacroDef>
-}
-impl MacResult for MacroRulesDefiner {
-    fn make_def(&mut self) -> Option<MacroDef> {
-        Some(self.def.take().expect("empty MacroRulesDefiner"))
-    }
-}
-
 /// Given `lhses` and `rhses`, this is the new macro we create
 fn generic_extension<'cx>(cx: &'cx ExtCtxt,
                           sp: Span,
@@ -219,7 +210,7 @@ pub fn add_new_extension<'cx>(cx: &'cx mut ExtCtxt,
                               sp: Span,
                               name: Ident,
                               arg: Vec<ast::TokenTree> )
-                              -> Box<MacResult+'cx> {
+                              -> MacroDef {
 
     let lhs_nm =  gensym_ident("lhs");
     let rhs_nm =  gensym_ident("rhs");
@@ -279,10 +270,8 @@ pub fn add_new_extension<'cx>(cx: &'cx mut ExtCtxt,
         rhses: rhses,
     };
 
-    box MacroRulesDefiner {
-        def: Some(MacroDef {
-            name: token::get_ident(name).to_string(),
-            ext: NormalTT(exp, Some(sp))
-        })
-    } as Box<MacResult+'cx>
+    MacroDef {
+        name: token::get_ident(name).to_string(),
+        ext: NormalTT(exp, Some(sp))
+    }
 }
diff --git a/src/test/auxiliary/macro_crate_MacroRulesTT.rs b/src/test/auxiliary/macro_crate_MacroRulesTT.rs
new file mode 100644 (file)
index 0000000..d50c27a
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// force-host
+
+#![feature(plugin_registrar)]
+
+extern crate syntax;
+extern crate rustc;
+
+use syntax::parse::token;
+use syntax::ext::base::MacroRulesTT;
+use rustc::plugin::Registry;
+
+#[plugin_registrar]
+pub fn plugin_registrar(reg: &mut Registry) {
+    reg.register_syntax_extension(token::intern("bogus"), MacroRulesTT);
+}
diff --git a/src/test/compile-fail-fulldeps/plugin-MacroRulesTT.rs b/src/test/compile-fail-fulldeps/plugin-MacroRulesTT.rs
new file mode 100644 (file)
index 0000000..302a64c
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:macro_crate_MacroRulesTT.rs
+// ignore-stage1
+// ignore-android
+// error-pattern: plugin tried to register a new MacroRulesTT
+
+#![feature(phase)]
+
+#[phase(plugin)]
+extern crate macro_crate_MacroRulesTT;
+
+fn main() { }