diff --git a/derive/src/codegen.rs b/derive/src/codegen.rs index 497a7aa..bdc4dbc 100644 --- a/derive/src/codegen.rs +++ b/derive/src/codegen.rs @@ -23,18 +23,18 @@ pub fn codegen(ext_def: &ExtDefinition, to: &mut TokenStream) { Trap, RuntimeValue, RuntimeArgs, Externals, ValueType, ModuleImportResolver, Signature, FuncRef, Error, FuncInstance, derive_support::{ - WasmResult, - ConvertibleToWasm, + IntoWasmResult, + IntoWasmValue, }, }; #[inline(always)] - fn materialize_arg_ty(_w: Option) -> ValueType { + fn materialize_arg_ty(_w: Option) -> ValueType { W::VALUE_TYPE } #[inline(always)] - fn materialize_ret_type(_w: Option) -> Option { + fn materialize_ret_type(_w: Option) -> Option { W::VALUE_TYPE } @@ -66,7 +66,7 @@ fn emit_dispatch_func_arm(func: &ExternalFunc) -> TokenStream { #unmarshall_args }; let epilogue = quote_spanned! {return_ty_span=> - WasmResult::to_wasm_result(r) + IntoWasmResult::into_wasm_result(r) }; let call = { diff --git a/derive/src/model.rs b/derive/src/model.rs index 834b596..6dc3e31 100644 --- a/derive/src/model.rs +++ b/derive/src/model.rs @@ -23,8 +23,6 @@ pub struct ExternalFunc { // TODO: Rename args to params pub args: Vec, pub return_ty: Option, - // TODO: remove - pub arity: usize, } /// The core structure that contains the list of all functions diff --git a/derive/src/parser.rs b/derive/src/parser.rs index 55f2702..0ac0f03 100644 --- a/derive/src/parser.rs +++ b/derive/src/parser.rs @@ -2,7 +2,7 @@ use crate::model::{self, ExtDefinition, ExternalFunc, Param}; use syn::{ItemImpl, ImplItem, ImplItemMethod, FnArg, ReturnType, Ident}; use syn::spanned::Spanned; -/// Parse an incoming stream of tokens into a list of external functions. +/// Parse an incoming stream of tokens into externalities definition. pub fn parse(input: proc_macro2::TokenStream) -> Result { let item_impl = syn::parse2::(input).map_err(|_| ())?; @@ -35,7 +35,6 @@ pub fn parse(input: proc_macro2::TokenStream) -> Result { name: sig.ident.to_string(), args, return_ty, - arity: sig.decl.inputs.len() - 1, // self TODO: handle this properly }); }, _ => {}, diff --git a/src/derive_support.rs b/src/derive_support.rs index d4d88e1..ce5f886 100644 --- a/src/derive_support.rs +++ b/src/derive_support.rs @@ -1,53 +1,66 @@ use {ValueType, RuntimeValue, Trap}; +use nan_preserving_float::{F32, F64}; -pub trait ConvertibleToWasm { +/// A trait that represents a value that can be directly coerced to one of +/// wasm base value types. +pub trait IntoWasmValue { const VALUE_TYPE: ValueType; - type NativeType; - fn to_runtime_value(self) -> RuntimeValue; + /// Perform the conversion. + fn into_wasm_value(self) -> RuntimeValue; } -impl ConvertibleToWasm for i32 { type NativeType = i32; const VALUE_TYPE: ValueType = ValueType::I32; fn to_runtime_value(self) -> RuntimeValue { RuntimeValue::I32(self) } } -impl ConvertibleToWasm for u32 { type NativeType = u32; const VALUE_TYPE: ValueType = ValueType::I32; fn to_runtime_value(self) -> RuntimeValue { RuntimeValue::I32(self as i32) } } -impl ConvertibleToWasm for i64 { type NativeType = i64; const VALUE_TYPE: ValueType = ValueType::I64; fn to_runtime_value(self) -> RuntimeValue { RuntimeValue::I64(self) } } -impl ConvertibleToWasm for u64 { type NativeType = u64; const VALUE_TYPE: ValueType = ValueType::I64; fn to_runtime_value(self) -> RuntimeValue { RuntimeValue::I64(self as i64) } } -impl ConvertibleToWasm for isize { type NativeType = i32; const VALUE_TYPE: ValueType = ValueType::I32; fn to_runtime_value(self) -> RuntimeValue { RuntimeValue::I32(self as i32) } } -impl ConvertibleToWasm for usize { type NativeType = u32; const VALUE_TYPE: ValueType = ValueType::I32; fn to_runtime_value(self) -> RuntimeValue { RuntimeValue::I32(self as u32 as i32) } } -impl ConvertibleToWasm for *const T { type NativeType = u32; const VALUE_TYPE: ValueType = ValueType::I32; fn to_runtime_value(self) -> RuntimeValue { RuntimeValue::I32(self as isize as i32) } } -impl ConvertibleToWasm for *mut T { type NativeType = u32; const VALUE_TYPE: ValueType = ValueType::I32; fn to_runtime_value(self) -> RuntimeValue { RuntimeValue::I32(self as isize as i32) } } +macro_rules! impl_convertible_to_wasm { + // TODO: Replace it to Kleene ? operator + ($ty:ty, $wasm_ty:ident $(, as $cast_to:ty)* ) => { + impl IntoWasmValue for $ty { + const VALUE_TYPE: ValueType = ValueType::$wasm_ty; + fn into_wasm_value(self) -> RuntimeValue { + RuntimeValue::$wasm_ty(self $( as $cast_to)*) + } + } + }; +} -pub trait WasmResult { +impl_convertible_to_wasm!(i32, I32); +impl_convertible_to_wasm!(u32, I32, as i32); +impl_convertible_to_wasm!(i64, I64); +impl_convertible_to_wasm!(u64, I64, as i64); +impl_convertible_to_wasm!(F32, F32); +impl_convertible_to_wasm!(F64, F64); + +pub trait IntoWasmResult { const VALUE_TYPE: Option; - fn to_wasm_result(self) -> Result, Trap>; + fn into_wasm_result(self) -> Result, Trap>; } -impl WasmResult for () { +impl IntoWasmResult for () { const VALUE_TYPE: Option = None; - fn to_wasm_result(self) -> Result, Trap> { + fn into_wasm_result(self) -> Result, Trap> { Ok(None) } } -impl> WasmResult for Result { +impl> IntoWasmResult for Result { const VALUE_TYPE: Option = Some(R::VALUE_TYPE); - fn to_wasm_result(self) -> Result, Trap> { + fn into_wasm_result(self) -> Result, Trap> { self - .map(|v| Some(v.to_runtime_value())) + .map(|v| Some(v.into_wasm_value())) .map_err(Into::into) } } -impl> WasmResult for Result<(), E> { +impl> IntoWasmResult for Result<(), E> { const VALUE_TYPE: Option = None; - fn to_wasm_result(self) -> Result, Trap> { + fn into_wasm_result(self) -> Result, Trap> { self .map(|_| None) .map_err(Into::into) } } -impl WasmResult for R { +impl IntoWasmResult for R { const VALUE_TYPE: Option = Some(R::VALUE_TYPE); - fn to_wasm_result(self) -> Result, Trap> { - Ok(Some(self.to_runtime_value())) + fn into_wasm_result(self) -> Result, Trap> { + Ok(Some(self.into_wasm_value())) } }