Skip to content

Commit 9ee9c49

Browse files
committed
introducing let-syntax
The let-syntax expander is different in that it doesn't apply a mark to its token trees before expansion. This is used for macro_rules, and it's because macro_rules is essentially MTWT's let-syntax. You don't want to mark before expand sees let-syntax, because there's no "after" syntax to mark again. In some sense, the cleaner approach might be to introduce a new AST node that macro_rules expands into; this would make it clearer that the expansion of a macro is distinct from the addition of a new macro binding. This should work for now, though...
1 parent 92c2ff6 commit 9ee9c49

File tree

3 files changed

+30
-3
lines changed

3 files changed

+30
-3
lines changed

src/librustc/plugin/registry.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
use lint::LintPassObject;
1414

1515
use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT};
16-
use syntax::ext::base::{IdentTT, ItemDecorator, ItemModifier, BasicMacroExpander};
16+
use syntax::ext::base::{IdentTT, LetSyntaxTT, ItemDecorator, ItemModifier, BasicMacroExpander};
1717
use syntax::ext::base::{MacroExpanderFn};
1818
use syntax::codemap::Span;
1919
use syntax::parse::token;
@@ -57,6 +57,8 @@ impl Registry {
5757
IdentTT(ext, _) => IdentTT(ext, Some(self.krate_span)),
5858
ItemDecorator(ext) => ItemDecorator(ext),
5959
ItemModifier(ext) => ItemModifier(ext),
60+
// there's probably a nicer way to signal this:
61+
LetSyntaxTT(_, _) => fail!("can't register a new LetSyntax!"),
6062
}));
6163
}
6264

src/libsyntax/ext/base.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,8 +264,15 @@ pub enum SyntaxExtension {
264264
/// A function-like syntax extension that has an extra ident before
265265
/// the block.
266266
///
267-
/// `macro_rules!` is an `IdentTT`.
268267
IdentTT(Box<IdentMacroExpander + 'static>, Option<Span>),
268+
269+
/// An ident macro that has two properties:
270+
/// - it adds a macro definition to the environment, and
271+
/// - the definition it adds doesn't introduce any new
272+
/// identifiers.
273+
///
274+
/// `macro_rules!` is a LetSyntaxTT
275+
LetSyntaxTT(Box<IdentMacroExpander + 'static>, Option<Span>),
269276
}
270277

271278
pub type NamedSyntaxExtension = (Name, SyntaxExtension);
@@ -300,7 +307,7 @@ pub fn syntax_expander_table() -> SyntaxEnv {
300307

301308
let mut syntax_expanders = SyntaxEnv::new();
302309
syntax_expanders.insert(intern("macro_rules"),
303-
IdentTT(box BasicIdentMacroExpander {
310+
LetSyntaxTT(box BasicIdentMacroExpander {
304311
expander: ext::tt::macro_rules::add_new_extension,
305312
span: None,
306313
},

src/libsyntax/ext/expand.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,24 @@ fn expand_item_mac(it: Gc<ast::Item>, fld: &mut MacroExpander)
484484
let marked_tts = mark_tts(tts.as_slice(), fm);
485485
expander.expand(fld.cx, it.span, it.ident, marked_tts)
486486
}
487+
Some(&LetSyntaxTT(ref expander, span)) => {
488+
if it.ident.name == parse::token::special_idents::invalid.name {
489+
fld.cx.span_err(pth.span,
490+
format!("macro {}! expects an ident argument",
491+
extnamestr.get()).as_slice());
492+
return SmallVector::zero();
493+
}
494+
fld.cx.bt_push(ExpnInfo {
495+
call_site: it.span,
496+
callee: NameAndSpan {
497+
name: extnamestr.get().to_string(),
498+
format: MacroBang,
499+
span: span
500+
}
501+
});
502+
// DON'T mark before expansion:
503+
expander.expand(fld.cx, it.span, it.ident, tts)
504+
}
487505
_ => {
488506
fld.cx.span_err(it.span,
489507
format!("{}! is not legal in item position",

0 commit comments

Comments
 (0)