diff options
| author | John Clements <clements@racket-lang.org> | 2014-07-07 09:54:08 -0700 |
|---|---|---|
| committer | John Clements <clements@racket-lang.org> | 2014-07-08 16:26:43 -0700 |
| commit | 9ee9c49cb4823c5bddbd9ec1ece6dfafa9e833ea (patch) | |
| tree | 74a30492aa2aadaf28eb0d591d22fb89dd62ae9f /src/libsyntax | |
| parent | 92c2ff6d697fe7be2d4e3979b4dec9f86b969b69 (diff) | |
| download | rust-9ee9c49cb4823c5bddbd9ec1ece6dfafa9e833ea.tar.gz rust-9ee9c49cb4823c5bddbd9ec1ece6dfafa9e833ea.zip | |
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...
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ext/base.rs | 11 | ||||
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 18 |
2 files changed, 27 insertions, 2 deletions
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index a540b23551b..a2a442f8b6a 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -264,8 +264,15 @@ pub enum SyntaxExtension { /// A function-like syntax extension that has an extra ident before /// the block. /// - /// `macro_rules!` is an `IdentTT`. 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>), } pub type NamedSyntaxExtension = (Name, SyntaxExtension); @@ -300,7 +307,7 @@ pub fn syntax_expander_table() -> SyntaxEnv { let mut syntax_expanders = SyntaxEnv::new(); syntax_expanders.insert(intern("macro_rules"), - IdentTT(box BasicIdentMacroExpander { + LetSyntaxTT(box BasicIdentMacroExpander { expander: ext::tt::macro_rules::add_new_extension, span: None, }, diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 69e629bb3c6..709db52262d 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -484,6 +484,24 @@ fn expand_item_mac(it: Gc<ast::Item>, fld: &mut MacroExpander) let marked_tts = mark_tts(tts.as_slice(), fm); expander.expand(fld.cx, it.span, it.ident, marked_tts) } + Some(&LetSyntaxTT(ref expander, span)) => { + if it.ident.name == parse::token::special_idents::invalid.name { + fld.cx.span_err(pth.span, + format!("macro {}! expects an ident argument", + extnamestr.get()).as_slice()); + return SmallVector::zero(); + } + fld.cx.bt_push(ExpnInfo { + call_site: it.span, + callee: NameAndSpan { + name: extnamestr.get().to_string(), + format: MacroBang, + span: span + } + }); + // DON'T mark before expansion: + expander.expand(fld.cx, it.span, it.ident, tts) + } _ => { fld.cx.span_err(it.span, format!("{}! is not legal in item position", |
