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 { let arity = input.parse()?; input.parse::()?; 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) }