Skip to content

Commit 5e5924b

Browse files
author
Keegan McAllister
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 d1cf1b1 commit 5e5924b

File tree

7 files changed

+92
-64
lines changed

7 files changed

+92
-64
lines changed

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 session::Session;
1415

1516
use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT};
16-
use syntax::ext::base::{IdentTT, LetSyntaxTT, Decorator, Modifier};
17+
use syntax::ext::base::{IdentTT, Decorator, Modifier, MacroRulesTT};
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
Decorator(ext) => Decorator(ext),
6571
Modifier(ext) => Modifier(ext),
66-
// there's probably a nicer way to signal this:
67-
LetSyntaxTT(_, _) => panic!("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/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.borrow().rustc_diagnostic_macros {

src/libsyntax/ext/base.rs

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

331-
/// An ident macro that has two properties:
332-
/// - it adds a macro definition to the environment, and
333-
/// - the definition it adds doesn't introduce any new
334-
/// identifiers.
335-
///
336-
/// `macro_rules!` is a LetSyntaxTT
337-
LetSyntaxTT(Box<IdentMacroExpander + 'static>, Option<Span>),
331+
/// Represents `macro_rules!` itself.
332+
MacroRulesTT,
338333
}
339334

340335
pub type NamedSyntaxExtension = (Name, SyntaxExtension);
@@ -364,8 +359,7 @@ fn initial_syntax_expander_table(ecfg: &expand::ExpansionConfig) -> SyntaxEnv {
364359
}
365360

366361
let mut syntax_expanders = SyntaxEnv::new();
367-
syntax_expanders.insert(intern("macro_rules"),
368-
LetSyntaxTT(box ext::tt::macro_rules::add_new_extension, None));
362+
syntax_expanders.insert(intern("macro_rules"), MacroRulesTT);
369363
syntax_expanders.insert(intern("fmt"),
370364
builtin_normal_expander(
371365
ext::fmt::expand_syntax_ext));

src/libsyntax/ext/expand.rs

Lines changed: 22 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
10-
use self::Either::*;
1110

1211
use ast::{Block, Crate, DeclLocal, ExprMac, PatMac};
1312
use ast::{Local, Ident, MacInvocTT};
@@ -18,6 +17,7 @@ use ast;
1817
use ast_util::path_to_ident;
1918
use ext::mtwt;
2019
use ext::build::AstBuilder;
20+
use ext::tt::macro_rules;
2121
use attr;
2222
use attr::AttrMetaMethods;
2323
use codemap;
@@ -33,11 +33,6 @@ use util::small_vector::SmallVector;
3333
use visit;
3434
use visit::Visitor;
3535

36-
enum Either<L,R> {
37-
Left(L),
38-
Right(R)
39-
}
40-
4136
pub fn expand_type(t: P<ast::Ty>,
4237
fld: &mut MacroExpander,
4338
impl_ty: Option<P<ast::Ty>>)
@@ -548,8 +543,8 @@ pub fn expand_item_mac(it: P<ast::Item>, fld: &mut MacroExpander)
548543

549544
let extnamestr = token::get_ident(extname);
550545
let fm = fresh_mark();
551-
let def_or_items = {
552-
let mut expanded = match fld.cx.syntax_env.find(&extname.name) {
546+
let items = {
547+
let expanded = match fld.cx.syntax_env.find(&extname.name) {
553548
None => {
554549
fld.cx.span_err(path_span,
555550
format!("macro undefined: '{}!'",
@@ -600,23 +595,32 @@ pub fn expand_item_mac(it: P<ast::Item>, fld: &mut MacroExpander)
600595
let marked_tts = mark_tts(tts[], fm);
601596
expander.expand(fld.cx, it.span, it.ident, marked_tts)
602597
}
603-
LetSyntaxTT(ref expander, span) => {
598+
MacroRulesTT => {
604599
if it.ident.name == parse::token::special_idents::invalid.name {
605600
fld.cx.span_err(path_span,
606-
format!("macro {}! expects an ident argument",
607-
extnamestr.get())[]);
601+
format!("macro_rules! expects an ident argument")[]);
608602
return SmallVector::zero();
609603
}
610604
fld.cx.bt_push(ExpnInfo {
611605
call_site: it.span,
612606
callee: NameAndSpan {
613607
name: extnamestr.get().to_string(),
614608
format: MacroBang,
615-
span: span
609+
span: None,
616610
}
617611
});
618-
// DON'T mark before expansion:
619-
expander.expand(fld.cx, it.span, it.ident, tts)
612+
// DON'T mark before expansion.
613+
let MacroDef { name, ext }
614+
= macro_rules::add_new_extension(fld.cx, it.span, it.ident, tts);
615+
616+
fld.cx.syntax_env.insert(intern(name.as_slice()), ext);
617+
if attr::contains_name(it.attrs.as_slice(), "macro_export") {
618+
fld.cx.exported_macros.push(it);
619+
}
620+
621+
// macro_rules! has a side effect but expands to nothing.
622+
fld.cx.bt_pop();
623+
return SmallVector::zero();
620624
}
621625
_ => {
622626
fld.cx.span_err(it.span,
@@ -627,31 +631,17 @@ pub fn expand_item_mac(it: P<ast::Item>, fld: &mut MacroExpander)
627631
}
628632
};
629633

630-
match expanded.make_def() {
631-
Some(def) => Left(def),
632-
None => Right(expanded.make_items())
633-
}
634+
expanded.make_items()
634635
};
635636

636-
let items = match def_or_items {
637-
Left(MacroDef { name, ext }) => {
638-
// hidden invariant: this should only be possible as the
639-
// result of expanding a LetSyntaxTT, and thus doesn't
640-
// need to be marked. Not that it could be marked anyway.
641-
// create issue to recommend refactoring here?
642-
fld.cx.syntax_env.insert(intern(name[]), ext);
643-
if attr::contains_name(it.attrs[], "macro_export") {
644-
fld.cx.exported_macros.push(it);
645-
}
646-
SmallVector::zero()
647-
}
648-
Right(Some(items)) => {
637+
let items = match items {
638+
Some(items) => {
649639
items.into_iter()
650640
.map(|i| mark_item(i, fm))
651641
.flat_map(|i| fld.fold_item(i).into_iter())
652642
.collect()
653643
}
654-
Right(None) => {
644+
None => {
655645
fld.cx.span_err(path_span,
656646
format!("non-item macro in item position: {}",
657647
extnamestr.get())[]);

src/libsyntax/ext/tt/macro_rules.rs

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -129,15 +129,6 @@ impl TTMacroExpander for MacroRulesMacroExpander {
129129
}
130130
}
131131

132-
struct MacroRulesDefiner {
133-
def: Option<MacroDef>
134-
}
135-
impl MacResult for MacroRulesDefiner {
136-
fn make_def(&mut self) -> Option<MacroDef> {
137-
Some(self.def.take().expect("empty MacroRulesDefiner"))
138-
}
139-
}
140-
141132
/// Given `lhses` and `rhses`, this is the new macro we create
142133
fn generic_extension<'cx>(cx: &'cx ExtCtxt,
143134
sp: Span,
@@ -219,7 +210,7 @@ pub fn add_new_extension<'cx>(cx: &'cx mut ExtCtxt,
219210
sp: Span,
220211
name: Ident,
221212
arg: Vec<ast::TokenTree> )
222-
-> Box<MacResult+'cx> {
213+
-> MacroDef {
223214

224215
let lhs_nm = gensym_ident("lhs");
225216
let rhs_nm = gensym_ident("rhs");
@@ -279,10 +270,8 @@ pub fn add_new_extension<'cx>(cx: &'cx mut ExtCtxt,
279270
rhses: rhses,
280271
};
281272

282-
box MacroRulesDefiner {
283-
def: Some(MacroDef {
284-
name: token::get_ident(name).to_string(),
285-
ext: NormalTT(exp, Some(sp))
286-
})
287-
} as Box<MacResult+'cx>
273+
MacroDef {
274+
name: token::get_ident(name).to_string(),
275+
ext: NormalTT(exp, Some(sp))
276+
}
288277
}
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)