1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#![crate_type="dylib"]
#![cfg_attr(not(feature = "with-syntex"), feature(plugin, plugin_registrar, quote, rustc_private))]

extern crate syn;
//use syn::aster;
#[macro_use]
extern crate quote;

#[cfg(not(feature = "with-syntex"))]
extern crate syntax;
//extern crate rustc;
#[cfg(not(feature = "with-syntex"))]
extern crate rustc_plugin;

#[cfg(feature = "with-syntex")]
extern crate syntex;
#[cfg(feature = "with-syntex")]
extern crate syntex_syntax as syntax;
#[cfg(feature = "with-syntex")]
use std::path::Path;

//mod resource;
mod util;
mod tuple;
mod map;

#[cfg(feature = "with-syntex")]
pub fn expand<S, D>(src: S, dst: D) -> Result<(), syntex::Error>
    where S: AsRef<Path>, D: AsRef<Path>
{
    let mut reg = syntex::Registry::new();

    reg.add_decorator("derive_NifMap", map_transcoder_decorator_shim);
    reg.add_decorator("derive_NifTuple", tuple_transcoder_decorator_shim);

    //reg.add_decorator("NifResource", resource::resource_struct_def_decorator);
    //use syntax::ext::base::{TTMacroExpander, ExtCtxt, MacResult};
    //use syntax::tokenstream::TokenTree;;
    //use syntax::codemap::Span;

    //struct ResourceStructInitMacroHack {}
    //impl TTMacroExpander for ResourceStructInitMacroHack {
    //    fn expand<'cx>(&self,
    //                   ecx: &'cx mut ExtCtxt,
    //                   span: Span,
    //                   token_tree: &[TokenTree])
    //        -> Box<MacResult+'cx> {
    //            resource::resource_struct_init_macro(ecx, span, token_tree)
    //        }
    //}
    //reg.add_macro("resource_struct_init", ResourceStructInitMacroHack {});

    reg.expand("", src.as_ref(), dst.as_ref())
}

macro_rules! shim_syn_decorator {
    ($decorator_name:ident, $shim_name:ident, $wrapped:path) => {
        fn $shim_name(
            cx: &mut syntax::ext::base::ExtCtxt,
            span: syntax::codemap::Span,
            meta_item: &syntax::ast::MetaItem,
            annotatable: &syntax::ext::base::Annotatable,
            push: &mut FnMut(syntax::ext::base::Annotatable),
        ) {
            let item = match *annotatable {
                syntax::ext::base::Annotatable::Item(ref item) => item,
                _ => {
                    cx.span_err(
                        meta_item.span,
                        "decorated item must be either struct or enum"
                        );
                    return;
                },
            };

            let s = syntax::print::pprust::item_to_string(item);
            let syn_item = syn::parse_macro_input(&s).unwrap();

            let expanded = match $wrapped(&syn_item) {
                Ok(expanded) => expanded.to_string(),
                Err(msg) => {
                    cx.span_err(span, &msg);
                    return;
                }
            };

            use syntax::parse;
            let name = stringify!($decorator_name).to_string();
            let sess = parse::ParseSess::new();
            let impl_item = parse::parse_item_from_source_str(name, expanded, &sess);
            push(syntax::ext::base::Annotatable::Item(impl_item.unwrap().unwrap()));
        }
    };
}

shim_syn_decorator!(NifTuple, tuple_transcoder_decorator_shim, tuple::transcoder_decorator);
shim_syn_decorator!(NifMap, map_transcoder_decorator_shim, map::transcoder_decorator);

#[cfg(not(feature = "with-syntex"))]
#[plugin_registrar]
pub fn register(reg: &mut rustc_plugin::Registry) {
    reg.register_syntax_extension(
        syntax::parse::token::intern("derive_NifMap"),
        syntax::ext::base::MultiDecorator(Box::new(map_transcoder_decorator_shim)));
    reg.register_syntax_extension(
        syntax::parse::token::intern("derive_NifTuple"),
        syntax::ext::base::MultiDecorator(Box::new(tuple_transcoder_decorator_shim)));

    //reg.register_syntax_extension(
    //    builder.name("NifResource"),
    //    syntax::ext::base::MultiDecorator(Box::new(resource::resource_struct_def_decorator)));
    //reg.register_macro("resource_struct_init", resource::resource_struct_init_macro);
}