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:
bors 2014-09-13 05:25:57 +00:00
commit a9cf19889a
4 changed files with 57 additions and 48 deletions

View File

@ -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.

View File

@ -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"),

View File

@ -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!()

View File

@ -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])