diff options
Diffstat (limited to 'matrix-macros/src')
-rw-r--r-- | matrix-macros/src/lib.rs | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/matrix-macros/src/lib.rs b/matrix-macros/src/lib.rs new file mode 100644 index 0000000..8099fd6 --- /dev/null +++ b/matrix-macros/src/lib.rs @@ -0,0 +1,52 @@ +use proc_macro::TokenStream; +use syn::{ItemFn, parse::Parse, Token, LitBool, LitInt}; +use quote::quote; + +struct NativeFuncParams { + arity: LitInt, + variadic: LitBool, +} + +impl Parse for NativeFuncParams { + fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> { + let arity = input.parse()?; + input.parse::<Token![,]>()?; + let variadic = input.parse()?; + Ok(Self { arity , variadic }) + } +} + +#[proc_macro_attribute] +pub fn native_func(input: TokenStream, annotated_item: TokenStream) -> TokenStream { + let itemfn: ItemFn = syn::parse(annotated_item).unwrap(); + + let input: NativeFuncParams = syn::parse(input).unwrap(); + let arity = input.arity; + let variadic = input.variadic; + + let visibility = itemfn.vis; + let block = itemfn.block; + let name = itemfn.sig.ident; + let name_str = name.to_string(); + let inputs = itemfn.sig.inputs; + let output = itemfn.sig.output; + + assert!(itemfn.sig.constness.is_none(), "item must not be const"); + assert!(itemfn.sig.asyncness.is_none(), "item must not be async"); + assert!(itemfn.sig.unsafety.is_none(), "item must not be unsafe"); + assert!(itemfn.sig.abi.is_none(), "item must not contain an ABI specifier"); + assert!(itemfn.sig.variadic.is_none(), "item must not be variadic"); + + let expanded = quote! { + #visibility fn #name() -> ::std::rc::Rc< ::matrix::chunk::Function> { + ::std::rc::Rc::new( ::matrix::chunk::Function { + name: ::std::rc::Rc::from( #name_str ), + arity: #arity, + variadic: #variadic, + fun: ::matrix::chunk::InnerFunction::Native(Box::new(|#inputs| #output #block)) + }) + } + }; + + TokenStream::from(expanded) +} |