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...
This commit is contained in:
@@ -13,7 +13,7 @@
|
|||||||
use lint::LintPassObject;
|
use lint::LintPassObject;
|
||||||
|
|
||||||
use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT};
|
use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT};
|
||||||
use syntax::ext::base::{IdentTT, ItemDecorator, ItemModifier, BasicMacroExpander};
|
use syntax::ext::base::{IdentTT, LetSyntaxTT, ItemDecorator, ItemModifier, BasicMacroExpander};
|
||||||
use syntax::ext::base::{MacroExpanderFn};
|
use syntax::ext::base::{MacroExpanderFn};
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
use syntax::parse::token;
|
use syntax::parse::token;
|
||||||
@@ -57,6 +57,8 @@ impl Registry {
|
|||||||
IdentTT(ext, _) => IdentTT(ext, Some(self.krate_span)),
|
IdentTT(ext, _) => IdentTT(ext, Some(self.krate_span)),
|
||||||
ItemDecorator(ext) => ItemDecorator(ext),
|
ItemDecorator(ext) => ItemDecorator(ext),
|
||||||
ItemModifier(ext) => ItemModifier(ext),
|
ItemModifier(ext) => ItemModifier(ext),
|
||||||
|
// there's probably a nicer way to signal this:
|
||||||
|
LetSyntaxTT(_, _) => fail!("can't register a new LetSyntax!"),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -264,8 +264,15 @@ pub enum SyntaxExtension {
|
|||||||
/// A function-like syntax extension that has an extra ident before
|
/// A function-like syntax extension that has an extra ident before
|
||||||
/// the block.
|
/// the block.
|
||||||
///
|
///
|
||||||
/// `macro_rules!` is an `IdentTT`.
|
|
||||||
IdentTT(Box<IdentMacroExpander + 'static>, Option<Span>),
|
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);
|
pub type NamedSyntaxExtension = (Name, SyntaxExtension);
|
||||||
@@ -300,7 +307,7 @@ pub fn syntax_expander_table() -> SyntaxEnv {
|
|||||||
|
|
||||||
let mut syntax_expanders = SyntaxEnv::new();
|
let mut syntax_expanders = SyntaxEnv::new();
|
||||||
syntax_expanders.insert(intern("macro_rules"),
|
syntax_expanders.insert(intern("macro_rules"),
|
||||||
IdentTT(box BasicIdentMacroExpander {
|
LetSyntaxTT(box BasicIdentMacroExpander {
|
||||||
expander: ext::tt::macro_rules::add_new_extension,
|
expander: ext::tt::macro_rules::add_new_extension,
|
||||||
span: None,
|
span: None,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -484,6 +484,24 @@ fn expand_item_mac(it: Gc<ast::Item>, fld: &mut MacroExpander)
|
|||||||
let marked_tts = mark_tts(tts.as_slice(), fm);
|
let marked_tts = mark_tts(tts.as_slice(), fm);
|
||||||
expander.expand(fld.cx, it.span, it.ident, marked_tts)
|
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,
|
fld.cx.span_err(it.span,
|
||||||
format!("{}! is not legal in item position",
|
format!("{}! is not legal in item position",
|
||||||
|
|||||||
Reference in New Issue
Block a user