Skip to content

Instantly share code, notes, and snippets.

@azyobuzin
Created January 25, 2015 08:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save azyobuzin/ecdae200c7469e1bb16c to your computer and use it in GitHub Desktop.
Save azyobuzin/ecdae200c7469e1bb16c to your computer and use it in GitHub Desktop.
Decorator
[package]
name = "decorator"
version = "0.0.1"
[lib]
name = "decorator_ext"
path = "lib.rs"
plugin = true
crate-type = ["dylib"]
[[bin]]
name = "decorator"
path = "main.rs"
#![allow(unstable)]
#![feature(box_syntax, plugin_registrar, quote)]
extern crate fmt_macros;
extern crate rustc;
extern crate syntax;
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("string"),
base::Decorator(box expand_string)
);
}
fn expand_string(cx: &mut base::ExtCtxt, _: Span, meta_item: &ast::MetaItem,
item: &ast::Item, mut push: Box<FnMut(P<ast::Item>)>)
{
let target = item.ident;
let format = match meta_item.node {
ast::MetaNameValue(_, ast::Lit {node: ast::LitStr(ref x, _), ..}) => x,
_ => return
};
let format = format.get();
let p = fmt_macros::Parser::new(format);
let needed_members = p
.filter_map(|x| match x {
fmt_macros::Piece::NextArgument(fmt_macros::Argument {
position: fmt_macros::Position::ArgumentNamed(name), ..
}) => {
let id = cx.ident_of(name);
Some(quote_tokens!(cx, $id = self.$id))
},
_ => None
})
.collect::<Vec<_>>()
.connect(&ast::TtToken(DUMMY_SP, token::Comma));
push(quote_item!(cx,
impl ::std::fmt::String for $target {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
write!(f, $format, $needed_members)
}
}
).unwrap());
}
#![feature(plugin)]
#[plugin]
#[no_link]
extern crate decorator_ext;
#[string="{name}: Lv {level}"]
struct Pokemon {
name: String,
level: u8
}
fn main() {
println!("{}", Pokemon {
name: "ムクホーク".to_string(),
level: 100
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment