use proc_macro::TokenStream; use syn::{ItemFn, parse::Parse, Token, LitInt}; use quote::quote; struct NativeFuncParams { arity: LitInt, variadic: Option<Token![..]>, } impl Parse for NativeFuncParams { fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> { let arity = 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.is_some(); 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_lang::prelude::Function> { ::std::rc::Rc::new( ::matrix_lang::prelude::Function { name: ::std::rc::Rc::from( #name_str ), arity: #arity, variadic: #variadic, fun: ::matrix_lang::prelude::InnerFunction::Native( ::std::rc::Rc::new( |#inputs| #output #block ) ) }) } }; TokenStream::from(expanded) }