use proc_macro::TokenStream; use proc_macro2::Ident; use quote::{quote, ToTokens}; use syn::{Generics, Path, Attribute, GenericParam, parse_macro_input, DeriveInput, TypeParamBound}; mod enum_derive; #[allow(unused_imports)] use enum_derive::*; mod struct_derive; #[allow(unused_imports)] use struct_derive::*; #[allow(dead_code)] pub(crate) struct ReflectDef { //pub ident: Ident, pub type_path: Path, pub generics: Generics, pub attributes: Vec } impl syn::parse::Parse for ReflectDef { fn parse(input: syn::parse::ParseStream) -> syn::Result { let attributes = input.call(Attribute::parse_outer)?; let type_path = Path::parse_mod_style(input)?; //let ident = type_path. //type_path.require_ident()?; let mut generics = input.parse::()?; generics.where_clause = input.parse()?; Ok(Self { //ident: ident.clone(), type_path, generics, attributes, }) } } #[proc_macro_derive(Reflect)] pub fn derive_reflect(input: proc_macro::TokenStream) -> proc_macro::TokenStream { let input = parse_macro_input!(input as DeriveInput); let stream = match &input.data { syn::Data::Enum(e) => { enum_derive::derive_reflect_enum(&input, e) }, syn::Data::Struct(s) => { struct_derive::derive_reflect_struct(&input, s) }, //syn::Data::Union(_) => todo!(), _ => todo!() }; proc_macro::TokenStream::from(stream) } /// Implements `Reflect` for Values. `ReflectRef` and `ReflectMut` will be the `Value` /// variants, its used for simple types and primitives. #[proc_macro] pub fn impl_reflect_trait_value(input: TokenStream) -> TokenStream { let reflect = syn::parse_macro_input!(input as ReflectDef); let type_path = reflect.type_path; // convert the type path to a string. This would not create a leading separator let type_path_str = { let idents: Vec = type_path.segments.iter() .map(|segment| segment.ident.to_string()) .collect(); idents.join("::") }; let (impl_generics, ty_generics, where_clause) = reflect.generics.split_for_impl(); TokenStream::from(quote! { impl #impl_generics lyra_engine::reflect::Reflect for #type_path #ty_generics #where_clause { fn name(&self) -> ::std::string::String { #type_path_str.to_string() } fn type_id(&self) -> std::any::TypeId { std::any::TypeId::of::<#type_path #ty_generics>() } fn as_any(&self) -> &dyn std::any::Any { self } fn as_any_mut(&mut self) -> &mut dyn std::any::Any { self } fn apply(&mut self, val: &dyn lyra_engine::reflect::Reflect) { let val = val.as_any().downcast_ref::() .expect("The type of `val` is not the same as `self`"); *self = val.clone(); } fn clone_inner(&self) -> Box { Box::new(self.clone()) } fn reflect_ref(&self) -> lyra_engine::reflect::ReflectRef { lyra_engine::reflect::ReflectRef::Value(self) } fn reflect_mut(&mut self) -> lyra_engine::reflect::ReflectMut { lyra_engine::reflect::ReflectMut::Value(self) } fn reflect_val(&self) -> &dyn lyra_engine::reflect::Reflect { self } fn reflect_val_mut(&mut self) -> &mut dyn lyra_engine::reflect::Reflect { self } } }) } pub(crate) fn add_trait_bounds(mut generics: Generics, add_bounds: Vec) -> Generics { for param in &mut generics.params { if let GenericParam::Type(ref mut type_param) = *param { for bound in add_bounds.iter() { type_param.bounds.push(bound.clone()); } } } generics }