mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-03-31 01:11:06 +00:00
94 lines
2.5 KiB
Rust
94 lines
2.5 KiB
Rust
|
#![feature(proc_macro)]
|
||
|
|
||
|
extern crate syn;
|
||
|
#[macro_use]
|
||
|
extern crate quote;
|
||
|
extern crate proc_macro;
|
||
|
extern crate proc_macro2;
|
||
|
extern crate serde_json;
|
||
|
extern crate wasm_bindgen_shared;
|
||
|
|
||
|
use proc_macro::TokenStream;
|
||
|
use proc_macro2::Literal;
|
||
|
use quote::{Tokens, ToTokens};
|
||
|
|
||
|
mod ast;
|
||
|
|
||
|
#[proc_macro]
|
||
|
pub fn wasm_bindgen(input: TokenStream) -> TokenStream {
|
||
|
let file = syn::parse::<syn::File>(input)
|
||
|
.expect("expected a set of valid Rust items");
|
||
|
|
||
|
|
||
|
let mut ret = Tokens::new();
|
||
|
|
||
|
for item in file.items.iter() {
|
||
|
item.to_tokens(&mut ret);
|
||
|
match *item {
|
||
|
syn::Item::Fn(ref f) => bindgen_fn(f, &mut ret),
|
||
|
_ => panic!("unexpected item in bindgen macro"),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ret.into()
|
||
|
}
|
||
|
|
||
|
fn bindgen_fn(input: &syn::ItemFn, into: &mut Tokens) {
|
||
|
let function = ast::Function::from(input);
|
||
|
|
||
|
let export_name = function.export_name();
|
||
|
let generated_name = function.rust_symbol();
|
||
|
let mut args = vec![];
|
||
|
let arg_conversions = vec![quote!{}];
|
||
|
let real_name = &input.ident;
|
||
|
let mut converted_arguments = vec![];
|
||
|
let ret = syn::Ident::from("_ret");
|
||
|
|
||
|
for (i, ty) in function.arguments.iter().enumerate() {
|
||
|
let ident = syn::Ident::from(format!("arg{}", i));
|
||
|
match *ty {
|
||
|
ast::Type::Integer(i) => {
|
||
|
args.push(quote! { #ident: #i });
|
||
|
converted_arguments.push(quote! { #ident });
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
let ret_ty;
|
||
|
let convert_ret;
|
||
|
match function.ret {
|
||
|
Some(ast::Type::Integer(i)) => {
|
||
|
ret_ty = quote! { -> #i };
|
||
|
convert_ret = quote! { #ret };
|
||
|
}
|
||
|
None => {
|
||
|
ret_ty = quote! {};
|
||
|
convert_ret = quote! {};
|
||
|
}
|
||
|
}
|
||
|
|
||
|
let generated_static_name = function.generated_static_name();
|
||
|
let generated_static = function.generate_static();
|
||
|
let generated_static_value = syn::Lit {
|
||
|
value: syn::LitKind::Other(Literal::byte_string(&generated_static)),
|
||
|
span: Default::default(),
|
||
|
};
|
||
|
let generated_static_length = generated_static.len();
|
||
|
|
||
|
|
||
|
let tokens = quote! {
|
||
|
#[no_mangle]
|
||
|
#[allow(non_upper_case_globals)]
|
||
|
pub static #generated_static_name: [u8; #generated_static_length] =
|
||
|
*#generated_static_value;
|
||
|
|
||
|
#[no_mangle]
|
||
|
#[export_name = #export_name]
|
||
|
pub extern fn #generated_name(#(#args),*) #ret_ty {
|
||
|
#(#arg_conversions);*
|
||
|
let #ret = #real_name(#(#converted_arguments),*);
|
||
|
#convert_ret
|
||
|
}
|
||
|
};
|
||
|
tokens.to_tokens(into);
|
||
|
}
|