improve function parsing

This commit is contained in:
vms 2020-07-02 23:56:59 +03:00
parent 2c68bb7a2c
commit 06dc49e6e3
5 changed files with 95 additions and 30 deletions

View File

@ -23,5 +23,6 @@ quote = "1.0.7"
proc-macro2 = "1.0.18"
serde = { version = "1.0.110", features = ["derive"] }
serde_json = "1.0.56"
uuid = { version = "0.8.1", features = ["v4"] }
fluence-sdk-main = { path = "../main", version = "=0.1.11" }

View File

@ -164,23 +164,24 @@ impl ParsedType {
}
}
pub(crate) trait ArgumentsGenerator {
// TODO: replace String with Ident
pub(crate) trait MacroPartsGenerator {
fn generate_arguments(&self) -> Vec<WasmType>;
}
pub(crate) trait PrologGenerator {
fn generate_return_expression(&self) -> proc_macro2::TokenStream;
fn generate_return_type(&self) -> String;
fn generate_fn_prolog(
&self,
generated_arg_id: usize,
supplied_arg_start_id: usize,
) -> proc_macro2::TokenStream;
}
pub(crate) trait EpilogGenerator {
fn generate_fn_epilog(&self) -> proc_macro2::TokenStream;
}
impl ArgumentsGenerator for ParsedType {
impl MacroPartsGenerator for ParsedType {
fn generate_arguments(&self) -> Vec<WasmType> {
// TODO: investigate possible issues in conversion between signed and unsigned types
match self {
@ -201,9 +202,37 @@ impl ArgumentsGenerator for ParsedType {
ParsedType::Record(_) => vec![WasmType::I32, WasmType::I32],
}
}
}
impl PrologGenerator for ParsedType {
fn generate_return_expression(&self) -> proc_macro2::TokenStream {
match self {
ParsedType::Empty => quote! {},
ParsedType::Utf8String => quote! {},
ParsedType::ByteVector => quote! {},
ParsedType::Record(_) => quote! {},
_ => quote! {
let result =
},
}
}
fn generate_return_type(&self) -> String {
match self {
ParsedType::I8 => "-> i32",
ParsedType::I16 => "-> i32",
ParsedType::I32 => "-> i32",
ParsedType::I64 => "-> i64",
ParsedType::U8 => "-> i32",
ParsedType::U16 => "-> i32",
ParsedType::U32 => "-> i32",
ParsedType::U64 => "-> i64",
ParsedType::F32 => "-> f32",
ParsedType::F64 => "-> f64",
ParsedType::Boolean => "-> i32",
_ => "",
}
.to_string()
}
fn generate_fn_prolog(
&self,
generated_ard_id: usize,
@ -266,44 +295,42 @@ impl PrologGenerator for ParsedType {
},
}
}
}
impl EpilogGenerator for ParsedType {
fn generate_fn_epilog(&self) -> proc_macro2::TokenStream {
match self {
ParsedType::Empty => quote! {},
ParsedType::I8 => quote! {
return result;
return result as _;
},
ParsedType::I16 => quote! {
return result;
return result as _;
},
ParsedType::I32 => quote! {
return result;
return result as _;
},
ParsedType::I64 => quote! {
return result;
return result as _;
},
ParsedType::U8 => quote! {
return result;
return result as _;
},
ParsedType::U16 => quote! {
return result;
return result as _;
},
ParsedType::U32 => quote! {
return result;
return result as _;
},
ParsedType::U64 => quote! {
return result;
return result as _;
},
ParsedType::F32 => quote! {
return result;
return result as _;
},
ParsedType::F64 => quote! {
return result;
return result as _;
},
ParsedType::Boolean => quote! {
return result;
return result as _;
},
ParsedType::Utf8String => quote! {
fluence::set_result_ptr(result.as_ptr() as _);

View File

@ -23,6 +23,8 @@ use crate::fce_ast_types::FCEAst;
use proc_macro2::TokenStream;
const GENERATED_FUNCS_PREFIX: &str = "__fce_generated_func_";
const GENERATED_SECTION_NAME: &str = "fce_generated_section";
const GENERATED_SECTION_PREFIX: &str = "__fce_generated_section";
pub(crate) trait TokenStreamGenerator {
fn generate_token_stream(self) -> syn::Result<TokenStream>;

View File

@ -15,19 +15,50 @@
*/
use crate::fce_ast_types;
use crate::parsed_type::ArgumentsGenerator;
use crate::parsed_type::EpilogGenerator;
use crate::parsed_type::PrologGenerator;
use crate::parsed_type::MacroPartsGenerator;
use super::GENERATED_FUNCS_PREFIX;
use super::GENERATED_SECTION_NAME;
use super::GENERATED_SECTION_PREFIX;
use super::TokenStreamGenerator;
use proc_macro2::TokenStream;
use quote::quote;
use crate::wasm_type::WasmType;
impl TokenStreamGenerator for fce_ast_types::AstFunctionItem {
fn generate_token_stream(self) -> syn::Result<TokenStream> {
let data = serde_json::to_string(&self).unwrap();
let data_size = data.len();
let func_name = self.name;
let prefix = "__fce_generated_func_";
let prefix = GENERATED_FUNCS_PREFIX;
let section_name = GENERATED_SECTION_NAME;
let section_prefix = GENERATED_SECTION_PREFIX;
let generated_global_name = uuid::Uuid::new_v4().to_string();
let return_type = self.output_type.generate_return_type();
let return_expression = self.output_type.generate_return_expression();
let epilog = self.output_type.generate_fn_epilog();
let mut prolog = TokenStream::new();
let mut args: Vec<String> = Vec::with_capacity(self.input_types.len());
let mut raw_args: Vec<WasmType> = Vec::with_capacity(self.input_types.len());
let mut input_type_id = 0;
for input_type in self.input_types {
let type_prolog = input_type.generate_fn_prolog(input_type_id, input_type_id);
let type_raw_args = input_type.generate_arguments();
args.extend(
type_raw_args
.iter()
.enumerate()
.map(|(id, _)| format!("converted_arg_{}", input_type_id + id)),
);
input_type_id += type_raw_args.len();
raw_args.extend(type_raw_args);
prolog.extend(type_prolog);
}
let embedded_tokens = quote! {
#[cfg_attr(
@ -36,10 +67,10 @@ impl TokenStreamGenerator for fce_ast_types::AstFunctionItem {
)]
#[doc(hidden)]
#[allow(clippy::all)]
pub extern "C" fn #prefix_#func_name(#(#raw_args)*) #ret_type {
pub extern "C" fn #prefix#func_name(#(#raw_args)*) #return_type {
#prolog
#ret_expression #func_name(#(#args)*);
#return_expression #func_name(#(#args)*);
#epilog
}
@ -48,7 +79,7 @@ impl TokenStreamGenerator for fce_ast_types::AstFunctionItem {
#[allow(clippy::all)]
#[doc(hidden)]
#[link_section = #section_name]
pub static #generated_global_name: [u8; #size] = { #data };
pub static #func_name#section_prefix#generated_global_name: [u8; #data_size] = { #data };
};
Ok(embedded_tokens)

View File

@ -1,5 +1,4 @@
use proc_macro2::TokenStream;
use quote::TokenStreamExt;
pub(crate) enum WasmType {
I32,
@ -10,6 +9,11 @@ pub(crate) enum WasmType {
impl quote::ToTokens for WasmType {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.append(self.clone());
match self {
WasmType::I32 => "i32".to_tokens(tokens),
WasmType::I64 => "i64".to_tokens(tokens),
WasmType::F32 => "f32".to_tokens(tokens),
WasmType::F64 => "f64".to_tokens(tokens),
}
}
}