diff options
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ext/base.rs | 29 | ||||
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 47 |
2 files changed, 65 insertions, 11 deletions
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 459c0d1d0e3..ae8c13a5f98 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -38,6 +38,9 @@ pub struct MacroDef { pub type ItemDecorator = fn(&mut ExtCtxt, Span, @ast::MetaItem, @ast::Item, |@ast::Item|); +pub type ItemModifier = + fn(&mut ExtCtxt, Span, @ast::MetaItem, @ast::Item) -> @ast::Item; + pub struct BasicMacroExpander { expander: MacroExpanderFn, span: Option<Span> @@ -126,21 +129,27 @@ impl MacResult { } } +/// An enum representing the different kinds of syntax extensions. pub enum SyntaxExtension { - // #[deriving] and such + /// A syntax extension that is attached to an item and creates new items + /// based upon it. + /// + /// `#[deriving(...)]` is an `ItemDecorator`. ItemDecorator(ItemDecorator), - // Token-tree expanders - NormalTT(~MacroExpander:'static, Option<Span>), + /// A syntax extension that is attached to an item and modifies it + /// in-place. + ItemModifier(ItemModifier), - // An IdentTT is a macro that has an - // identifier in between the name of the - // macro and the argument. Currently, - // the only examples of this is - // macro_rules! + /// A normal, function-like syntax extension. + /// + /// `bytes!` is a `NormalTT`. + NormalTT(~MacroExpander:'static, Option<Span>), - // perhaps macro_rules! will lose its odd special identifier argument, - // and this can go away also + /// A function-like syntax extension that has an extra ident before + /// the block. + /// + /// `macro_rules!` is an `IdentTT`. IdentTT(~IdentMacroExpander:'static, Option<Span>), } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 30b04b7f377..dc79ceb4daa 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -260,7 +260,9 @@ macro_rules! with_exts_frame ( // When we enter a module, record it, for the sake of `module!` pub fn expand_item(it: @ast::Item, fld: &mut MacroExpander) -> SmallVector<@ast::Item> { - let mut decorator_items: SmallVector<@ast::Item> = SmallVector::zero(); + let it = expand_item_modifiers(it, fld); + + let mut decorator_items = SmallVector::zero(); for attr in it.attrs.rev_iter() { let mname = attr.name(); @@ -307,6 +309,48 @@ pub fn expand_item(it: @ast::Item, fld: &mut MacroExpander) new_items } +fn expand_item_modifiers(mut it: @ast::Item, fld: &mut MacroExpander) + -> @ast::Item { + let (modifiers, attrs) = it.attrs.partitioned(|attr| { + match fld.extsbox.find(&intern(attr.name().get())) { + Some(&ItemModifier(_)) => true, + _ => false + } + }); + + it = @ast::Item { + attrs: attrs, + ..(*it).clone() + }; + + if modifiers.is_empty() { + return it; + } + + for attr in modifiers.iter() { + let mname = attr.name(); + + match fld.extsbox.find(&intern(mname.get())) { + Some(&ItemModifier(dec_fn)) => { + fld.cx.bt_push(ExpnInfo { + call_site: attr.span, + callee: NameAndSpan { + name: mname.get().to_str(), + format: MacroAttribute, + span: None, + } + }); + it = dec_fn(fld.cx, attr.span, attr.node.value, it); + fld.cx.bt_pop(); + } + _ => unreachable!() + } + } + + // expansion may have added new ItemModifiers + expand_item_modifiers(it, fld) +} + // does this attribute list contain "macro_escape" ? pub fn contains_macro_escape(attrs: &[ast::Attribute]) -> bool { attr::contains_name(attrs, "macro_escape") @@ -492,6 +536,7 @@ fn load_extern_macros(krate: &ast::ViewItem, fld: &mut MacroExpander) { NormalTT(ext, _) => NormalTT(ext, Some(krate.span)), IdentTT(ext, _) => IdentTT(ext, Some(krate.span)), ItemDecorator(ext) => ItemDecorator(ext), + ItemModifier(ext) => ItemModifier(ext), }; fld.extsbox.insert(name, extension); }); |
