diff --git a/examples/tictactoe.rs b/examples/tictactoe.rs index bef8c90..18ee78f 100644 --- a/examples/tictactoe.rs +++ b/examples/tictactoe.rs @@ -4,8 +4,9 @@ use std::env; use std::fmt; use std::rc::Rc; use parity_wasm::elements::Module; -use parity_wasm::interpreter::{Error as InterpreterError, HostModule, HostModuleBuilder, - ModuleInstance, UserError}; +use parity_wasm::interpreter::{ + Error as InterpreterError, HostModule, HostModuleBuilder, + ModuleInstance, UserError}; #[derive(Debug)] pub enum Error { @@ -157,16 +158,16 @@ fn env_host_module<'a>() -> HostModule> { let mut builder = HostModuleBuilder::::new(); builder.with_func1( "set", - |state: &Runtime, idx: i32| -> Result, InterpreterError> { + |state: &Runtime, idx: i32| -> Result<(), InterpreterError> { state.game.set(idx, state.player)?; - Ok(None) + Ok(()) }, ); builder.with_func1( "get", - |state: &Runtime, idx: i32| -> Result, InterpreterError> { + |state: &Runtime, idx: i32| -> Result { let val: i32 = tictactoe::Player::into_i32(state.game.get(idx).unwrap()); - Ok(Some(val)) + Ok(val) }, ); builder.build() diff --git a/src/interpreter/host.rs b/src/interpreter/host.rs index ac9e8ae..3f616e7 100644 --- a/src/interpreter/host.rs +++ b/src/interpreter/host.rs @@ -7,7 +7,7 @@ use interpreter::func::FuncInstance; use interpreter::global::GlobalInstance; use interpreter::memory::MemoryInstance; use interpreter::table::TableInstance; -use interpreter::value::RuntimeValue; +use interpreter::value::{RuntimeValue, TryInto}; use interpreter::Error; use interpreter::ImportResolver; @@ -25,8 +25,8 @@ impl HostModuleBuilder { } pub fn with_func0< - Cl: Fn(&St) -> Result, Error> + 'static, - Ret: AsReturnVal + 'static, + Cl: Fn(&St) -> Result + 'static, + Ret: IntoReturnVal + 'static, N: Into, >( &mut self, @@ -35,8 +35,8 @@ impl HostModuleBuilder { ) { let func_type = FunctionType::new(vec![], Ret::value_type()); let host_func = Rc::new(move |state: &St, _args: &[RuntimeValue]| -> Result, Error> { - let result = f(state); - result.map(|r| r.and_then(|r| r.as_return_val())) + let result = f(state)?.into_return_val(); + Ok(result) }); let func = FuncInstance::alloc_host(Rc::new(func_type), host_func); @@ -44,8 +44,8 @@ impl HostModuleBuilder { } pub fn with_func1< - Cl: Fn(&St, P1) -> Result, Error> + 'static, - Ret: AsReturnVal + 'static, + Cl: Fn(&St, P1) -> Result + 'static, + Ret: IntoReturnVal + 'static, P1: FromArg + 'static, N: Into, >( @@ -56,8 +56,8 @@ impl HostModuleBuilder { let func_type = FunctionType::new(vec![P1::value_type()], Ret::value_type()); let host_func = Rc::new(move |state: &St, args: &[RuntimeValue]| -> Result, Error> { let arg0 = P1::from_arg(&args[0]); - let result = f(state, arg0); - result.map(|r| r.and_then(|r| r.as_return_val())) + let result = f(state, arg0)?.into_return_val(); + Ok(result) }); let func = FuncInstance::alloc_host(Rc::new(func_type), host_func); @@ -65,8 +65,8 @@ impl HostModuleBuilder { } pub fn with_func2< - Cl: Fn(&St, P1, P2) -> Result, Error> + 'static, - Ret: AsReturnVal + 'static, + Cl: Fn(&St, P1, P2) -> Result + 'static, + Ret: IntoReturnVal + 'static, P1: FromArg + 'static, P2: FromArg + 'static, N: Into, @@ -79,8 +79,8 @@ impl HostModuleBuilder { let host_func = Rc::new(move |state: &St, args: &[RuntimeValue]| -> Result, Error> { let p1 = P1::from_arg(&args[0]); let p2 = P2::from_arg(&args[1]); - let result = f(state, p1, p2); - result.map(|r| r.and_then(|r| r.as_return_val())) + let result = f(state, p1, p2)?.into_return_val(); + Ok(result) }); let func = FuncInstance::alloc_host(Rc::new(func_type), host_func); @@ -177,49 +177,66 @@ impl ImportResolver for HostModule { } } -pub trait AnyFunc { - fn call_as_any( - &self, - state: &St, - args: &[RuntimeValue], - ) -> Result, Error>; -} - -pub trait FromArg { +pub trait FromArg where Self: Sized { fn from_arg(arg: &RuntimeValue) -> Self; fn value_type() -> ValueType; } -impl FromArg for i32 { - fn from_arg(arg: &RuntimeValue) -> Self { - match arg { - &RuntimeValue::I32(v) => v, - unexpected => panic!("Expected I32, got {:?}", unexpected), - } - } +macro_rules! impl_from_arg { + ($ty: ident, $val_ty: ident) => { + impl FromArg for $ty { + fn from_arg(arg: &RuntimeValue) -> Self { + arg + .try_into() + .expect( + concat!("Due to validation, arg expected to be ", stringify!($val_ty)) + ) + } - fn value_type() -> ValueType { - ValueType::I32 + fn value_type() -> ValueType { + use self::ValueType::*; + $val_ty + } + } } } -pub trait AsReturnVal { - fn as_return_val(self) -> Option; +impl_from_arg!(i32, I32); +impl_from_arg!(u32, I32); +impl_from_arg!(i64, I64); +impl_from_arg!(u64, I64); +impl_from_arg!(f32, F32); +impl_from_arg!(f64, F64); + +pub trait IntoReturnVal { + fn into_return_val(self) -> Option; fn value_type() -> Option; } -impl AsReturnVal for i32 { - fn as_return_val(self) -> Option { - Some(self.into()) - } +macro_rules! impl_into_return_val { + ($ty: ident, $val_ty: ident) => { + impl IntoReturnVal for $ty { + fn into_return_val(self) -> Option { + Some(self.into()) + } - fn value_type() -> Option { - Some(ValueType::I32) + fn value_type() -> Option { + use self::ValueType::*; + Some($val_ty) + } + } } } -impl AsReturnVal for () { - fn as_return_val(self) -> Option { +impl_into_return_val!(i32, I32); +impl_into_return_val!(u32, I32); +impl_into_return_val!(i64, I64); +impl_into_return_val!(u64, I64); +impl_into_return_val!(f32, F32); +impl_into_return_val!(f64, F64); + +impl IntoReturnVal for () { + fn into_return_val(self) -> Option { None } @@ -227,27 +244,3 @@ impl AsReturnVal for () { None } } - -impl AnyFunc for Fn(&St) -> Result, Error> { - fn call_as_any( - &self, - state: &St, - _args: &[RuntimeValue], - ) -> Result, Error> { - let result = self(state); - result.map(|r| r.and_then(|r| r.as_return_val())) - } -} - -impl AnyFunc for Fn(&St, P1, P2) -> Result, Error> { - fn call_as_any( - &self, - state: &St, - args: &[RuntimeValue], - ) -> Result, Error> { - let p1 = P1::from_arg(&args[0]); - let p2 = P2::from_arg(&args[1]); - let result = self(state, p1, p2); - result.map(|r| r.and_then(|r| r.as_return_val())) - } -} diff --git a/src/interpreter/mod.rs b/src/interpreter/mod.rs index 41c54d1..2e15000 100644 --- a/src/interpreter/mod.rs +++ b/src/interpreter/mod.rs @@ -151,7 +151,7 @@ pub use self::memory::MemoryInstance; pub use self::table::TableInstance; pub use self::program::ProgramInstance; pub use self::value::RuntimeValue; -pub use self::host::{HostModule, HostModuleBuilder, HostFunc, AsReturnVal, FromArg}; +pub use self::host::{HostModule, HostModuleBuilder, HostFunc, IntoReturnVal, FromArg}; pub use self::imports::{ImportResolver, Imports}; pub use self::module::ModuleInstance; pub use self::global::GlobalInstance; diff --git a/src/interpreter/tests/basics.rs b/src/interpreter/tests/basics.rs index 8cd9e8f..25d0294 100644 --- a/src/interpreter/tests/basics.rs +++ b/src/interpreter/tests/basics.rs @@ -133,7 +133,7 @@ fn build_env_module() -> HostModule { let sum = memory_value + fn_argument; state.memory.set(0, &vec![sum]).unwrap(); state.values.borrow_mut().push(sum as i32); - Ok(Some(sum as i32)) + Ok(sum as i32) }); builder.with_func2("sub", |state: &TestState, arg: i32, unused: i32| { let memory_value = state.memory.get(0, 1).unwrap()[0]; @@ -144,9 +144,9 @@ fn build_env_module() -> HostModule { let diff = memory_value - fn_argument; state.memory.set(0, &vec![diff]).unwrap(); state.values.borrow_mut().push(diff as i32); - Ok(Some(diff as i32)) + Ok(diff as i32) }); - builder.with_func2("err", |_: &TestState, _unused1: i32, _unused2: i32| -> Result, Error> { + builder.with_func2("err", |_: &TestState, _unused1: i32, _unused2: i32| -> Result { Err(Error::User(Box::new(UserErrorWithCode { error_code: 777 }))) }); builder.insert_memory("memory", Rc::new(MemoryInstance::new(&MemoryType::new(256, None)).unwrap())); @@ -323,14 +323,14 @@ fn native_ref_state() { let mut host_module_builder = HostModuleBuilder::::new(); host_module_builder.with_func1( "inc", - |state: &HostState, val: i32| -> Result, Error> { + |state: &HostState, val: i32| -> Result<(), Error> { let mut ext_state = state.ext_state.borrow_mut(); // TODO: fix this fn inc(acc: &mut i32, val: i32) { *acc += val; } inc(&mut *ext_state, val); - Ok(None) + Ok(()) }, ); host_module_builder.build() diff --git a/src/interpreter/value.rs b/src/interpreter/value.rs index bab3adf..4b7b94a 100644 --- a/src/interpreter/value.rs +++ b/src/interpreter/value.rs @@ -153,6 +153,18 @@ impl From for RuntimeValue { } } +impl From for RuntimeValue { + fn from(val: u32) -> Self { + RuntimeValue::I32(val as i32) + } +} + +impl From for RuntimeValue { + fn from(val: u64) -> Self { + RuntimeValue::I64(val as i64) + } +} + impl From for RuntimeValue { fn from(val: f32) -> Self { RuntimeValue::F32(val)