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
use proc_macro::{TokenStream}; use quote::{quote, ToTokens}; use syn::{parse_macro_input, DeriveInput}; #[proc_macro_derive(Escher)] pub fn derive_escher(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as DeriveInput); let name = input.ident; let generics = input.generics; let mut impl_params: Vec<Box<dyn ToTokens>> = vec![Box::new(quote! { 'a })]; let mut type_params: Vec<Box<dyn ToTokens>> = vec![]; let mut out_params: Vec<Box<dyn ToTokens>> = vec![]; for _ in generics.lifetimes() { type_params.push(Box::new(quote! { '_ })); out_params.push(Box::new(quote! { 'a })); } for ident in generics.type_params().map(|p| &p.ident) { impl_params.push(Box::new(quote! { #ident: 'a })); type_params.push(Box::new(ident.clone())); out_params.push(Box::new(ident.clone())); } for param in generics.const_params() { let ident = ¶m.ident; let ty = ¶m.ty; impl_params.push(Box::new(quote! { const #ident: #ty })); type_params.push(Box::new(ident.clone())); out_params.push(Box::new(ident.clone())); } TokenStream::from(quote! { unsafe impl<#(#impl_params),*> escher::Bind<'a> for #name<#(#type_params),*> { type Out = #name<#(#out_params),*>; } }) }