diff options
| author | Keegan McAllister <kmcallister@mozilla.com> | 2014-09-15 16:09:09 -0700 |
|---|---|---|
| committer | Keegan McAllister <kmcallister@mozilla.com> | 2015-01-05 11:38:12 -0800 |
| commit | 5e5924b79915326d81db2aebfe73d2a20b8506f1 (patch) | |
| tree | 16d55df447ad54f7d8a0dff9a900d12e7b091dd1 | |
| parent | d1cf1b1e6bf0b33fe3bb9fa01d9d94f797c9f9fc (diff) | |
| download | rust-5e5924b79915326d81db2aebfe73d2a20b8506f1.tar.gz rust-5e5924b79915326d81db2aebfe73d2a20b8506f1.zip | |
Replace LetSyntaxTT with MacroRulesTT
The implementation of LetSyntaxTT was specialized to macro_rules! in various ways. This gets rid of the false generality and simplifies the code.
| -rw-r--r-- | src/librustc/plugin/registry.rs | 21 | ||||
| -rw-r--r-- | src/librustc_driver/driver.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/ext/base.rs | 12 | ||||
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 54 | ||||
| -rw-r--r-- | src/libsyntax/ext/tt/macro_rules.rs | 21 | ||||
| -rw-r--r-- | src/test/auxiliary/macro_crate_MacroRulesTT.rs | 25 | ||||
| -rw-r--r-- | src/test/compile-fail-fulldeps/plugin-MacroRulesTT.rs | 21 |
7 files changed, 92 insertions, 64 deletions
diff --git a/src/librustc/plugin/registry.rs b/src/librustc/plugin/registry.rs index 99e870a901e..c5550902f19 100644 --- a/src/librustc/plugin/registry.rs +++ b/src/librustc/plugin/registry.rs @@ -11,9 +11,10 @@ //! 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; @@ -29,7 +30,11 @@ use std::collections::HashMap; /// 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 @@ impl Registry { 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; + } })); } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 1455aa3c99b..0d9736a8273 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -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 { diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 91cc8a24622..4b38e6c0cb2 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -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 initial_syntax_expander_table(ecfg: &expand::ExpansionConfig) -> SyntaxEnv { } 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)); diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index b3f30dd4581..a1a13f23064 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -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; 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; @@ -33,11 +33,6 @@ use util::small_vector::SmallVector; 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())[]); diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 08014dc1338..15b75442ca2 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -129,15 +129,6 @@ impl TTMacroExpander for MacroRulesMacroExpander { } } -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 index 00000000000..d50c27a4e75 --- /dev/null +++ b/src/test/auxiliary/macro_crate_MacroRulesTT.rs @@ -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 index 00000000000..302a64c5ed3 --- /dev/null +++ b/src/test/compile-fail-fulldeps/plugin-MacroRulesTT.rs @@ -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() { } |
