Make it compile.
This commit is contained in:
parent
9c156890e4
commit
f121d206aa
|
@ -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()))
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
23
src/host.rs
23
src/host.rs
|
@ -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.
|
||||||
|
|
13
src/lib.rs
13
src/lib.rs
|
@ -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())
|
||||||
|
|
|
@ -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)))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue