pub use self::SyntaxExtension::{MultiDecorator, MultiModifier, NormalTT, IdentTT};
-use ast::{self, Attribute, Name, PatKind};
+use ast::{self, Attribute, Name, PatKind, MetaItem};
use attr::HasAttrs;
use codemap::{self, CodeMap, ExpnInfo, Spanned, respan};
use syntax_pos::{Span, ExpnId, NO_EXPANSION};
}
}
+pub type BuiltinDeriveFn =
+ for<'cx> fn(&'cx mut ExtCtxt, Span, &MetaItem, &Annotatable, &mut FnMut(Annotatable));
+
/// An enum representing the different kinds of syntax extensions.
pub enum SyntaxExtension {
/// A syntax extension that is attached to an item and creates new items
IdentTT(Box<IdentMacroExpander>, Option<Span>, bool),
CustomDerive(Box<MultiItemModifier>),
+
+ /// An attribute-like procedural macro that derives a builtin trait.
+ BuiltinDerive(BuiltinDeriveFn),
}
pub type NamedSyntaxExtension = (Name, SyntaxExtension);
let tok_result = mac.expand(self.cx, attr.span, attr_toks, item_toks);
self.parse_expansion(tok_result, kind, name, attr.span)
}
- SyntaxExtension::CustomDerive(_) => {
+ SyntaxExtension::CustomDerive(..) | SyntaxExtension::BuiltinDerive(..) => {
self.cx.span_err(attr.span, &format!("`{}` is a derive mode", name));
kind.dummy(attr.span)
}
return kind.dummy(span);
}
- SyntaxExtension::CustomDerive(..) => {
+ SyntaxExtension::CustomDerive(..) | SyntaxExtension::BuiltinDerive(..) => {
self.cx.span_err(path.span, &format!("`{}` is a derive mode", extname));
return kind.dummy(span);
}
mitem: &MetaItem,
item: &Annotatable,
push: &mut FnMut(Annotatable)) {
+ deriving::warn_if_deprecated(cx, span, "Decodable");
expand_deriving_decodable_imp(cx, span, mitem, item, push, "serialize")
}
mitem: &MetaItem,
item: &Annotatable,
push: &mut FnMut(Annotatable)) {
+ deriving::warn_if_deprecated(cx, span, "Encodable");
expand_deriving_encodable_imp(cx, span, mitem, item, push, "serialize")
}
//! The compiler code necessary to implement the `#[derive]` extensions.
+use std::rc::Rc;
use syntax::ast::{self, MetaItem};
use syntax::attr::HasAttrs;
use syntax::codemap;
-use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxExtension};
+use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxExtension, Resolver};
use syntax::ext::build::AstBuilder;
use syntax::feature_gate;
use syntax::ptr::P;
for titem in traits.iter() {
let tname = titem.word().unwrap().name();
let name = Symbol::intern(&format!("derive({})", tname));
+ let tname_cx = ast::Ident::with_empty_ctxt(titem.name().unwrap());
let mitem = cx.meta_word(titem.span, name);
+ let path = ast::Path::from_ident(titem.span, tname_cx);
+ let ext = cx.resolver.resolve_macro(cx.current_expansion.mark, &path, false).unwrap();
let span = Span {
expn_id: cx.codemap().record_expansion(codemap::ExpnInfo {
..titem.span
};
- let my_item = Annotatable::Item(item);
- expand_builtin(&tname.as_str(), cx, span, &mitem, &my_item, &mut |a| {
- items.push(a);
- });
- item = my_item.expect_item();
+ if let SyntaxExtension::BuiltinDerive(ref func) = *ext {
+ let my_item = Annotatable::Item(item);
+ func(cx, span, &mitem, &my_item, &mut |a| {
+ items.push(a)
+ });
+ item = my_item.expect_item();
+ } else {
+ unreachable!();
+ }
}
items.insert(0, Annotatable::Item(item));
}
}
- fn expand_builtin(name: &str,
- ecx: &mut ExtCtxt,
- span: Span,
- mitem: &MetaItem,
- item: &Annotatable,
- push: &mut FnMut(Annotatable)) {
- match name {
- $(
- $name => {
- warn_if_deprecated(ecx, span, $name);
- $func(ecx, span, mitem, item, push);
- }
- )*
- _ => panic!("not a builtin derive mode: {}", name),
- }
+ pub fn register_builtin_derives(resolver: &mut Resolver) {
+ $(
+ resolver.add_ext(
+ ast::Ident::with_empty_ctxt(Symbol::intern($name)),
+ Rc::new(SyntaxExtension::BuiltinDerive($func))
+ );
+ )*
}
}
}
pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver,
user_exts: Vec<NamedSyntaxExtension>,
enable_quotes: bool) {
+ deriving::register_builtin_derives(resolver);
+
let mut register = |name, ext| {
resolver.add_ext(ast::Ident::with_empty_ctxt(name), Rc::new(ext));
};