Skip to content

Instantly share code, notes, and snippets.

@azyobuzin

azyobuzin/Cargo.toml

Created Jan 25, 2015
Embed
What would you like to do?
Modifier, MultiModifier
[package]
name = "modifier"
version = "0.0.1"
[lib]
name = "modifier_ext"
path = "lib.rs"
plugin = true
crate-type = ["dylib"]
[[bin]]
name = "modifier"
path = "main.rs"
#![allow(unstable)]
#![feature(box_syntax, plugin_registrar)]
extern crate fmt_macros;
extern crate rustc;
extern crate syntax;
use std::ascii::AsciiExt;
use rustc::plugin::Registry;
use syntax::ast;
use syntax::codemap::{DUMMY_SP, Span};
use syntax::ext::base;
use syntax::parse::token;
use syntax::ptr::P;
#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
reg.register_syntax_extension(
token::intern("upper_enum"),
base::Modifier(box expand_upper_enum)
);
reg.register_syntax_extension(
token::intern("instance_method"),
base::MultiModifier(box expand_instance_method)
);
}
fn expand_upper_enum(cx: &mut base::ExtCtxt, sp: Span,
_: &ast::MetaItem, item: P<ast::Item>) -> P<ast::Item>
{
let (variants, generics) = match item.node {
ast::ItemEnum(ref def, ref generics) =>
(def.variants.clone(), generics.clone()),
_ => {
cx.span_err(sp, "#[upper_enum] can be applied only for enum");
return item.clone();
}
};
let mut ret = (*item).clone();
ret.node = ast::ItemEnum(
ast::EnumDef {
variants: variants.into_iter().map(|ref s| {
let mut v = s.node.clone();
v.name = cx.ident_of(&v.name.as_str().to_ascii_uppercase()[]);
P(ast::Variant { node: v, span: s.span })
}).collect()
},
generics
);
P(ret)
}
fn expand_instance_method(cx: &mut base::ExtCtxt, sp: Span,
_: &ast::MetaItem, item: base::Annotatable) -> base::Annotatable
{
let mut method = match item {
base::Annotatable::ImplItem(ast::MethodImplItem(ref p)) => (**p).clone(),
_ => {
cx.span_err(sp, "#[instance_method] can be applied only for methods in impl");
return item.clone();
}
};
let (a, b, c, _, e, f, g, h) = match method.node {
ast::MethDecl(a, b, c, d, e, f, g, h) => (a, b, c, d, e, f, g, h),
_ => return item.clone()
};
let mut fndecl = (*f).clone();
let mut inputs = Vec::with_capacity(fndecl.inputs.len() + 1);
let self_ident = cx.ident_of("self");
inputs.push(ast::Arg::new_self(DUMMY_SP, ast::MutImmutable, self_ident));
inputs.extend(fndecl.inputs.into_iter());
let explicit_self = ast::ExplicitSelf {
node: ast::SelfValue(self_ident),
span: DUMMY_SP
};
fndecl.inputs = inputs;
method.node = ast::MethDecl(a, b, c, explicit_self, e, P(fndecl), g, h);
base::Annotatable::ImplItem(ast::MethodImplItem(P(method)))
}
#![feature(plugin)]
#[plugin]
#[no_link]
extern crate modifier_ext;
#[derive(Show)] //derive は Decorator の一種
#[upper_enum]
enum Nemui {
Meccha, SorehodoDemonai
}
impl Nemui {
#[instance_method]
fn print() {
println!("{:?}", self);
}
}
fn main() {
Nemui::MECCHA.print();
Nemui::SOREHODODEMONAI.print();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.