Skip to content

Commit 9d5ebd5

Browse files
committed
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.
1 parent 63eaba2 commit 9d5ebd5

File tree

7 files changed

+97
-71
lines changed

7 files changed

+97
-71
lines changed

src/librustc/driver/driver.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
216216
= time(time_passes, "plugin loading", (), |_|
217217
plugin::load::load_plugins(sess, &krate, addl_plugins.take().unwrap()));
218218

219-
let mut registry = Registry::new(&krate);
219+
let mut registry = Registry::new(sess, &krate);
220220

221221
time(time_passes, "plugin registration", (), |_| {
222222
if sess.features.rustc_diagnostic_macros.get() {

src/librustc/plugin/registry.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@
1111
//! Used by plugin crates to tell `rustc` about the plugins they provide.
1212
1313
use lint::{LintPassObject, LintId, Lint};
14+
use driver::session::Session;
1415

1516
use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT};
16-
use syntax::ext::base::{IdentTT, LetSyntaxTT, ItemDecorator, ItemModifier};
17+
use syntax::ext::base::{IdentTT, MacroRulesTT, ItemDecorator, ItemModifier};
1718
use syntax::ext::base::{MacroExpanderFn};
1819
use syntax::codemap::Span;
1920
use syntax::parse::token;
@@ -29,7 +30,11 @@ use std::collections::HashMap;
2930
/// This struct has public fields and other methods for use by `rustc`
3031
/// itself. They are not documented here, and plugin authors should
3132
/// not use them.
32-
pub struct Registry {
33+
pub struct Registry<'a> {
34+
/// Compiler session. Useful if you want to emit diagnostic messages
35+
/// from the plugin registrar.
36+
pub sess: &'a Session,
37+
3338
#[doc(hidden)]
3439
pub krate_span: Span,
3540

@@ -43,10 +48,11 @@ pub struct Registry {
4348
pub lint_groups: HashMap<&'static str, Vec<LintId>>,
4449
}
4550

46-
impl Registry {
51+
impl<'a> Registry<'a> {
4752
#[doc(hidden)]
48-
pub fn new(krate: &ast::Crate) -> Registry {
53+
pub fn new(sess: &'a Session, krate: &ast::Crate) -> Registry<'a> {
4954
Registry {
55+
sess: sess,
5056
krate_span: krate.span,
5157
syntax_exts: vec!(),
5258
lint_passes: vec!(),
@@ -63,8 +69,11 @@ impl Registry {
6369
IdentTT(ext, _) => IdentTT(ext, Some(self.krate_span)),
6470
ItemDecorator(ext) => ItemDecorator(ext),
6571
ItemModifier(ext) => ItemModifier(ext),
66-
// there's probably a nicer way to signal this:
67-
LetSyntaxTT(_, _) => fail!("can't register a new LetSyntax!"),
72+
73+
MacroRulesTT => {
74+
self.sess.err("plugin tried to register a new MacroRulesTT");
75+
return;
76+
}
6877
}));
6978
}
7079

src/libsyntax/ext/base.rs

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -321,13 +321,8 @@ pub enum SyntaxExtension {
321321
///
322322
IdentTT(Box<IdentMacroExpander + 'static>, Option<Span>),
323323

324-
/// An ident macro that has two properties:
325-
/// - it adds a macro definition to the environment, and
326-
/// - the definition it adds doesn't introduce any new
327-
/// identifiers.
328-
///
329-
/// `macro_rules!` is a LetSyntaxTT
330-
LetSyntaxTT(Box<IdentMacroExpander + 'static>, Option<Span>),
324+
/// Represents `macro_rules!` itself.
325+
MacroRulesTT,
331326
}
332327

333328
pub type NamedSyntaxExtension = (Name, SyntaxExtension);
@@ -357,8 +352,7 @@ fn initial_syntax_expander_table() -> SyntaxEnv {
357352
}
358353

359354
let mut syntax_expanders = SyntaxEnv::new();
360-
syntax_expanders.insert(intern("macro_rules"),
361-
LetSyntaxTT(box ext::tt::macro_rules::add_new_extension, None));
355+
syntax_expanders.insert(intern("macro_rules"), MacroRulesTT);
362356
syntax_expanders.insert(intern("fmt"),
363357
builtin_normal_expander(
364358
ext::fmt::expand_syntax_ext));

src/libsyntax/ext/expand.rs

Lines changed: 22 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use ast::TokenTree;
1515
use ast;
1616
use ext::mtwt;
1717
use ext::build::AstBuilder;
18+
use ext::tt::macro_rules;
1819
use attr;
1920
use attr::AttrMetaMethods;
2021
use codemap;
@@ -32,11 +33,6 @@ use visit::Visitor;
3233

3334
use std::gc::Gc;
3435

35-
enum Either<L,R> {
36-
Left(L),
37-
Right(R)
38-
}
39-
4036
pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
4137
e.and_then(|ast::Expr {id, node, span}| match node {
4238
// expr_mac should really be expr_ext or something; it's the
@@ -387,8 +383,8 @@ pub fn expand_item_mac(it: P<ast::Item>, fld: &mut MacroExpander)
387383

388384
let extnamestr = token::get_ident(extname);
389385
let fm = fresh_mark();
390-
let def_or_items = {
391-
let mut expanded = match fld.cx.syntax_env.find(&extname.name) {
386+
let items = {
387+
let expanded = match fld.cx.syntax_env.find(&extname.name) {
392388
None => {
393389
fld.cx.span_err(path_span,
394390
format!("macro undefined: '{}!'",
@@ -439,23 +435,31 @@ pub fn expand_item_mac(it: P<ast::Item>, fld: &mut MacroExpander)
439435
let marked_tts = mark_tts(tts.as_slice(), fm);
440436
expander.expand(fld.cx, it.span, it.ident, marked_tts)
441437
}
442-
LetSyntaxTT(ref expander, span) => {
438+
MacroRulesTT => {
443439
if it.ident.name == parse::token::special_idents::invalid.name {
444-
fld.cx.span_err(path_span,
445-
format!("macro {}! expects an ident argument",
446-
extnamestr.get()).as_slice());
440+
fld.cx.span_err(path_span, "macro_rules! expects an ident argument");
447441
return SmallVector::zero();
448442
}
449443
fld.cx.bt_push(ExpnInfo {
450444
call_site: it.span,
451445
callee: NameAndSpan {
452446
name: extnamestr.get().to_string(),
453447
format: MacroBang,
454-
span: span
448+
span: None,
455449
}
456450
});
457-
// DON'T mark before expansion:
458-
expander.expand(fld.cx, it.span, it.ident, tts)
451+
// DON'T mark before expansion.
452+
let MacroDef { name, ext }
453+
= macro_rules::add_new_extension(fld.cx, it.span, it.ident, tts);
454+
455+
fld.cx.syntax_env.insert(intern(name.as_slice()), ext);
456+
if attr::contains_name(it.attrs.as_slice(), "macro_export") {
457+
fld.cx.exported_macros.push(it);
458+
}
459+
460+
// macro_rules! has a side effect but expands to nothing.
461+
fld.cx.bt_pop();
462+
return SmallVector::zero();
459463
}
460464
_ => {
461465
fld.cx.span_err(it.span,
@@ -466,31 +470,17 @@ pub fn expand_item_mac(it: P<ast::Item>, fld: &mut MacroExpander)
466470
}
467471
};
468472

469-
match expanded.make_def() {
470-
Some(def) => Left(def),
471-
None => Right(expanded.make_items())
472-
}
473+
expanded.make_items()
473474
};
474475

475-
let items = match def_or_items {
476-
Left(MacroDef { name, ext }) => {
477-
// hidden invariant: this should only be possible as the
478-
// result of expanding a LetSyntaxTT, and thus doesn't
479-
// need to be marked. Not that it could be marked anyway.
480-
// create issue to recommend refactoring here?
481-
fld.cx.syntax_env.insert(intern(name.as_slice()), ext);
482-
if attr::contains_name(it.attrs.as_slice(), "macro_export") {
483-
fld.cx.exported_macros.push(it);
484-
}
485-
SmallVector::zero()
486-
}
487-
Right(Some(items)) => {
476+
let items = match items {
477+
Some(items) => {
488478
items.move_iter()
489479
.map(|i| mark_item(i, fm))
490480
.flat_map(|i| fld.fold_item(i).move_iter())
491481
.collect()
492482
}
493-
Right(None) => {
483+
None => {
494484
fld.cx.span_err(path_span,
495485
format!("non-item macro in item position: {}",
496486
extnamestr.get()).as_slice());

src/libsyntax/ext/tt/macro_rules.rs

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -126,15 +126,6 @@ impl TTMacroExpander for MacroRulesMacroExpander {
126126
}
127127
}
128128

129-
struct MacroRulesDefiner {
130-
def: Option<MacroDef>
131-
}
132-
impl MacResult for MacroRulesDefiner {
133-
fn make_def(&mut self) -> Option<MacroDef> {
134-
Some(self.def.take().expect("empty MacroRulesDefiner"))
135-
}
136-
}
137-
138129
/// Given `lhses` and `rhses`, this is the new macro we create
139130
fn generic_extension<'cx>(cx: &'cx ExtCtxt,
140131
sp: Span,
@@ -209,14 +200,12 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt,
209200
cx.span_fatal(best_fail_spot, best_fail_msg.as_slice());
210201
}
211202

212-
/// This procedure performs the expansion of the
213-
/// macro_rules! macro. It parses the RHS and adds
214-
/// an extension to the current context.
215-
pub fn add_new_extension<'cx>(cx: &'cx mut ExtCtxt,
216-
sp: Span,
217-
name: Ident,
218-
arg: Vec<ast::TokenTree> )
219-
-> Box<MacResult+'cx> {
203+
/// This procedure implements the macro_rules! macro.
204+
/// It parses the RHS and returns a macro definition.
205+
pub fn add_new_extension(cx: &mut ExtCtxt,
206+
sp: Span,
207+
name: Ident,
208+
arg: Vec<ast::TokenTree>) -> MacroDef {
220209
// these spans won't matter, anyways
221210
fn ms(m: Matcher_) -> Matcher {
222211
Spanned {
@@ -268,10 +257,8 @@ pub fn add_new_extension<'cx>(cx: &'cx mut ExtCtxt,
268257
rhses: rhses,
269258
};
270259

271-
box MacroRulesDefiner {
272-
def: Some(MacroDef {
273-
name: token::get_ident(name).to_string(),
274-
ext: NormalTT(exp, Some(sp))
275-
})
276-
} as Box<MacResult+'cx>
260+
MacroDef {
261+
name: token::get_ident(name).to_string(),
262+
ext: NormalTT(exp, Some(sp))
263+
}
277264
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2014 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+
// force-host
12+
13+
#![feature(plugin_registrar)]
14+
15+
extern crate syntax;
16+
extern crate rustc;
17+
18+
use syntax::parse::token;
19+
use syntax::ext::base::MacroRulesTT;
20+
use rustc::plugin::Registry;
21+
22+
#[plugin_registrar]
23+
pub fn plugin_registrar(reg: &mut Registry) {
24+
reg.register_syntax_extension(token::intern("bogus"), MacroRulesTT);
25+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2014 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+
// aux-build:macro_crate_MacroRulesTT.rs
12+
// ignore-stage1
13+
// ignore-android
14+
// error-pattern: plugin tried to register a new MacroRulesTT
15+
16+
#![feature(phase)]
17+
18+
#[phase(plugin)]
19+
extern crate macro_crate_MacroRulesTT;
20+
21+
fn main() { }

0 commit comments

Comments
 (0)