mirror of
https://github.com/fluencelabs/marine-rs-sdk-test
synced 2025-03-15 04:30:50 +00:00
Merge pull request #5 from fluencelabs/record_support
Record refactoring
This commit is contained in:
commit
0f8638c594
@ -25,7 +25,7 @@ pub struct AstFunctionSignature {
|
||||
#[serde(skip)]
|
||||
pub visibility: Option<syn::Visibility>,
|
||||
pub name: String,
|
||||
pub input_types: Vec<ParsedType>,
|
||||
pub arguments: Vec<(String, ParsedType)>,
|
||||
// fce supports only one return value now,
|
||||
// waiting for adding multi-value support in Wasmer.
|
||||
pub output_type: Option<ParsedType>,
|
||||
|
@ -44,4 +44,4 @@ pub use parsed_type::ParsedType;
|
||||
pub use token_stream_generator::GENERATED_WRAPPER_FUNC_PREFIX;
|
||||
pub use token_stream_generator::GENERATED_SECTION_PREFIX;
|
||||
pub use token_stream_generator::GENERATED_GLOBAL_PREFIX;
|
||||
pub use wasm_type::WasmType;
|
||||
pub use wasm_type::RustType;
|
||||
|
@ -36,22 +36,44 @@ pub(super) fn try_to_ast_signature(
|
||||
visibility: syn::Visibility,
|
||||
) -> Result<fce_ast_types::AstFunctionSignature> {
|
||||
use crate::parsed_type::ParsedType;
|
||||
use syn::spanned::Spanned;
|
||||
use quote::ToTokens;
|
||||
|
||||
check_function(&signature)?;
|
||||
|
||||
let syn::Signature { inputs, output, .. } = signature;
|
||||
|
||||
let input_types = inputs
|
||||
let arguments = inputs
|
||||
.iter()
|
||||
.map(ParsedType::from_fn_arg)
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
.map(|arg| -> Result<(String, ParsedType)> {
|
||||
let pat = match arg {
|
||||
syn::FnArg::Typed(arg) => arg,
|
||||
_ => {
|
||||
return Err(syn::Error::new(
|
||||
arg.span(),
|
||||
"`self` argument types aren't supported",
|
||||
))
|
||||
}
|
||||
};
|
||||
Ok((
|
||||
pat.pat
|
||||
.to_token_stream()
|
||||
.to_string()
|
||||
.split(' ')
|
||||
.last()
|
||||
.unwrap_or_default()
|
||||
.to_string(),
|
||||
ParsedType::from_type(pat.ty.as_ref())?,
|
||||
))
|
||||
})
|
||||
.collect::<Result<Vec<(_, _)>>>()?;
|
||||
|
||||
let output_type = ParsedType::from_return_type(&output)?;
|
||||
|
||||
let ast_function_item = fce_ast_types::AstFunctionSignature {
|
||||
visibility: Some(visibility),
|
||||
name: signature.ident.to_string(),
|
||||
input_types,
|
||||
arguments,
|
||||
output_type,
|
||||
};
|
||||
|
||||
|
@ -37,7 +37,14 @@ impl ParseMacroInput for syn::ItemStruct {
|
||||
.iter()
|
||||
.map(|field| {
|
||||
check_field(field)?;
|
||||
let field_name = field.ident.as_ref().map(|ident| ident.to_string());
|
||||
let field_name = field.ident.as_ref().map(|ident| {
|
||||
ident
|
||||
.to_string()
|
||||
.split(' ')
|
||||
.last()
|
||||
.unwrap_or_default()
|
||||
.to_string()
|
||||
});
|
||||
let field_type = ParsedType::from_type(&field.ty)?;
|
||||
Ok(AstRecordField {
|
||||
name: field_name,
|
||||
|
@ -48,7 +48,7 @@ pub enum ParsedType {
|
||||
Boolean,
|
||||
Utf8String,
|
||||
ByteVector,
|
||||
Record(String), // full type name
|
||||
Record(String), // short type name
|
||||
}
|
||||
|
||||
impl ParsedType {
|
||||
@ -114,7 +114,7 @@ impl ParsedType {
|
||||
syn::Type::Path(path) => Ok(&path.path),
|
||||
_ => Err(Error::new(
|
||||
input_type.span(),
|
||||
"Incorrect argument type - only Vec<u8> and String are supported",
|
||||
"Incorrect argument type - passing only by value is supported now",
|
||||
)),
|
||||
}?;
|
||||
|
||||
@ -152,14 +152,19 @@ impl ParsedType {
|
||||
type_segment.span(),
|
||||
"type with lifetimes or generics aren't allowed".to_string(),
|
||||
)),
|
||||
_ => Ok(ParsedType::Record(path.into_token_stream().to_string())),
|
||||
_ => Ok(ParsedType::Record(
|
||||
(&type_segment.ident).into_token_stream().to_string(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_fn_arg(fn_arg: &syn::FnArg) -> syn::Result<Self> {
|
||||
match fn_arg {
|
||||
syn::FnArg::Typed(arg) => ParsedType::from_type(&arg.ty),
|
||||
_ => Err(Error::new(fn_arg.span(), "Unknown argument")),
|
||||
_ => Err(Error::new(
|
||||
fn_arg.span(),
|
||||
"`self` argument types aren't supported",
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,28 +15,29 @@
|
||||
*/
|
||||
|
||||
use super::ParsedType;
|
||||
use crate::wasm_type::WasmType;
|
||||
use crate::wasm_type::RustType;
|
||||
|
||||
/// This trait could be used to generate raw args needed to construct a export function.
|
||||
pub(crate) trait FnArgGlueCodeGenerator {
|
||||
fn generate_arguments(&self) -> Vec<WasmType>;
|
||||
fn generate_arguments(&self) -> Vec<RustType>;
|
||||
}
|
||||
|
||||
impl FnArgGlueCodeGenerator for ParsedType {
|
||||
fn generate_arguments(&self) -> Vec<WasmType> {
|
||||
match self {
|
||||
ParsedType::Boolean
|
||||
| ParsedType::I8
|
||||
| ParsedType::I16
|
||||
| ParsedType::I32
|
||||
| ParsedType::U8
|
||||
| ParsedType::U16
|
||||
| ParsedType::U32
|
||||
| ParsedType::Record(_) => vec![WasmType::I32],
|
||||
ParsedType::I64 | ParsedType::U64 => vec![WasmType::I64],
|
||||
ParsedType::F32 => vec![WasmType::F32],
|
||||
ParsedType::F64 => vec![WasmType::F64],
|
||||
ParsedType::Utf8String | ParsedType::ByteVector => vec![WasmType::I32, WasmType::I32],
|
||||
impl FnArgGlueCodeGenerator for (String, ParsedType) {
|
||||
fn generate_arguments(&self) -> Vec<RustType> {
|
||||
match self.1 {
|
||||
ParsedType::Boolean => vec![RustType::I32],
|
||||
ParsedType::I8 => vec![RustType::I8],
|
||||
ParsedType::I16 => vec![RustType::I16],
|
||||
ParsedType::I32 => vec![RustType::I32],
|
||||
ParsedType::I64 => vec![RustType::I64],
|
||||
ParsedType::U8 => vec![RustType::U8],
|
||||
ParsedType::U16 => vec![RustType::U16],
|
||||
ParsedType::U32 => vec![RustType::U32],
|
||||
ParsedType::U64 => vec![RustType::U64],
|
||||
ParsedType::Record(_) => vec![RustType::U32],
|
||||
ParsedType::F32 => vec![RustType::F32],
|
||||
ParsedType::F64 => vec![RustType::F64],
|
||||
ParsedType::Utf8String | ParsedType::ByteVector => vec![RustType::U32, RustType::U32],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -53,19 +53,17 @@ impl FnEpilogGlueCodeGenerator for Option<ParsedType> {
|
||||
|
||||
fn generate_fn_return_type(ty: &Option<ParsedType>) -> proc_macro2::TokenStream {
|
||||
let ty = match ty {
|
||||
Some(ParsedType::Boolean)
|
||||
| Some(ParsedType::I8)
|
||||
| Some(ParsedType::I16)
|
||||
| Some(ParsedType::I32)
|
||||
| Some(ParsedType::U8)
|
||||
| Some(ParsedType::U16)
|
||||
| Some(ParsedType::U32) => Some("i32"),
|
||||
|
||||
Some(ParsedType::I64) | Some(ParsedType::U64) => Some("i64"),
|
||||
|
||||
Some(ParsedType::Boolean) => Some("i32"),
|
||||
Some(ParsedType::I8) => Some("i8"),
|
||||
Some(ParsedType::I16) => Some("i16"),
|
||||
Some(ParsedType::I32) => Some("i32"),
|
||||
Some(ParsedType::I64) => Some("i64"),
|
||||
Some(ParsedType::U8) => Some("u8"),
|
||||
Some(ParsedType::U16) => Some("u16"),
|
||||
Some(ParsedType::U32) => Some("u32"),
|
||||
Some(ParsedType::U64) => Some("u64"),
|
||||
Some(ParsedType::F32) => Some("f32"),
|
||||
Some(ParsedType::F64) => Some("f64"),
|
||||
|
||||
None
|
||||
| Some(ParsedType::Utf8String)
|
||||
| Some(ParsedType::ByteVector)
|
||||
|
@ -17,14 +17,14 @@
|
||||
use super::ParsedType;
|
||||
use super::FnArgGlueCodeGenerator;
|
||||
use crate::new_ident;
|
||||
use crate::wasm_type::WasmType;
|
||||
use crate::wasm_type::RustType;
|
||||
|
||||
use quote::quote;
|
||||
|
||||
/// Describes various parts of a function prolog.
|
||||
pub(crate) struct FnPrologDescriptor {
|
||||
pub(crate) raw_arg_names: Vec<syn::Ident>,
|
||||
pub(crate) raw_arg_types: Vec<WasmType>,
|
||||
pub(crate) raw_arg_types: Vec<RustType>,
|
||||
pub(crate) prolog: proc_macro2::TokenStream,
|
||||
pub(crate) args: Vec<syn::Ident>,
|
||||
}
|
||||
@ -44,7 +44,7 @@ pub(crate) trait FnPrologGlueCodeGenerator {
|
||||
fn generate_prolog(&self) -> FnPrologDescriptor;
|
||||
}
|
||||
|
||||
impl FnPrologGlueCodeGenerator for Vec<ParsedType> {
|
||||
impl FnPrologGlueCodeGenerator for Vec<(String, ParsedType)> {
|
||||
fn generate_prolog(&self) -> FnPrologDescriptor {
|
||||
let mut prolog = proc_macro2::TokenStream::new();
|
||||
let mut args: Vec<syn::Ident> = Vec::with_capacity(self.len());
|
||||
@ -52,9 +52,9 @@ impl FnPrologGlueCodeGenerator for Vec<ParsedType> {
|
||||
let mut raw_arg_types = Vec::with_capacity(self.len());
|
||||
|
||||
let mut input_type_id = 0;
|
||||
for input_type in self {
|
||||
let type_prolog = generate_type_prolog(input_type, input_type_id, input_type_id);
|
||||
let curr_raw_arg_types = input_type.generate_arguments();
|
||||
for arg in self {
|
||||
let type_prolog = generate_type_prolog(&arg.1, input_type_id, input_type_id);
|
||||
let curr_raw_arg_types = arg.generate_arguments();
|
||||
|
||||
args.push(new_ident!(format!("converted_arg_{}", input_type_id)));
|
||||
|
||||
@ -87,6 +87,12 @@ fn generate_type_prolog(
|
||||
let generated_arg_id = new_ident!(format!("converted_arg_{}", generated_arg_id));
|
||||
|
||||
match ty {
|
||||
ParsedType::Boolean => {
|
||||
let supplied_arg_start_id = new_ident!(format!("arg_{}", supplied_arg_start_id));
|
||||
quote! {
|
||||
let #generated_arg_id = #supplied_arg_start_id != 0;
|
||||
}
|
||||
}
|
||||
ty if !ty.is_complex_type() => {
|
||||
let supplied_arg_start_id = new_ident!(format!("arg_{}", supplied_arg_start_id));
|
||||
quote! {
|
||||
|
@ -36,7 +36,8 @@ impl ForeignModArgGlueCodeGenerator for ParsedType {
|
||||
#arg.__fce_generated_serialize() as _
|
||||
}
|
||||
}
|
||||
_ => quote! { arg },
|
||||
ParsedType::Boolean => quote! { #arg as _ },
|
||||
_ => quote! { #arg },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -41,6 +41,9 @@ impl ForeignModEpilogGlueCodeGenerator for Option<ParsedType> {
|
||||
fn generate_wrapper_epilog(&self) -> proc_macro2::TokenStream {
|
||||
match self {
|
||||
None => quote!(),
|
||||
Some(ParsedType::Boolean) => quote! {
|
||||
return result != 0;
|
||||
},
|
||||
Some(ty) if !ty.is_complex_type() => quote! {
|
||||
return result as _;
|
||||
},
|
||||
|
@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
use super::ParsedType;
|
||||
use crate::wasm_type::WasmType;
|
||||
use crate::wasm_type::RustType;
|
||||
use crate::new_ident;
|
||||
|
||||
pub(crate) struct WrapperDescriptor {
|
||||
@ -28,7 +28,7 @@ pub(crate) struct WrapperDescriptor {
|
||||
|
||||
pub(crate) struct ExternDescriptor {
|
||||
pub(crate) raw_arg_names: Vec<syn::Ident>,
|
||||
pub(crate) raw_arg_types: Vec<WasmType>,
|
||||
pub(crate) raw_arg_types: Vec<RustType>,
|
||||
}
|
||||
|
||||
/// This trait could be used to generate various parts needed to construct prolog of an wrapper
|
||||
@ -57,25 +57,28 @@ pub(crate) trait ForeignModPrologGlueCodeGenerator {
|
||||
fn generate_extern_prolog(&self) -> ExternDescriptor;
|
||||
}
|
||||
|
||||
impl ForeignModPrologGlueCodeGenerator for Vec<ParsedType> {
|
||||
impl ForeignModPrologGlueCodeGenerator for Vec<(String, ParsedType)> {
|
||||
fn generate_wrapper_prolog(&self) -> WrapperDescriptor {
|
||||
use crate::parsed_type::foreign_mod_arg::ForeignModArgGlueCodeGenerator;
|
||||
|
||||
let arg_types: Vec<proc_macro2::TokenStream> = self
|
||||
.iter()
|
||||
.map(|input_type| input_type.to_token_stream())
|
||||
.map(|(_, input_type)| input_type.to_token_stream())
|
||||
.collect();
|
||||
|
||||
let (arg_names, arg_transforms, arg_drops) = self
|
||||
.iter()
|
||||
.enumerate()
|
||||
.fold((Vec::new(), proc_macro2::TokenStream::new(), proc_macro2::TokenStream::new()), |(mut arg_names, mut arg_transforms, mut arg_drops), (id, ty)| {
|
||||
.fold((Vec::new(), proc_macro2::TokenStream::new(), proc_macro2::TokenStream::new()), |(mut arg_names, mut arg_transforms, mut arg_drops), (id, (_, ty))| {
|
||||
let arg_ident = new_ident!(format!("arg_{}", id));
|
||||
arg_names.push(arg_ident.clone());
|
||||
|
||||
if ty.is_complex_type() {
|
||||
arg_transforms.extend(quote::quote! { let mut #arg_ident = std::mem::ManuallyDrop::new(#arg_ident); });
|
||||
arg_drops.extend(quote::quote! { std::mem::ManuallyDrop::drop(&mut #arg_ident); });
|
||||
match ty {
|
||||
ParsedType::ByteVector | ParsedType::Utf8String => {
|
||||
arg_transforms.extend(quote::quote! { let mut #arg_ident = std::mem::ManuallyDrop::new(#arg_ident); });
|
||||
arg_drops.extend(quote::quote! { std::mem::ManuallyDrop::drop(&mut #arg_ident); });
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
|
||||
(arg_names, arg_transforms, arg_drops)
|
||||
@ -84,7 +87,7 @@ impl ForeignModPrologGlueCodeGenerator for Vec<ParsedType> {
|
||||
let raw_args: Vec<proc_macro2::TokenStream> = self
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(id, input_type)| input_type.generate_raw_args(id))
|
||||
.map(|(id, (_, input_type))| input_type.generate_raw_args(id))
|
||||
.collect();
|
||||
|
||||
WrapperDescriptor {
|
||||
@ -99,7 +102,7 @@ impl ForeignModPrologGlueCodeGenerator for Vec<ParsedType> {
|
||||
fn generate_extern_prolog(&self) -> ExternDescriptor {
|
||||
use crate::parsed_type::FnArgGlueCodeGenerator;
|
||||
|
||||
let raw_arg_types: Vec<WasmType> = self
|
||||
let raw_arg_types: Vec<RustType> = self
|
||||
.iter()
|
||||
.map(|input_type| input_type.generate_arguments())
|
||||
.flatten()
|
||||
|
@ -49,7 +49,7 @@ impl quote::ToTokens for fce_ast_types::AstFunctionItem {
|
||||
raw_arg_types,
|
||||
prolog,
|
||||
args,
|
||||
} = &signature.input_types.generate_prolog();
|
||||
} = &signature.arguments.generate_prolog();
|
||||
|
||||
let FnEpilogDescriptor {
|
||||
fn_return_type,
|
||||
|
@ -74,7 +74,7 @@ fn generate_extern_section_items(extern_item: &fce_ast_types::AstExternModItem)
|
||||
let ExternDescriptor {
|
||||
raw_arg_names,
|
||||
raw_arg_types,
|
||||
} = signature.input_types.generate_extern_prolog();
|
||||
} = signature.arguments.generate_extern_prolog();
|
||||
|
||||
let func = quote! {
|
||||
#[link_name = #link_name]
|
||||
@ -110,7 +110,7 @@ fn generate_wrapper_functions(extern_item: &fce_ast_types::AstExternModItem) ->
|
||||
raw_args,
|
||||
arg_transforms,
|
||||
arg_drops,
|
||||
} = signature.input_types.generate_wrapper_prolog();
|
||||
} = signature.arguments.generate_wrapper_prolog();
|
||||
|
||||
let FnEpilogDescriptor {
|
||||
return_expression, ..
|
||||
|
@ -1,21 +1,33 @@
|
||||
use proc_macro2::TokenStream;
|
||||
|
||||
/// Raw Wasm types according to the spec except i128.
|
||||
pub enum WasmType {
|
||||
pub enum RustType {
|
||||
U8,
|
||||
U16,
|
||||
U32,
|
||||
U64,
|
||||
I8,
|
||||
I16,
|
||||
I32,
|
||||
I64,
|
||||
F32,
|
||||
F64,
|
||||
}
|
||||
|
||||
impl quote::ToTokens for WasmType {
|
||||
impl quote::ToTokens for RustType {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let call_site = proc_macro2::Span::call_site();
|
||||
match self {
|
||||
WasmType::I32 => syn::Ident::new("i32", call_site).to_tokens(tokens),
|
||||
WasmType::I64 => syn::Ident::new("i64", call_site).to_tokens(tokens),
|
||||
WasmType::F32 => syn::Ident::new("f32", call_site).to_tokens(tokens),
|
||||
WasmType::F64 => syn::Ident::new("f64", call_site).to_tokens(tokens),
|
||||
RustType::U8 => syn::Ident::new("u8", call_site).to_tokens(tokens),
|
||||
RustType::U16 => syn::Ident::new("u16", call_site).to_tokens(tokens),
|
||||
RustType::U32 => syn::Ident::new("u32", call_site).to_tokens(tokens),
|
||||
RustType::U64 => syn::Ident::new("u64", call_site).to_tokens(tokens),
|
||||
RustType::I8 => syn::Ident::new("i8", call_site).to_tokens(tokens),
|
||||
RustType::I16 => syn::Ident::new("i16", call_site).to_tokens(tokens),
|
||||
RustType::I32 => syn::Ident::new("i32", call_site).to_tokens(tokens),
|
||||
RustType::I64 => syn::Ident::new("i64", call_site).to_tokens(tokens),
|
||||
RustType::F32 => syn::Ident::new("f32", call_site).to_tokens(tokens),
|
||||
RustType::F64 => syn::Ident::new("f64", call_site).to_tokens(tokens),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user