Merge branch 'syntax' of https://github.com/aochagavia/rust into mulit-decor

Conflicts:
	src/librustc/plugin/registry.rs
	src/libsyntax/ext/base.rs
	src/libsyntax/ext/cfg_attr.rs
	src/libsyntax/ext/deriving/mod.rs
	src/libsyntax/ext/expand.rs
	src/libsyntax/print/pprust.rs
	src/test/auxiliary/macro_crate_test.rs
This commit is contained in:
Nick Cameron
2015-04-25 14:04:46 +12:00
7 changed files with 239 additions and 14 deletions

View File

@@ -14,8 +14,13 @@ use lint::{LintPassObject, LintId, Lint};
use session::Session;
use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT};
<<<<<<< HEAD
use syntax::ext::base::{IdentTT, Decorator, Modifier, MultiModifier, MacroRulesTT};
use syntax::ext::base::MacroExpanderFn;
=======
use syntax::ext::base::{IdentTT, Decorator, MultiDecorator, Modifier, MultiModifier, MacroRulesTT};
use syntax::ext::base::{MacroExpanderFn};
>>>>>>> 143f2db3174103e459218958f567985b1f47944b
use syntax::codemap::Span;
use syntax::parse::token;
use syntax::ptr::P;
@@ -84,6 +89,7 @@ impl<'a> Registry<'a> {
/// Register a syntax extension of any kind.
///
/// This is the most general hook into `libsyntax`'s expansion behavior.
#[allow(deprecated)]
pub fn register_syntax_extension(&mut self, name: ast::Name, extension: SyntaxExtension) {
self.syntax_exts.push((name, match extension {
NormalTT(ext, _, allow_internal_unstable) => {
@@ -93,6 +99,7 @@ impl<'a> Registry<'a> {
IdentTT(ext, Some(self.krate_span), allow_internal_unstable)
}
Decorator(ext) => Decorator(ext),
MultiDecorator(ext) => MultiDecorator(ext),
Modifier(ext) => Modifier(ext),
MultiModifier(ext) => MultiModifier(ext),
MacroRulesTT => {

View File

@@ -30,6 +30,8 @@ use std::collections::HashMap;
use std::rc::Rc;
use std::default::Default;
#[unstable(feature = "rustc_private")]
#[deprecated(since = "1.0.0", reason = "replaced by MultiItemDecorator")]
pub trait ItemDecorator {
fn expand(&self,
ecx: &mut ExtCtxt,
@@ -39,6 +41,9 @@ pub trait ItemDecorator {
push: &mut FnMut(P<ast::Item>));
}
#[allow(deprecated)]
#[unstable(feature = "rustc_private")]
#[deprecated(since = "1.0.0", reason = "replaced by MultiItemDecorator")]
impl<F> ItemDecorator for F
where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, &ast::Item, &mut FnMut(P<ast::Item>))
{
@@ -52,6 +57,8 @@ impl<F> ItemDecorator for F
}
}
#[unstable(feature = "rustc_private")]
#[deprecated(since = "1.0.0", reason = "replaced by MultiItemModifier")]
pub trait ItemModifier {
fn expand(&self,
ecx: &mut ExtCtxt,
@@ -61,9 +68,13 @@ pub trait ItemModifier {
-> P<ast::Item>;
}
#[allow(deprecated)]
#[unstable(feature = "rustc_private")]
#[deprecated(since = "1.0.0", reason = "replaced by MultiItemModifier")]
impl<F> ItemModifier for F
where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, P<ast::Item>) -> P<ast::Item>
{
fn expand(&self,
ecx: &mut ExtCtxt,
span: Span,
@@ -127,6 +138,29 @@ impl Annotatable {
}
}
// A more flexible ItemDecorator.
pub trait MultiItemDecorator {
fn expand(&self,
ecx: &mut ExtCtxt,
sp: Span,
meta_item: &ast::MetaItem,
item: &Annotatable,
push: Box<FnMut(Annotatable)>);
}
impl<F> MultiItemDecorator for F
where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, &Annotatable, Box<FnMut(Annotatable)>)
{
fn expand(&self,
ecx: &mut ExtCtxt,
sp: Span,
meta_item: &ast::MetaItem,
item: &Annotatable,
push: Box<FnMut(Annotatable)>) {
(*self)(ecx, sp, meta_item, item, push)
}
}
// A more flexible ItemModifier (ItemModifier should go away, eventually, FIXME).
// meta_item is the annotation, item is the item being modified, parent_item
// is the impl or trait item is declared in if item is part of such a thing.
@@ -397,12 +431,20 @@ impl MacResult for DummyResult {
pub enum SyntaxExtension {
/// A syntax extension that is attached to an item and creates new items
/// based upon it.
///
/// `#[derive(...)]` is an `ItemDecorator`.
#[unstable(feature = "rustc_private")]
#[deprecated(since = "1.0.0", reason = "replaced by MultiDecorator")]
Decorator(Box<ItemDecorator + 'static>),
/// A syntax extension that is attached to an item and creates new items
/// based upon it.
///
/// `#[derive(...)]` is a `MultiItemDecorator`.
MultiDecorator(Box<MultiItemDecorator + 'static>),
/// A syntax extension that is attached to an item and modifies it
/// in-place.
#[unstable(feature = "rustc_private")]
#[deprecated(since = "1.0.0", reason = "replaced by MultiModifier")]
Modifier(Box<ItemModifier + 'static>),
/// A syntax extension that is attached to an item and modifies it
@@ -473,6 +515,13 @@ fn initial_syntax_expander_table<'feat>(ecfg: &expand::ExpansionConfig<'feat>)
syntax_expanders.insert(intern("log_syntax"),
builtin_normal_expander(
ext::log_syntax::expand_syntax_ext));
<<<<<<< HEAD
=======
syntax_expanders.insert(intern("derive"),
MultiDecorator(box ext::deriving::expand_meta_derive));
syntax_expanders.insert(intern("deriving"),
MultiDecorator(box ext::deriving::expand_deprecated_deriving));
>>>>>>> 143f2db3174103e459218958f567985b1f47944b
ext::deriving::register_all(&mut syntax_expanders);
@@ -537,6 +586,11 @@ fn initial_syntax_expander_table<'feat>(ecfg: &expand::ExpansionConfig<'feat>)
syntax_expanders.insert(intern("cfg"),
builtin_normal_expander(
ext::cfg::expand_cfg));
<<<<<<< HEAD
=======
syntax_expanders.insert(intern("cfg_attr"),
MultiModifier(box ext::cfg_attr::expand));
>>>>>>> 143f2db3174103e459218958f567985b1f47944b
syntax_expanders.insert(intern("trace_macros"),
builtin_normal_expander(
ext::trace_macros::expand_trace_macros));

View File

@@ -13,9 +13,9 @@
//! FIXME (#2810): hygiene. Search for "__" strings (in other files too). We also assume "extra" is
//! the standard library, and "std" is the core library.
use ast::{Item, MetaItem, MetaWord};
use ast::{Item, MetaItem, MetaWord, MetaList, MetaNameValue};
use attr::AttrMetaMethods;
use ext::base::{ExtCtxt, SyntaxEnv, Decorator, ItemDecorator, Modifier};
use ext::base::{ExtCtxt, SyntaxEnv, Decorator, ItemDecorator, Modifier, Annotatable};
use ext::build::AstBuilder;
use feature_gate;
use codemap::Span;
@@ -78,9 +78,19 @@ pub mod ord;
pub mod generic;
fn expand_derive(cx: &mut ExtCtxt,
_: Span,
span: Span,
mitem: &MetaItem,
item: P<Item>) -> P<Item> {
annotatable: &Annotatable)
-> P<Annotatable> {
// Derive can only be applied to items
let item = match annotatable {
&Annotatable::Item(ref it) => it.clone(),
_ => {
cx.span_err(span, "`derive` can only be applied to items");
return;
}
};
item.map(|mut item| {
if mitem.value_str().is_some() {
cx.span_err(mitem.span, "unexpected value in `derive`");
@@ -113,7 +123,7 @@ fn expand_derive(cx: &mut ExtCtxt,
intern_and_get_ident(&format!("derive_{}", tname)))));
}
item
Annotatable::Item(item)
})
}

View File

@@ -477,6 +477,7 @@ pub fn expand_item(it: P<ast::Item>, fld: &mut MacroExpander)
.into_iter().map(|i| i.expect_item()).collect()
}
#[allow(deprecated)] // This is needed because the `ItemModifier` trait is used
fn expand_item_modifiers(mut it: P<ast::Item>, fld: &mut MacroExpander)
-> P<ast::Item> {
// partition the attributes into ItemModifiers and others
@@ -1082,6 +1083,7 @@ impl<'a> Folder for PatIdentRenamer<'a> {
}
}
#[allow(deprecated)] // This is needed because the `Decorator` variant is used
fn expand_annotatable(a: Annotatable,
fld: &mut MacroExpander)
-> SmallVector<Annotatable> {
@@ -1120,9 +1122,31 @@ fn expand_annotatable(a: Annotatable,
let mut items: SmallVector<P<ast::Item>> = SmallVector::zero();
dec.expand(fld.cx, attr.span, &*attr.node.value, &**it,
&mut |item| items.push(item));
decorator_items.extend(
items.into_iter()
.flat_map(|item| expand_item(item, fld).into_iter()));
decorator_items.extend(items.into_iter()
.flat_map(|item| expand_item(item, fld).into_iter()
.map(|i| Annotatable::Item(i))));
fld.cx.bt_pop();
}
MultiDecorator(ref dec) => {
attr::mark_used(attr);
fld.cx.bt_push(ExpnInfo {
call_site: attr.span,
callee: NameAndSpan {
name: mname.get().to_string(),
format: MacroAttribute,
span: None
}
});
// we'd ideally decorator_items.push_all(expand_annotatable(ann, fld)),
// but that double-mut-borrows fld
let mut anns: SmallVector<Annotatable> = SmallVector::zero();
dec.expand(fld.cx, attr.span, &*attr.node.value, &a,
&mut |ann| anns.push(ann));
decorator_items.extend(anns.into_iter()
.flat_map(|ann| expand_annotatable(ann, fld).into_iter()));
fld.cx.bt_pop();
}
@@ -1184,7 +1208,7 @@ fn expand_annotatable(a: Annotatable,
}
};
new_items.push_all(decorator_items.into_iter().map(|i| Annotatable::Item(i)).collect());
new_items.push_all(decorator_items);
new_items
}

View File

@@ -814,7 +814,6 @@ impl<'a> State<'a> {
word(&mut self.s, ";")
}
/// Pretty-print an item
pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
try!(self.hardbreak_if_not_bol());

View File

@@ -19,8 +19,7 @@ extern crate rustc;
use syntax::ast::{self, TokenTree, Item, MetaItem};
use syntax::codemap::Span;
use syntax::ext::base::*;
use syntax::parse::token;
use syntax::parse;
use syntax::parse::{self, token};
use syntax::ptr::P;
use rustc::plugin::Registry;
@@ -42,6 +41,9 @@ pub fn plugin_registrar(reg: &mut Registry) {
token::intern("into_multi_foo"),
// FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
MultiModifier(Box::new(expand_into_foo_multi)));
reg.register_syntax_extension(
token::intern("duplicate"),
MultiDecorator(box expand_duplicate));
}
fn expand_make_a_1(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
@@ -104,6 +106,83 @@ fn expand_into_foo_multi(cx: &mut ExtCtxt,
}
}
// Create a duplicate of the annotatable, based on the MetaItem
fn expand_duplicate(cx: &mut ExtCtxt,
sp: Span,
mi: &MetaItem,
it: &Annotatable,
mut push: Box<FnMut(Annotatable)>)
{
let copy_name = match mi.node {
ast::MetaItem_::MetaList(_, ref xs) => {
if let ast::MetaItem_::MetaWord(ref w) = xs[0].node {
token::str_to_ident(w.get())
} else {
cx.span_err(mi.span, "Expected word");
return;
}
}
_ => {
cx.span_err(mi.span, "Expected list");
return;
}
};
// Duplicate the item but replace its ident by the MetaItem
match it.clone() {
Annotatable::Item(it) => {
let mut new_it = (*it).clone();
new_it.attrs.clear();
new_it.ident = copy_name;
push(Annotatable::Item(P(new_it)));
}
Annotatable::ImplItem(it) => {
match it {
ImplItem::MethodImplItem(m) => {
let mut new_m = (*m).clone();
new_m.attrs.clear();
replace_method_name(&mut new_m.node, copy_name);
push(Annotatable::ImplItem(ImplItem::MethodImplItem(P(new_m))));
}
ImplItem::TypeImplItem(t) => {
let mut new_t = (*t).clone();
new_t.attrs.clear();
new_t.ident = copy_name;
push(Annotatable::ImplItem(ImplItem::TypeImplItem(P(new_t))));
}
}
}
Annotatable::TraitItem(it) => {
match it {
TraitItem::RequiredMethod(rm) => {
let mut new_rm = rm.clone();
new_rm.attrs.clear();
new_rm.ident = copy_name;
push(Annotatable::TraitItem(TraitItem::RequiredMethod(new_rm)));
}
TraitItem::ProvidedMethod(pm) => {
let mut new_pm = (*pm).clone();
new_pm.attrs.clear();
replace_method_name(&mut new_pm.node, copy_name);
push(Annotatable::TraitItem(TraitItem::ProvidedMethod(P(new_pm))));
}
TraitItem::TypeTraitItem(t) => {
let mut new_t = (*t).clone();
new_t.attrs.clear();
new_t.ty_param.ident = copy_name;
push(Annotatable::TraitItem(TraitItem::TypeTraitItem(P(new_t))));
}
}
}
}
fn replace_method_name(m: &mut ast::Method_, i: ast::Ident) {
if let &mut ast::Method_::MethDecl(ref mut ident, _, _, _, _, _, _, _) = m {
*ident = i
}
}
}
fn expand_forged_ident(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box<MacResult+'static> {
use syntax::ext::quote::rt::*;

View File

@@ -0,0 +1,52 @@
// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// aux-build:macro_crate_test.rs
// ignore-stage1
#![feature(plugin)]
#[plugin] #[no_link]
extern crate macro_crate_test;
// The duplicate macro will create a copy of the item with the given identifier
#[duplicate(MyCopy)]
struct MyStruct {
number: i32
}
trait TestTrait {
#[duplicate(TestType2)]
type TestType;
#[duplicate(required_fn2)]
fn required_fn(&self);
#[duplicate(provided_fn2)]
fn provided_fn(&self) { }
}
impl TestTrait for MyStruct {
#[duplicate(TestType2)]
type TestType = f64;
#[duplicate(required_fn2)]
fn required_fn(&self) { }
}
fn main() {
let s = MyStruct { number: 42 };
s.required_fn();
s.required_fn2();
s.provided_fn();
s.provided_fn2();
let s = MyCopy { number: 42 };
}