auto merge of #12234 : sfackler/rust/restructure-item-decorator, r=huonw
The old method of building up a list of items and threading it through all of the decorators was unwieldy and not really scalable as non-deriving ItemDecorators become possible. The API is now that the decorator gets an immutable reference to the item it's attached to, and a callback that it can pass new items to. If we want to add syntax extensions that can modify the item they're attached to, we can add that later, but I think it'll have to be separate from ItemDecorator to avoid strange ordering issues. @huonw
This commit is contained in:
commit
18477ac68a
@ -35,7 +35,7 @@ pub struct MacroDef {
|
||||
}
|
||||
|
||||
pub type ItemDecorator =
|
||||
fn(&mut ExtCtxt, Span, @ast::MetaItem, ~[@ast::Item]) -> ~[@ast::Item];
|
||||
fn(&mut ExtCtxt, Span, @ast::MetaItem, @ast::Item, |@ast::Item|);
|
||||
|
||||
pub struct BasicMacroExpander {
|
||||
expander: MacroExpanderFn,
|
||||
|
@ -17,8 +17,8 @@ use ext::deriving::generic::*;
|
||||
pub fn expand_deriving_clone(cx: &mut ExtCtxt,
|
||||
span: Span,
|
||||
mitem: @MetaItem,
|
||||
in_items: ~[@Item])
|
||||
-> ~[@Item] {
|
||||
item: @Item,
|
||||
push: |@Item|) {
|
||||
let trait_def = TraitDef {
|
||||
span: span,
|
||||
path: Path::new(~["std", "clone", "Clone"]),
|
||||
@ -38,14 +38,14 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt,
|
||||
]
|
||||
};
|
||||
|
||||
trait_def.expand(cx, mitem, in_items)
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
}
|
||||
|
||||
pub fn expand_deriving_deep_clone(cx: &mut ExtCtxt,
|
||||
span: Span,
|
||||
mitem: @MetaItem,
|
||||
in_items: ~[@Item])
|
||||
-> ~[@Item] {
|
||||
item: @Item,
|
||||
push: |@Item|) {
|
||||
let trait_def = TraitDef {
|
||||
span: span,
|
||||
path: Path::new(~["std", "clone", "DeepClone"]),
|
||||
@ -67,7 +67,7 @@ pub fn expand_deriving_deep_clone(cx: &mut ExtCtxt,
|
||||
]
|
||||
};
|
||||
|
||||
trait_def.expand(cx, mitem, in_items)
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
}
|
||||
|
||||
fn cs_clone(
|
||||
|
@ -17,7 +17,8 @@ use ext::deriving::generic::*;
|
||||
pub fn expand_deriving_eq(cx: &mut ExtCtxt,
|
||||
span: Span,
|
||||
mitem: @MetaItem,
|
||||
in_items: ~[@Item]) -> ~[@Item] {
|
||||
item: @Item,
|
||||
push: |@Item|) {
|
||||
// structures are equal if all fields are equal, and non equal, if
|
||||
// any fields are not equal or if the enum variants are different
|
||||
fn cs_eq(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> @Expr {
|
||||
@ -54,5 +55,5 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt,
|
||||
md!("ne", cs_ne)
|
||||
]
|
||||
};
|
||||
trait_def.expand(cx, mitem, in_items)
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
}
|
||||
|
@ -18,7 +18,8 @@ use ext::deriving::generic::*;
|
||||
pub fn expand_deriving_ord(cx: &mut ExtCtxt,
|
||||
span: Span,
|
||||
mitem: @MetaItem,
|
||||
in_items: ~[@Item]) -> ~[@Item] {
|
||||
item: @Item,
|
||||
push: |@Item|) {
|
||||
macro_rules! md (
|
||||
($name:expr, $op:expr, $equal:expr) => {
|
||||
MethodDef {
|
||||
@ -46,7 +47,7 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt,
|
||||
md!("ge", false, true)
|
||||
]
|
||||
};
|
||||
trait_def.expand(cx, mitem, in_items)
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
}
|
||||
|
||||
/// Strict inequality.
|
||||
|
@ -17,7 +17,8 @@ use ext::deriving::generic::*;
|
||||
pub fn expand_deriving_totaleq(cx: &mut ExtCtxt,
|
||||
span: Span,
|
||||
mitem: @MetaItem,
|
||||
in_items: ~[@Item]) -> ~[@Item] {
|
||||
item: @Item,
|
||||
push: |@Item|) {
|
||||
fn cs_equals(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> @Expr {
|
||||
cs_and(|cx, span, _, _| cx.expr_bool(span, false),
|
||||
cx, span, substr)
|
||||
@ -41,5 +42,5 @@ pub fn expand_deriving_totaleq(cx: &mut ExtCtxt,
|
||||
}
|
||||
]
|
||||
};
|
||||
trait_def.expand(cx, mitem, in_items)
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
}
|
||||
|
@ -19,7 +19,8 @@ use std::cmp::{Ordering, Equal, Less, Greater};
|
||||
pub fn expand_deriving_totalord(cx: &mut ExtCtxt,
|
||||
span: Span,
|
||||
mitem: @MetaItem,
|
||||
in_items: ~[@Item]) -> ~[@Item] {
|
||||
item: @Item,
|
||||
push: |@Item|) {
|
||||
let trait_def = TraitDef {
|
||||
span: span,
|
||||
path: Path::new(~["std", "cmp", "TotalOrd"]),
|
||||
@ -39,7 +40,7 @@ pub fn expand_deriving_totalord(cx: &mut ExtCtxt,
|
||||
]
|
||||
};
|
||||
|
||||
trait_def.expand(cx, mitem, in_items)
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
}
|
||||
|
||||
|
||||
|
@ -24,7 +24,8 @@ use parse::token;
|
||||
pub fn expand_deriving_decodable(cx: &mut ExtCtxt,
|
||||
span: Span,
|
||||
mitem: @MetaItem,
|
||||
in_items: ~[@Item]) -> ~[@Item] {
|
||||
item: @Item,
|
||||
push: |@Item|) {
|
||||
let trait_def = TraitDef {
|
||||
span: span,
|
||||
path: Path::new_(~["serialize", "Decodable"], None,
|
||||
@ -49,7 +50,7 @@ pub fn expand_deriving_decodable(cx: &mut ExtCtxt,
|
||||
]
|
||||
};
|
||||
|
||||
trait_def.expand(cx, mitem, in_items)
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
}
|
||||
|
||||
fn decodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
|
||||
|
@ -17,8 +17,8 @@ use ext::deriving::generic::*;
|
||||
pub fn expand_deriving_default(cx: &mut ExtCtxt,
|
||||
span: Span,
|
||||
mitem: @MetaItem,
|
||||
in_items: ~[@Item])
|
||||
-> ~[@Item] {
|
||||
item: @Item,
|
||||
push: |@Item|) {
|
||||
let trait_def = TraitDef {
|
||||
span: span,
|
||||
path: Path::new(~["std", "default", "Default"]),
|
||||
@ -37,7 +37,7 @@ pub fn expand_deriving_default(cx: &mut ExtCtxt,
|
||||
},
|
||||
]
|
||||
};
|
||||
trait_def.expand(cx, mitem, in_items)
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
}
|
||||
|
||||
fn default_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr {
|
||||
|
@ -85,7 +85,8 @@ use parse::token;
|
||||
pub fn expand_deriving_encodable(cx: &mut ExtCtxt,
|
||||
span: Span,
|
||||
mitem: @MetaItem,
|
||||
in_items: ~[@Item]) -> ~[@Item] {
|
||||
item: @Item,
|
||||
push: |@Item|) {
|
||||
let trait_def = TraitDef {
|
||||
span: span,
|
||||
path: Path::new_(~["serialize", "Encodable"], None,
|
||||
@ -110,7 +111,7 @@ pub fn expand_deriving_encodable(cx: &mut ExtCtxt,
|
||||
]
|
||||
};
|
||||
|
||||
trait_def.expand(cx, mitem, in_items)
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
}
|
||||
|
||||
fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
|
||||
|
@ -322,27 +322,23 @@ impl<'a> TraitDef<'a> {
|
||||
pub fn expand(&self,
|
||||
cx: &mut ExtCtxt,
|
||||
_mitem: @ast::MetaItem,
|
||||
in_items: ~[@ast::Item]) -> ~[@ast::Item] {
|
||||
let mut result = ~[];
|
||||
for item in in_items.iter() {
|
||||
result.push(*item);
|
||||
match item.node {
|
||||
ast::ItemStruct(struct_def, ref generics) => {
|
||||
result.push(self.expand_struct_def(cx,
|
||||
struct_def,
|
||||
item.ident,
|
||||
generics));
|
||||
}
|
||||
ast::ItemEnum(ref enum_def, ref generics) => {
|
||||
result.push(self.expand_enum_def(cx,
|
||||
enum_def,
|
||||
item.ident,
|
||||
generics));
|
||||
}
|
||||
_ => ()
|
||||
item: @ast::Item,
|
||||
push: |@ast::Item|) {
|
||||
match item.node {
|
||||
ast::ItemStruct(struct_def, ref generics) => {
|
||||
push(self.expand_struct_def(cx,
|
||||
struct_def,
|
||||
item.ident,
|
||||
generics));
|
||||
}
|
||||
ast::ItemEnum(ref enum_def, ref generics) => {
|
||||
push(self.expand_enum_def(cx,
|
||||
enum_def,
|
||||
item.ident,
|
||||
generics));
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -18,7 +18,8 @@ use ext::deriving::generic::*;
|
||||
pub fn expand_deriving_iter_bytes(cx: &mut ExtCtxt,
|
||||
span: Span,
|
||||
mitem: @MetaItem,
|
||||
in_items: ~[@Item]) -> ~[@Item] {
|
||||
item: @Item,
|
||||
push: |@Item|) {
|
||||
let trait_def = TraitDef {
|
||||
span: span,
|
||||
path: Path::new(~["std", "to_bytes", "IterBytes"]),
|
||||
@ -41,7 +42,7 @@ pub fn expand_deriving_iter_bytes(cx: &mut ExtCtxt,
|
||||
]
|
||||
};
|
||||
|
||||
trait_def.expand(cx, mitem, in_items)
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
}
|
||||
|
||||
fn iter_bytes_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr {
|
||||
|
@ -48,25 +48,24 @@ pub mod generic;
|
||||
pub fn expand_meta_deriving(cx: &mut ExtCtxt,
|
||||
_span: Span,
|
||||
mitem: @MetaItem,
|
||||
in_items: ~[@Item])
|
||||
-> ~[@Item] {
|
||||
item: @Item,
|
||||
push: |@Item|) {
|
||||
match mitem.node {
|
||||
MetaNameValue(_, ref l) => {
|
||||
cx.span_err(l.span, "unexpected value in `deriving`");
|
||||
in_items
|
||||
}
|
||||
MetaWord(_) | MetaList(_, []) => {
|
||||
cx.span_warn(mitem.span, "empty trait list in `deriving`");
|
||||
in_items
|
||||
}
|
||||
MetaList(_, ref titems) => {
|
||||
titems.rev_iter().fold(in_items, |in_items, &titem| {
|
||||
for &titem in titems.rev_iter() {
|
||||
match titem.node {
|
||||
MetaNameValue(ref tname, _) |
|
||||
MetaList(ref tname, _) |
|
||||
MetaWord(ref tname) => {
|
||||
macro_rules! expand(($func:path) => ($func(cx, titem.span,
|
||||
titem, in_items)));
|
||||
titem, item,
|
||||
|i| push(i))));
|
||||
match tname.get() {
|
||||
"Clone" => expand!(clone::expand_deriving_clone),
|
||||
"DeepClone" => expand!(clone::expand_deriving_deep_clone),
|
||||
@ -94,12 +93,11 @@ pub fn expand_meta_deriving(cx: &mut ExtCtxt,
|
||||
ref tname => {
|
||||
cx.span_err(titem.span, format!("unknown \
|
||||
`deriving` trait: `{}`", *tname));
|
||||
in_items
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,8 @@ use parse::token::InternedString;
|
||||
pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt,
|
||||
span: Span,
|
||||
mitem: @MetaItem,
|
||||
in_items: ~[@Item]) -> ~[@Item] {
|
||||
item: @Item,
|
||||
push: |@Item|) {
|
||||
let trait_def = TraitDef {
|
||||
span: span,
|
||||
path: Path::new(~["std", "num", "FromPrimitive"]),
|
||||
@ -61,7 +62,7 @@ pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt,
|
||||
]
|
||||
};
|
||||
|
||||
trait_def.expand(cx, mitem, in_items)
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
}
|
||||
|
||||
fn cs_from(name: &str, cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr {
|
||||
|
@ -19,8 +19,8 @@ use opt_vec;
|
||||
pub fn expand_deriving_rand(cx: &mut ExtCtxt,
|
||||
span: Span,
|
||||
mitem: @MetaItem,
|
||||
in_items: ~[@Item])
|
||||
-> ~[@Item] {
|
||||
item: @Item,
|
||||
push: |@Item|) {
|
||||
let trait_def = TraitDef {
|
||||
span: span,
|
||||
path: Path::new(~["std", "rand", "Rand"]),
|
||||
@ -46,7 +46,7 @@ pub fn expand_deriving_rand(cx: &mut ExtCtxt,
|
||||
}
|
||||
]
|
||||
};
|
||||
trait_def.expand(cx, mitem, in_items)
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
}
|
||||
|
||||
fn rand_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr {
|
||||
|
@ -23,8 +23,8 @@ use std::hashmap::HashMap;
|
||||
pub fn expand_deriving_show(cx: &mut ExtCtxt,
|
||||
span: Span,
|
||||
mitem: @MetaItem,
|
||||
in_items: ~[@Item])
|
||||
-> ~[@Item] {
|
||||
item: @Item,
|
||||
push: |@Item|) {
|
||||
// &mut ::std::fmt::Formatter
|
||||
let fmtr = Ptr(~Literal(Path::new(~["std", "fmt", "Formatter"])),
|
||||
Borrowed(None, ast::MutMutable));
|
||||
@ -47,7 +47,7 @@ pub fn expand_deriving_show(cx: &mut ExtCtxt,
|
||||
}
|
||||
]
|
||||
};
|
||||
trait_def.expand(cx, mitem, in_items)
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
}
|
||||
|
||||
// we construct a format string and then defer to std::fmt, since that
|
||||
|
@ -20,8 +20,8 @@ use parse::token;
|
||||
pub fn expand_deriving_to_str(cx: &mut ExtCtxt,
|
||||
span: Span,
|
||||
mitem: @MetaItem,
|
||||
in_items: ~[@Item])
|
||||
-> ~[@Item] {
|
||||
item: @Item,
|
||||
push: |@Item|) {
|
||||
let trait_def = TraitDef {
|
||||
span: span,
|
||||
path: Path::new(~["std", "to_str", "ToStr"]),
|
||||
@ -40,7 +40,7 @@ pub fn expand_deriving_to_str(cx: &mut ExtCtxt,
|
||||
}
|
||||
]
|
||||
};
|
||||
trait_def.expand(cx, mitem, in_items)
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
}
|
||||
|
||||
// It used to be the case that this deriving implementation invoked
|
||||
|
@ -17,8 +17,8 @@ use ext::deriving::generic::*;
|
||||
pub fn expand_deriving_zero(cx: &mut ExtCtxt,
|
||||
span: Span,
|
||||
mitem: @MetaItem,
|
||||
in_items: ~[@Item])
|
||||
-> ~[@Item] {
|
||||
item: @Item,
|
||||
push: |@Item|) {
|
||||
let trait_def = TraitDef {
|
||||
span: span,
|
||||
path: Path::new(~["std", "num", "Zero"]),
|
||||
@ -53,7 +53,7 @@ pub fn expand_deriving_zero(cx: &mut ExtCtxt,
|
||||
}
|
||||
]
|
||||
};
|
||||
trait_def.expand(cx, mitem, in_items)
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
}
|
||||
|
||||
fn zero_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr {
|
||||
|
@ -29,7 +29,6 @@ use visit::Visitor;
|
||||
use util::small_vector::SmallVector;
|
||||
|
||||
use std::cast;
|
||||
use std::vec;
|
||||
use std::unstable::dynamic_lib::DynamicLibrary;
|
||||
use std::os;
|
||||
|
||||
@ -220,8 +219,9 @@ pub fn expand_mod_items(module_: &ast::Mod, fld: &mut MacroExpander) -> ast::Mod
|
||||
// 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 new_items = vec::flat_map(module_.items, |item| {
|
||||
item.attrs.rev_iter().fold(~[*item], |items, attr| {
|
||||
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())) {
|
||||
@ -234,14 +234,14 @@ pub fn expand_mod_items(module_: &ast::Mod, fld: &mut MacroExpander) -> ast::Mod
|
||||
span: None
|
||||
}
|
||||
});
|
||||
let r = dec_fn(fld.cx, attr.span, attr.node.value, items);
|
||||
dec_fn(fld.cx, attr.span, attr.node.value, *item,
|
||||
|item| new_items.push(item));
|
||||
fld.cx.bt_pop();
|
||||
r
|
||||
},
|
||||
_ => items,
|
||||
_ => {},
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ast::Mod {
|
||||
items: new_items,
|
||||
|
Loading…
Reference in New Issue
Block a user