diff options
| author | Steven Fackler <sfackler@gmail.com> | 2014-02-13 22:57:43 -0800 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2014-02-14 07:48:00 -0800 |
| commit | 07ea23e15dab673a3016d21b601234b296e59e57 (patch) | |
| tree | 20d962e6a3b84c9149b9ff9c026aaa2d13421f3f /src/libsyntax | |
| parent | c1fac653962d28425134a4f1ec89d1ebea647cf3 (diff) | |
| download | rust-07ea23e15dab673a3016d21b601234b296e59e57.tar.gz rust-07ea23e15dab673a3016d21b601234b296e59e57.zip | |
Expand ItemDecorator extensions in all contexts
Now that fold_item can return multiple items, this is pretty trivial. It also recursively expands generated items so ItemDecorators can generate items that are tagged with ItemDecorators! Closes #4913
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 85 | ||||
| -rw-r--r-- | src/libsyntax/util/small_vector.rs | 8 |
2 files changed, 40 insertions, 53 deletions
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index e59afc6ffa6..97766e1a14b 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -203,52 +203,6 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr { } } -// This is a secondary mechanism for invoking syntax extensions on items: -// "decorator" attributes, such as #[auto_encode]. These are invoked by an -// attribute prefixing an item, and are interpreted by feeding the item -// through the named attribute _as a syntax extension_ and splicing in the -// resulting item vec into place in favour of the decorator. Note that -// these do _not_ work for macro extensions, just ItemDecorator ones. -// -// NB: there is some redundancy between this and expand_item, below, and -// they might benefit from some amount of semantic and language-UI merger. -pub fn expand_mod_items(module_: &ast::Mod, fld: &mut MacroExpander) -> ast::Mod { - // Fold the contents first: - let module_ = noop_fold_mod(module_, fld); - - // For each item, look through the attributes. If any of them are - // decorated with "item decorators", then use that function to transform - // the item into a new set of items. - let mut new_items = module_.items.clone(); - for item in module_.items.iter() { - for attr in item.attrs.rev_iter() { - let mname = attr.name(); - - match fld.extsbox.find(&intern(mname.get())) { - Some(&ItemDecorator(dec_fn)) => { - fld.cx.bt_push(ExpnInfo { - call_site: attr.span, - callee: NameAndSpan { - name: mname.get().to_str(), - format: MacroAttribute, - span: None - } - }); - dec_fn(fld.cx, attr.span, attr.node.value, *item, - |item| new_items.push(item)); - fld.cx.bt_pop(); - }, - _ => {}, - } - } - } - - ast::Mod { - items: new_items, - ..module_ - } -} - // eval $e with a new exts frame: macro_rules! with_exts_frame ( ($extsboxexpr:expr,$macros_escape:expr,$e:expr) => @@ -263,7 +217,35 @@ 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> { - match it.node { + let mut decorator_items = SmallVector::zero(); + for attr in it.attrs.rev_iter() { + let mname = attr.name(); + + match fld.extsbox.find(&intern(mname.get())) { + Some(&ItemDecorator(dec_fn)) => { + fld.cx.bt_push(ExpnInfo { + call_site: attr.span, + callee: NameAndSpan { + name: mname.get().to_str(), + format: MacroAttribute, + span: None + } + }); + // we'd ideally decorator_items.push_all(expand_item(item, fld)), + // but that double-mut-borrows fld + dec_fn(fld.cx, attr.span, attr.node.value, it, + |item| decorator_items.push(item)); + fld.cx.bt_pop(); + } + _ => {} + } + } + + let decorator_items = decorator_items.move_iter() + .flat_map(|item| expand_item(item, fld).move_iter()) + .collect(); + + let mut new_items = match it.node { ast::ItemMac(..) => expand_item_mac(it, fld), ast::ItemMod(_) | ast::ItemForeignMod(_) => { fld.cx.mod_push(it.ident); @@ -275,7 +257,10 @@ pub fn expand_item(it: @ast::Item, fld: &mut MacroExpander) result }, _ => noop_fold_item(it, fld) - } + }; + + new_items.push_all(decorator_items); + new_items } // does this attribute list contain "macro_escape" ? @@ -778,10 +763,6 @@ impl<'a> Folder for MacroExpander<'a> { expand_expr(expr, self) } - fn fold_mod(&mut self, module: &ast::Mod) -> ast::Mod { - expand_mod_items(module, self) - } - fn fold_item(&mut self, item: @ast::Item) -> SmallVector<@ast::Item> { expand_item(item, self) } diff --git a/src/libsyntax/util/small_vector.rs b/src/libsyntax/util/small_vector.rs index e0d7fdd8790..32e5b83ee04 100644 --- a/src/libsyntax/util/small_vector.rs +++ b/src/libsyntax/util/small_vector.rs @@ -1,4 +1,4 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -64,6 +64,12 @@ impl<T> SmallVector<T> { } } + pub fn push_all(&mut self, other: SmallVector<T>) { + for v in other.move_iter() { + self.push(v); + } + } + pub fn get<'a>(&'a self, idx: uint) -> &'a T { match *self { One(ref v) if idx == 0 => v, |
