use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, Data, DeriveInput, GenericParam};
pub fn into_shape_derive(input: TokenStream) -> TokenStream {
let ast = parse_macro_input!(input as DeriveInput);
let name = &ast.ident;
let name_str = name.to_string();
let generics = &ast.generics;
if generics.params.len() != 1 {
panic!("IntoShape requires exactly one generic type parameter");
}
let _type_param = match &generics.params[0] {
GenericParam::Type(ty) => &ty.ident,
_ => panic!("IntoShape requires the generic parameter to be a type parameter"),
};
let fields = match &ast.data {
Data::Struct(data_struct) => {
let field_impls = data_struct
.fields
.iter()
.filter_map(|field| {
let field_name = field.ident.as_ref()?;
let field_name_str = field_name.to_string();
Some(quote! {
(#field_name_str.to_string(), Box::new(self.#field_name.into()))
})
})
.collect::<Vec<_>>();
field_impls
}
_ => panic!("IntoShape can only be derived for structs"),
};
let expanded = quote! {
impl<F: slop_algebra::Field, EF: slop_algebra::ExtensionField<F>> Into<sp1_hypercube::ir::Shape<sp1_hypercube::ir::ExprRef<F>, sp1_hypercube::ir::ExprExtRef<EF>>>
for #name<sp1_hypercube::ir::ExprRef<F>>
{
fn into(self) -> sp1_hypercube::ir::Shape<sp1_hypercube::ir::ExprRef<F>, sp1_hypercube::ir::ExprExtRef<EF>> {
sp1_hypercube::ir::Shape::Struct(
#name_str.to_string(),
vec![
#(#fields,)*
],
)
}
}
};
TokenStream::from(expanded)
}