Make it compile.

This commit is contained in:
Sergey Pepyakin 2018-01-31 19:00:30 +03:00
parent 9c156890e4
commit f121d206aa
5 changed files with 47 additions and 25 deletions

View File

@ -152,12 +152,12 @@ impl<'a> Externals for Runtime<'a> {
) -> Result<Option<RuntimeValue>, Trap> { ) -> Result<Option<RuntimeValue>, Trap> {
match index { match index {
SET_FUNC_INDEX => { SET_FUNC_INDEX => {
let idx: i32 = args.nth(0)?; let idx: i32 = args.nth(0);
self.game.set(idx, self.player)?; self.game.set(idx, self.player)?;
Ok(None) Ok(None)
} }
GET_FUNC_INDEX => { GET_FUNC_INDEX => {
let idx: i32 = args.nth(0)?; let idx: i32 = args.nth(0);
let val: i32 = tictactoe::Player::into_i32(self.game.get(idx)?); let val: i32 = tictactoe::Player::into_i32(self.game.get(idx)?);
Ok(Some(val.into())) Ok(Some(val.into()))
} }

View File

@ -13,13 +13,14 @@ use wasmi::{
GlobalInstance, GlobalRef, ImportResolver, ImportsBuilder, GlobalInstance, GlobalRef, ImportResolver, ImportsBuilder,
MemoryInstance, MemoryRef, ModuleImportResolver, ModuleInstance, MemoryInstance, MemoryRef, ModuleImportResolver, ModuleInstance,
ModuleRef, RuntimeValue, TableInstance, TableRef, ValueType, ModuleRef, RuntimeValue, TableInstance, TableRef, ValueType,
Module, Signature, MemoryDescriptor, Module, Signature, MemoryDescriptor, Trap,
TableDescriptor, GlobalDescriptor, FuncInstance, RuntimeArgs, TableDescriptor, GlobalDescriptor, FuncInstance, RuntimeArgs,
}; };
#[derive(Debug)] #[derive(Debug)]
enum Error { enum Error {
Load(String), Load(String),
Start(Trap),
Interpreter(InterpreterError), Interpreter(InterpreterError),
} }
@ -58,7 +59,7 @@ impl Externals for SpecModule {
&mut self, &mut self,
index: usize, index: usize,
args: RuntimeArgs, args: RuntimeArgs,
) -> Result<Option<RuntimeValue>, InterpreterError> { ) -> Result<Option<RuntimeValue>, Trap> {
match index { match index {
PRINT_FUNC_INDEX => { PRINT_FUNC_INDEX => {
println!("print: {:?}", args); println!("print: {:?}", args);
@ -243,7 +244,9 @@ fn try_load(
) -> Result<(), Error> { ) -> Result<(), Error> {
let module = try_load_module(base_dir, module_path)?; let module = try_load_module(base_dir, module_path)?;
let instance = ModuleInstance::new(&module, &ImportsBuilder::default())?; let instance = ModuleInstance::new(&module, &ImportsBuilder::default())?;
instance.run_start(spec_driver.spec_module())?; instance
.run_start(spec_driver.spec_module())
.map_err(|trap| Error::Start(trap))?;
Ok(()) Ok(())
} }

View File

@ -14,18 +14,23 @@ impl<'a> From<&'a [RuntimeValue]> for RuntimeArgs<'a> {
impl<'a> RuntimeArgs<'a> { impl<'a> RuntimeArgs<'a> {
/// Extract argument by index `idx` returning error if cast is invalid or not enough arguments /// Extract argument by index `idx` returning error if cast is invalid or not enough arguments
pub fn nth<T>(&self, idx: usize) -> Result<T, Error> where RuntimeValue: TryInto<T, Error> { pub fn nth_checked<T>(&self, idx: usize) -> Result<T, Error> where RuntimeValue: TryInto<T, Error> {
Ok(self.nth_value(idx)?.try_into().map_err(|_| Error::Value("Invalid argument cast".to_owned()))?) Ok(self.nth_value_checked(idx)?.try_into().map_err(|_| Error::Value("Invalid argument cast".to_owned()))?)
} }
/// Extract argument as a runtime value by index `idx` returning error is not enough arguments /// Extract argument as a runtime value by index `idx` returning error is not enough arguments
pub fn nth_value(&self, idx: usize) -> Result<RuntimeValue, Error> { pub fn nth_value_checked(&self, idx: usize) -> Result<RuntimeValue, Error> {
if self.0.len() <= idx { if self.0.len() <= idx {
return Err(Error::Value("Invalid argument index".to_owned())); return Err(Error::Value("Invalid argument index".to_owned()));
} }
Ok(self.0[idx]) Ok(self.0[idx])
} }
pub fn nth<T>(&self, idx: usize) -> T where RuntimeValue: TryInto<T, Error> {
let value = self.nth_value_checked(idx).expect("Invalid argument index");
value.try_into().expect("Unexpected argument type")
}
/// Total number of arguments /// Total number of arguments
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
self.0.len() self.0.len()
@ -104,7 +109,7 @@ impl HostError {
/// ```rust /// ```rust
/// use wasmi::{ /// use wasmi::{
/// Externals, RuntimeValue, RuntimeArgs, Error, ModuleImportResolver, /// Externals, RuntimeValue, RuntimeArgs, Error, ModuleImportResolver,
/// FuncRef, ValueType, Signature, FuncInstance /// FuncRef, ValueType, Signature, FuncInstance, Trap,
/// }; /// };
/// ///
/// struct HostExternals { /// struct HostExternals {
@ -118,11 +123,11 @@ impl HostError {
/// &mut self, /// &mut self,
/// index: usize, /// index: usize,
/// args: RuntimeArgs, /// args: RuntimeArgs,
/// ) -> Result<Option<RuntimeValue>, Error> { /// ) -> Result<Option<RuntimeValue>, Trap> {
/// match index { /// match index {
/// ADD_FUNC_INDEX => { /// ADD_FUNC_INDEX => {
/// let a: u32 = args.nth(0).unwrap(); /// let a: u32 = args.nth(0);
/// let b: u32 = args.nth(1).unwrap(); /// let b: u32 = args.nth(1);
/// let result = a + b; /// let result = a + b;
/// ///
/// Ok(Some(RuntimeValue::I32(result as i32))) /// Ok(Some(RuntimeValue::I32(result as i32)))
@ -201,14 +206,14 @@ mod tests {
#[test] #[test]
fn i32_runtime_args() { fn i32_runtime_args() {
let args: RuntimeArgs = (&[RuntimeValue::I32(0)][..]).into(); let args: RuntimeArgs = (&[RuntimeValue::I32(0)][..]).into();
let val: i32 = args.nth(0).unwrap(); let val: i32 = args.nth_checked(0).unwrap();
assert_eq!(val, 0); assert_eq!(val, 0);
} }
#[test] #[test]
fn i64_invalid_arg_cast() { fn i64_invalid_arg_cast() {
let args: RuntimeArgs = (&[RuntimeValue::I64(90534534545322)][..]).into(); let args: RuntimeArgs = (&[RuntimeValue::I64(90534534545322)][..]).into();
assert!(args.nth::<i32>(0).is_err()); assert!(args.nth_checked::<i32>(0).is_err());
} }
// Tests that `HostError` trait is object safe. // Tests that `HostError` trait is object safe.

View File

@ -116,6 +116,7 @@ pub enum Trap {
DivisionByZero, DivisionByZero,
InvalidConversionToInt, InvalidConversionToInt,
StackOverflow, StackOverflow,
Host(Box<host::HostError>),
} }
/// Internal interpreter error. /// Internal interpreter error.
@ -204,6 +205,18 @@ impl<U> From<U> for Error where U: host::HostError + Sized {
} }
} }
impl<U> From<U> for Trap where U: host::HostError + Sized {
fn from(e: U) -> Self {
Trap::Host(Box::new(e))
}
}
impl From<Trap> for Error {
fn from(e: Trap) -> Error {
Error::Trap(e)
}
}
impl From<validation::Error> for Error { impl From<validation::Error> for Error {
fn from(e: validation::Error) -> Error { fn from(e: validation::Error) -> Error {
Error::Validation(e.to_string()) Error::Validation(e.to_string())

View File

@ -82,20 +82,20 @@ impl Externals for TestHost {
) -> Result<Option<RuntimeValue>, Trap> { ) -> Result<Option<RuntimeValue>, Trap> {
match index { match index {
SUB_FUNC_INDEX => { SUB_FUNC_INDEX => {
let a: i32 = args.nth(0)?; let a: i32 = args.nth(0);
let b: i32 = args.nth(1)?; let b: i32 = args.nth(1);
let result: RuntimeValue = (a - b).into(); let result: RuntimeValue = (a - b).into();
Ok(Some(result)) Ok(Some(result))
} }
ERR_FUNC_INDEX => { ERR_FUNC_INDEX => {
let error_code: u32 = args.nth(0)?; let error_code: u32 = args.nth(0);
let error = HostErrorWithCode { error_code }; let error = HostErrorWithCode { error_code };
Err(Error::Host(Box::new(error))) Err(Trap::Host(Box::new(error)))
} }
INC_MEM_FUNC_INDEX => { INC_MEM_FUNC_INDEX => {
let ptr: u32 = args.nth(0)?; let ptr: u32 = args.nth(0);
let memory = self.memory.as_ref().expect( let memory = self.memory.as_ref().expect(
"Function 'inc_mem' expects attached memory", "Function 'inc_mem' expects attached memory",
@ -108,7 +108,7 @@ impl Externals for TestHost {
Ok(None) Ok(None)
} }
GET_MEM_FUNC_INDEX => { GET_MEM_FUNC_INDEX => {
let ptr: u32 = args.nth(0)?; let ptr: u32 = args.nth(0);
let memory = self.memory.as_ref().expect( let memory = self.memory.as_ref().expect(
"Function 'get_mem' expects attached memory", "Function 'get_mem' expects attached memory",
@ -119,7 +119,7 @@ impl Externals for TestHost {
Ok(Some(RuntimeValue::I32(buf[0] as i32))) Ok(Some(RuntimeValue::I32(buf[0] as i32)))
} }
RECURSE_FUNC_INDEX => { RECURSE_FUNC_INDEX => {
let val = args.nth_value(0)?; let val = args.nth_value_checked(0).expect("Exactly one argument expected");
let instance = self.instance let instance = self.instance
.as_ref() .as_ref()
@ -131,7 +131,7 @@ impl Externals for TestHost {
.expect("expected to be Some"); .expect("expected to be Some");
if val.value_type() != result.value_type() { if val.value_type() != result.value_type() {
return Err(Error::Host(Box::new(HostErrorWithCode { error_code: 123 }))); return Err(Trap::Host(Box::new(HostErrorWithCode { error_code: 123 })));
} }
Ok(Some(result)) Ok(Some(result))
} }
@ -263,7 +263,7 @@ fn host_err() {
); );
let host_error: Box<HostError> = match error { let host_error: Box<HostError> = match error {
Error::Host(err) => err, Error::Trap(Trap::Host(err)) => err,
err => panic!("Unexpected error {:?}", err), err => panic!("Unexpected error {:?}", err),
}; };
@ -467,7 +467,7 @@ fn defer_providing_externals() {
) -> Result<Option<RuntimeValue>, Trap> { ) -> Result<Option<RuntimeValue>, Trap> {
match index { match index {
INC_FUNC_INDEX => { INC_FUNC_INDEX => {
let a = args.nth::<u32>(0)?; let a = args.nth::<u32>(0);
*self.acc += a; *self.acc += a;
Ok(None) Ok(None)
} }
@ -661,7 +661,8 @@ fn dynamically_add_host_func() {
Signature::new(&[][..], Some(ValueType::I32)), Signature::new(&[][..], Some(ValueType::I32)),
host_func_index as usize, host_func_index as usize,
); );
self.table.set(table_index, Some(added_func))?; self.table.set(table_index, Some(added_func))
.map_err(|_| Trap::TableAccessOutOfBounds)?;
Ok(Some(RuntimeValue::I32(table_index as i32))) Ok(Some(RuntimeValue::I32(table_index as i32)))
} }