auto merge of #17162 : sfackler/rust/decorator-traits, r=huonw
The other extension types already worked this way and it can be useful to track some state along with the extension. I also removed the `BasicMacroExpander` and `BasicIdentMacroExpander` since the span inside of them was never used. The expander function types now directly implement the relevant trait.
This commit is contained in:
commit
a9cf19889a
@ -13,7 +13,7 @@
|
|||||||
use lint::{LintPassObject, LintId, Lint};
|
use lint::{LintPassObject, LintId, Lint};
|
||||||
|
|
||||||
use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT};
|
use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT};
|
||||||
use syntax::ext::base::{IdentTT, LetSyntaxTT, ItemDecorator, ItemModifier, BasicMacroExpander};
|
use syntax::ext::base::{IdentTT, LetSyntaxTT, ItemDecorator, ItemModifier};
|
||||||
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;
|
||||||
@ -71,15 +71,10 @@ impl Registry {
|
|||||||
/// Register a macro of the usual kind.
|
/// Register a macro of the usual kind.
|
||||||
///
|
///
|
||||||
/// This is a convenience wrapper for `register_syntax_extension`.
|
/// This is a convenience wrapper for `register_syntax_extension`.
|
||||||
/// It builds for you a `NormalTT` with a `BasicMacroExpander`,
|
/// It builds for you a `NormalTT` that calls `expander`,
|
||||||
/// and also takes care of interning the macro's name.
|
/// and also takes care of interning the macro's name.
|
||||||
pub fn register_macro(&mut self, name: &str, expander: MacroExpanderFn) {
|
pub fn register_macro(&mut self, name: &str, expander: MacroExpanderFn) {
|
||||||
self.register_syntax_extension(
|
self.register_syntax_extension(token::intern(name), NormalTT(box expander, None));
|
||||||
token::intern(name),
|
|
||||||
NormalTT(box BasicMacroExpander {
|
|
||||||
expander: expander,
|
|
||||||
span: None,
|
|
||||||
}, None));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register a compiler lint pass.
|
/// Register a compiler lint pass.
|
||||||
|
@ -39,15 +39,44 @@ pub struct MacroDef {
|
|||||||
pub ext: SyntaxExtension
|
pub ext: SyntaxExtension
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type ItemDecorator =
|
pub trait ItemDecorator {
|
||||||
fn(&mut ExtCtxt, Span, Gc<ast::MetaItem>, Gc<ast::Item>, |Gc<ast::Item>|);
|
fn expand(&self,
|
||||||
|
ecx: &mut ExtCtxt,
|
||||||
|
sp: Span,
|
||||||
|
meta_item: Gc<ast::MetaItem>,
|
||||||
|
item: Gc<ast::Item>,
|
||||||
|
push: |Gc<ast::Item>|);
|
||||||
|
}
|
||||||
|
|
||||||
pub type ItemModifier =
|
impl ItemDecorator for fn(&mut ExtCtxt, Span, Gc<ast::MetaItem>, Gc<ast::Item>, |Gc<ast::Item>|) {
|
||||||
fn(&mut ExtCtxt, Span, Gc<ast::MetaItem>, Gc<ast::Item>) -> Gc<ast::Item>;
|
fn expand(&self,
|
||||||
|
ecx: &mut ExtCtxt,
|
||||||
|
sp: Span,
|
||||||
|
meta_item: Gc<ast::MetaItem>,
|
||||||
|
item: Gc<ast::Item>,
|
||||||
|
push: |Gc<ast::Item>|) {
|
||||||
|
(*self)(ecx, sp, meta_item, item, push)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct BasicMacroExpander {
|
pub trait ItemModifier {
|
||||||
pub expander: MacroExpanderFn,
|
fn expand(&self,
|
||||||
pub span: Option<Span>
|
ecx: &mut ExtCtxt,
|
||||||
|
span: Span,
|
||||||
|
meta_item: Gc<ast::MetaItem>,
|
||||||
|
item: Gc<ast::Item>)
|
||||||
|
-> Gc<ast::Item>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ItemModifier for fn(&mut ExtCtxt, Span, Gc<ast::MetaItem>, Gc<ast::Item>) -> Gc<ast::Item> {
|
||||||
|
fn expand(&self,
|
||||||
|
ecx: &mut ExtCtxt,
|
||||||
|
span: Span,
|
||||||
|
meta_item: Gc<ast::MetaItem>,
|
||||||
|
item: Gc<ast::Item>)
|
||||||
|
-> Gc<ast::Item> {
|
||||||
|
(*self)(ecx, span, meta_item, item)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents a thing that maps token trees to Macro Results
|
/// Represents a thing that maps token trees to Macro Results
|
||||||
@ -60,24 +89,18 @@ pub trait TTMacroExpander {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub type MacroExpanderFn =
|
pub type MacroExpanderFn =
|
||||||
fn<'cx>(ecx: &'cx mut ExtCtxt, span: codemap::Span, token_tree: &[ast::TokenTree])
|
fn<'cx>(&'cx mut ExtCtxt, Span, &[ast::TokenTree]) -> Box<MacResult+'cx>;
|
||||||
-> Box<MacResult+'cx>;
|
|
||||||
|
|
||||||
impl TTMacroExpander for BasicMacroExpander {
|
impl TTMacroExpander for MacroExpanderFn {
|
||||||
fn expand<'cx>(&self,
|
fn expand<'cx>(&self,
|
||||||
ecx: &'cx mut ExtCtxt,
|
ecx: &'cx mut ExtCtxt,
|
||||||
span: Span,
|
span: Span,
|
||||||
token_tree: &[ast::TokenTree])
|
token_tree: &[ast::TokenTree])
|
||||||
-> Box<MacResult+'cx> {
|
-> Box<MacResult+'cx> {
|
||||||
(self.expander)(ecx, span, token_tree)
|
(*self)(ecx, span, token_tree)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct BasicIdentMacroExpander {
|
|
||||||
pub expander: IdentMacroExpanderFn,
|
|
||||||
pub span: Option<Span>
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait IdentMacroExpander {
|
pub trait IdentMacroExpander {
|
||||||
fn expand<'cx>(&self,
|
fn expand<'cx>(&self,
|
||||||
cx: &'cx mut ExtCtxt,
|
cx: &'cx mut ExtCtxt,
|
||||||
@ -87,20 +110,20 @@ pub trait IdentMacroExpander {
|
|||||||
-> Box<MacResult+'cx>;
|
-> Box<MacResult+'cx>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IdentMacroExpander for BasicIdentMacroExpander {
|
pub type IdentMacroExpanderFn =
|
||||||
|
fn<'cx>(&'cx mut ExtCtxt, Span, ast::Ident, Vec<ast::TokenTree>) -> Box<MacResult+'cx>;
|
||||||
|
|
||||||
|
impl IdentMacroExpander for IdentMacroExpanderFn {
|
||||||
fn expand<'cx>(&self,
|
fn expand<'cx>(&self,
|
||||||
cx: &'cx mut ExtCtxt,
|
cx: &'cx mut ExtCtxt,
|
||||||
sp: Span,
|
sp: Span,
|
||||||
ident: ast::Ident,
|
ident: ast::Ident,
|
||||||
token_tree: Vec<ast::TokenTree> )
|
token_tree: Vec<ast::TokenTree> )
|
||||||
-> Box<MacResult+'cx> {
|
-> Box<MacResult+'cx> {
|
||||||
(self.expander)(cx, sp, ident, token_tree)
|
(*self)(cx, sp, ident, token_tree)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type IdentMacroExpanderFn =
|
|
||||||
fn<'cx>(&'cx mut ExtCtxt, Span, ast::Ident, Vec<ast::TokenTree>) -> Box<MacResult+'cx>;
|
|
||||||
|
|
||||||
/// The result of a macro expansion. The return values of the various
|
/// The result of a macro expansion. The return values of the various
|
||||||
/// methods are spliced into the AST at the callsite of the macro (or
|
/// methods are spliced into the AST at the callsite of the macro (or
|
||||||
/// just into the compiler's internal macro table, for `make_def`).
|
/// just into the compiler's internal macro table, for `make_def`).
|
||||||
@ -281,11 +304,11 @@ pub enum SyntaxExtension {
|
|||||||
/// based upon it.
|
/// based upon it.
|
||||||
///
|
///
|
||||||
/// `#[deriving(...)]` is an `ItemDecorator`.
|
/// `#[deriving(...)]` is an `ItemDecorator`.
|
||||||
ItemDecorator(ItemDecorator),
|
ItemDecorator(Box<ItemDecorator + 'static>),
|
||||||
|
|
||||||
/// A syntax extension that is attached to an item and modifies it
|
/// A syntax extension that is attached to an item and modifies it
|
||||||
/// in-place.
|
/// in-place.
|
||||||
ItemModifier(ItemModifier),
|
ItemModifier(Box<ItemModifier + 'static>),
|
||||||
|
|
||||||
/// A normal, function-like syntax extension.
|
/// A normal, function-like syntax extension.
|
||||||
///
|
///
|
||||||
@ -329,20 +352,12 @@ impl BlockInfo {
|
|||||||
fn initial_syntax_expander_table() -> SyntaxEnv {
|
fn initial_syntax_expander_table() -> SyntaxEnv {
|
||||||
// utility function to simplify creating NormalTT syntax extensions
|
// utility function to simplify creating NormalTT syntax extensions
|
||||||
fn builtin_normal_expander(f: MacroExpanderFn) -> SyntaxExtension {
|
fn builtin_normal_expander(f: MacroExpanderFn) -> SyntaxExtension {
|
||||||
NormalTT(box BasicMacroExpander {
|
NormalTT(box f, None)
|
||||||
expander: f,
|
|
||||||
span: None,
|
|
||||||
},
|
|
||||||
None)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut syntax_expanders = SyntaxEnv::new();
|
let mut syntax_expanders = SyntaxEnv::new();
|
||||||
syntax_expanders.insert(intern("macro_rules"),
|
syntax_expanders.insert(intern("macro_rules"),
|
||||||
LetSyntaxTT(box BasicIdentMacroExpander {
|
LetSyntaxTT(box ext::tt::macro_rules::add_new_extension, None));
|
||||||
expander: ext::tt::macro_rules::add_new_extension,
|
|
||||||
span: None,
|
|
||||||
},
|
|
||||||
None));
|
|
||||||
syntax_expanders.insert(intern("fmt"),
|
syntax_expanders.insert(intern("fmt"),
|
||||||
builtin_normal_expander(
|
builtin_normal_expander(
|
||||||
ext::fmt::expand_syntax_ext));
|
ext::fmt::expand_syntax_ext));
|
||||||
@ -371,7 +386,7 @@ fn initial_syntax_expander_table() -> SyntaxEnv {
|
|||||||
builtin_normal_expander(
|
builtin_normal_expander(
|
||||||
ext::log_syntax::expand_syntax_ext));
|
ext::log_syntax::expand_syntax_ext));
|
||||||
syntax_expanders.insert(intern("deriving"),
|
syntax_expanders.insert(intern("deriving"),
|
||||||
ItemDecorator(ext::deriving::expand_meta_deriving));
|
ItemDecorator(box ext::deriving::expand_meta_deriving));
|
||||||
|
|
||||||
// Quasi-quoting expanders
|
// Quasi-quoting expanders
|
||||||
syntax_expanders.insert(intern("quote_tokens"),
|
syntax_expanders.insert(intern("quote_tokens"),
|
||||||
|
@ -251,7 +251,7 @@ fn expand_item(it: Gc<ast::Item>, fld: &mut MacroExpander)
|
|||||||
|
|
||||||
match fld.cx.syntax_env.find(&intern(mname.get())) {
|
match fld.cx.syntax_env.find(&intern(mname.get())) {
|
||||||
Some(rc) => match *rc {
|
Some(rc) => match *rc {
|
||||||
ItemDecorator(dec_fn) => {
|
ItemDecorator(ref dec) => {
|
||||||
attr::mark_used(attr);
|
attr::mark_used(attr);
|
||||||
|
|
||||||
fld.cx.bt_push(ExpnInfo {
|
fld.cx.bt_push(ExpnInfo {
|
||||||
@ -266,8 +266,7 @@ fn expand_item(it: Gc<ast::Item>, fld: &mut MacroExpander)
|
|||||||
// we'd ideally decorator_items.push_all(expand_item(item, fld)),
|
// we'd ideally decorator_items.push_all(expand_item(item, fld)),
|
||||||
// but that double-mut-borrows fld
|
// but that double-mut-borrows fld
|
||||||
let mut items: SmallVector<Gc<ast::Item>> = SmallVector::zero();
|
let mut items: SmallVector<Gc<ast::Item>> = SmallVector::zero();
|
||||||
dec_fn(fld.cx, attr.span, attr.node.value, it,
|
dec.expand(fld.cx, attr.span, attr.node.value, it, |item| items.push(item));
|
||||||
|item| items.push(item));
|
|
||||||
decorator_items.extend(items.move_iter()
|
decorator_items.extend(items.move_iter()
|
||||||
.flat_map(|item| expand_item(item, fld).move_iter()));
|
.flat_map(|item| expand_item(item, fld).move_iter()));
|
||||||
|
|
||||||
@ -328,7 +327,7 @@ fn expand_item_modifiers(mut it: Gc<ast::Item>, fld: &mut MacroExpander)
|
|||||||
|
|
||||||
match fld.cx.syntax_env.find(&intern(mname.get())) {
|
match fld.cx.syntax_env.find(&intern(mname.get())) {
|
||||||
Some(rc) => match *rc {
|
Some(rc) => match *rc {
|
||||||
ItemModifier(dec_fn) => {
|
ItemModifier(ref mac) => {
|
||||||
attr::mark_used(attr);
|
attr::mark_used(attr);
|
||||||
fld.cx.bt_push(ExpnInfo {
|
fld.cx.bt_push(ExpnInfo {
|
||||||
call_site: attr.span,
|
call_site: attr.span,
|
||||||
@ -338,7 +337,7 @@ fn expand_item_modifiers(mut it: Gc<ast::Item>, fld: &mut MacroExpander)
|
|||||||
span: None,
|
span: None,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
it = dec_fn(fld.cx, attr.span, attr.node.value, it);
|
it = mac.expand(fld.cx, attr.span, attr.node.value, it);
|
||||||
fld.cx.bt_pop();
|
fld.cx.bt_pop();
|
||||||
}
|
}
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
|
@ -36,7 +36,7 @@ pub fn plugin_registrar(reg: &mut Registry) {
|
|||||||
reg.register_macro("identity", expand_identity);
|
reg.register_macro("identity", expand_identity);
|
||||||
reg.register_syntax_extension(
|
reg.register_syntax_extension(
|
||||||
token::intern("into_foo"),
|
token::intern("into_foo"),
|
||||||
ItemModifier(expand_into_foo));
|
ItemModifier(box expand_into_foo));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expand_make_a_1(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
|
fn expand_make_a_1(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
|
||||||
|
Loading…
Reference in New Issue
Block a user