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
#![feature(box_patterns)]
extern crate syn;
#[macro_use]
extern crate quote;
mod args;
mod func;
mod obj;
mod ret;
use lazy_static::lazy_static;
use proc_macro::{TokenStream, TokenTree};
use std::collections::HashSet;
use std::sync::Mutex;
use syn::{Block, Ident, ItemFn, ReturnType};
const EXTERN_LOVM2_INITIALIZER: &str = "lovm2_module_initialize";
use self::args::*;
use self::func::*;
use self::obj::*;
use self::ret::*;
type GenResult<T> = Result<T, String>;
lazy_static! {
static ref FUNCS: Mutex<HashSet<String>> = Mutex::new(HashSet::new());
}
#[proc_macro]
pub fn lovm2_module_init(_args: TokenStream) -> TokenStream {
let initfn = Ident::new(EXTERN_LOVM2_INITIALIZER, proc_macro2::Span::call_site());
let funcs = FUNCS.lock().unwrap();
let names = funcs.iter();
let result = quote! {
#[doc(hidden)]
#[no_mangle]
pub extern fn #initfn(lib: Rc<Library>, slots: &mut HashMap<Variable, CallableRef>) {
#(
let slot = SharedObjectSlot::new(lib.clone(), #names).expect("name not found");
slots.insert(
Variable::from(#names),
Rc::new(slot)
);
)*
}
};
result.into()
}
#[proc_macro_attribute]
pub fn lovm2_function(attrs: TokenStream, item: TokenStream) -> TokenStream {
use crate::quote::ToTokens;
let is_extern = match attrs.into_iter().next() {
Some(TokenTree::Ident(ident)) => ident.to_string() == "extern",
_ => false,
};
let item_fn = syn::parse::<syn::ItemFn>(item).unwrap();
let mut function = Function::from(item_fn).unwrap();
if is_extern {
function.set_extern(true);
FUNCS.lock().unwrap().insert(function.name.to_string());
}
function.generate_rust_function().into_token_stream().into()
}
#[proc_macro_attribute]
pub fn lovm2_object(_attr: TokenStream, item: TokenStream) -> TokenStream {
use crate::quote::ToTokens;
let obj = Object::from(item);
obj.generate_rust_structure().into_token_stream().into()
}