Skip to content

Commit

Permalink
feat(move-bindgen): more sane codegen
Browse files Browse the repository at this point in the history
still doesn't support generics properly
  • Loading branch information
benluelo committed Sep 23, 2024
1 parent ea561fd commit 42907d7
Show file tree
Hide file tree
Showing 3 changed files with 767 additions and 442 deletions.
116 changes: 85 additions & 31 deletions lib/move-bindgen-derive/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use std::convert;

use quote::quote;
use quote::{format_ident, quote};
use syn::{
parse_macro_input, parse_quote, parse_quote_spanned, spanned::Spanned, Data, DeriveInput, Expr,
Field, MetaNameValue, WhereClause, WherePredicate,
};

#[proc_macro_derive(TypeTagged, attributes(type_tag))]
#[proc_macro_derive(MoveOutputType, attributes(move_output_type))]
pub fn type_tagged(ts: proc_macro::TokenStream) -> proc_macro::TokenStream {
derive_type_tagged(parse_macro_input!(ts as DeriveInput))
// .inspect(|x| println!("{x}"))
Expand Down Expand Up @@ -38,7 +38,7 @@ fn derive_type_tagged(

let [module] = attrs
.into_iter()
.filter(|attr| attr.path().is_ident("type_tag"))
.filter(|attr| attr.path().is_ident("move_output_type"))
.map(|attr| {
let mnv =
syn::parse2::<MetaNameValue>(attr.meta.require_list().unwrap().tokens.clone())
Expand All @@ -54,23 +54,72 @@ fn derive_type_tagged(
.try_into()
.unwrap();

let ident_str = ident.to_string();
let module_str = module.to_string();

let body = match data {
Data::Struct(_) => {
quote! {
::move_bindgen::move_core_types::language_storage::TypeTag::Struct(
::std::boxed::Box::new(
::move_bindgen::move_core_types::language_storage::StructTag {
address: ctx,
module: ::move_bindgen::move_core_types::ident_str!(#module_str).into(),
name: ::move_bindgen::move_core_types::ident_str!(#ident_str).into(),
type_args: vec![],
}
)
)
}
let (raw_ident, raw, from_raw, into_raw) = match data {
Data::Struct(data) => {
let raw_ident = format_ident!("Raw{ident}");

let from_raw = {
let fields = data.fields.iter().map(|field| {
let name = field
.ident
.as_ref()
.expect("tuple structs are not supported by move");
let ty = &field.ty;
quote! {
#name: <#ty as ::move_bindgen::MoveOutputType>::from_raw(raw.#name)
}
});

quote! {
#ident {
#(#fields,)*
}
}
};

let into_raw = {
let fields = data.fields.iter().map(|field| {
let name = field
.ident
.as_ref()
.expect("tuple structs are not supported by move");
let ty = &field.ty;
quote! {
#name: <#ty as ::move_bindgen::MoveOutputType>::into_raw(self.#name)
}
});

quote! {
#raw_ident {
#(#fields,)*
}
}
};

let fields = data.fields.iter().map(|field| {
let name = field
.ident
.as_ref()
.expect("tuple structs are not supported by move");
let ty = &field.ty;
quote! {
pub #name: <#ty as ::move_bindgen::MoveOutputType>::Raw
}
});

let raw = quote! {
#[derive(
Debug,
::move_bindgen::serde::Serialize,
::move_bindgen::serde::Deserialize,
)]
#[serde(crate = "::move_bindgen::serde")]
pub struct #raw_ident {
#(#fields,)*
}
};

(raw_ident, raw, from_raw, into_raw)
}
_ => panic!(),
};
Expand All @@ -85,27 +134,32 @@ fn derive_type_tagged(
Ok(quote! {
const _: () = {
#[automatically_derived]
impl #impl_generics ::move_bindgen::TypeTagged for #ident #ty_generics #where_clause {
// type Ctx = (#(#ctxs,)* ::move_bindgen::move_core_types::account_address::AccountAddress);
type Ctx = ::move_bindgen::move_core_types::account_address::AccountAddress;
impl #impl_generics ::move_bindgen::MoveOutputType for #ident #ty_generics #where_clause {
type Raw = #raw_ident;

fn type_tag(ctx: Self::Ctx) -> ::move_bindgen::move_core_types::language_storage::TypeTag {
#body
fn from_raw(raw: Self::Raw) -> Self {
#from_raw
}
}

#[automatically_derived]
impl #impl_generics #ident #ty_generics #original_where_clause {
pub fn with_address(self, address: ::move_bindgen::move_core_types::account_address::AccountAddress) -> (Self, ::move_bindgen::move_core_types::account_address::AccountAddress) {
(self, address)
fn into_raw(self) -> Self::Raw {
#into_raw
}
}

// #[automatically_derived]
// impl #impl_generics #ident #ty_generics #original_where_clause {
// pub fn with_address(self, address: ::move_bindgen::move_core_types::account_address::AccountAddress) -> (Self, ::move_bindgen::move_core_types::account_address::AccountAddress) {
// (self, address)
// }
// }
};

#raw
})
}

fn mk_where_clause(data: &Data) -> Vec<WherePredicate> {
let f = |Field { ty, .. }: &Field| parse_quote_spanned!(ty.span()=> #ty: ::move_bindgen::TypeTagged);
let f = |Field { ty, .. }: &Field| parse_quote_spanned!(ty.span()=> #ty: ::move_bindgen::MoveOutputType);

match data {
Data::Struct(s) => s.fields.iter().map(f).collect(),
Expand Down
Loading

0 comments on commit 42907d7

Please sign in to comment.