mirror of
https://github.com/fluencelabs/marine-rs-sdk-test
synced 2024-12-04 15:20:18 +00:00
little refactoring
This commit is contained in:
parent
ea11a617cd
commit
12685c59fc
@ -33,7 +33,7 @@ use proc_macro_error::proc_macro_error;
|
||||
use syn::spanned::Spanned;
|
||||
|
||||
/// This macro allows user to write tests for services in the following form:
|
||||
///```ignore
|
||||
///```rust
|
||||
/// #[fce_test(config = "/path/to/Config.toml", modules_dir = "path/to/service/modules")]
|
||||
/// fn test() {
|
||||
/// let service_result = greeting.greeting("John".to_string());
|
||||
|
@ -19,13 +19,19 @@ use crate::parsed_type::ParsedType;
|
||||
use serde::Serialize;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub struct AstFuncArgument {
|
||||
pub name: String,
|
||||
pub ty: ParsedType,
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub struct AstFunctionSignature {
|
||||
// Option is needed only for skipping serialization/deserialization of syn::ItemFn
|
||||
#[serde(skip)]
|
||||
pub visibility: Option<syn::Visibility>,
|
||||
pub name: String,
|
||||
pub arguments: Vec<(String, ParsedType)>,
|
||||
pub arguments: Vec<AstFuncArgument>,
|
||||
// fce supports only one return value now,
|
||||
// waiting for adding multi-value support in Wasmer.
|
||||
pub output_type: Option<ParsedType>,
|
||||
|
@ -16,7 +16,10 @@
|
||||
|
||||
use super::ParseMacroInput;
|
||||
use crate::fce_ast_types;
|
||||
use crate::fce_ast_types::{FCEAst, AstFunctionItem};
|
||||
use crate::fce_ast_types::FCEAst;
|
||||
use crate::fce_ast_types::AstFunctionItem;
|
||||
use crate::fce_ast_types::AstFuncArgument;
|
||||
use crate::syn_error;
|
||||
|
||||
use syn::Result;
|
||||
|
||||
@ -45,7 +48,7 @@ pub(super) fn try_to_ast_signature(
|
||||
|
||||
let arguments = inputs
|
||||
.iter()
|
||||
.map(|arg| -> Result<(String, ParsedType)> {
|
||||
.map(|arg| -> Result<_> {
|
||||
let pat = match arg {
|
||||
syn::FnArg::Typed(arg) => arg,
|
||||
_ => {
|
||||
@ -55,18 +58,21 @@ pub(super) fn try_to_ast_signature(
|
||||
))
|
||||
}
|
||||
};
|
||||
Ok((
|
||||
pat.pat
|
||||
.to_token_stream()
|
||||
.to_string()
|
||||
.split(' ')
|
||||
.last()
|
||||
.unwrap_or_default()
|
||||
.to_string(),
|
||||
ParsedType::from_type(pat.ty.as_ref())?,
|
||||
))
|
||||
|
||||
let name = pat
|
||||
.pat
|
||||
.to_token_stream()
|
||||
.to_string()
|
||||
.split(' ')
|
||||
.last()
|
||||
.unwrap_or_default()
|
||||
.to_string();
|
||||
let ty = ParsedType::from_type(pat.ty.as_ref())?;
|
||||
let ast_arg = AstFuncArgument { name, ty };
|
||||
|
||||
Ok(ast_arg)
|
||||
})
|
||||
.collect::<Result<Vec<(_, _)>>>()?;
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
|
||||
let output_type = ParsedType::from_return_type(&output)?;
|
||||
|
||||
@ -81,8 +87,8 @@ pub(super) fn try_to_ast_signature(
|
||||
}
|
||||
|
||||
/// Check whether the #[fce] macro could be applied to a function.
|
||||
#[rustfmt::skip]
|
||||
fn check_function(signature: &syn::Signature) -> Result<()> {
|
||||
use syn::Error;
|
||||
use syn::spanned::Spanned;
|
||||
|
||||
let syn::Signature {
|
||||
@ -95,34 +101,19 @@ fn check_function(signature: &syn::Signature) -> Result<()> {
|
||||
} = signature;
|
||||
|
||||
if let Some(constness) = constness {
|
||||
return Err(Error::new(
|
||||
constness.span,
|
||||
"FCE export function shouldn't be constant",
|
||||
));
|
||||
return syn_error!(constness.span, "FCE export function shouldn't be constant");
|
||||
}
|
||||
if let Some(unsafety) = unsafety {
|
||||
return Err(Error::new(
|
||||
unsafety.span,
|
||||
"FCE export function shouldn't be unsafe",
|
||||
));
|
||||
return syn_error!(unsafety.span, "FCE export function shouldn't be unsafe");
|
||||
}
|
||||
if let Some(abi) = abi {
|
||||
return Err(Error::new(
|
||||
abi.extern_token.span,
|
||||
"FCE export function shouldn't have any custom linkage",
|
||||
));
|
||||
return syn_error!(abi.extern_token.span, "FCE export function shouldn't have any custom linkage");
|
||||
}
|
||||
if generics.where_clause.is_some() {
|
||||
return Err(Error::new(
|
||||
signature.span(),
|
||||
"FCE export function shouldn't use template parameters",
|
||||
));
|
||||
return syn_error!(signature.span(), "FCE export function shouldn't use template parameters");
|
||||
}
|
||||
if variadic.is_some() {
|
||||
return Err(Error::new(
|
||||
variadic.span(),
|
||||
"FCE export function shouldn't use variadic interface",
|
||||
));
|
||||
return syn_error!(variadic.span(), "FCE export function shouldn't use variadic interface");
|
||||
}
|
||||
|
||||
// TODO: check for a lifetime
|
||||
|
@ -17,8 +17,8 @@
|
||||
use super::ParseMacroInput;
|
||||
use crate::fce_ast_types;
|
||||
use crate::fce_ast_types::FCEAst;
|
||||
use crate::syn_error;
|
||||
|
||||
use syn::Error;
|
||||
use syn::Result;
|
||||
use syn::spanned::Spanned;
|
||||
|
||||
@ -30,7 +30,7 @@ impl ParseMacroInput for syn::ItemForeignMod {
|
||||
fn parse_macro_input(self) -> Result<FCEAst> {
|
||||
match &self.abi.name {
|
||||
Some(name) if name.value() != "C" => {
|
||||
return Err(Error::new(self.span(), "only 'C' abi is allowed"))
|
||||
return syn_error!(self.span(), "only 'C' abi is allowed")
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
@ -69,10 +69,10 @@ impl ParseMacroInput for syn::ItemForeignMod {
|
||||
.collect();
|
||||
|
||||
match wasm_import_module {
|
||||
Some(namespace) if namespace.is_empty() => Err(Error::new(
|
||||
Some(namespace) if namespace.is_empty() => syn_error!(
|
||||
self_span,
|
||||
"import module name should be defined by 'wasm_import_module' directive",
|
||||
)),
|
||||
"import module name should be defined by 'wasm_import_module' directive"
|
||||
),
|
||||
Some(namespace) => {
|
||||
let extern_mod_item = fce_ast_types::AstExternModItem {
|
||||
namespace,
|
||||
@ -81,10 +81,10 @@ impl ParseMacroInput for syn::ItemForeignMod {
|
||||
};
|
||||
Ok(FCEAst::ExternMod(extern_mod_item))
|
||||
}
|
||||
None => Err(Error::new(
|
||||
None => syn_error!(
|
||||
self_span,
|
||||
"import module name should be defined by 'wasm_import_module' directive",
|
||||
)),
|
||||
"import module name should be defined by 'wasm_import_module' directive"
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -93,10 +93,10 @@ fn parse_raw_foreign_item(raw_item: syn::ForeignItem) -> Result<fce_ast_types::A
|
||||
let function_item = match raw_item {
|
||||
syn::ForeignItem::Fn(function_item) => function_item,
|
||||
_ => {
|
||||
return Err(Error::new(
|
||||
return syn_error!(
|
||||
raw_item.span(),
|
||||
"#[fce] could be applied only to a function, struct ot extern block",
|
||||
))
|
||||
"#[fce] could be applied only to a function, struct ot extern block"
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
@ -117,10 +117,10 @@ fn parse_raw_foreign_item(raw_item: syn::ForeignItem) -> Result<fce_ast_types::A
|
||||
None => None,
|
||||
};
|
||||
|
||||
let function = super::item_fn::try_to_ast_signature(function_item.sig, function_item.vis)?;
|
||||
let signature = super::item_fn::try_to_ast_signature(function_item.sig, function_item.vis)?;
|
||||
let ast_extern_fn_item = fce_ast_types::AstExternFnItem {
|
||||
link_name,
|
||||
signature: function,
|
||||
signature,
|
||||
};
|
||||
|
||||
Ok(ast_extern_fn_item)
|
||||
|
@ -15,13 +15,14 @@
|
||||
*/
|
||||
|
||||
use super::ParseMacroInput;
|
||||
use crate::{fce_ast_types, AstRecordField};
|
||||
use crate::fce_ast_types;
|
||||
use crate::AstRecordField;
|
||||
use crate::fce_ast_types::FCEAst;
|
||||
use crate::syn_error;
|
||||
use crate::parsed_type::ParsedType;
|
||||
|
||||
use syn::Error;
|
||||
use syn::Result;
|
||||
use syn::spanned::Spanned;
|
||||
use crate::parsed_type::ParsedType;
|
||||
|
||||
impl ParseMacroInput for syn::ItemStruct {
|
||||
fn parse_macro_input(self) -> Result<FCEAst> {
|
||||
@ -29,29 +30,10 @@ impl ParseMacroInput for syn::ItemStruct {
|
||||
|
||||
let fields = match &self.fields {
|
||||
syn::Fields::Named(named_fields) => &named_fields.named,
|
||||
syn::Fields::Unnamed(unnamed_fields) => &unnamed_fields.unnamed,
|
||||
_ => return Err(Error::new(self.span(), "only named field allowed")),
|
||||
_ => return syn_error!(self.span(), "only named fields are allowed in structs"),
|
||||
};
|
||||
|
||||
let fields = fields
|
||||
.iter()
|
||||
.map(|field| {
|
||||
check_field(field)?;
|
||||
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,
|
||||
ty: field_type,
|
||||
})
|
||||
})
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
let fields = fields_into_ast(fields)?;
|
||||
|
||||
let name = self.ident.to_string();
|
||||
let ast_record_item = fce_ast_types::AstRecordItem {
|
||||
@ -69,15 +51,38 @@ fn check_record(record: &syn::ItemStruct) -> Result<()> {
|
||||
|| record.generics.gt_token.is_some()
|
||||
|| record.generics.where_clause.is_some()
|
||||
{
|
||||
return Err(Error::new(
|
||||
return syn_error!(
|
||||
record.span(),
|
||||
"#[fce] couldn't be applied to a struct with generics or lifetimes",
|
||||
));
|
||||
"#[fce] couldn't be applied to a struct with generics or lifetimes"
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn fields_into_ast(
|
||||
fields: &syn::punctuated::Punctuated<syn::Field, syn::Token![,]>,
|
||||
) -> Result<Vec<AstRecordField>> {
|
||||
fields
|
||||
.iter()
|
||||
.map(|field| {
|
||||
check_field(field)?;
|
||||
let name = field.ident.as_ref().map(|ident| {
|
||||
ident
|
||||
.to_string()
|
||||
.split(' ')
|
||||
.last()
|
||||
.unwrap_or_default()
|
||||
.to_string()
|
||||
});
|
||||
let ty = ParsedType::from_type(&field.ty)?;
|
||||
|
||||
let record_field = AstRecordField { name, ty };
|
||||
Ok(record_field)
|
||||
})
|
||||
.collect::<Result<Vec<_>>>()
|
||||
}
|
||||
|
||||
/// Check that record fields satisfy the following requirements:
|
||||
/// - all fields must be public
|
||||
/// - field must have only doc attributes
|
||||
@ -85,10 +90,10 @@ fn check_field(field: &syn::Field) -> Result<()> {
|
||||
match field.vis {
|
||||
syn::Visibility::Public(_) => {}
|
||||
_ => {
|
||||
return Err(Error::new(
|
||||
return syn_error!(
|
||||
field.span(),
|
||||
"#[fce] could be applied only to struct with all public fields",
|
||||
))
|
||||
"#[fce] could be applied only to struct with all public fields"
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
@ -104,7 +109,7 @@ fn check_field(field: &syn::Field) -> Result<()> {
|
||||
});
|
||||
|
||||
if !is_all_attrs_public {
|
||||
return Err(Error::new(field.span(), "field attributes isn't allowed"));
|
||||
return syn_error!(field.span(), "field attributes isn't allowed");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
use super::ParsedType;
|
||||
use crate::fce_ast_types::AstFuncArgument;
|
||||
use crate::wasm_type::RustType;
|
||||
|
||||
/// This trait could be used to generate raw args needed to construct a export function.
|
||||
@ -22,9 +23,9 @@ pub(crate) trait FnArgGlueCodeGenerator {
|
||||
fn generate_arguments(&self) -> Vec<RustType>;
|
||||
}
|
||||
|
||||
impl FnArgGlueCodeGenerator for (String, ParsedType) {
|
||||
impl FnArgGlueCodeGenerator for AstFuncArgument {
|
||||
fn generate_arguments(&self) -> Vec<RustType> {
|
||||
match self.1 {
|
||||
match self.ty {
|
||||
ParsedType::Boolean(_) => vec![RustType::I32],
|
||||
ParsedType::I8(_) => vec![RustType::I8],
|
||||
ParsedType::I16(_) => vec![RustType::I16],
|
||||
|
@ -18,6 +18,7 @@ use super::ParsedType;
|
||||
use super::passing_style_of;
|
||||
use super::PassingStyle;
|
||||
use crate::new_ident;
|
||||
use crate::fce_ast_types::AstFuncArgument;
|
||||
|
||||
use quote::quote;
|
||||
|
||||
@ -29,6 +30,13 @@ pub(crate) struct FnEpilogDescriptor {
|
||||
pub(crate) mem_forget: proc_macro2::TokenStream,
|
||||
}
|
||||
|
||||
/// Contains all ingredients needed for epilog creation.
|
||||
pub(crate) struct FnEpilogIngredients<'i> {
|
||||
pub(crate) args: &'i [AstFuncArgument],
|
||||
pub(crate) converted_args: &'i [syn::Ident],
|
||||
pub(crate) return_type: &'i Option<ParsedType>,
|
||||
}
|
||||
|
||||
/// This trait could be used to generate various parts needed to construct epilog of an export
|
||||
/// function. They are marked with # in the following example:
|
||||
/// ```ignore
|
||||
@ -44,24 +52,18 @@ pub(crate) trait FnEpilogGlueCodeGenerator {
|
||||
fn generate_fn_epilog(&self) -> FnEpilogDescriptor;
|
||||
}
|
||||
|
||||
impl FnEpilogGlueCodeGenerator
|
||||
for (
|
||||
&Vec<(String, ParsedType)>,
|
||||
&Vec<syn::Ident>,
|
||||
&Option<ParsedType>,
|
||||
)
|
||||
{
|
||||
impl FnEpilogGlueCodeGenerator for FnEpilogIngredients<'_> {
|
||||
fn generate_fn_epilog(&self) -> FnEpilogDescriptor {
|
||||
FnEpilogDescriptor {
|
||||
fn_return_type: generate_fn_return_type(self.2),
|
||||
return_expression: generate_return_expression(self.2),
|
||||
epilog: generate_epilog(self.2),
|
||||
mem_forget: generate_mem_forget(self.0, self.1, self.2),
|
||||
fn_return_type: generate_fn_return_type(self.return_type),
|
||||
return_expression: generate_return_expression(self.return_type),
|
||||
epilog: generate_epilog(self.return_type),
|
||||
mem_forget: generate_mem_forgets(self),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_fn_return_type(ty: &Option<ParsedType>) -> proc_macro2::TokenStream {
|
||||
pub(crate) fn generate_fn_return_type(ty: &Option<ParsedType>) -> proc_macro2::TokenStream {
|
||||
let ty = match ty {
|
||||
Some(ParsedType::Boolean(_)) => Some("i32"),
|
||||
Some(ParsedType::I8(_)) => Some("i8"),
|
||||
@ -90,7 +92,7 @@ fn generate_fn_return_type(ty: &Option<ParsedType>) -> proc_macro2::TokenStream
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_return_expression(ty: &Option<ParsedType>) -> proc_macro2::TokenStream {
|
||||
pub(crate) fn generate_return_expression(ty: &Option<ParsedType>) -> proc_macro2::TokenStream {
|
||||
match ty {
|
||||
None => quote! {},
|
||||
_ => quote! {
|
||||
@ -115,10 +117,10 @@ fn generate_epilog(ty: &Option<ParsedType>) -> proc_macro2::TokenStream {
|
||||
}
|
||||
}
|
||||
Some(ParsedType::Vector(ty, _)) => {
|
||||
let generated_serializer_name = String::from("__fce_generated_vec_serializer");
|
||||
let generated_serializer_name = "__fce_generated_vec_serializer";
|
||||
let generated_serializer_ident = new_ident!(generated_serializer_name);
|
||||
let vector_serializer =
|
||||
super::vector_utils::generate_vector_serializer(ty, &generated_serializer_name);
|
||||
super::vector_utils::generate_vector_serializer(ty, generated_serializer_name);
|
||||
|
||||
quote! {
|
||||
#vector_serializer
|
||||
@ -136,12 +138,8 @@ fn generate_epilog(ty: &Option<ParsedType>) -> proc_macro2::TokenStream {
|
||||
/// If an export function returns a reference, this is probably a reference to one
|
||||
/// of the function arguments. If that's the case, reference must be still valid after
|
||||
/// the end of the function. Their deletion will be handled by IT with calling `release_objects`.
|
||||
fn generate_mem_forget(
|
||||
args: &Vec<(String, ParsedType)>,
|
||||
converted_args: &Vec<syn::Ident>,
|
||||
ret_type: &Option<ParsedType>,
|
||||
) -> proc_macro2::TokenStream {
|
||||
let passing_style = ret_type.as_ref().map(passing_style_of);
|
||||
fn generate_mem_forgets(ingredients: &FnEpilogIngredients<'_>) -> proc_macro2::TokenStream {
|
||||
let passing_style = ingredients.return_type.as_ref().map(passing_style_of);
|
||||
|
||||
match passing_style {
|
||||
// result will be deleted by IT side
|
||||
@ -149,21 +147,21 @@ fn generate_mem_forget(
|
||||
quote! { fluence::internal::add_object_to_release(Box::new(result)); }
|
||||
}
|
||||
Some(PassingStyle::ByRef) | Some(PassingStyle::ByMutRef) => {
|
||||
mem_forget_by_args(args, converted_args)
|
||||
mem_forget_by_args(ingredients.args, ingredients.converted_args)
|
||||
}
|
||||
None => quote! {},
|
||||
}
|
||||
}
|
||||
|
||||
fn mem_forget_by_args(
|
||||
args: &Vec<(String, ParsedType)>,
|
||||
converted_args: &Vec<syn::Ident>,
|
||||
args: &[AstFuncArgument],
|
||||
converted_args: &[syn::Ident],
|
||||
) -> proc_macro2::TokenStream {
|
||||
debug_assert!(args.len() == converted_args.len());
|
||||
|
||||
let mut res = proc_macro2::TokenStream::new();
|
||||
for ((_, arg), converted_arg) in args.iter().zip(converted_args) {
|
||||
let arg_passing_style = passing_style_of(arg);
|
||||
for (arg, converted_arg) in args.iter().zip(converted_args) {
|
||||
let arg_passing_style = passing_style_of(&arg.ty);
|
||||
match arg_passing_style {
|
||||
// such values will be deleted inside an export function because they are being moved
|
||||
PassingStyle::ByValue => {}
|
||||
|
@ -19,6 +19,7 @@ use super::FnArgGlueCodeGenerator;
|
||||
use super::passing_style_of;
|
||||
use crate::new_ident;
|
||||
use crate::wasm_type::RustType;
|
||||
use crate::fce_ast_types::AstFuncArgument;
|
||||
use crate::parsed_type::PassingStyle;
|
||||
|
||||
use quote::quote;
|
||||
@ -47,7 +48,7 @@ pub(crate) trait FnPrologGlueCodeGenerator {
|
||||
fn generate_prolog(&self) -> FnPrologDescriptor;
|
||||
}
|
||||
|
||||
impl FnPrologGlueCodeGenerator for Vec<(String, ParsedType)> {
|
||||
impl FnPrologGlueCodeGenerator for Vec<AstFuncArgument> {
|
||||
fn generate_prolog(&self) -> FnPrologDescriptor {
|
||||
let mut raw_arg_names = Vec::with_capacity(self.len());
|
||||
let mut raw_arg_types = Vec::with_capacity(self.len());
|
||||
@ -57,11 +58,11 @@ impl FnPrologGlueCodeGenerator for Vec<(String, ParsedType)> {
|
||||
|
||||
let mut input_type_id = 0;
|
||||
for arg in self {
|
||||
let passing_style = passing_style_of(&arg.1);
|
||||
let passing_style = passing_style_of(&arg.ty);
|
||||
let TypeLifter {
|
||||
converted_arg_ident,
|
||||
type_lifter_glue_code,
|
||||
} = generate_type_lifting_prolog(&arg.1, passing_style, input_type_id, input_type_id);
|
||||
} = generate_type_lifting_prolog(&arg.ty, passing_style, input_type_id, input_type_id);
|
||||
|
||||
let curr_raw_arg_types = arg.generate_arguments();
|
||||
let arg = quote! { #passing_style #converted_arg_ident };
|
||||
|
@ -57,11 +57,11 @@ impl ForeignModEpilogGlueCodeGenerator for Option<ParsedType> {
|
||||
)
|
||||
},
|
||||
Some(ParsedType::Vector(ty, _)) => {
|
||||
let generated_deserializer_name = String::from("__fce_generated_vec_deserializer");
|
||||
let generated_deserializer_name = "__fce_generated_vec_deserializer";
|
||||
let generated_deserializer_ident = new_ident!(generated_deserializer_name);
|
||||
let vector_deserializer = super::vector_utils::generate_vector_deserializer(
|
||||
ty,
|
||||
&generated_deserializer_name,
|
||||
generated_deserializer_name,
|
||||
);
|
||||
|
||||
quote! {
|
||||
|
@ -18,6 +18,7 @@ use super::ParsedType;
|
||||
use crate::wasm_type::RustType;
|
||||
use crate::new_ident;
|
||||
use crate::parsed_type::PassingStyle;
|
||||
use crate::fce_ast_types::AstFuncArgument;
|
||||
|
||||
pub(crate) struct WrapperDescriptor {
|
||||
pub(crate) arg_names: Vec<syn::Ident>,
|
||||
@ -58,32 +59,33 @@ pub(crate) trait ForeignModPrologGlueCodeGenerator {
|
||||
fn generate_extern_prolog(&self) -> ExternDescriptor;
|
||||
}
|
||||
|
||||
impl ForeignModPrologGlueCodeGenerator for Vec<(String, ParsedType)> {
|
||||
impl ForeignModPrologGlueCodeGenerator for Vec<AstFuncArgument> {
|
||||
fn generate_wrapper_prolog(&self) -> WrapperDescriptor {
|
||||
use crate::parsed_type::foreign_mod_arg::ForeignModArgGlueCodeGenerator;
|
||||
use quote::ToTokens;
|
||||
|
||||
let arg_types: Vec<proc_macro2::TokenStream> = self
|
||||
.iter()
|
||||
.map(|(_, input_type)| input_type.to_token_stream())
|
||||
.map(|arg| arg.ty.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, arg)| {
|
||||
let arg_name = format!("arg_{}", id);
|
||||
let arg_ident = new_ident!(arg_name);
|
||||
arg_names.push(arg_ident.clone());
|
||||
|
||||
// arguments of following two types shouldn't be deleted after transformation to raw view
|
||||
match ty {
|
||||
match &arg.ty {
|
||||
ParsedType::Utf8String(PassingStyle::ByValue) => {
|
||||
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); });
|
||||
},
|
||||
ParsedType::Vector(ty, _) => {
|
||||
let generated_serializer_name = format!("__fce_generated_vec_serializer_{}", arg_name);
|
||||
|
||||
let generated_serializer_ident = new_ident!(generated_serializer_name);
|
||||
let vector_serializer = super::vector_utils::generate_vector_serializer(ty, &generated_serializer_name);
|
||||
|
||||
@ -104,7 +106,7 @@ impl ForeignModPrologGlueCodeGenerator for Vec<(String, ParsedType)> {
|
||||
let raw_args: Vec<proc_macro2::TokenStream> = self
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(id, (_, input_type))| input_type.generate_raw_args(id))
|
||||
.map(|(id, arg)| arg.ty.generate_raw_args(id))
|
||||
.collect();
|
||||
|
||||
WrapperDescriptor {
|
||||
|
@ -17,8 +17,10 @@
|
||||
use crate::fce_ast_types;
|
||||
use crate::parsed_type::FnEpilogGlueCodeGenerator;
|
||||
use crate::parsed_type::FnEpilogDescriptor;
|
||||
use crate::parsed_type::FnEpilogIngredients;
|
||||
use crate::parsed_type::FnPrologGlueCodeGenerator;
|
||||
use crate::parsed_type::FnPrologDescriptor;
|
||||
|
||||
use crate::new_ident;
|
||||
|
||||
use proc_macro2::TokenStream;
|
||||
@ -52,17 +54,18 @@ impl quote::ToTokens for fce_ast_types::AstFunctionItem {
|
||||
args,
|
||||
} = &signature.arguments.generate_prolog();
|
||||
|
||||
let epilog_ingredients = FnEpilogIngredients {
|
||||
args: &signature.arguments,
|
||||
converted_args: converted_arg_idents,
|
||||
return_type: &signature.output_type,
|
||||
};
|
||||
|
||||
let FnEpilogDescriptor {
|
||||
fn_return_type,
|
||||
return_expression,
|
||||
epilog,
|
||||
mem_forget,
|
||||
} = (
|
||||
&signature.arguments,
|
||||
converted_arg_idents,
|
||||
&signature.output_type,
|
||||
)
|
||||
.generate_fn_epilog();
|
||||
} = epilog_ingredients.generate_fn_epilog();
|
||||
|
||||
// here this Option must be Some
|
||||
let original_func = &self.original;
|
||||
|
@ -42,7 +42,7 @@ impl quote::ToTokens for fce_ast_types::AstExternModItem {
|
||||
#[link(wasm_import_module = #wasm_import_module_name)]
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
extern "C" {
|
||||
#generated_imports
|
||||
#(#generated_imports)*
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
@ -61,15 +61,14 @@ impl quote::ToTokens for fce_ast_types::AstExternModItem {
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_extern_section_items(extern_item: &fce_ast_types::AstExternModItem) -> TokenStream {
|
||||
let mut token_stream = TokenStream::new();
|
||||
fn generate_extern_section_items(
|
||||
extern_item: &fce_ast_types::AstExternModItem,
|
||||
) -> Vec<TokenStream> {
|
||||
let mut section_items = Vec::with_capacity(extern_item.imports.len());
|
||||
|
||||
for import in &extern_item.imports {
|
||||
let signature = &import.signature;
|
||||
|
||||
let FnEpilogDescriptor { fn_return_type, .. } =
|
||||
(&vec![], &vec![], &signature.output_type).generate_fn_epilog();
|
||||
|
||||
let fn_return_type = crate::parsed_type::generate_fn_return_type(&signature.output_type);
|
||||
let link_name = import.link_name.as_ref().unwrap_or(&signature.name);
|
||||
let import_name = generate_import_name(&signature.name);
|
||||
let ExternDescriptor {
|
||||
@ -82,10 +81,10 @@ fn generate_extern_section_items(extern_item: &fce_ast_types::AstExternModItem)
|
||||
fn #import_name(#(#raw_arg_names: #raw_arg_types),*) #fn_return_type;
|
||||
};
|
||||
|
||||
token_stream.extend(func);
|
||||
section_items.push(func);
|
||||
}
|
||||
|
||||
token_stream
|
||||
section_items
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
@ -113,10 +112,8 @@ fn generate_wrapper_functions(extern_item: &fce_ast_types::AstExternModItem) ->
|
||||
arg_drops,
|
||||
} = signature.arguments.generate_wrapper_prolog();
|
||||
|
||||
let FnEpilogDescriptor {
|
||||
return_expression, ..
|
||||
} = (&vec![], &vec![], &signature.output_type).generate_fn_epilog();
|
||||
|
||||
let return_expression =
|
||||
crate::parsed_type::generate_return_expression(&signature.output_type);
|
||||
let epilog = signature.output_type.generate_wrapper_epilog();
|
||||
|
||||
let wrapper_func = quote! {
|
||||
|
@ -50,6 +50,7 @@ impl RecordSerializerGlueCodeGenerator for fce_ast_types::AstRecordItem {
|
||||
field.name.as_ref().unwrap(),
|
||||
id
|
||||
);
|
||||
|
||||
let generated_serializer_ident = new_ident!(generated_serializer_name);
|
||||
let vector_serializer = crate::parsed_type::generate_vector_serializer(
|
||||
ty,
|
||||
|
@ -44,6 +44,13 @@ macro_rules! prepare_global_data {
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! syn_error {
|
||||
($span:expr, $message:expr) => {
|
||||
Err(syn::Error::new($span, $message))
|
||||
};
|
||||
}
|
||||
|
||||
/// Calculate record size in an internal serialized view.
|
||||
pub fn get_record_size<'a>(
|
||||
fields: impl Iterator<Item = &'a crate::parsed_type::ParsedType>,
|
||||
|
@ -16,7 +16,7 @@ error: types with lifetimes or generics aren't allowed
|
||||
14 | fn test3(_arg_1: std::collections::HashMap<i32, String>) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: Incorrect argument type - passing only by value is supported now
|
||||
error: Incorrect argument type, only path or reference are available on this position
|
||||
--> $DIR/improper_types.rs:17:26
|
||||
|
|
||||
17 | fn test4(_arg_1: i32) -> (i32, i32) {
|
||||
|
8
fluence/tests/records/unnamed_structs.rs
Normal file
8
fluence/tests/records/unnamed_structs.rs
Normal file
@ -0,0 +1,8 @@
|
||||
#![allow(improper_ctypes)]
|
||||
|
||||
use fluence::fce;
|
||||
|
||||
fn main() {}
|
||||
|
||||
#[fce]
|
||||
struct A(pub i32, pub u32);
|
5
fluence/tests/records/unnamed_structs.stderr
Normal file
5
fluence/tests/records/unnamed_structs.stderr
Normal file
@ -0,0 +1,5 @@
|
||||
error: only named fields are allowed in structs
|
||||
--> $DIR/unnamed_structs.rs:8:1
|
||||
|
|
||||
8 | struct A(pub i32, pub u32);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
@ -13,4 +13,5 @@ fn test() {
|
||||
tests.pass("tests/records/empty_struct.rs");
|
||||
tests.compile_fail("tests/records/struct_with_improper_types.rs");
|
||||
tests.compile_fail("tests/records/struct_with_private_fields.rs");
|
||||
tests.compile_fail("tests/records/unnamed_structs.rs");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user