Remove E: UserError everywhere

This commit is contained in:
Sergey Pepyakin
2017-11-25 22:55:45 +03:00
parent 6a3b9af597
commit 5b9e1f04ba
13 changed files with 459 additions and 478 deletions

View File

@ -3,7 +3,7 @@ use std::collections::HashMap;
use builder::module;
use elements::{Module, ExportEntry, Internal, GlobalEntry, GlobalType,
ValueType, InitExpr, Opcode, Opcodes};
use interpreter::{Error, UserError};
use interpreter::Error;
use interpreter::env_native::NATIVE_INDEX_FUNC_MIN;
use interpreter::module::{ModuleInstanceInterface, ModuleInstance, ExecutionParams,
ItemIndex, CallerContext, ExportEntryType, InternalFunctionReference, InternalFunction, FunctionSignature};
@ -84,13 +84,13 @@ pub struct EnvParams {
pub static_size: Option<u32>,
}
pub struct EnvModuleInstance<E: UserError> {
pub struct EnvModuleInstance {
_params: EnvParams,
instance: ModuleInstance<E>,
instance: ModuleInstance,
}
impl<E> EnvModuleInstance<E> where E: UserError {
pub fn new(params: EnvParams, module: Module) -> Result<Self, Error<E>> {
impl EnvModuleInstance {
pub fn new(params: EnvParams, module: Module) -> Result<Self, Error> {
let mut instance = ModuleInstance::new(Weak::default(), "env".into(), module)?;
instance.instantiate(None)?;
@ -101,52 +101,52 @@ impl<E> EnvModuleInstance<E> where E: UserError {
}
}
impl<E> ModuleInstanceInterface<E> for EnvModuleInstance<E> where E: UserError {
fn execute_index(&self, index: u32, params: ExecutionParams<E>) -> Result<Option<RuntimeValue>, Error<E>> {
impl ModuleInstanceInterface for EnvModuleInstance {
fn execute_index(&self, index: u32, params: ExecutionParams) -> Result<Option<RuntimeValue>, Error> {
self.instance.execute_index(index, params)
}
fn execute_export(&self, name: &str, params: ExecutionParams<E>) -> Result<Option<RuntimeValue>, Error<E>> {
fn execute_export(&self, name: &str, params: ExecutionParams) -> Result<Option<RuntimeValue>, Error> {
self.instance.execute_export(name, params)
}
fn export_entry<'a>(&self, name: &str, required_type: &ExportEntryType) -> Result<Internal, Error<E>> {
fn export_entry<'a>(&self, name: &str, required_type: &ExportEntryType) -> Result<Internal, Error> {
self.instance.export_entry(name, required_type)
}
fn table(&self, index: ItemIndex) -> Result<Arc<TableInstance<E>>, Error<E>> {
fn table(&self, index: ItemIndex) -> Result<Arc<TableInstance>, Error> {
self.instance.table(index)
}
fn memory(&self, index: ItemIndex) -> Result<Arc<MemoryInstance<E>>, Error<E>> {
fn memory(&self, index: ItemIndex) -> Result<Arc<MemoryInstance>, Error> {
self.instance.memory(index)
}
fn global<'a>(&self, index: ItemIndex, variable_type: Option<VariableType>, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>>) -> Result<Arc<VariableInstance<E>>, Error<E>> {
fn global<'a>(&self, index: ItemIndex, variable_type: Option<VariableType>, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>) -> Result<Arc<VariableInstance>, Error> {
self.instance.global(index, variable_type, externals)
}
fn function_type(&self, function_index: ItemIndex) -> Result<FunctionSignature, Error<E>> {
fn function_type(&self, function_index: ItemIndex) -> Result<FunctionSignature, Error> {
self.instance.function_type(function_index)
}
fn function_type_by_index(&self, type_index: u32) -> Result<FunctionSignature, Error<E>> {
fn function_type_by_index(&self, type_index: u32) -> Result<FunctionSignature, Error> {
self.instance.function_type_by_index(type_index)
}
fn function_reference<'a>(&self, index: ItemIndex, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>>) -> Result<InternalFunctionReference<'a, E>, Error<E>> {
fn function_reference<'a>(&self, index: ItemIndex, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>) -> Result<InternalFunctionReference<'a>, Error> {
self.instance.function_reference(index, externals)
}
fn function_reference_indirect<'a>(&self, table_idx: u32, type_idx: u32, func_idx: u32, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>>) -> Result<InternalFunctionReference<'a, E>, Error<E>> {
fn function_reference_indirect<'a>(&self, table_idx: u32, type_idx: u32, func_idx: u32, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>) -> Result<InternalFunctionReference<'a>, Error> {
self.instance.function_reference_indirect(table_idx, type_idx, func_idx, externals)
}
fn function_body<'a>(&'a self, _internal_index: u32) -> Result<Option<InternalFunction<'a>>, Error<E>> {
fn function_body<'a>(&'a self, _internal_index: u32) -> Result<Option<InternalFunction<'a>>, Error> {
Ok(None)
}
fn call_internal_function(&self, outer: CallerContext<E>, index: u32) -> Result<Option<RuntimeValue>, Error<E>> {
fn call_internal_function(&self, outer: CallerContext, index: u32) -> Result<Option<RuntimeValue>, Error> {
// to make interpreter independent of *SCRIPTEN runtime, just make abort/assert = interpreter Error
match index {
INDEX_FUNC_ABORT => self.global(ItemIndex::IndexSpace(INDEX_GLOBAL_ABORT), Some(VariableType::I32), None)
@ -173,7 +173,7 @@ impl<E> ModuleInstanceInterface<E> for EnvModuleInstance<E> where E: UserError {
}
}
pub fn env_module<E: UserError>(params: EnvParams) -> Result<EnvModuleInstance<E>, Error<E>> {
pub fn env_module(params: EnvParams) -> Result<EnvModuleInstance, Error> {
debug_assert!(params.total_stack < params.total_memory);
debug_assert!((params.total_stack % LINEAR_MEMORY_PAGE_SIZE) == 0);
debug_assert!((params.total_memory % LINEAR_MEMORY_PAGE_SIZE) == 0);

View File

@ -3,7 +3,7 @@ use std::collections::HashMap;
use std::borrow::Cow;
use parking_lot::RwLock;
use elements::{Internal, ValueType};
use interpreter::{Error, UserError};
use interpreter::Error;
use interpreter::module::{ModuleInstanceInterface, ExecutionParams, ItemIndex,
CallerContext, ExportEntryType, InternalFunctionReference, InternalFunction, FunctionSignature};
use interpreter::memory::MemoryInstance;
@ -17,9 +17,9 @@ pub const NATIVE_INDEX_FUNC_MIN: u32 = 10001;
pub const NATIVE_INDEX_GLOBAL_MIN: u32 = 20001;
/// User functions executor.
pub trait UserFunctionExecutor<E: UserError> {
pub trait UserFunctionExecutor {
/// Execute function with given name.
fn execute(&mut self, name: &str, context: CallerContext<E>) -> Result<Option<RuntimeValue>, Error<E>>;
fn execute(&mut self, name: &str, context: CallerContext) -> Result<Option<RuntimeValue>, Error>;
}
/// User function descriptor
@ -68,21 +68,21 @@ impl UserFunctionDescriptor {
}
/// Set of user-defined module elements.
pub struct UserDefinedElements<'a, E: 'a + UserError> {
pub struct UserDefinedElements<'a> {
/// User globals list.
pub globals: HashMap<String, Arc<VariableInstance<E>>>,
pub globals: HashMap<String, Arc<VariableInstance>>,
/// User functions list.
pub functions: Cow<'static, [UserFunctionDescriptor]>,
/// Functions executor.
pub executor: Option<&'a mut UserFunctionExecutor<E>>,
pub executor: Option<&'a mut UserFunctionExecutor>,
}
/// Native module instance.
pub struct NativeModuleInstance<'a, E: 'a + UserError> {
pub struct NativeModuleInstance<'a> {
/// Underllying module reference.
env: Arc<ModuleInstanceInterface<E>>,
env: Arc<ModuleInstanceInterface>,
/// User function executor.
executor: RwLock<Option<&'a mut UserFunctionExecutor<E>>>,
executor: RwLock<Option<&'a mut UserFunctionExecutor>>,
/// By-name functions index.
functions_by_name: HashMap<String, u32>,
/// User functions list.
@ -90,12 +90,12 @@ pub struct NativeModuleInstance<'a, E: 'a + UserError> {
/// By-name functions index.
globals_by_name: HashMap<String, u32>,
/// User globals list.
globals: Vec<Arc<VariableInstance<E>>>,
globals: Vec<Arc<VariableInstance>>,
}
impl<'a, E> NativeModuleInstance<'a, E> where E: UserError {
impl<'a> NativeModuleInstance<'a> {
/// Create new native module
pub fn new(env: Arc<ModuleInstanceInterface<E>>, elements: UserDefinedElements<'a, E>) -> Result<Self, Error<E>> {
pub fn new(env: Arc<ModuleInstanceInterface>, elements: UserDefinedElements<'a>) -> Result<Self, Error> {
if !elements.functions.is_empty() && elements.executor.is_none() {
return Err(Error::Function("trying to construct native env module with functions, but without executor".into()));
}
@ -111,16 +111,16 @@ impl<'a, E> NativeModuleInstance<'a, E> where E: UserError {
}
}
impl<'a, E> ModuleInstanceInterface<E> for NativeModuleInstance<'a, E> where E: UserError {
fn execute_index(&self, index: u32, params: ExecutionParams<E>) -> Result<Option<RuntimeValue>, Error<E>> {
impl<'a> ModuleInstanceInterface for NativeModuleInstance<'a> {
fn execute_index(&self, index: u32, params: ExecutionParams) -> Result<Option<RuntimeValue>, Error> {
self.env.execute_index(index, params)
}
fn execute_export(&self, name: &str, params: ExecutionParams<E>) -> Result<Option<RuntimeValue>, Error<E>> {
fn execute_export(&self, name: &str, params: ExecutionParams) -> Result<Option<RuntimeValue>, Error> {
self.env.execute_export(name, params)
}
fn export_entry<'b>(&self, name: &str, required_type: &ExportEntryType) -> Result<Internal, Error<E>> {
fn export_entry<'b>(&self, name: &str, required_type: &ExportEntryType) -> Result<Internal, Error> {
if let Some(index) = self.functions_by_name.get(name) {
let composite_index = NATIVE_INDEX_FUNC_MIN + *index;
match required_type {
@ -177,15 +177,15 @@ impl<'a, E> ModuleInstanceInterface<E> for NativeModuleInstance<'a, E> where E:
self.env.export_entry(name, required_type)
}
fn table(&self, index: ItemIndex) -> Result<Arc<TableInstance<E>>, Error<E>> {
fn table(&self, index: ItemIndex) -> Result<Arc<TableInstance>, Error> {
self.env.table(index)
}
fn memory(&self, index: ItemIndex) -> Result<Arc<MemoryInstance<E>>, Error<E>> {
fn memory(&self, index: ItemIndex) -> Result<Arc<MemoryInstance>, Error> {
self.env.memory(index)
}
fn global<'b>(&self, global_index: ItemIndex, variable_type: Option<VariableType>, externals: Option<&'b HashMap<String, Arc<ModuleInstanceInterface<E> + 'b>>>) -> Result<Arc<VariableInstance<E>>, Error<E>> {
fn global<'b>(&self, global_index: ItemIndex, variable_type: Option<VariableType>, externals: Option<&'b HashMap<String, Arc<ModuleInstanceInterface + 'b>>>) -> Result<Arc<VariableInstance>, Error> {
let index = match global_index {
ItemIndex::IndexSpace(index) | ItemIndex::Internal(index) => index,
ItemIndex::External(_) => unreachable!("trying to get global, exported by native env module"),
@ -201,7 +201,7 @@ impl<'a, E> ModuleInstanceInterface<E> for NativeModuleInstance<'a, E> where E:
.ok_or(Error::Native(format!("trying to get native global with index {}", index)))
}
fn function_type(&self, function_index: ItemIndex) -> Result<FunctionSignature, Error<E>> {
fn function_type(&self, function_index: ItemIndex) -> Result<FunctionSignature, Error> {
let index = match function_index {
ItemIndex::IndexSpace(index) | ItemIndex::Internal(index) => index,
ItemIndex::External(_) => unreachable!("trying to call function, exported by native env module"),
@ -216,23 +216,23 @@ impl<'a, E> ModuleInstanceInterface<E> for NativeModuleInstance<'a, E> where E:
.ok_or(Error::Native(format!("missing native env function with index {}", index)))?))
}
fn function_type_by_index(&self, type_index: u32) -> Result<FunctionSignature, Error<E>> {
fn function_type_by_index(&self, type_index: u32) -> Result<FunctionSignature, Error> {
self.function_type(ItemIndex::Internal(type_index))
}
fn function_reference<'b>(&self, index: ItemIndex, externals: Option<&'b HashMap<String, Arc<ModuleInstanceInterface<E> + 'b>>>) -> Result<InternalFunctionReference<'b, E>, Error<E>> {
fn function_reference<'b>(&self, index: ItemIndex, externals: Option<&'b HashMap<String, Arc<ModuleInstanceInterface + 'b>>>) -> Result<InternalFunctionReference<'b>, Error> {
self.env.function_reference(index, externals)
}
fn function_reference_indirect<'b>(&self, table_idx: u32, type_idx: u32, func_idx: u32, externals: Option<&'b HashMap<String, Arc<ModuleInstanceInterface<E> + 'b>>>) -> Result<InternalFunctionReference<'b, E>, Error<E>> {
fn function_reference_indirect<'b>(&self, table_idx: u32, type_idx: u32, func_idx: u32, externals: Option<&'b HashMap<String, Arc<ModuleInstanceInterface + 'b>>>) -> Result<InternalFunctionReference<'b>, Error> {
self.env.function_reference_indirect(table_idx, type_idx, func_idx, externals)
}
fn function_body<'b>(&'b self, _internal_index: u32) -> Result<Option<InternalFunction<'b>>, Error<E>> {
fn function_body<'b>(&'b self, _internal_index: u32) -> Result<Option<InternalFunction<'b>>, Error> {
Ok(None)
}
fn call_internal_function(&self, outer: CallerContext<E>, index: u32) -> Result<Option<RuntimeValue>, Error<E>> {
fn call_internal_function(&self, outer: CallerContext, index: u32) -> Result<Option<RuntimeValue>, Error> {
if index < NATIVE_INDEX_FUNC_MIN || index >= NATIVE_INDEX_GLOBAL_MIN {
return self.env.call_internal_function(outer, index);
}
@ -248,7 +248,7 @@ impl<'a, E> ModuleInstanceInterface<E> for NativeModuleInstance<'a, E> where E:
}
/// Create wrapper for env module with given native user functions.
pub fn env_native_module<'a, E: UserError>(env: Arc<ModuleInstanceInterface<E>>, user_elements: UserDefinedElements<'a, E>) -> Result<NativeModuleInstance<E>, Error<E>> {
pub fn env_native_module<'a>(env: Arc<ModuleInstanceInterface>, user_elements: UserDefinedElements<'a>) -> Result<NativeModuleInstance, Error> {
NativeModuleInstance::new(env, user_elements)
}

View File

@ -1,7 +1,7 @@
use std::sync::{Arc, Weak};
use std::collections::HashMap;
use elements::{ImportSection, ImportEntry, External, Internal};
use interpreter::{Error, UserError};
use interpreter::Error;
use interpreter::memory::MemoryInstance;
use interpreter::module::{ModuleInstanceInterface, ItemIndex, ExportEntryType, FunctionSignature};
use interpreter::program::ProgramInstanceEssence;
@ -9,9 +9,9 @@ use interpreter::table::TableInstance;
use interpreter::variable::{VariableInstance, VariableType};
/// Module imports.
pub struct ModuleImports<E: UserError> {
pub struct ModuleImports {
/// Program instance.
program: Weak<ProgramInstanceEssence<E>>,
program: Weak<ProgramInstanceEssence>,
/// External functions.
functions: Vec<usize>,
/// External tables.
@ -22,9 +22,9 @@ pub struct ModuleImports<E: UserError> {
globals: Vec<usize>,
}
impl<E> ModuleImports<E> where E: UserError {
impl ModuleImports {
/// Create new imports for given import section.
pub fn new(program: Weak<ProgramInstanceEssence<E>>, import_section: Option<&ImportSection>) -> Self {
pub fn new(program: Weak<ProgramInstanceEssence>, import_section: Option<&ImportSection>) -> Self {
let mut functions = Vec::new();
let mut tables = Vec::new();
let mut memory = Vec::new();
@ -104,7 +104,7 @@ impl<E> ModuleImports<E> where E: UserError {
}
/// Get module reference.
pub fn module<'a>(&self, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>>, name: &str) -> Result<Arc<ModuleInstanceInterface<E> + 'a>, Error<E>> {
pub fn module<'a>(&self, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>, name: &str) -> Result<Arc<ModuleInstanceInterface + 'a>, Error> {
if let Some(externals) = externals {
if let Some(module) = externals.get(name).cloned() {
return Ok(module);
@ -118,7 +118,7 @@ impl<E> ModuleImports<E> where E: UserError {
}
/// Get function index.
pub fn function<'a>(&self, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>>, import: &ImportEntry, required_type: Option<FunctionSignature>) -> Result<u32, Error<E>> {
pub fn function<'a>(&self, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>, import: &ImportEntry, required_type: Option<FunctionSignature>) -> Result<u32, Error> {
let (_, export) = self.external_export(externals, import, &required_type.map(|ft| ExportEntryType::Function(ft)).unwrap_or(ExportEntryType::Any))?;
if let Internal::Function(external_index) = export {
return Ok(external_index);
@ -128,7 +128,7 @@ impl<E> ModuleImports<E> where E: UserError {
}
/// Get table reference.
pub fn table<'a>(&self, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>>, import: &ImportEntry) -> Result<Arc<TableInstance<E>>, Error<E>> {
pub fn table<'a>(&self, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>, import: &ImportEntry) -> Result<Arc<TableInstance>, Error> {
let (module, export) = self.external_export(externals, import, &ExportEntryType::Any)?;
if let Internal::Table(external_index) = export {
return module.table(ItemIndex::Internal(external_index));
@ -138,7 +138,7 @@ impl<E> ModuleImports<E> where E: UserError {
}
/// Get memory reference.
pub fn memory<'a>(&self, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>>, import: &ImportEntry) -> Result<Arc<MemoryInstance<E>>, Error<E>> {
pub fn memory<'a>(&self, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>, import: &ImportEntry) -> Result<Arc<MemoryInstance>, Error> {
let (module, export) = self.external_export(externals, import, &ExportEntryType::Any)?;
if let Internal::Memory(external_index) = export {
return module.memory(ItemIndex::Internal(external_index));
@ -148,7 +148,7 @@ impl<E> ModuleImports<E> where E: UserError {
}
/// Get global reference.
pub fn global<'a>(&self, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>>, import: &ImportEntry, required_type: Option<VariableType>) -> Result<Arc<VariableInstance<E>>, Error<E>> {
pub fn global<'a>(&self, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>, import: &ImportEntry, required_type: Option<VariableType>) -> Result<Arc<VariableInstance>, Error> {
let (module, export) = self.external_export(externals, import, &required_type.clone().map(|rt| ExportEntryType::Global(rt)).unwrap_or(ExportEntryType::Any))?;
if let Internal::Global(external_index) = export {
return module.global(ItemIndex::Internal(external_index), required_type, externals);
@ -157,7 +157,7 @@ impl<E> ModuleImports<E> where E: UserError {
Err(Error::Program(format!("wrong import {} from module {} (expecting global)", import.field(), import.module())))
}
fn external_export<'a>(&self, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>>, import: &ImportEntry, required_type: &ExportEntryType) -> Result<(Arc<ModuleInstanceInterface<E> + 'a>, Internal), Error<E>> {
fn external_export<'a>(&self, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>, import: &ImportEntry, required_type: &ExportEntryType) -> Result<(Arc<ModuleInstanceInterface + 'a>, Internal), Error> {
self.module(externals, import.module())
.and_then(|m|
m.export_entry(import.field(), required_type)

View File

@ -4,7 +4,7 @@ use std::ops::Range;
use std::cmp;
use parking_lot::RwLock;
use elements::{MemoryType, ResizableLimits};
use interpreter::{Error, UserError};
use interpreter::Error;
use interpreter::module::check_limits;
/// Linear memory page size.
@ -13,15 +13,13 @@ pub const LINEAR_MEMORY_PAGE_SIZE: u32 = 65536;
const LINEAR_MEMORY_MAX_PAGES: u32 = 65536;
/// Linear memory instance.
pub struct MemoryInstance<E: UserError> {
pub struct MemoryInstance {
/// Memofy limits.
limits: ResizableLimits,
/// Linear memory buffer.
buffer: RwLock<Vec<u8>>,
/// Maximum buffer size.
maximum_size: u32,
/// Dummy to avoid compilation error.
_dummy: ::std::marker::PhantomData<E>,
}
struct CheckedRegion<'a, B: 'a> where B: ::std::ops::Deref<Target=Vec<u8>> {
@ -47,9 +45,9 @@ impl<'a, B: 'a> CheckedRegion<'a, B> where B: ::std::ops::Deref<Target=Vec<u8>>
}
}
impl<E> MemoryInstance<E> where E: UserError {
impl MemoryInstance {
/// Create new linear memory instance.
pub fn new(memory_type: &MemoryType) -> Result<Arc<Self>, Error<E>> {
pub fn new(memory_type: &MemoryType) -> Result<Arc<Self>, Error> {
check_limits(memory_type.limits())?;
let maximum_size = match memory_type.limits().maximum() {
@ -65,7 +63,6 @@ impl<E> MemoryInstance<E> where E: UserError {
limits: memory_type.limits().clone(),
buffer: RwLock::new(vec![0; initial_size as usize]),
maximum_size: maximum_size,
_dummy: Default::default(),
};
Ok(Arc::new(memory))
@ -82,7 +79,7 @@ impl<E> MemoryInstance<E> where E: UserError {
}
/// Get data at given offset.
pub fn get(&self, offset: u32, size: usize) -> Result<Vec<u8>, Error<E>> {
pub fn get(&self, offset: u32, size: usize) -> Result<Vec<u8>, Error> {
let buffer = self.buffer.read();
let region = self.checked_region(&buffer, offset as usize, size)?;
@ -90,7 +87,7 @@ impl<E> MemoryInstance<E> where E: UserError {
}
/// Write memory slice into another slice
pub fn get_into(&self, offset: u32, target: &mut [u8]) -> Result<(), Error<E>> {
pub fn get_into(&self, offset: u32, target: &mut [u8]) -> Result<(), Error> {
let buffer = self.buffer.read();
let region = self.checked_region(&buffer, offset as usize, target.len())?;
@ -100,7 +97,7 @@ impl<E> MemoryInstance<E> where E: UserError {
}
/// Set data at given offset.
pub fn set(&self, offset: u32, value: &[u8]) -> Result<(), Error<E>> {
pub fn set(&self, offset: u32, value: &[u8]) -> Result<(), Error> {
let mut buffer = self.buffer.write();
let range = self.checked_region(&buffer, offset as usize, value.len())?.range();
@ -111,7 +108,7 @@ impl<E> MemoryInstance<E> where E: UserError {
/// Increases the size of the linear memory by given number of pages.
/// Returns -1 if allocation fails or previous memory size, if succeeds.
pub fn grow(&self, pages: u32) -> Result<u32, Error<E>> {
pub fn grow(&self, pages: u32) -> Result<u32, Error> {
let mut buffer = self.buffer.write();
let old_size = buffer.len() as u32;
match calculate_memory_size(old_size, pages, self.maximum_size) {
@ -123,7 +120,7 @@ impl<E> MemoryInstance<E> where E: UserError {
}
}
fn checked_region<'a, B>(&self, buffer: &'a B, offset: usize, size: usize) -> Result<CheckedRegion<'a, B>, Error<E>>
fn checked_region<'a, B>(&self, buffer: &'a B, offset: usize, size: usize) -> Result<CheckedRegion<'a, B>, Error>
where B: ::std::ops::Deref<Target=Vec<u8>>
{
let end = offset.checked_add(size)
@ -141,7 +138,7 @@ impl<E> MemoryInstance<E> where E: UserError {
}
/// Copy memory region. Semantically equivalent to `memmove`.
pub fn copy(&self, src_offset: usize, dst_offset: usize, len: usize) -> Result<(), Error<E>> {
pub fn copy(&self, src_offset: usize, dst_offset: usize, len: usize) -> Result<(), Error> {
let buffer = self.buffer.write();
let read_region = self.checked_region(&buffer, src_offset, len)?;
@ -158,7 +155,7 @@ impl<E> MemoryInstance<E> where E: UserError {
/// Copy memory region, non-overlapping version. Semantically equivalent to `memcpy`,
/// but returns Error if source overlaping with destination.
pub fn copy_nonoverlapping(&self, src_offset: usize, dst_offset: usize, len: usize) -> Result<(), Error<E>> {
pub fn copy_nonoverlapping(&self, src_offset: usize, dst_offset: usize, len: usize) -> Result<(), Error> {
let buffer = self.buffer.write();
let read_region = self.checked_region(&buffer, src_offset, len)?;
@ -178,7 +175,7 @@ impl<E> MemoryInstance<E> where E: UserError {
}
/// Clear memory region with a specified value. Semantically equivalent to `memset`.
pub fn clear(&self, offset: usize, new_val: u8, len: usize) -> Result<(), Error<E>> {
pub fn clear(&self, offset: usize, new_val: u8, len: usize) -> Result<(), Error> {
let mut buffer = self.buffer.write();
let range = self.checked_region(&buffer, offset, len)?.range();
@ -187,7 +184,7 @@ impl<E> MemoryInstance<E> where E: UserError {
}
/// Zero memory region
pub fn zero(&self, offset: usize, len: usize) -> Result<(), Error<E>> {
pub fn zero(&self, offset: usize, len: usize) -> Result<(), Error> {
self.clear(offset, 0, len)
}
}

View File

@ -30,7 +30,7 @@ impl UserError {
/// Internal interpreter error.
#[derive(Debug)]
pub enum Error<E> where E: UserError {
pub enum Error {
/// Program-level error.
Program(String),
/// Validation error.
@ -63,10 +63,9 @@ pub enum Error<E> where E: UserError {
Trap(String),
/// Custom user error.
User(Box<UserError>),
Other(E),
}
impl<E> Into<String> for Error<E> where E: UserError {
impl Into<String> for Error {
fn into(self) -> String {
match self {
Error::Program(s) => s,
@ -85,12 +84,11 @@ impl<E> Into<String> for Error<E> where E: UserError {
Error::Native(s) => s,
Error::Trap(s) => format!("trap: {}", s),
Error::User(e) => format!("user: {}", e),
Error::Other(_) => panic!("TODO: Remove this arm "),
}
}
}
impl<E> ::std::fmt::Display for Error<E> where E: UserError {
impl ::std::fmt::Display for Error {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
match *self {
Error::Program(ref s) => write!(f, "Program: {}", s),
@ -109,7 +107,6 @@ impl<E> ::std::fmt::Display for Error<E> where E: UserError {
Error::Native(ref s) => write!(f, "Native: {}", s),
Error::Trap(ref s) => write!(f, "Trap: {}", s),
Error::User(ref e) => write!(f, "User: {}", e),
Error::Other(_) => panic!("TODO: Remove this arm "),
}
}
}
@ -124,7 +121,7 @@ impl ::std::fmt::Display for DummyUserError {
fn fmt(&self, _f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { Ok(()) }
}
impl<U> From<U> for Error<U> where U: UserError + Sized {
impl<U> From<U> for Error where U: UserError + Sized {
fn from(e: U) -> Self {
Error::User(Box::new(e))
}
@ -157,16 +154,20 @@ pub use self::env_native::{env_native_module, UserDefinedElements, UserFunctionE
pub use self::env::EnvParams;
/// Default type of Error if you do not need any custom user errors.
pub type DummyError = Error<DummyUserError>;
#[deprecated]
pub type DummyError = Error;
/// Default type of ProgramInstance if you do not need any custom user errors.
/// To work with custom user errors or interpreter internals, use CustomProgramInstance.
pub type DefaultProgramInstance = self::program::ProgramInstance<DummyUserError>;
#[deprecated]
pub type DefaultProgramInstance = self::program::ProgramInstance;
/// Default type of ModuleInstance if you do not need any custom user errors.
/// To work with custom user errors or interpreter internals, use CustomModuleInstance.
pub type DefaultModuleInstance = self::module::ModuleInstance<DummyUserError>;
#[deprecated]
pub type DefaultModuleInstance = self::module::ModuleInstance;
/// Default type of ModuleInstanceInterface if you do not need any custom user errors.
/// To work with custom user errors or interpreter internals, use CustomModuleInstanceInterface.
pub type DefaultModuleInstanceInterface = self::module::ModuleInstanceInterface<DummyUserError>;
#[deprecated]
pub type DefaultModuleInstanceInterface = self::module::ModuleInstanceInterface;

View File

@ -3,7 +3,7 @@ use std::iter::repeat;
use std::sync::{Arc, Weak};
use std::fmt;
use elements::{Module, InitExpr, Opcode, Type, FunctionType, Internal, External, BlockType, ResizableLimits, Local, ValueType};
use interpreter::{Error, UserError};
use interpreter::Error;
use interpreter::env_native::UserFunctionDescriptor;
use interpreter::imports::ModuleImports;
use interpreter::memory::MemoryInstance;
@ -22,11 +22,11 @@ const DEFAULT_FRAME_STACK_LIMIT: usize = 1024;
/// Execution context.
#[derive(Clone)]
pub struct ExecutionParams<'a, E: UserError> {
pub struct ExecutionParams<'a> {
/// Arguments.
pub args: Vec<RuntimeValue>,
/// Execution-local external modules.
pub externals: HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>,
pub externals: HashMap<String, Arc<ModuleInstanceInterface + 'a>>,
}
/// Export type.
@ -50,31 +50,31 @@ pub enum FunctionSignature<'a> {
}
/// Module instance API.
pub trait ModuleInstanceInterface<E: UserError> {
pub trait ModuleInstanceInterface {
/// Execute function with the given index.
fn execute_index(&self, index: u32, params: ExecutionParams<E>) -> Result<Option<RuntimeValue>, Error<E>>;
fn execute_index(&self, index: u32, params: ExecutionParams) -> Result<Option<RuntimeValue>, Error>;
/// Execute function with the given export name.
fn execute_export(&self, name: &str, params: ExecutionParams<E>) -> Result<Option<RuntimeValue>, Error<E>>;
fn execute_export(&self, name: &str, params: ExecutionParams) -> Result<Option<RuntimeValue>, Error>;
/// Get export entry.
fn export_entry<'a>(&self, name: &str, required_type: &ExportEntryType) -> Result<Internal, Error<E>>;
fn export_entry<'a>(&self, name: &str, required_type: &ExportEntryType) -> Result<Internal, Error>;
/// Get table reference.
fn table(&self, index: ItemIndex) -> Result<Arc<TableInstance<E>>, Error<E>>;
fn table(&self, index: ItemIndex) -> Result<Arc<TableInstance>, Error>;
/// Get memory reference.
fn memory(&self, index: ItemIndex) -> Result<Arc<MemoryInstance<E>>, Error<E>>;
fn memory(&self, index: ItemIndex) -> Result<Arc<MemoryInstance>, Error>;
/// Get global reference.
fn global<'a>(&self, index: ItemIndex, variable_type: Option<VariableType>, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>>) -> Result<Arc<VariableInstance<E>>, Error<E>>;
fn global<'a>(&self, index: ItemIndex, variable_type: Option<VariableType>, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>) -> Result<Arc<VariableInstance>, Error>;
/// Get function type for given function index.
fn function_type(&self, function_index: ItemIndex) -> Result<FunctionSignature, Error<E>>;
fn function_type(&self, function_index: ItemIndex) -> Result<FunctionSignature, Error>;
/// Get function type for given function index.
fn function_type_by_index(&self, type_index: u32) -> Result<FunctionSignature, Error<E>>;
fn function_type_by_index(&self, type_index: u32) -> Result<FunctionSignature, Error>;
/// Get function reference.
fn function_reference<'a>(&self, index: ItemIndex, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>>) -> Result<InternalFunctionReference<'a, E>, Error<E>>;
fn function_reference<'a>(&self, index: ItemIndex, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>) -> Result<InternalFunctionReference<'a>, Error>;
/// Get function indirect reference.
fn function_reference_indirect<'a>(&self, table_idx: u32, type_idx: u32, func_idx: u32, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>>) -> Result<InternalFunctionReference<'a, E>, Error<E>>;
fn function_reference_indirect<'a>(&self, table_idx: u32, type_idx: u32, func_idx: u32, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>) -> Result<InternalFunctionReference<'a>, Error>;
/// Get internal function for interpretation.
fn function_body<'a>(&'a self, internal_index: u32) -> Result<Option<InternalFunction<'a>>, Error<E>>;
fn function_body<'a>(&'a self, internal_index: u32) -> Result<Option<InternalFunction<'a>>, Error>;
/// Call function with given internal index.
fn call_internal_function(&self, outer: CallerContext<E>, index: u32) -> Result<Option<RuntimeValue>, Error<E>>;
fn call_internal_function(&self, outer: CallerContext, index: u32) -> Result<Option<RuntimeValue>, Error>;
}
/// Item index in items index space.
@ -89,7 +89,7 @@ pub enum ItemIndex {
}
/// Module instance.
pub struct ModuleInstance<E: UserError> {
pub struct ModuleInstance {
/// Module name.
name: String,
/// Module.
@ -97,48 +97,39 @@ pub struct ModuleInstance<E: UserError> {
/// Function labels.
functions_labels: HashMap<u32, HashMap<usize, usize>>,
/// Module imports.
imports: ModuleImports<E>,
imports: ModuleImports,
/// Module exports.
exports: HashMap<String, Vec<Internal>>,
/// Tables.
tables: Vec<Arc<TableInstance<E>>>,
tables: Vec<Arc<TableInstance>>,
/// Linear memory regions.
memory: Vec<Arc<MemoryInstance<E>>>,
memory: Vec<Arc<MemoryInstance>>,
/// Globals.
globals: Vec<Arc<VariableInstance<E>>>,
globals: Vec<Arc<VariableInstance>>,
}
/// Caller context.
pub struct CallerContext<'a, E: 'a + UserError> {
pub struct CallerContext<'a> {
/// Value stack limit
pub value_stack_limit: usize,
/// Frame stack limit
pub frame_stack_limit: usize,
/// Stack of the input parameters
pub value_stack: &'a mut StackWithLimit<RuntimeValue, E>,
pub value_stack: &'a mut StackWithLimit<RuntimeValue>,
/// Execution-local external modules.
pub externals: &'a HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>,
pub externals: &'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>,
}
/// Internal function reference.
pub struct InternalFunctionReference<'a, E: UserError> {
#[derive(Clone)]
pub struct InternalFunctionReference<'a> {
/// Module reference.
pub module: Arc<ModuleInstanceInterface<E> + 'a>,
pub module: Arc<ModuleInstanceInterface + 'a>,
/// Internal function index.
pub internal_index: u32,
}
// TODO: This impl should be removed once `E` not needed anymore.
impl<'a, E> Clone for InternalFunctionReference<'a, E> where E: UserError {
fn clone(&self) -> InternalFunctionReference<'a, E> {
InternalFunctionReference {
module: Arc::clone(&self.module),
internal_index: self.internal_index,
}
}
}
impl<'a, E> fmt::Debug for InternalFunctionReference<'a, E> where E: UserError {
impl<'a> fmt::Debug for InternalFunctionReference<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "InternalFunctionReference")
}
@ -154,9 +145,9 @@ pub struct InternalFunction<'a> {
pub labels: &'a HashMap<usize, usize>,
}
impl<'a, E> ExecutionParams<'a, E> where E: UserError {
impl<'a> ExecutionParams<'a> {
/// Create new execution params with given externa; module override.
pub fn with_external(name: String, module: Arc<ModuleInstanceInterface<E> + 'a>) -> Self {
pub fn with_external(name: String, module: Arc<ModuleInstanceInterface + 'a>) -> Self {
let mut externals = HashMap::new();
externals.insert(name, module);
ExecutionParams {
@ -172,7 +163,7 @@ impl<'a, E> ExecutionParams<'a, E> where E: UserError {
}
}
impl<'a, E> Default for ExecutionParams<'a, E> where E: UserError {
impl<'a> Default for ExecutionParams<'a> {
fn default() -> Self {
ExecutionParams {
args: Vec::default(),
@ -181,8 +172,8 @@ impl<'a, E> Default for ExecutionParams<'a, E> where E: UserError {
}
}
impl<'a, E> From<Vec<RuntimeValue>> for ExecutionParams<'a, E> where E: UserError {
fn from(args: Vec<RuntimeValue>) -> ExecutionParams<'a, E> {
impl<'a> From<Vec<RuntimeValue>> for ExecutionParams<'a> {
fn from(args: Vec<RuntimeValue>) -> ExecutionParams<'a> {
ExecutionParams {
args: args,
externals: HashMap::new(),
@ -190,9 +181,9 @@ impl<'a, E> From<Vec<RuntimeValue>> for ExecutionParams<'a, E> where E: UserErro
}
}
impl<E> ModuleInstance<E> where E: UserError {
impl ModuleInstance {
/// Instantiate given module within program context.
pub fn new<'a>(program: Weak<ProgramInstanceEssence<E>>, name: String, module: Module) -> Result<Self, Error<E>> {
pub fn new<'a>(program: Weak<ProgramInstanceEssence>, name: String, module: Module) -> Result<Self, Error> {
// load entries from import section
let imports = ModuleImports::new(program, module.import_section());
@ -240,7 +231,7 @@ impl<E> ModuleInstance<E> where E: UserError {
}
/// Run instantiation-time procedures (validation). Module is not completely validated until this call.
pub fn instantiate<'a>(&mut self, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>>) -> Result<(), Error<E>> {
pub fn instantiate<'a>(&mut self, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>) -> Result<(), Error> {
// validate start section
if let Some(start_function) = self.module.start_section() {
let func_type_index = self.require_function(ItemIndex::IndexSpace(start_function))?;
@ -442,7 +433,7 @@ impl<E> ModuleInstance<E> where E: UserError {
}
/// Run start function [if any].
pub fn run_start_function(&self) -> Result<(), Error<E>> {
pub fn run_start_function(&self) -> Result<(), Error> {
// execute start function (if any)
if let Some(start_function) = self.module.start_section() {
self.execute_index(start_function, ExecutionParams::default())?;
@ -450,11 +441,11 @@ impl<E> ModuleInstance<E> where E: UserError {
Ok(())
}
fn self_ref<'a>(&self, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>>) -> Result<Arc<ModuleInstanceInterface<E> + 'a>, Error<E>> {
fn self_ref<'a>(&self, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>) -> Result<Arc<ModuleInstanceInterface + 'a>, Error> {
self.imports.module(externals, &self.name)
}
fn require_function(&self, index: ItemIndex) -> Result<u32, Error<E>> {
fn require_function(&self, index: ItemIndex) -> Result<u32, Error> {
match self.imports.parse_function_index(index) {
ItemIndex::IndexSpace(_) => unreachable!("parse_function_index resolves IndexSpace option"),
ItemIndex::Internal(index) => self.module.function_section()
@ -474,8 +465,8 @@ impl<E> ModuleInstance<E> where E: UserError {
}
}
impl<E> ModuleInstanceInterface<E> for ModuleInstance<E> where E: UserError {
fn execute_index(&self, index: u32, params: ExecutionParams<E>) -> Result<Option<RuntimeValue>, Error<E>> {
impl ModuleInstanceInterface for ModuleInstance {
fn execute_index(&self, index: u32, params: ExecutionParams) -> Result<Option<RuntimeValue>, Error> {
let ExecutionParams { args, externals } = params;
let mut args = StackWithLimit::with_data(args, DEFAULT_VALUE_STACK_LIMIT);
let function_reference = self.function_reference(ItemIndex::IndexSpace(index), Some(&externals))?;
@ -483,7 +474,7 @@ impl<E> ModuleInstanceInterface<E> for ModuleInstance<E> where E: UserError {
function_reference.module.call_internal_function(function_context, function_reference.internal_index)
}
fn execute_export(&self, name: &str, params: ExecutionParams<E>) -> Result<Option<RuntimeValue>, Error<E>> {
fn execute_export(&self, name: &str, params: ExecutionParams) -> Result<Option<RuntimeValue>, Error> {
let index = self.exports.get(name)
.ok_or(Error::Function(format!("missing executable export with name {}", name)))
.and_then(|l| l.iter()
@ -500,7 +491,7 @@ impl<E> ModuleInstanceInterface<E> for ModuleInstance<E> where E: UserError {
self.execute_index(index, params)
}
fn export_entry<'a>(&self, name: &str, required_type: &ExportEntryType) -> Result<Internal, Error<E>> {
fn export_entry<'a>(&self, name: &str, required_type: &ExportEntryType) -> Result<Internal, Error> {
self.exports.get(name)
.ok_or(Error::Function(format!("missing export entry with name {}", name)))
.and_then(|l| l.iter()
@ -522,7 +513,7 @@ impl<E> ModuleInstanceInterface<E> for ModuleInstance<E> where E: UserError {
.ok_or(Error::Program(format!("unresolved export {}", name))))
}
fn table(&self, index: ItemIndex) -> Result<Arc<TableInstance<E>>, Error<E>> {
fn table(&self, index: ItemIndex) -> Result<Arc<TableInstance>, Error> {
match self.imports.parse_table_index(index) {
ItemIndex::IndexSpace(_) => unreachable!("parse_table_index resolves IndexSpace option"),
ItemIndex::Internal(index) => self.tables.get(index as usize).cloned()
@ -535,7 +526,7 @@ impl<E> ModuleInstanceInterface<E> for ModuleInstance<E> where E: UserError {
}
}
fn memory(&self, index: ItemIndex) -> Result<Arc<MemoryInstance<E>>, Error<E>> {
fn memory(&self, index: ItemIndex) -> Result<Arc<MemoryInstance>, Error> {
match self.imports.parse_memory_index(index) {
ItemIndex::IndexSpace(_) => unreachable!("parse_memory_index resolves IndexSpace option"),
ItemIndex::Internal(index) => self.memory.get(index as usize).cloned()
@ -548,7 +539,7 @@ impl<E> ModuleInstanceInterface<E> for ModuleInstance<E> where E: UserError {
}
}
fn global<'a>(&self, index: ItemIndex, variable_type: Option<VariableType>, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>>) -> Result<Arc<VariableInstance<E>>, Error<E>> {
fn global<'a>(&self, index: ItemIndex, variable_type: Option<VariableType>, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>) -> Result<Arc<VariableInstance>, Error> {
match self.imports.parse_global_index(index) {
ItemIndex::IndexSpace(_) => unreachable!("parse_global_index resolves IndexSpace option"),
ItemIndex::Internal(index) => self.globals.get(index as usize).cloned()
@ -561,7 +552,7 @@ impl<E> ModuleInstanceInterface<E> for ModuleInstance<E> where E: UserError {
}
}
fn function_type(&self, function_index: ItemIndex) -> Result<FunctionSignature, Error<E>> {
fn function_type(&self, function_index: ItemIndex) -> Result<FunctionSignature, Error> {
match self.imports.parse_function_index(function_index) {
ItemIndex::IndexSpace(_) => unreachable!("parse_function_index resolves IndexSpace option"),
ItemIndex::Internal(index) => self.require_function(ItemIndex::Internal(index))
@ -577,7 +568,7 @@ impl<E> ModuleInstanceInterface<E> for ModuleInstance<E> where E: UserError {
}
}
fn function_type_by_index(&self, type_index: u32) -> Result<FunctionSignature, Error<E>> {
fn function_type_by_index(&self, type_index: u32) -> Result<FunctionSignature, Error> {
self.module.type_section()
.ok_or(Error::Validation(format!("type reference {} exists in module without type section", type_index)))
.and_then(|s| match s.types().get(type_index as usize) {
@ -587,7 +578,7 @@ impl<E> ModuleInstanceInterface<E> for ModuleInstance<E> where E: UserError {
.map(FunctionSignature::Module)
}
fn function_reference<'a>(&self, index: ItemIndex, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>>) -> Result<InternalFunctionReference<'a, E>, Error<E>> {
fn function_reference<'a>(&self, index: ItemIndex, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>) -> Result<InternalFunctionReference<'a>, Error> {
match self.imports.parse_function_index(index) {
ItemIndex::IndexSpace(_) => unreachable!("parse_function_index resolves IndexSpace option"),
ItemIndex::Internal(index) => Ok(InternalFunctionReference {
@ -609,7 +600,7 @@ impl<E> ModuleInstanceInterface<E> for ModuleInstance<E> where E: UserError {
}
}
fn function_reference_indirect<'a>(&self, table_idx: u32, type_idx: u32, func_idx: u32, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>>) -> Result<InternalFunctionReference<'a, E>, Error<E>> {
fn function_reference_indirect<'a>(&self, table_idx: u32, type_idx: u32, func_idx: u32, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>) -> Result<InternalFunctionReference<'a>, Error> {
let table = self.table(ItemIndex::IndexSpace(table_idx))?;
let (module, index) = match table.get(func_idx)? {
RuntimeValue::AnyFunc(module, index) => (module.clone(), index),
@ -628,7 +619,7 @@ impl<E> ModuleInstanceInterface<E> for ModuleInstance<E> where E: UserError {
module.function_reference(ItemIndex::IndexSpace(index), externals)
}
fn function_body<'a>(&'a self, internal_index: u32) -> Result<Option<InternalFunction<'a>>, Error<E>> {
fn function_body<'a>(&'a self, internal_index: u32) -> Result<Option<InternalFunction<'a>>, Error> {
let function_body = self.module
.code_section()
.ok_or(Error::Function(format!("trying to call function with index {} in module without code section", internal_index)))
@ -645,7 +636,7 @@ impl<E> ModuleInstanceInterface<E> for ModuleInstance<E> where E: UserError {
}))
}
fn call_internal_function(&self, outer: CallerContext<E>, index: u32) -> Result<Option<RuntimeValue>, Error<E>> {
fn call_internal_function(&self, outer: CallerContext, index: u32) -> Result<Option<RuntimeValue>, Error> {
let function_type = self.function_type(ItemIndex::Internal(index))?;
let args = prepare_function_args(&function_type, outer.value_stack)?;
let function_ref = InternalFunctionReference { module: self.self_ref(Some(outer.externals))?, internal_index: index };
@ -654,9 +645,9 @@ impl<E> ModuleInstanceInterface<E> for ModuleInstance<E> where E: UserError {
}
}
impl<'a, E> CallerContext<'a, E> where E: UserError {
impl<'a> CallerContext<'a> {
/// Top most args
pub fn topmost(args: &'a mut StackWithLimit<RuntimeValue, E>, externals: &'a HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>) -> Self {
pub fn topmost(args: &'a mut StackWithLimit<RuntimeValue>, externals: &'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>) -> Self {
CallerContext {
value_stack_limit: DEFAULT_VALUE_STACK_LIMIT,
frame_stack_limit: DEFAULT_FRAME_STACK_LIMIT,
@ -666,7 +657,7 @@ impl<'a, E> CallerContext<'a, E> where E: UserError {
}
/// Nested context
pub fn nested(outer: &'a mut FunctionContext<E>) -> Self {
pub fn nested(outer: &'a mut FunctionContext) -> Self {
CallerContext {
value_stack_limit: outer.value_stack().limit() - outer.value_stack().len(),
frame_stack_limit: outer.frame_stack().limit() - outer.frame_stack().len(),
@ -676,7 +667,7 @@ impl<'a, E> CallerContext<'a, E> where E: UserError {
}
}
pub fn check_limits<E: UserError>(limits: &ResizableLimits) -> Result<(), Error<E>> {
pub fn check_limits(limits: &ResizableLimits) -> Result<(), Error> {
if let Some(maximum) = limits.maximum() {
if maximum < limits.initial() {
return Err(Error::Validation(format!("maximum limit {} is lesser than minimum {}", maximum, limits.initial())));
@ -686,7 +677,7 @@ pub fn check_limits<E: UserError>(limits: &ResizableLimits) -> Result<(), Error<
Ok(())
}
fn get_initializer<E: UserError>(expr: &InitExpr, module: &Module, imports: &ModuleImports<E>, expected_type: VariableType) -> Result<RuntimeValue, Error<E>> {
fn get_initializer(expr: &InitExpr, module: &Module, imports: &ModuleImports, expected_type: VariableType) -> Result<RuntimeValue, Error> {
let first_opcode = match expr.code().len() {
1 => &expr.code()[0],
2 if expr.code().len() == 2 && expr.code()[1] == Opcode::End => &expr.code()[0],

View File

@ -2,44 +2,44 @@ use std::sync::Arc;
use std::collections::HashMap;
use parking_lot::RwLock;
use elements::Module;
use interpreter::{Error, UserError};
use interpreter::Error;
use interpreter::env::{self, env_module};
use interpreter::module::{ModuleInstance, ModuleInstanceInterface};
/// Program instance. Program is a set of instantiated modules.
pub struct ProgramInstance<E: UserError> {
pub struct ProgramInstance {
/// Shared data reference.
essence: Arc<ProgramInstanceEssence<E>>,
essence: Arc<ProgramInstanceEssence>,
}
/// Program instance essence.
pub struct ProgramInstanceEssence<E: UserError> {
pub struct ProgramInstanceEssence {
/// Loaded modules.
modules: RwLock<HashMap<String, Arc<ModuleInstanceInterface<E>>>>,
modules: RwLock<HashMap<String, Arc<ModuleInstanceInterface>>>,
}
impl<E> ProgramInstance<E> where E: UserError {
impl ProgramInstance {
/// Create new program instance.
pub fn new() -> Result<Self, Error<E>> {
pub fn new() -> Result<Self, Error> {
ProgramInstance::with_env_params(env::EnvParams::default())
}
/// Create new program instance with custom env module params (mostly memory)
pub fn with_env_params(params: env::EnvParams) -> Result<Self, Error<E>> {
pub fn with_env_params(params: env::EnvParams) -> Result<Self, Error> {
Ok(ProgramInstance {
essence: Arc::new(ProgramInstanceEssence::with_env_params(params)?),
})
}
/// Create a new program instance with a custom env module
pub fn with_env_module(env_module: Arc<ModuleInstanceInterface<E>>) -> Self {
pub fn with_env_module(env_module: Arc<ModuleInstanceInterface>) -> Self {
ProgramInstance {
essence: Arc::new(ProgramInstanceEssence::with_env_module(env_module)),
}
}
/// Instantiate module with validation.
pub fn add_module<'a>(&self, name: &str, module: Module, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>>) -> Result<Arc<ModuleInstance<E>>, Error<E>> {
pub fn add_module<'a>(&self, name: &str, module: Module, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>) -> Result<Arc<ModuleInstance>, Error> {
let mut module_instance = ModuleInstance::new(Arc::downgrade(&self.essence), name.into(), module)?;
module_instance.instantiate(externals)?;
@ -50,30 +50,30 @@ impl<E> ProgramInstance<E> where E: UserError {
}
/// Insert instantiated module.
pub fn insert_loaded_module(&self, name: &str, module_instance: Arc<ModuleInstance<E>>) -> Result<Arc<ModuleInstance<E>>, Error<E>> {
pub fn insert_loaded_module(&self, name: &str, module_instance: Arc<ModuleInstance>) -> Result<Arc<ModuleInstance>, Error> {
// replace existing module with the same name with new one
self.essence.modules.write().insert(name.into(), module_instance.clone());
Ok(module_instance)
}
/// Get one of the modules by name
pub fn module(&self, name: &str) -> Option<Arc<ModuleInstanceInterface<E>>> {
pub fn module(&self, name: &str) -> Option<Arc<ModuleInstanceInterface>> {
self.essence.module(name)
}
}
impl<E> ProgramInstanceEssence<E> where E: UserError {
impl ProgramInstanceEssence {
/// Create new program essence.
pub fn new() -> Result<Self, Error<E>> {
pub fn new() -> Result<Self, Error> {
ProgramInstanceEssence::with_env_params(env::EnvParams::default())
}
pub fn with_env_params(env_params: env::EnvParams) -> Result<Self, Error<E>> {
pub fn with_env_params(env_params: env::EnvParams) -> Result<Self, Error> {
let env_mod = env_module(env_params)?;
Ok(ProgramInstanceEssence::with_env_module(Arc::new(env_mod)))
}
pub fn with_env_module(env_module: Arc<ModuleInstanceInterface<E>>) -> Self {
pub fn with_env_module(env_module: Arc<ModuleInstanceInterface>) -> Self {
let mut modules = HashMap::new();
modules.insert("env".into(), env_module);
ProgramInstanceEssence {
@ -83,7 +83,7 @@ impl<E> ProgramInstanceEssence<E> where E: UserError {
/// Get module reference.
pub fn module(&self, name: &str) -> Option<Arc<ModuleInstanceInterface<E>>> {
pub fn module(&self, name: &str) -> Option<Arc<ModuleInstanceInterface>> {
self.modules.read().get(name).cloned()
}
}

View File

@ -6,7 +6,7 @@ use std::fmt::{self, Display};
use std::iter::repeat;
use std::collections::{HashMap, VecDeque};
use elements::{Opcode, BlockType, Local};
use interpreter::{Error, UserError};
use interpreter::Error;
use interpreter::module::{ModuleInstanceInterface, CallerContext, ItemIndex, InternalFunctionReference, FunctionSignature};
use interpreter::stack::StackWithLimit;
use interpreter::value::{
@ -22,39 +22,37 @@ pub const DEFAULT_MEMORY_INDEX: u32 = 0;
pub const DEFAULT_TABLE_INDEX: u32 = 0;
/// Function interpreter.
pub struct Interpreter<E: UserError> {
_dummy: ::std::marker::PhantomData<E>,
}
pub struct Interpreter;
/// Function execution context.
pub struct FunctionContext<'a, E: 'a + UserError> {
pub struct FunctionContext<'a> {
/// Is context initialized.
pub is_initialized: bool,
/// Internal function reference.
pub function: InternalFunctionReference<'a, E>,
pub function: InternalFunctionReference<'a>,
/// Execution-local external modules.
pub externals: &'a HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>,
pub externals: &'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>,
/// Function return type.
pub return_type: BlockType,
/// Local variables.
pub locals: Vec<VariableInstance<E>>,
pub locals: Vec<VariableInstance>,
/// Values stack.
pub value_stack: StackWithLimit<RuntimeValue, E>,
pub value_stack: StackWithLimit<RuntimeValue>,
/// Blocks frames stack.
pub frame_stack: StackWithLimit<BlockFrame, E>,
pub frame_stack: StackWithLimit<BlockFrame>,
/// Current instruction position.
pub position: usize,
}
/// Interpreter action to execute after executing instruction.
#[derive(Debug)]
pub enum InstructionOutcome<'a, E: UserError> {
pub enum InstructionOutcome<'a> {
/// Continue with next instruction.
RunNextInstruction,
/// Branch to given frame.
Branch(usize),
/// Execute function call.
ExecuteCall(InternalFunctionReference<'a, E>),
ExecuteCall(InternalFunctionReference<'a>),
/// End current frame.
End,
/// Return from current function block.
@ -62,15 +60,15 @@ pub enum InstructionOutcome<'a, E: UserError> {
}
/// Function run result.
enum RunResult<'a, E: 'a + UserError> {
enum RunResult<'a> {
/// Function has returned (optional) value.
Return(Option<RuntimeValue>),
/// Function is calling other function.
NestedCall(FunctionContext<'a, E>),
NestedCall(FunctionContext<'a>),
}
impl<E> Interpreter<E> where E: UserError {
pub fn run_function(function_context: FunctionContext<E>) -> Result<Option<RuntimeValue>, Error<E>> {
impl Interpreter {
pub fn run_function(function_context: FunctionContext) -> Result<Option<RuntimeValue>, Error> {
let mut function_stack = VecDeque::new();
function_stack.push_back(function_context);
@ -120,7 +118,7 @@ impl<E> Interpreter<E> where E: UserError {
}
}
fn do_run_function<'a>(function_context: &mut FunctionContext<'a, E>, function_body: &[Opcode], function_labels: &HashMap<usize, usize>) -> Result<RunResult<'a, E>, Error<E>> {
fn do_run_function<'a>(function_context: &mut FunctionContext<'a>, function_body: &[Opcode], function_labels: &HashMap<usize, usize>) -> Result<RunResult<'a>, Error> {
loop {
let instruction = &function_body[function_context.position];
@ -158,7 +156,7 @@ impl<E> Interpreter<E> where E: UserError {
}))
}
fn run_instruction<'a>(context: &mut FunctionContext<'a, E>, labels: &HashMap<usize, usize>, opcode: &Opcode) -> Result<InstructionOutcome<'a, E>, Error<E>> {
fn run_instruction<'a>(context: &mut FunctionContext<'a>, labels: &HashMap<usize, usize>, opcode: &Opcode) -> Result<InstructionOutcome<'a>, Error> {
match opcode {
&Opcode::Unreachable => Interpreter::run_unreachable(context),
&Opcode::Nop => Interpreter::run_nop(context),
@ -352,25 +350,25 @@ impl<E> Interpreter<E> where E: UserError {
}
}
fn run_unreachable<'a>(_context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>> {
fn run_unreachable<'a>(_context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> {
Err(Error::Trap("programmatic".into()))
}
fn run_nop<'a>(_context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>> {
fn run_nop<'a>(_context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> {
Ok(InstructionOutcome::RunNextInstruction)
}
fn run_block<'a>(context: &mut FunctionContext<'a, E>, labels: &HashMap<usize, usize>, block_type: BlockType) -> Result<InstructionOutcome<'a, E>, Error<E>> {
fn run_block<'a>(context: &mut FunctionContext<'a>, labels: &HashMap<usize, usize>, block_type: BlockType) -> Result<InstructionOutcome<'a>, Error> {
context.push_frame(labels, BlockFrameType::Block, block_type)?;
Ok(InstructionOutcome::RunNextInstruction)
}
fn run_loop<'a>(context: &mut FunctionContext<'a, E>, labels: &HashMap<usize, usize>, block_type: BlockType) -> Result<InstructionOutcome<'a, E>, Error<E>> {
fn run_loop<'a>(context: &mut FunctionContext<'a>, labels: &HashMap<usize, usize>, block_type: BlockType) -> Result<InstructionOutcome<'a>, Error> {
context.push_frame(labels, BlockFrameType::Loop, block_type)?;
Ok(InstructionOutcome::RunNextInstruction)
}
fn run_if<'a>(context: &mut FunctionContext<'a, E>, labels: &HashMap<usize, usize>, block_type: BlockType) -> Result<InstructionOutcome<'a, E>, Error<E>> {
fn run_if<'a>(context: &mut FunctionContext<'a>, labels: &HashMap<usize, usize>, block_type: BlockType) -> Result<InstructionOutcome<'a>, Error> {
let branch = context.value_stack_mut().pop_as()?;
let block_frame_type = if branch { BlockFrameType::IfTrue } else {
let else_pos = labels[&context.position];
@ -385,23 +383,23 @@ impl<E> Interpreter<E> where E: UserError {
context.push_frame(labels, block_frame_type, block_type).map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_else<'a>(context: &mut FunctionContext<E>, labels: &HashMap<usize, usize>) -> Result<InstructionOutcome<'a, E>, Error<E>> {
fn run_else<'a>(context: &mut FunctionContext, labels: &HashMap<usize, usize>) -> Result<InstructionOutcome<'a>, Error> {
let end_pos = labels[&context.position];
context.pop_frame(false)?;
context.position = end_pos;
Ok(InstructionOutcome::RunNextInstruction)
}
fn run_end<'a>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>> {
fn run_end<'a>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> {
context.pop_frame(false)?;
Ok(InstructionOutcome::End)
}
fn run_br<'a>(_context: &mut FunctionContext<E>, label_idx: u32) -> Result<InstructionOutcome<'a, E>, Error<E>> {
fn run_br<'a>(_context: &mut FunctionContext, label_idx: u32) -> Result<InstructionOutcome<'a>, Error> {
Ok(InstructionOutcome::Branch(label_idx as usize))
}
fn run_br_if<'a>(context: &mut FunctionContext<E>, label_idx: u32) -> Result<InstructionOutcome<'a, E>, Error<E>> {
fn run_br_if<'a>(context: &mut FunctionContext, label_idx: u32) -> Result<InstructionOutcome<'a>, Error> {
if context.value_stack_mut().pop_as()? {
Ok(InstructionOutcome::Branch(label_idx as usize))
} else {
@ -409,20 +407,20 @@ impl<E> Interpreter<E> where E: UserError {
}
}
fn run_br_table<'a>(context: &mut FunctionContext<E>, table: &Vec<u32>, default: u32) -> Result<InstructionOutcome<'a, E>, Error<E>> {
fn run_br_table<'a>(context: &mut FunctionContext, table: &Vec<u32>, default: u32) -> Result<InstructionOutcome<'a>, Error> {
let index: u32 = context.value_stack_mut().pop_as()?;
Ok(InstructionOutcome::Branch(table.get(index as usize).cloned().unwrap_or(default) as usize))
}
fn run_return<'a>(_context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>> {
fn run_return<'a>(_context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> {
Ok(InstructionOutcome::Return)
}
fn run_call<'a>(context: &mut FunctionContext<'a, E>, func_idx: u32) -> Result<InstructionOutcome<'a, E>, Error<E>> {
fn run_call<'a>(context: &mut FunctionContext<'a>, func_idx: u32) -> Result<InstructionOutcome<'a>, Error> {
Ok(InstructionOutcome::ExecuteCall(context.module().function_reference(ItemIndex::IndexSpace(func_idx), Some(context.externals))?))
}
fn run_call_indirect<'a>(context: &mut FunctionContext<'a, E>, type_idx: u32) -> Result<InstructionOutcome<'a, E>, Error<E>> {
fn run_call_indirect<'a>(context: &mut FunctionContext<'a>, type_idx: u32) -> Result<InstructionOutcome<'a>, Error> {
let table_func_idx: u32 = context.value_stack_mut().pop_as()?;
let function_reference = context.module().function_reference_indirect(DEFAULT_TABLE_INDEX, type_idx, table_func_idx, Some(context.externals))?;
{
@ -437,19 +435,19 @@ impl<E> Interpreter<E> where E: UserError {
Ok(InstructionOutcome::ExecuteCall(function_reference))
}
fn run_drop<'a>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>> {
fn run_drop<'a>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> {
context
.value_stack_mut()
.pop()
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_select<'a>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>> {
fn run_select<'a>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> {
context
.value_stack_mut()
.pop_triple()
.and_then(|(left, mid, right)| {
let right: Result<_, Error<E>> = right.try_into();
let right: Result<_, Error> = right.try_into();
match (left, mid, right) {
(left, mid, Ok(condition)) => Ok((left, mid, condition)),
_ => Err(Error::Stack("expected to get int value from stack".into()))
@ -460,32 +458,32 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_get_local<'a>(context: &mut FunctionContext<E>, index: u32) -> Result<InstructionOutcome<'a, E>, Error<E>> {
fn run_get_local<'a>(context: &mut FunctionContext, index: u32) -> Result<InstructionOutcome<'a>, Error> {
context.get_local(index as usize)
.map(|value| context.value_stack_mut().push(value))
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_set_local<'a>(context: &mut FunctionContext<E>, index: u32) -> Result<InstructionOutcome<'a, E>, Error<E>> {
fn run_set_local<'a>(context: &mut FunctionContext, index: u32) -> Result<InstructionOutcome<'a>, Error> {
let arg = context.value_stack_mut().pop()?;
context.set_local(index as usize, arg)
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_tee_local<'a>(context: &mut FunctionContext<E>, index: u32) -> Result<InstructionOutcome<'a, E>, Error<E>> {
fn run_tee_local<'a>(context: &mut FunctionContext, index: u32) -> Result<InstructionOutcome<'a>, Error> {
let arg = context.value_stack().top()?.clone();
context.set_local(index as usize, arg)
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_get_global<'a>(context: &mut FunctionContext<E>, index: u32) -> Result<InstructionOutcome<'a, E>, Error<E>> {
fn run_get_global<'a>(context: &mut FunctionContext, index: u32) -> Result<InstructionOutcome<'a>, Error> {
context.module()
.global(ItemIndex::IndexSpace(index), None, Some(context.externals))
.and_then(|g| context.value_stack_mut().push(g.get()))
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_set_global<'a>(context: &mut FunctionContext<E>, index: u32) -> Result<InstructionOutcome<'a, E>, Error<E>> {
fn run_set_global<'a>(context: &mut FunctionContext, index: u32) -> Result<InstructionOutcome<'a>, Error> {
context
.value_stack_mut()
.pop()
@ -493,8 +491,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_load<'a, T>(context: &mut FunctionContext<E>, _align: u32, offset: u32) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: From<T>, T: LittleEndianConvert<E> {
fn run_load<'a, T>(context: &mut FunctionContext, _align: u32, offset: u32) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: From<T>, T: LittleEndianConvert {
let address = effective_address(offset, context.value_stack_mut().pop_as()?)?;
context.module()
.memory(ItemIndex::IndexSpace(DEFAULT_MEMORY_INDEX))
@ -504,8 +502,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_load_extend<'a, T, U>(context: &mut FunctionContext<E>, _align: u32, offset: u32) -> Result<InstructionOutcome<'a, E>, Error<E>>
where T: ExtendInto<U>, RuntimeValue: From<U>, T: LittleEndianConvert<E> {
fn run_load_extend<'a, T, U>(context: &mut FunctionContext, _align: u32, offset: u32) -> Result<InstructionOutcome<'a>, Error>
where T: ExtendInto<U>, RuntimeValue: From<U>, T: LittleEndianConvert {
let address = effective_address(offset, context.value_stack_mut().pop_as()?)?;
let stack_value: U = context.module()
.memory(ItemIndex::IndexSpace(DEFAULT_MEMORY_INDEX))
@ -518,8 +516,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_store<'a, T>(context: &mut FunctionContext<E>, _align: u32, offset: u32) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: TryInto<T, Error<E>>, T: LittleEndianConvert<E> {
fn run_store<'a, T>(context: &mut FunctionContext, _align: u32, offset: u32) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: TryInto<T, Error>, T: LittleEndianConvert {
let stack_value = context
.value_stack_mut()
.pop_as::<T>()
@ -531,8 +529,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_store_wrap<'a, T, U>(context: &mut FunctionContext<E>, _align: u32, offset: u32) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: TryInto<T, Error<E>>, T: WrapInto<U>, U: LittleEndianConvert<E> {
fn run_store_wrap<'a, T, U>(context: &mut FunctionContext, _align: u32, offset: u32) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: TryInto<T, Error>, T: WrapInto<U>, U: LittleEndianConvert {
let stack_value: T = context.value_stack_mut().pop().and_then(|v| v.try_into())?;
let stack_value = stack_value.wrap_into().into_little_endian();
let address = effective_address(offset, context.value_stack_mut().pop_as::<u32>()?)?;
@ -542,7 +540,7 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_current_memory<'a>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>> {
fn run_current_memory<'a>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> {
context.module()
.memory(ItemIndex::IndexSpace(DEFAULT_MEMORY_INDEX))
.map(|m| m.size())
@ -550,7 +548,7 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_grow_memory<'a>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>> {
fn run_grow_memory<'a>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error> {
let pages: u32 = context.value_stack_mut().pop_as()?;
context.module()
.memory(ItemIndex::IndexSpace(DEFAULT_MEMORY_INDEX))
@ -559,15 +557,15 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_const<'a>(context: &mut FunctionContext<E>, val: RuntimeValue) -> Result<InstructionOutcome<'a, E>, Error<E>> {
fn run_const<'a>(context: &mut FunctionContext, val: RuntimeValue) -> Result<InstructionOutcome<'a>, Error> {
context
.value_stack_mut()
.push(val)
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_eqz<'a, T>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: TryInto<T, Error<E>>, T: PartialEq<T> + Default {
fn run_eqz<'a, T>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: TryInto<T, Error>, T: PartialEq<T> + Default {
context
.value_stack_mut()
.pop_as::<T>()
@ -576,8 +574,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_eq<'a, T>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: TryInto<T, Error<E>>, T: PartialEq<T> {
fn run_eq<'a, T>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: TryInto<T, Error>, T: PartialEq<T> {
context
.value_stack_mut()
.pop_pair_as::<T>()
@ -586,8 +584,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_ne<'a, T>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: TryInto<T, Error<E>>, T: PartialEq<T> {
fn run_ne<'a, T>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: TryInto<T, Error>, T: PartialEq<T> {
context
.value_stack_mut()
.pop_pair_as::<T>()
@ -596,8 +594,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_lt<'a, T>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: TryInto<T, Error<E>>, T: PartialOrd<T> + Display {
fn run_lt<'a, T>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: TryInto<T, Error>, T: PartialOrd<T> + Display {
context
.value_stack_mut()
.pop_pair_as::<T>()
@ -606,8 +604,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_gt<'a, T>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: TryInto<T, Error<E>>, T: PartialOrd<T> {
fn run_gt<'a, T>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: TryInto<T, Error>, T: PartialOrd<T> {
context
.value_stack_mut()
.pop_pair_as::<T>()
@ -616,8 +614,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_lte<'a, T>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: TryInto<T, Error<E>>, T: PartialOrd<T> {
fn run_lte<'a, T>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: TryInto<T, Error>, T: PartialOrd<T> {
context
.value_stack_mut()
.pop_pair_as::<T>()
@ -626,8 +624,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_gte<'a, T>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: TryInto<T, Error<E>>, T: PartialOrd<T> {
fn run_gte<'a, T>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: TryInto<T, Error>, T: PartialOrd<T> {
context
.value_stack_mut()
.pop_pair_as::<T>()
@ -636,8 +634,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_clz<'a, T>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: From<T> + TryInto<T, Error<E>>, T: Integer<T, E> {
fn run_clz<'a, T>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> {
context
.value_stack_mut()
.pop_as::<T>()
@ -646,8 +644,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_ctz<'a, T>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: From<T> + TryInto<T, Error<E>>, T: Integer<T, E> {
fn run_ctz<'a, T>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> {
context
.value_stack_mut()
.pop_as::<T>()
@ -656,8 +654,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_popcnt<'a, T>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: From<T> + TryInto<T, Error<E>>, T: Integer<T, E> {
fn run_popcnt<'a, T>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> {
context
.value_stack_mut()
.pop_as::<T>()
@ -666,8 +664,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_add<'a, T>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: From<T> + TryInto<T, Error<E>>, T: ArithmeticOps<T, E> {
fn run_add<'a, T>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: ArithmeticOps<T> {
context
.value_stack_mut()
.pop_pair_as::<T>()
@ -676,8 +674,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_sub<'a, T>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: From<T> + TryInto<T, Error<E>>, T: ArithmeticOps<T, E> {
fn run_sub<'a, T>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: ArithmeticOps<T> {
context
.value_stack_mut()
.pop_pair_as::<T>()
@ -686,8 +684,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_mul<'a, T>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: From<T> + TryInto<T, Error<E>>, T: ArithmeticOps<T, E> {
fn run_mul<'a, T>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: ArithmeticOps<T> {
context
.value_stack_mut()
.pop_pair_as::<T>()
@ -696,8 +694,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_div<'a, T, U>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: From<T> + TryInto<T, Error<E>>, T: TransmuteInto<U> + Display, U: ArithmeticOps<U, E> + TransmuteInto<T> {
fn run_div<'a, T, U>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: TransmuteInto<U> + Display, U: ArithmeticOps<U> + TransmuteInto<T> {
context
.value_stack_mut()
.pop_pair_as::<T>()
@ -708,8 +706,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_rem<'a, T, U>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: From<T> + TryInto<T, Error<E>>, T: TransmuteInto<U>, U: Integer<U, E> + TransmuteInto<T> {
fn run_rem<'a, T, U>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: TransmuteInto<U>, U: Integer<U> + TransmuteInto<T> {
context
.value_stack_mut()
.pop_pair_as::<T>()
@ -720,8 +718,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_and<'a, T>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: From<<T as ops::BitAnd>::Output> + TryInto<T, Error<E>>, T: ops::BitAnd<T> {
fn run_and<'a, T>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: From<<T as ops::BitAnd>::Output> + TryInto<T, Error>, T: ops::BitAnd<T> {
context
.value_stack_mut()
.pop_pair_as::<T>()
@ -730,8 +728,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_or<'a, T>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: From<<T as ops::BitOr>::Output> + TryInto<T, Error<E>>, T: ops::BitOr<T> {
fn run_or<'a, T>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: From<<T as ops::BitOr>::Output> + TryInto<T, Error>, T: ops::BitOr<T> {
context
.value_stack_mut()
.pop_pair_as::<T>()
@ -740,8 +738,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_xor<'a, T>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: From<<T as ops::BitXor>::Output> + TryInto<T, Error<E>>, T: ops::BitXor<T> {
fn run_xor<'a, T>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: From<<T as ops::BitXor>::Output> + TryInto<T, Error>, T: ops::BitXor<T> {
context
.value_stack_mut()
.pop_pair_as::<T>()
@ -750,8 +748,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_shl<'a, T>(context: &mut FunctionContext<E>, mask: T) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: From<<T as ops::Shl<T>>::Output> + TryInto<T, Error<E>>, T: ops::Shl<T> + ops::BitAnd<T, Output=T> {
fn run_shl<'a, T>(context: &mut FunctionContext, mask: T) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: From<<T as ops::Shl<T>>::Output> + TryInto<T, Error>, T: ops::Shl<T> + ops::BitAnd<T, Output=T> {
context
.value_stack_mut()
.pop_pair_as::<T>()
@ -760,8 +758,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_shr<'a, T, U>(context: &mut FunctionContext<E>, mask: U) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: From<T> + TryInto<T, Error<E>>, T: TransmuteInto<U>, U: ops::Shr<U> + ops::BitAnd<U, Output=U>, <U as ops::Shr<U>>::Output: TransmuteInto<T> {
fn run_shr<'a, T, U>(context: &mut FunctionContext, mask: U) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: TransmuteInto<U>, U: ops::Shr<U> + ops::BitAnd<U, Output=U>, <U as ops::Shr<U>>::Output: TransmuteInto<T> {
context
.value_stack_mut()
.pop_pair_as::<T>()
@ -772,8 +770,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_rotl<'a, T>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: From<T> + TryInto<T, Error<E>>, T: Integer<T, E> {
fn run_rotl<'a, T>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> {
context
.value_stack_mut()
.pop_pair_as::<T>()
@ -782,8 +780,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_rotr<'a, T>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: From<T> + TryInto<T, Error<E>>, T: Integer<T, E> {
fn run_rotr<'a, T>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Integer<T> {
context
.value_stack_mut()
.pop_pair_as::<T>()
@ -792,8 +790,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_abs<'a, T>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: From<T> + TryInto<T, Error<E>>, T: Float<T, E> {
fn run_abs<'a, T>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
context
.value_stack_mut()
.pop_as::<T>()
@ -802,8 +800,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_neg<'a, T>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: From<<T as ops::Neg>::Output> + TryInto<T, Error<E>>, T: ops::Neg {
fn run_neg<'a, T>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: From<<T as ops::Neg>::Output> + TryInto<T, Error>, T: ops::Neg {
context
.value_stack_mut()
.pop_as::<T>()
@ -812,8 +810,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_ceil<'a, T>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: From<T> + TryInto<T, Error<E>>, T: Float<T, E> {
fn run_ceil<'a, T>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
context
.value_stack_mut()
.pop_as::<T>()
@ -822,8 +820,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_floor<'a, T>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: From<T> + TryInto<T, Error<E>>, T: Float<T, E> {
fn run_floor<'a, T>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
context
.value_stack_mut()
.pop_as::<T>()
@ -832,8 +830,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_trunc<'a, T>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: From<T> + TryInto<T, Error<E>>, T: Float<T, E> {
fn run_trunc<'a, T>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
context
.value_stack_mut()
.pop_as::<T>()
@ -842,8 +840,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_nearest<'a, T>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: From<T> + TryInto<T, Error<E>>, T: Float<T, E> {
fn run_nearest<'a, T>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
context
.value_stack_mut()
.pop_as::<T>()
@ -852,8 +850,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_sqrt<'a, T>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: From<T> + TryInto<T, Error<E>>, T: Float<T, E> {
fn run_sqrt<'a, T>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
context
.value_stack_mut()
.pop_as::<T>()
@ -862,8 +860,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_min<'a, T>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: From<T> + TryInto<T, Error<E>>, T: Float<T, E> {
fn run_min<'a, T>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
context
.value_stack_mut()
.pop_pair_as::<T>()
@ -872,8 +870,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_max<'a, T>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: From<T> + TryInto<T, Error<E>>, T: Float<T, E> {
fn run_max<'a, T>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
context
.value_stack_mut()
.pop_pair_as::<T>()
@ -882,8 +880,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_copysign<'a, T>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: From<T> + TryInto<T, Error<E>>, T: Float<T, E> {
fn run_copysign<'a, T>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: From<T> + TryInto<T, Error>, T: Float<T> {
context
.value_stack_mut()
.pop_pair_as::<T>()
@ -892,8 +890,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_wrap<'a, T, U>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: From<U> + TryInto<T, Error<E>>, T: WrapInto<U> {
fn run_wrap<'a, T, U>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: From<U> + TryInto<T, Error>, T: WrapInto<U> {
context
.value_stack_mut()
.pop_as::<T>()
@ -902,8 +900,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_trunc_to_int<'a, T, U, V>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: From<V> + TryInto<T, Error<E>>, T: TryTruncateInto<U, Error<E>>, U: TransmuteInto<V>, {
fn run_trunc_to_int<'a, T, U, V>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: From<V> + TryInto<T, Error>, T: TryTruncateInto<U, Error>, U: TransmuteInto<V>, {
context
.value_stack_mut()
.pop_as::<T>()
@ -913,8 +911,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_extend<'a, T, U, V>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: From<V> + TryInto<T, Error<E>>, T: ExtendInto<U>, U: TransmuteInto<V> {
fn run_extend<'a, T, U, V>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: From<V> + TryInto<T, Error>, T: ExtendInto<U>, U: TransmuteInto<V> {
context
.value_stack_mut()
.pop_as::<T>()
@ -924,8 +922,8 @@ impl<E> Interpreter<E> where E: UserError {
.map(|_| InstructionOutcome::RunNextInstruction)
}
fn run_reinterpret<'a, T, U>(context: &mut FunctionContext<E>) -> Result<InstructionOutcome<'a, E>, Error<E>>
where RuntimeValue: From<U>, RuntimeValue: TryInto<T, Error<E>>, T: TransmuteInto<U> {
fn run_reinterpret<'a, T, U>(context: &mut FunctionContext) -> Result<InstructionOutcome<'a>, Error>
where RuntimeValue: From<U>, RuntimeValue: TryInto<T, Error>, T: TransmuteInto<U> {
context
.value_stack_mut()
.pop_as::<T>()
@ -935,8 +933,8 @@ impl<E> Interpreter<E> where E: UserError {
}
}
impl<'a, E> FunctionContext<'a, E> where E: UserError {
pub fn new(function: InternalFunctionReference<'a, E>, externals: &'a HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>, value_stack_limit: usize, frame_stack_limit: usize, function_type: &FunctionSignature, args: Vec<VariableInstance<E>>) -> Self {
impl<'a> FunctionContext<'a> {
pub fn new(function: InternalFunctionReference<'a>, externals: &'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>, value_stack_limit: usize, frame_stack_limit: usize, function_type: &FunctionSignature, args: Vec<VariableInstance>) -> Self {
FunctionContext {
is_initialized: false,
function: function,
@ -949,7 +947,7 @@ impl<'a, E> FunctionContext<'a, E> where E: UserError {
}
}
pub fn nested(&mut self, function: InternalFunctionReference<'a, E>) -> Result<Self, Error<E>> {
pub fn nested(&mut self, function: InternalFunctionReference<'a>) -> Result<Self, Error> {
let (function_locals, function_return_type) = {
let function_type = function.module.function_type(ItemIndex::Internal(function.internal_index))?;
let function_return_type = function_type.return_type().map(|vt| BlockType::Value(vt)).unwrap_or(BlockType::NoResult);
@ -973,7 +971,7 @@ impl<'a, E> FunctionContext<'a, E> where E: UserError {
self.is_initialized
}
pub fn initialize(&mut self, locals: &[Local]) -> Result<(), Error<E>> {
pub fn initialize(&mut self, locals: &[Local]) -> Result<(), Error> {
debug_assert!(!self.is_initialized);
self.is_initialized = true;
@ -985,44 +983,44 @@ impl<'a, E> FunctionContext<'a, E> where E: UserError {
Ok(())
}
pub fn module(&self) -> &Arc<ModuleInstanceInterface<E> + 'a> {
pub fn module(&self) -> &Arc<ModuleInstanceInterface + 'a> {
&self.function.module
}
pub fn externals(&self) -> &HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>> {
pub fn externals(&self) -> &HashMap<String, Arc<ModuleInstanceInterface + 'a>> {
&self.externals
}
pub fn set_local(&mut self, index: usize, value: RuntimeValue) -> Result<InstructionOutcome<'a, E>, Error<E>> {
pub fn set_local(&mut self, index: usize, value: RuntimeValue) -> Result<InstructionOutcome<'a>, Error> {
self.locals.get_mut(index)
.ok_or(Error::Local(format!("expected to have local with index {}", index)))
.and_then(|l| l.set(value))
.map(|_| InstructionOutcome::RunNextInstruction)
}
pub fn get_local(&mut self, index: usize) -> Result<RuntimeValue, Error<E>> {
pub fn get_local(&mut self, index: usize) -> Result<RuntimeValue, Error> {
self.locals.get(index)
.ok_or(Error::Local(format!("expected to have local with index {}", index)))
.map(|l| l.get())
}
pub fn value_stack(&self) -> &StackWithLimit<RuntimeValue, E> {
pub fn value_stack(&self) -> &StackWithLimit<RuntimeValue> {
&self.value_stack
}
pub fn value_stack_mut(&mut self) -> &mut StackWithLimit<RuntimeValue, E> {
pub fn value_stack_mut(&mut self) -> &mut StackWithLimit<RuntimeValue> {
&mut self.value_stack
}
pub fn frame_stack(&self) -> &StackWithLimit<BlockFrame, E> {
pub fn frame_stack(&self) -> &StackWithLimit<BlockFrame> {
&self.frame_stack
}
pub fn frame_stack_mut(&mut self) -> &mut StackWithLimit<BlockFrame, E> {
pub fn frame_stack_mut(&mut self) -> &mut StackWithLimit<BlockFrame> {
&mut self.frame_stack
}
pub fn push_frame(&mut self, labels: &HashMap<usize, usize>, frame_type: BlockFrameType, block_type: BlockType) -> Result<(), Error<E>> {
pub fn push_frame(&mut self, labels: &HashMap<usize, usize>, frame_type: BlockFrameType, block_type: BlockType) -> Result<(), Error> {
let begin_position = self.position;
let branch_position = match frame_type {
BlockFrameType::Function => usize::MAX,
@ -1050,12 +1048,12 @@ impl<'a, E> FunctionContext<'a, E> where E: UserError {
})
}
pub fn discard_frame(&mut self) -> Result<(), Error<E>> {
pub fn discard_frame(&mut self) -> Result<(), Error> {
self.frame_stack.pop()
.map(|_| ())
}
pub fn pop_frame(&mut self, is_branch: bool) -> Result<(), Error<E>> {
pub fn pop_frame(&mut self, is_branch: bool) -> Result<(), Error> {
let frame = self.frame_stack.pop()?;
if frame.value_stack_len > self.value_stack.len() {
return Err(Error::Stack("invalid stack len".into()));
@ -1075,20 +1073,20 @@ impl<'a, E> FunctionContext<'a, E> where E: UserError {
}
}
impl<'a, E> fmt::Debug for FunctionContext<'a, E> where E: UserError {
impl<'a> fmt::Debug for FunctionContext<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "FunctionContext")
}
}
fn effective_address<E: UserError>(address: u32, offset: u32) -> Result<u32, Error<E>> {
fn effective_address(address: u32, offset: u32) -> Result<u32, Error> {
match offset.checked_add(address) {
None => Err(Error::Memory(format!("invalid memory access: {} + {}", offset, address))),
Some(address) => Ok(address),
}
}
pub fn prepare_function_args<E: UserError>(function_type: &FunctionSignature, caller_stack: &mut StackWithLimit<RuntimeValue, E>) -> Result<Vec<VariableInstance<E>>, Error<E>> {
pub fn prepare_function_args(function_type: &FunctionSignature, caller_stack: &mut StackWithLimit<RuntimeValue>) -> Result<Vec<VariableInstance>, Error> {
let mut args = function_type.params().iter().rev().map(|param_type| {
let param_value = caller_stack.pop()?;
let actual_type = param_value.variable_type();

View File

@ -1,32 +1,28 @@
use std::collections::VecDeque;
use interpreter::{Error, UserError};
use interpreter::Error;
use interpreter::value::{RuntimeValue, TryInto};
/// Stack with limit.
#[derive(Debug)]
pub struct StackWithLimit<T, E> where T: Clone, E: UserError {
pub struct StackWithLimit<T> where T: Clone {
/// Stack values.
values: VecDeque<T>,
/// Stack limit (maximal stack len).
limit: usize,
/// Dummy to avoid compilation error.
_dummy: ::std::marker::PhantomData<E>,
}
impl<T, E> StackWithLimit<T, E> where T: Clone, E: UserError {
impl<T> StackWithLimit<T> where T: Clone {
pub fn with_data(data: Vec<T>, limit: usize) -> Self {
StackWithLimit {
values: data.into_iter().collect(),
limit: limit,
_dummy: Default::default(),
limit: limit
}
}
pub fn with_limit(limit: usize) -> Self {
StackWithLimit {
values: VecDeque::new(),
limit: limit,
_dummy: Default::default(),
limit: limit
}
}
@ -46,19 +42,19 @@ impl<T, E> StackWithLimit<T, E> where T: Clone, E: UserError {
&self.values
}
pub fn top(&self) -> Result<&T, Error<E>> {
pub fn top(&self) -> Result<&T, Error> {
self.values
.back()
.ok_or(Error::Stack("non-empty stack expected".into()))
}
pub fn top_mut(&mut self) -> Result<&mut T, Error<E>> {
pub fn top_mut(&mut self) -> Result<&mut T, Error> {
self.values
.back_mut()
.ok_or(Error::Stack("non-empty stack expected".into()))
}
pub fn get(&self, index: usize) -> Result<&T, Error<E>> {
pub fn get(&self, index: usize) -> Result<&T, Error> {
if index >= self.values.len() {
return Err(Error::Stack(format!("trying to get value at position {} on stack of size {}", index, self.values.len())));
}
@ -66,7 +62,7 @@ impl<T, E> StackWithLimit<T, E> where T: Clone, E: UserError {
Ok(self.values.get(self.values.len() - 1 - index).expect("checked couple of lines above"))
}
pub fn push(&mut self, value: T) -> Result<(), Error<E>> {
pub fn push(&mut self, value: T) -> Result<(), Error> {
if self.values.len() >= self.limit {
return Err(Error::Stack(format!("exceeded stack limit {}", self.limit)));
}
@ -75,7 +71,7 @@ impl<T, E> StackWithLimit<T, E> where T: Clone, E: UserError {
Ok(())
}
pub fn push_penultimate(&mut self, value: T) -> Result<(), Error<E>> {
pub fn push_penultimate(&mut self, value: T) -> Result<(), Error> {
if self.values.is_empty() {
return Err(Error::Stack("trying to insert penultimate element into empty stack".into()));
}
@ -88,7 +84,7 @@ impl<T, E> StackWithLimit<T, E> where T: Clone, E: UserError {
Ok(())
}
pub fn pop(&mut self) -> Result<T, Error<E>> {
pub fn pop(&mut self) -> Result<T, Error> {
self.values
.pop_back()
.ok_or(Error::Stack("non-empty stack expected".into()))
@ -100,26 +96,26 @@ impl<T, E> StackWithLimit<T, E> where T: Clone, E: UserError {
}
}
impl<E> StackWithLimit<RuntimeValue, E> where E: UserError {
pub fn pop_as<T>(&mut self) -> Result<T, Error<E>>
where RuntimeValue: TryInto<T, Error<E>> {
impl StackWithLimit<RuntimeValue> {
pub fn pop_as<T>(&mut self) -> Result<T, Error>
where RuntimeValue: TryInto<T, Error> {
self.pop().and_then(TryInto::try_into)
}
pub fn pop_pair(&mut self) -> Result<(RuntimeValue, RuntimeValue), Error<E>> {
pub fn pop_pair(&mut self) -> Result<(RuntimeValue, RuntimeValue), Error> {
let right = self.pop()?;
let left = self.pop()?;
Ok((left, right))
}
pub fn pop_pair_as<T>(&mut self) -> Result<(T, T), Error<E>>
where RuntimeValue: TryInto<T, Error<E>> {
pub fn pop_pair_as<T>(&mut self) -> Result<(T, T), Error>
where RuntimeValue: TryInto<T, Error> {
let right = self.pop_as()?;
let left = self.pop_as()?;
Ok((left, right))
}
pub fn pop_triple(&mut self) -> Result<(RuntimeValue, RuntimeValue, RuntimeValue), Error<E>> {
pub fn pop_triple(&mut self) -> Result<(RuntimeValue, RuntimeValue, RuntimeValue), Error> {
let right = self.pop()?;
let mid = self.pop()?;
let left = self.pop()?;

View File

@ -2,29 +2,29 @@ use std::u32;
use std::sync::Arc;
use parking_lot::RwLock;
use elements::{TableType, ResizableLimits};
use interpreter::{Error, UserError};
use interpreter::Error;
use interpreter::module::check_limits;
use interpreter::variable::{VariableInstance, VariableType};
use interpreter::value::RuntimeValue;
/// Table instance.
pub struct TableInstance<E: UserError> {
pub struct TableInstance {
/// Table limits.
limits: ResizableLimits,
/// Table variables type.
variable_type: VariableType,
/// Table memory buffer.
buffer: RwLock<Vec<TableElement<E>>>,
buffer: RwLock<Vec<TableElement>>,
}
/// Table element. Cloneable wrapper around VariableInstance.
struct TableElement<E: UserError> {
pub var: VariableInstance<E>,
struct TableElement {
pub var: VariableInstance,
}
impl<E> TableInstance<E> where E: UserError {
impl TableInstance {
/// New instance of the table
pub fn new(table_type: &TableType) -> Result<Arc<Self>, Error<E>> {
pub fn new(table_type: &TableType) -> Result<Arc<Self>, Error> {
check_limits(table_type.limits())?;
let variable_type = table_type.elem_type().into();
@ -48,7 +48,7 @@ impl<E> TableInstance<E> where E: UserError {
}
/// Get the specific value in the table
pub fn get(&self, offset: u32) -> Result<RuntimeValue, Error<E>> {
pub fn get(&self, offset: u32) -> Result<RuntimeValue, Error> {
let buffer = self.buffer.read();
let buffer_len = buffer.len();
buffer.get(offset as usize)
@ -57,7 +57,7 @@ impl<E> TableInstance<E> where E: UserError {
}
/// Set the table value from raw slice
pub fn set_raw(&self, mut offset: u32, module_name: String, value: &[u32]) -> Result<(), Error<E>> {
pub fn set_raw(&self, mut offset: u32, module_name: String, value: &[u32]) -> Result<(), Error> {
for val in value {
match self.variable_type {
VariableType::AnyFunc => self.set(offset, RuntimeValue::AnyFunc(module_name.clone(), *val))?,
@ -69,7 +69,7 @@ impl<E> TableInstance<E> where E: UserError {
}
/// Set the table from runtime variable value
pub fn set(&self, offset: u32, value: RuntimeValue) -> Result<(), Error<E>> {
pub fn set(&self, offset: u32, value: RuntimeValue) -> Result<(), Error> {
let mut buffer = self.buffer.write();
let buffer_len = buffer.len();
buffer.get_mut(offset as usize)
@ -78,15 +78,15 @@ impl<E> TableInstance<E> where E: UserError {
}
}
impl<E> TableElement<E> where E: UserError {
pub fn new(var: VariableInstance<E>) -> Self {
impl TableElement {
pub fn new(var: VariableInstance) -> Self {
TableElement {
var: var,
}
}
}
impl<E> Clone for TableElement<E> where E: UserError {
impl Clone for TableElement {
fn clone(&self) -> Self {
TableElement::new(VariableInstance::new(self.var.is_mutable(), self.var.variable_type(), self.var.get())
.expect("it only fails when variable_type() != passed variable value; both are read from already constructed var; qed"))

View File

@ -2,7 +2,7 @@ use std::u32;
use std::sync::Arc;
use std::collections::HashMap;
use elements::{Opcode, BlockType, ValueType};
use interpreter::{Error, UserError};
use interpreter::Error;
use interpreter::runner::{DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDEX};
use interpreter::module::{ModuleInstance, ModuleInstanceInterface, ItemIndex, FunctionSignature};
use interpreter::stack::StackWithLimit;
@ -12,19 +12,19 @@ use interpreter::variable::VariableType;
const NATURAL_ALIGNMENT: u32 = 0xFFFFFFFF;
/// Function validation context.
pub struct FunctionValidationContext<'a, E: 'a + UserError> {
pub struct FunctionValidationContext<'a> {
/// Wasm module instance (in process of instantiation).
module_instance: &'a ModuleInstance<E>,
module_instance: &'a ModuleInstance,
/// Native externals.
externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>>,
externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>,
/// Current instruction position.
position: usize,
/// Local variables.
locals: &'a [ValueType],
/// Value stack.
value_stack: StackWithLimit<StackValueType, E>,
value_stack: StackWithLimit<StackValueType>,
/// Frame stack.
frame_stack: StackWithLimit<BlockFrame, E>,
frame_stack: StackWithLimit<BlockFrame>,
/// Function return type. None if validating expression.
return_type: Option<BlockType>,
/// Labels positions.
@ -75,9 +75,7 @@ pub enum BlockFrameType {
}
/// Function validator.
pub struct Validator<E: UserError> {
_dummy: ::std::marker::PhantomData<E>,
}
pub struct Validator;
/// Instruction outcome.
#[derive(Debug, Clone)]
@ -88,8 +86,8 @@ pub enum InstructionOutcome {
Unreachable,
}
impl<E> Validator<E> where E: UserError {
pub fn validate_function(context: &mut FunctionValidationContext<E>, block_type: BlockType, body: &[Opcode]) -> Result<(), Error<E>> {
impl Validator {
pub fn validate_function(context: &mut FunctionValidationContext, block_type: BlockType, body: &[Opcode]) -> Result<(), Error> {
context.push_label(BlockFrameType::Function, block_type)?;
Validator::validate_function_block(context, body)?;
while !context.frame_stack.is_empty() {
@ -99,7 +97,7 @@ impl<E> Validator<E> where E: UserError {
Ok(())
}
fn validate_function_block(context: &mut FunctionValidationContext<E>, body: &[Opcode]) -> Result<(), Error<E>> {
fn validate_function_block(context: &mut FunctionValidationContext, body: &[Opcode]) -> Result<(), Error> {
let body_len = body.len();
if body_len == 0 {
return Err(Error::Validation("Non-empty function body expected".into()));
@ -119,7 +117,7 @@ impl<E> Validator<E> where E: UserError {
}
}
fn validate_instruction(context: &mut FunctionValidationContext<E>, opcode: &Opcode) -> Result<InstructionOutcome, Error<E>> {
fn validate_instruction(context: &mut FunctionValidationContext, opcode: &Opcode) -> Result<InstructionOutcome, Error> {
debug!(target: "validator", "validating {:?}", opcode);
match opcode {
&Opcode::Unreachable => Ok(InstructionOutcome::Unreachable),
@ -314,49 +312,49 @@ impl<E> Validator<E> where E: UserError {
}
}
fn validate_const(context: &mut FunctionValidationContext<E>, value_type: StackValueType) -> Result<InstructionOutcome, Error<E>> {
fn validate_const(context: &mut FunctionValidationContext, value_type: StackValueType) -> Result<InstructionOutcome, Error> {
context.push_value(value_type)?;
Ok(InstructionOutcome::ValidateNextInstruction)
}
fn validate_unop(context: &mut FunctionValidationContext<E>, value_type: StackValueType) -> Result<InstructionOutcome, Error<E>> {
fn validate_unop(context: &mut FunctionValidationContext, value_type: StackValueType) -> Result<InstructionOutcome, Error> {
context.pop_value(value_type)?;
context.push_value(value_type)?;
Ok(InstructionOutcome::ValidateNextInstruction)
}
fn validate_binop(context: &mut FunctionValidationContext<E>, value_type: StackValueType) -> Result<InstructionOutcome, Error<E>> {
fn validate_binop(context: &mut FunctionValidationContext, value_type: StackValueType) -> Result<InstructionOutcome, Error> {
context.pop_value(value_type)?;
context.pop_value(value_type)?;
context.push_value(value_type)?;
Ok(InstructionOutcome::ValidateNextInstruction)
}
fn validate_testop(context: &mut FunctionValidationContext<E>, value_type: StackValueType) -> Result<InstructionOutcome, Error<E>> {
fn validate_testop(context: &mut FunctionValidationContext, value_type: StackValueType) -> Result<InstructionOutcome, Error> {
context.pop_value(value_type)?;
context.push_value(ValueType::I32.into())?;
Ok(InstructionOutcome::ValidateNextInstruction)
}
fn validate_relop(context: &mut FunctionValidationContext<E>, value_type: StackValueType) -> Result<InstructionOutcome, Error<E>> {
fn validate_relop(context: &mut FunctionValidationContext, value_type: StackValueType) -> Result<InstructionOutcome, Error> {
context.pop_value(value_type)?;
context.pop_value(value_type)?;
context.push_value(ValueType::I32.into())?;
Ok(InstructionOutcome::ValidateNextInstruction)
}
fn validate_cvtop(context: &mut FunctionValidationContext<E>, value_type1: StackValueType, value_type2: StackValueType) -> Result<InstructionOutcome, Error<E>> {
fn validate_cvtop(context: &mut FunctionValidationContext, value_type1: StackValueType, value_type2: StackValueType) -> Result<InstructionOutcome, Error> {
context.pop_value(value_type1)?;
context.push_value(value_type2)?;
Ok(InstructionOutcome::ValidateNextInstruction)
}
fn validate_drop(context: &mut FunctionValidationContext<E>) -> Result<InstructionOutcome, Error<E>> {
fn validate_drop(context: &mut FunctionValidationContext) -> Result<InstructionOutcome, Error> {
context.pop_any_value().map(|_| ())?;
Ok(InstructionOutcome::ValidateNextInstruction)
}
fn validate_select(context: &mut FunctionValidationContext<E>) -> Result<InstructionOutcome, Error<E>> {
fn validate_select(context: &mut FunctionValidationContext) -> Result<InstructionOutcome, Error> {
context.pop_value(ValueType::I32.into())?;
let select_type = context.pop_any_value()?;
context.pop_value(select_type)?;
@ -364,13 +362,13 @@ impl<E> Validator<E> where E: UserError {
Ok(InstructionOutcome::ValidateNextInstruction)
}
fn validate_get_local(context: &mut FunctionValidationContext<E>, index: u32) -> Result<InstructionOutcome, Error<E>> {
fn validate_get_local(context: &mut FunctionValidationContext, index: u32) -> Result<InstructionOutcome, Error> {
let local_type = context.require_local(index)?;
context.push_value(local_type)?;
Ok(InstructionOutcome::ValidateNextInstruction)
}
fn validate_set_local(context: &mut FunctionValidationContext<E>, index: u32) -> Result<InstructionOutcome, Error<E>> {
fn validate_set_local(context: &mut FunctionValidationContext, index: u32) -> Result<InstructionOutcome, Error> {
let local_type = context.require_local(index)?;
let value_type = context.pop_any_value()?;
if local_type != value_type {
@ -379,7 +377,7 @@ impl<E> Validator<E> where E: UserError {
Ok(InstructionOutcome::ValidateNextInstruction)
}
fn validate_tee_local(context: &mut FunctionValidationContext<E>, index: u32) -> Result<InstructionOutcome, Error<E>> {
fn validate_tee_local(context: &mut FunctionValidationContext, index: u32) -> Result<InstructionOutcome, Error> {
let local_type = context.require_local(index)?;
let value_type = context.tee_any_value()?;
if local_type != value_type {
@ -388,13 +386,13 @@ impl<E> Validator<E> where E: UserError {
Ok(InstructionOutcome::ValidateNextInstruction)
}
fn validate_get_global(context: &mut FunctionValidationContext<E>, index: u32) -> Result<InstructionOutcome, Error<E>> {
fn validate_get_global(context: &mut FunctionValidationContext, index: u32) -> Result<InstructionOutcome, Error> {
let global_type = context.require_global(index, None)?;
context.push_value(global_type)?;
Ok(InstructionOutcome::ValidateNextInstruction)
}
fn validate_set_global(context: &mut FunctionValidationContext<E>, index: u32) -> Result<InstructionOutcome, Error<E>> {
fn validate_set_global(context: &mut FunctionValidationContext, index: u32) -> Result<InstructionOutcome, Error> {
let global_type = context.require_global(index, Some(true))?;
let value_type = context.pop_any_value()?;
if global_type != value_type {
@ -403,7 +401,7 @@ impl<E> Validator<E> where E: UserError {
Ok(InstructionOutcome::ValidateNextInstruction)
}
fn validate_load(context: &mut FunctionValidationContext<E>, align: u32, max_align: u32, value_type: StackValueType) -> Result<InstructionOutcome, Error<E>> {
fn validate_load(context: &mut FunctionValidationContext, align: u32, max_align: u32, value_type: StackValueType) -> Result<InstructionOutcome, Error> {
if align != NATURAL_ALIGNMENT {
if 1u32.checked_shl(align).unwrap_or(u32::MAX) > max_align {
return Err(Error::Validation(format!("Too large memory alignment 2^{} (expected at most {})", align, max_align)));
@ -416,7 +414,7 @@ impl<E> Validator<E> where E: UserError {
Ok(InstructionOutcome::ValidateNextInstruction)
}
fn validate_store(context: &mut FunctionValidationContext<E>, align: u32, max_align: u32, value_type: StackValueType) -> Result<InstructionOutcome, Error<E>> {
fn validate_store(context: &mut FunctionValidationContext, align: u32, max_align: u32, value_type: StackValueType) -> Result<InstructionOutcome, Error> {
if align != NATURAL_ALIGNMENT {
if 1u32.checked_shl(align).unwrap_or(u32::MAX) > max_align {
return Err(Error::Validation(format!("Too large memory alignment 2^{} (expected at most {})", align, max_align)));
@ -429,20 +427,20 @@ impl<E> Validator<E> where E: UserError {
Ok(InstructionOutcome::ValidateNextInstruction)
}
fn validate_block(context: &mut FunctionValidationContext<E>, block_type: BlockType) -> Result<InstructionOutcome, Error<E>> {
fn validate_block(context: &mut FunctionValidationContext, block_type: BlockType) -> Result<InstructionOutcome, Error> {
context.push_label(BlockFrameType::Block, block_type).map(|_| InstructionOutcome::ValidateNextInstruction)
}
fn validate_loop(context: &mut FunctionValidationContext<E>, block_type: BlockType) -> Result<InstructionOutcome, Error<E>> {
fn validate_loop(context: &mut FunctionValidationContext, block_type: BlockType) -> Result<InstructionOutcome, Error> {
context.push_label(BlockFrameType::Loop, block_type).map(|_| InstructionOutcome::ValidateNextInstruction)
}
fn validate_if(context: &mut FunctionValidationContext<E>, block_type: BlockType) -> Result<InstructionOutcome, Error<E>> {
fn validate_if(context: &mut FunctionValidationContext, block_type: BlockType) -> Result<InstructionOutcome, Error> {
context.pop_value(ValueType::I32.into())?;
context.push_label(BlockFrameType::IfTrue, block_type).map(|_| InstructionOutcome::ValidateNextInstruction)
}
fn validate_else(context: &mut FunctionValidationContext<E>) -> Result<InstructionOutcome, Error<E>> {
fn validate_else(context: &mut FunctionValidationContext) -> Result<InstructionOutcome, Error> {
let block_type = {
let top_frame = context.top_label()?;
if top_frame.frame_type != BlockFrameType::IfTrue {
@ -458,7 +456,7 @@ impl<E> Validator<E> where E: UserError {
context.push_label(BlockFrameType::IfFalse, block_type).map(|_| InstructionOutcome::ValidateNextInstruction)
}
fn validate_end(context: &mut FunctionValidationContext<E>) -> Result<InstructionOutcome, Error<E>> {
fn validate_end(context: &mut FunctionValidationContext) -> Result<InstructionOutcome, Error> {
{
let top_frame = context.top_label()?;
if top_frame.frame_type == BlockFrameType::IfTrue {
@ -471,7 +469,7 @@ impl<E> Validator<E> where E: UserError {
context.pop_label().map(|_| InstructionOutcome::ValidateNextInstruction)
}
fn validate_br(context: &mut FunctionValidationContext<E>, idx: u32) -> Result<InstructionOutcome, Error<E>> {
fn validate_br(context: &mut FunctionValidationContext, idx: u32) -> Result<InstructionOutcome, Error> {
let (frame_type, frame_block_type) = {
let frame = context.require_label(idx)?;
(frame.frame_type, frame.block_type)
@ -485,7 +483,7 @@ impl<E> Validator<E> where E: UserError {
Ok(InstructionOutcome::Unreachable)
}
fn validate_br_if(context: &mut FunctionValidationContext<E>, idx: u32) -> Result<InstructionOutcome, Error<E>> {
fn validate_br_if(context: &mut FunctionValidationContext, idx: u32) -> Result<InstructionOutcome, Error> {
context.pop_value(ValueType::I32.into())?;
if let BlockType::Value(value_type) = context.require_label(idx)?.block_type {
context.tee_value(value_type.into())?;
@ -493,7 +491,7 @@ impl<E> Validator<E> where E: UserError {
Ok(InstructionOutcome::ValidateNextInstruction)
}
fn validate_br_table(context: &mut FunctionValidationContext<E>, table: &Vec<u32>, default: u32) -> Result<InstructionOutcome, Error<E>> {
fn validate_br_table(context: &mut FunctionValidationContext, table: &Vec<u32>, default: u32) -> Result<InstructionOutcome, Error> {
let mut required_block_type = None;
{
@ -525,14 +523,14 @@ impl<E> Validator<E> where E: UserError {
Ok(InstructionOutcome::Unreachable)
}
fn validate_return(context: &mut FunctionValidationContext<E>) -> Result<InstructionOutcome, Error<E>> {
fn validate_return(context: &mut FunctionValidationContext) -> Result<InstructionOutcome, Error> {
if let BlockType::Value(value_type) = context.return_type()? {
context.tee_value(value_type.into())?;
}
Ok(InstructionOutcome::Unreachable)
}
fn validate_call(context: &mut FunctionValidationContext<E>, idx: u32) -> Result<InstructionOutcome, Error<E>> {
fn validate_call(context: &mut FunctionValidationContext, idx: u32) -> Result<InstructionOutcome, Error> {
let (argument_types, return_type) = context.require_function(idx)?;
for argument_type in argument_types.iter().rev() {
context.pop_value((*argument_type).into())?;
@ -543,7 +541,7 @@ impl<E> Validator<E> where E: UserError {
Ok(InstructionOutcome::ValidateNextInstruction)
}
fn validate_call_indirect(context: &mut FunctionValidationContext<E>, idx: u32) -> Result<InstructionOutcome, Error<E>> {
fn validate_call_indirect(context: &mut FunctionValidationContext, idx: u32) -> Result<InstructionOutcome, Error> {
context.require_table(DEFAULT_TABLE_INDEX, VariableType::AnyFunc)?;
context.pop_value(ValueType::I32.into())?;
@ -557,13 +555,13 @@ impl<E> Validator<E> where E: UserError {
Ok(InstructionOutcome::ValidateNextInstruction)
}
fn validate_current_memory(context: &mut FunctionValidationContext<E>) -> Result<InstructionOutcome, Error<E>> {
fn validate_current_memory(context: &mut FunctionValidationContext) -> Result<InstructionOutcome, Error> {
context.require_memory(DEFAULT_MEMORY_INDEX)?;
context.push_value(ValueType::I32.into())?;
Ok(InstructionOutcome::ValidateNextInstruction)
}
fn validate_grow_memory(context: &mut FunctionValidationContext<E>) -> Result<InstructionOutcome, Error<E>> {
fn validate_grow_memory(context: &mut FunctionValidationContext) -> Result<InstructionOutcome, Error> {
context.require_memory(DEFAULT_MEMORY_INDEX)?;
context.pop_value(ValueType::I32.into())?;
context.push_value(ValueType::I32.into())?;
@ -571,10 +569,10 @@ impl<E> Validator<E> where E: UserError {
}
}
impl<'a, E> FunctionValidationContext<'a, E> where E: UserError {
impl<'a> FunctionValidationContext<'a> {
pub fn new(
module_instance: &'a ModuleInstance<E>,
externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>>,
module_instance: &'a ModuleInstance,
externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>,
locals: &'a [ValueType],
value_stack_limit: usize,
frame_stack_limit: usize,
@ -592,11 +590,11 @@ impl<'a, E> FunctionValidationContext<'a, E> where E: UserError {
}
}
pub fn push_value(&mut self, value_type: StackValueType) -> Result<(), Error<E>> {
pub fn push_value(&mut self, value_type: StackValueType) -> Result<(), Error> {
self.value_stack.push(value_type.into())
}
pub fn pop_value(&mut self, value_type: StackValueType) -> Result<(), Error<E>> {
pub fn pop_value(&mut self, value_type: StackValueType) -> Result<(), Error> {
self.check_stack_access()?;
match self.value_stack.pop()? {
StackValueType::Specific(stack_value_type) if stack_value_type == value_type => Ok(()),
@ -609,7 +607,7 @@ impl<'a, E> FunctionValidationContext<'a, E> where E: UserError {
}
}
pub fn tee_value(&mut self, value_type: StackValueType) -> Result<(), Error<E>> {
pub fn tee_value(&mut self, value_type: StackValueType) -> Result<(), Error> {
self.check_stack_access()?;
match *self.value_stack.top()? {
StackValueType::Specific(stack_value_type) if stack_value_type == value_type => Ok(()),
@ -618,7 +616,7 @@ impl<'a, E> FunctionValidationContext<'a, E> where E: UserError {
}
}
pub fn pop_any_value(&mut self) -> Result<StackValueType, Error<E>> {
pub fn pop_any_value(&mut self) -> Result<StackValueType, Error> {
self.check_stack_access()?;
match self.value_stack.pop()? {
StackValueType::Specific(stack_value_type) => Ok(StackValueType::Specific(stack_value_type)),
@ -630,20 +628,20 @@ impl<'a, E> FunctionValidationContext<'a, E> where E: UserError {
}
}
pub fn tee_any_value(&mut self) -> Result<StackValueType, Error<E>> {
pub fn tee_any_value(&mut self) -> Result<StackValueType, Error> {
self.check_stack_access()?;
self.value_stack.top().map(Clone::clone)
}
pub fn unreachable(&mut self) -> Result<(), Error<E>> {
pub fn unreachable(&mut self) -> Result<(), Error> {
self.value_stack.push(StackValueType::AnyUnlimited)
}
pub fn top_label(&self) -> Result<&BlockFrame, Error<E>> {
pub fn top_label(&self) -> Result<&BlockFrame, Error> {
self.frame_stack.top()
}
pub fn push_label(&mut self, frame_type: BlockFrameType, block_type: BlockType) -> Result<(), Error<E>> {
pub fn push_label(&mut self, frame_type: BlockFrameType, block_type: BlockType) -> Result<(), Error> {
self.frame_stack.push(BlockFrame {
frame_type: frame_type,
block_type: block_type,
@ -654,7 +652,7 @@ impl<'a, E> FunctionValidationContext<'a, E> where E: UserError {
})
}
pub fn pop_label(&mut self) -> Result<InstructionOutcome, Error<E>> {
pub fn pop_label(&mut self) -> Result<InstructionOutcome, Error> {
let frame = self.frame_stack.pop()?;
let actual_value_type = if self.value_stack.len() > frame.value_stack_len {
Some(self.value_stack.pop()?)
@ -678,22 +676,22 @@ impl<'a, E> FunctionValidationContext<'a, E> where E: UserError {
Ok(InstructionOutcome::ValidateNextInstruction)
}
pub fn require_label(&self, idx: u32) -> Result<&BlockFrame, Error<E>> {
pub fn require_label(&self, idx: u32) -> Result<&BlockFrame, Error> {
self.frame_stack.get(idx as usize)
}
pub fn return_type(&self) -> Result<BlockType, Error<E>> {
pub fn return_type(&self) -> Result<BlockType, Error> {
self.return_type.ok_or(Error::Validation("Trying to return from expression".into()))
}
pub fn require_local(&self, idx: u32) -> Result<StackValueType, Error<E>> {
pub fn require_local(&self, idx: u32) -> Result<StackValueType, Error> {
self.locals.get(idx as usize)
.cloned()
.map(Into::into)
.ok_or(Error::Validation(format!("Trying to access local with index {} when there are only {} locals", idx, self.locals.len())))
}
pub fn require_global(&self, idx: u32, mutability: Option<bool>) -> Result<StackValueType, Error<E>> {
pub fn require_global(&self, idx: u32, mutability: Option<bool>) -> Result<StackValueType, Error> {
self.module_instance
.global(ItemIndex::IndexSpace(idx), None, self.externals.clone())
.and_then(|g| match mutability {
@ -709,13 +707,13 @@ impl<'a, E> FunctionValidationContext<'a, E> where E: UserError {
})
}
pub fn require_memory(&self, idx: u32) -> Result<(), Error<E>> {
pub fn require_memory(&self, idx: u32) -> Result<(), Error> {
self.module_instance
.memory(ItemIndex::IndexSpace(idx))
.map(|_| ())
}
pub fn require_table(&self, idx: u32, variable_type: VariableType) -> Result<(), Error<E>> {
pub fn require_table(&self, idx: u32, variable_type: VariableType) -> Result<(), Error> {
self.module_instance
.table(ItemIndex::IndexSpace(idx))
.and_then(|t| if t.variable_type() == variable_type {
@ -725,12 +723,12 @@ impl<'a, E> FunctionValidationContext<'a, E> where E: UserError {
})
}
pub fn require_function(&self, idx: u32) -> Result<(Vec<ValueType>, BlockType), Error<E>> {
pub fn require_function(&self, idx: u32) -> Result<(Vec<ValueType>, BlockType), Error> {
self.module_instance.function_type(ItemIndex::IndexSpace(idx))
.map(|ft| (ft.params().to_vec(), ft.return_type().map(BlockType::Value).unwrap_or(BlockType::NoResult)))
}
pub fn require_function_type(&self, idx: u32) -> Result<(Vec<ValueType>, BlockType), Error<E>> {
pub fn require_function_type(&self, idx: u32) -> Result<(Vec<ValueType>, BlockType), Error> {
self.module_instance.function_type_by_index(idx)
.map(|ft| (ft.params().to_vec(), ft.return_type().map(BlockType::Value).unwrap_or(BlockType::NoResult)))
}
@ -739,7 +737,7 @@ impl<'a, E> FunctionValidationContext<'a, E> where E: UserError {
self.labels
}
fn check_stack_access(&self) -> Result<(), Error<E>> {
fn check_stack_access(&self) -> Result<(), Error> {
let value_stack_min = self.frame_stack.top().expect("at least 1 topmost block").value_stack_len;
if self.value_stack.len() > value_stack_min {
Ok(())

View File

@ -1,7 +1,7 @@
use std::{i32, i64, u32, u64, f32};
use std::io;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use interpreter::{Error, UserError};
use interpreter::Error;
use interpreter::variable::VariableType;
/// Runtime value.
@ -52,15 +52,15 @@ pub trait TransmuteInto<T> {
}
/// Convert from and to little endian.
pub trait LittleEndianConvert<E: UserError> where Self: Sized {
pub trait LittleEndianConvert where Self: Sized {
/// Convert to little endian buffer.
fn into_little_endian(self) -> Vec<u8>;
/// Convert from little endian buffer.
fn from_little_endian(buffer: Vec<u8>) -> Result<Self, Error<E>>;
fn from_little_endian(buffer: Vec<u8>) -> Result<Self, Error>;
}
/// Arithmetic operations.
pub trait ArithmeticOps<T, E: UserError> {
pub trait ArithmeticOps<T> {
/// Add two values.
fn add(self, other: T) -> T;
/// Subtract two values.
@ -68,11 +68,11 @@ pub trait ArithmeticOps<T, E: UserError> {
/// Multiply two values.
fn mul(self, other: T) -> T;
/// Divide two values.
fn div(self, other: T) -> Result<T, Error<E>>;
fn div(self, other: T) -> Result<T, Error>;
}
/// Integer value.
pub trait Integer<T, E: UserError>: ArithmeticOps<T, E> {
pub trait Integer<T>: ArithmeticOps<T> {
/// Counts leading zeros in the bitwise representation of the value.
fn leading_zeros(self) -> T;
/// Counts trailing zeros in the bitwise representation of the value.
@ -84,11 +84,11 @@ pub trait Integer<T, E: UserError>: ArithmeticOps<T, E> {
/// Get right bit rotation result.
fn rotr(self, other: T) -> T;
/// Get division remainder.
fn rem(self, other: T) -> Result<T, Error<E>>;
fn rem(self, other: T) -> Result<T, Error>;
}
/// Float-point value.
pub trait Float<T, E: UserError>: ArithmeticOps<T, E> {
pub trait Float<T>: ArithmeticOps<T> {
/// Get absolute value.
fn abs(self) -> T;
/// Returns the largest integer less than or equal to a number.
@ -178,8 +178,8 @@ impl From<f64> for RuntimeValue {
}
}
impl<E> TryInto<bool, Error<E>> for RuntimeValue where E: UserError {
fn try_into(self) -> Result<bool, Error<E>> {
impl TryInto<bool, Error> for RuntimeValue {
fn try_into(self) -> Result<bool, Error> {
match self {
RuntimeValue::I32(val) => Ok(val != 0),
_ => Err(Error::Value(format!("32-bit int value expected"))),
@ -187,8 +187,8 @@ impl<E> TryInto<bool, Error<E>> for RuntimeValue where E: UserError {
}
}
impl<E> TryInto<i32, Error<E>> for RuntimeValue where E: UserError {
fn try_into(self) -> Result<i32, Error<E>> {
impl TryInto<i32, Error> for RuntimeValue {
fn try_into(self) -> Result<i32, Error> {
match self {
RuntimeValue::I32(val) => Ok(val),
_ => Err(Error::Value(format!("32-bit int value expected"))),
@ -196,8 +196,8 @@ impl<E> TryInto<i32, Error<E>> for RuntimeValue where E: UserError {
}
}
impl<E> TryInto<i64, Error<E>> for RuntimeValue where E: UserError {
fn try_into(self) -> Result<i64, Error<E>> {
impl TryInto<i64, Error> for RuntimeValue {
fn try_into(self) -> Result<i64, Error> {
match self {
RuntimeValue::I64(val) => Ok(val),
_ => Err(Error::Value(format!("64-bit int value expected"))),
@ -205,8 +205,8 @@ impl<E> TryInto<i64, Error<E>> for RuntimeValue where E: UserError {
}
}
impl<E> TryInto<f32, Error<E>> for RuntimeValue where E: UserError {
fn try_into(self) -> Result<f32, Error<E>> {
impl TryInto<f32, Error> for RuntimeValue {
fn try_into(self) -> Result<f32, Error> {
match self {
RuntimeValue::F32(val) => Ok(val),
_ => Err(Error::Value(format!("32-bit float value expected"))),
@ -214,8 +214,8 @@ impl<E> TryInto<f32, Error<E>> for RuntimeValue where E: UserError {
}
}
impl<E> TryInto<f64, Error<E>> for RuntimeValue where E: UserError {
fn try_into(self) -> Result<f64, Error<E>> {
impl TryInto<f64, Error> for RuntimeValue {
fn try_into(self) -> Result<f64, Error> {
match self {
RuntimeValue::F64(val) => Ok(val),
_ => Err(Error::Value(format!("64-bit float value expected"))),
@ -223,8 +223,8 @@ impl<E> TryInto<f64, Error<E>> for RuntimeValue where E: UserError {
}
}
impl<E> TryInto<u32, Error<E>> for RuntimeValue where E: UserError {
fn try_into(self) -> Result<u32, Error<E>> {
impl TryInto<u32, Error> for RuntimeValue {
fn try_into(self) -> Result<u32, Error> {
match self {
RuntimeValue::I32(val) => Ok(val as u32),
_ => Err(Error::Value(format!("32-bit int value expected"))),
@ -232,8 +232,8 @@ impl<E> TryInto<u32, Error<E>> for RuntimeValue where E: UserError {
}
}
impl<E> TryInto<u64, Error<E>> for RuntimeValue where E: UserError {
fn try_into(self) -> Result<u64, Error<E>> {
impl TryInto<u64, Error> for RuntimeValue {
fn try_into(self) -> Result<u64, Error> {
match self {
RuntimeValue::I64(val) => Ok(val as u64),
_ => Err(Error::Value(format!("64-bit int value expected"))),
@ -265,8 +265,8 @@ impl_wrap_into!(f64, f32);
macro_rules! impl_try_truncate_into {
($from: ident, $into: ident) => {
impl<E> TryTruncateInto<$into, Error<E>> for $from where E: UserError {
fn try_truncate_into(self) -> Result<$into, Error<E>> {
impl TryTruncateInto<$into, Error> for $from {
fn try_truncate_into(self) -> Result<$into, Error> {
// Casting from a float to an integer will round the float towards zero
// NOTE: currently this will cause Undefined Behavior if the rounded value cannot be represented by the
// target integer type. This includes Inf and NaN. This is a bug and will be fixed.
@ -373,31 +373,31 @@ impl TransmuteInto<f64> for i64 {
fn transmute_into(self) -> f64 { f64_from_bits(self as _) }
}
impl<E> LittleEndianConvert<E> for i8 where E: UserError {
impl LittleEndianConvert for i8 {
fn into_little_endian(self) -> Vec<u8> {
vec![self as u8]
}
fn from_little_endian(buffer: Vec<u8>) -> Result<Self, Error<E>> {
fn from_little_endian(buffer: Vec<u8>) -> Result<Self, Error> {
buffer.get(0)
.map(|v| *v as i8)
.ok_or(Error::Value("invalid little endian buffer".into()))
}
}
impl<E> LittleEndianConvert<E> for u8 where E: UserError {
impl LittleEndianConvert for u8 {
fn into_little_endian(self) -> Vec<u8> {
vec![self]
}
fn from_little_endian(buffer: Vec<u8>) -> Result<Self, Error<E>> {
fn from_little_endian(buffer: Vec<u8>) -> Result<Self, Error> {
buffer.get(0)
.cloned()
.ok_or(Error::Value("invalid little endian buffer".into()))
}
}
impl<E> LittleEndianConvert<E> for i16 where E: UserError {
impl LittleEndianConvert for i16 {
fn into_little_endian(self) -> Vec<u8> {
let mut vec = Vec::with_capacity(2);
vec.write_i16::<LittleEndian>(self)
@ -405,13 +405,13 @@ impl<E> LittleEndianConvert<E> for i16 where E: UserError {
vec
}
fn from_little_endian(buffer: Vec<u8>) -> Result<Self, Error<E>> {
fn from_little_endian(buffer: Vec<u8>) -> Result<Self, Error> {
io::Cursor::new(buffer).read_i16::<LittleEndian>()
.map_err(|e| Error::Value(e.to_string()))
}
}
impl<E> LittleEndianConvert<E> for u16 where E: UserError {
impl LittleEndianConvert for u16 {
fn into_little_endian(self) -> Vec<u8> {
let mut vec = Vec::with_capacity(2);
vec.write_u16::<LittleEndian>(self)
@ -419,13 +419,13 @@ impl<E> LittleEndianConvert<E> for u16 where E: UserError {
vec
}
fn from_little_endian(buffer: Vec<u8>) -> Result<Self, Error<E>> {
fn from_little_endian(buffer: Vec<u8>) -> Result<Self, Error> {
io::Cursor::new(buffer).read_u16::<LittleEndian>()
.map_err(|e| Error::Value(e.to_string()))
}
}
impl<E> LittleEndianConvert<E> for i32 where E: UserError {
impl LittleEndianConvert for i32 {
fn into_little_endian(self) -> Vec<u8> {
let mut vec = Vec::with_capacity(4);
vec.write_i32::<LittleEndian>(self)
@ -433,13 +433,13 @@ impl<E> LittleEndianConvert<E> for i32 where E: UserError {
vec
}
fn from_little_endian(buffer: Vec<u8>) -> Result<Self, Error<E>> {
fn from_little_endian(buffer: Vec<u8>) -> Result<Self, Error> {
io::Cursor::new(buffer).read_i32::<LittleEndian>()
.map_err(|e| Error::Value(e.to_string()))
}
}
impl<E> LittleEndianConvert<E> for u32 where E: UserError {
impl LittleEndianConvert for u32 {
fn into_little_endian(self) -> Vec<u8> {
let mut vec = Vec::with_capacity(4);
vec.write_u32::<LittleEndian>(self)
@ -447,13 +447,13 @@ impl<E> LittleEndianConvert<E> for u32 where E: UserError {
vec
}
fn from_little_endian(buffer: Vec<u8>) -> Result<Self, Error<E>> {
fn from_little_endian(buffer: Vec<u8>) -> Result<Self, Error> {
io::Cursor::new(buffer).read_u32::<LittleEndian>()
.map_err(|e| Error::Value(e.to_string()))
}
}
impl<E> LittleEndianConvert<E> for i64 where E: UserError {
impl LittleEndianConvert for i64 {
fn into_little_endian(self) -> Vec<u8> {
let mut vec = Vec::with_capacity(8);
vec.write_i64::<LittleEndian>(self)
@ -461,13 +461,13 @@ impl<E> LittleEndianConvert<E> for i64 where E: UserError {
vec
}
fn from_little_endian(buffer: Vec<u8>) -> Result<Self, Error<E>> {
fn from_little_endian(buffer: Vec<u8>) -> Result<Self, Error> {
io::Cursor::new(buffer).read_i64::<LittleEndian>()
.map_err(|e| Error::Value(e.to_string()))
}
}
impl<E> LittleEndianConvert<E> for f32 where E: UserError {
impl LittleEndianConvert for f32 {
fn into_little_endian(self) -> Vec<u8> {
let mut vec = Vec::with_capacity(4);
vec.write_f32::<LittleEndian>(self)
@ -475,14 +475,14 @@ impl<E> LittleEndianConvert<E> for f32 where E: UserError {
vec
}
fn from_little_endian(buffer: Vec<u8>) -> Result<Self, Error<E>> {
fn from_little_endian(buffer: Vec<u8>) -> Result<Self, Error> {
io::Cursor::new(buffer).read_u32::<LittleEndian>()
.map(f32_from_bits)
.map_err(|e| Error::Value(e.to_string()))
}
}
impl<E> LittleEndianConvert<E> for f64 where E: UserError {
impl LittleEndianConvert for f64 {
fn into_little_endian(self) -> Vec<u8> {
let mut vec = Vec::with_capacity(8);
vec.write_f64::<LittleEndian>(self)
@ -490,7 +490,7 @@ impl<E> LittleEndianConvert<E> for f64 where E: UserError {
vec
}
fn from_little_endian(buffer: Vec<u8>) -> Result<Self, Error<E>> {
fn from_little_endian(buffer: Vec<u8>) -> Result<Self, Error> {
io::Cursor::new(buffer).read_u64::<LittleEndian>()
.map(f64_from_bits)
.map_err(|e| Error::Value(e.to_string()))
@ -535,11 +535,11 @@ fn f64_from_bits(mut v: u64) -> f64 {
macro_rules! impl_integer_arithmetic_ops {
($type: ident) => {
impl<E> ArithmeticOps<$type, E> for $type where E: UserError {
impl ArithmeticOps<$type> for $type {
fn add(self, other: $type) -> $type { self.wrapping_add(other) }
fn sub(self, other: $type) -> $type { self.wrapping_sub(other) }
fn mul(self, other: $type) -> $type { self.wrapping_mul(other) }
fn div(self, other: $type) -> Result<$type, Error<E>> {
fn div(self, other: $type) -> Result<$type, Error> {
if other == 0 { Err(Error::Value("Division by zero".to_owned())) }
else {
let (result, overflow) = self.overflowing_div(other);
@ -561,11 +561,11 @@ impl_integer_arithmetic_ops!(u64);
macro_rules! impl_float_arithmetic_ops {
($type: ident) => {
impl<E> ArithmeticOps<$type, E> for $type where E: UserError {
impl ArithmeticOps<$type> for $type {
fn add(self, other: $type) -> $type { self + other }
fn sub(self, other: $type) -> $type { self - other }
fn mul(self, other: $type) -> $type { self * other }
fn div(self, other: $type) -> Result<$type, Error<E>> { Ok(self / other) }
fn div(self, other: $type) -> Result<$type, Error> { Ok(self / other) }
}
}
}
@ -575,13 +575,13 @@ impl_float_arithmetic_ops!(f64);
macro_rules! impl_integer {
($type: ident) => {
impl<E> Integer<$type, E> for $type where E: UserError {
impl Integer<$type> for $type {
fn leading_zeros(self) -> $type { self.leading_zeros() as $type }
fn trailing_zeros(self) -> $type { self.trailing_zeros() as $type }
fn count_ones(self) -> $type { self.count_ones() as $type }
fn rotl(self, other: $type) -> $type { self.rotate_left(other as u32) }
fn rotr(self, other: $type) -> $type { self.rotate_right(other as u32) }
fn rem(self, other: $type) -> Result<$type, Error<E>> {
fn rem(self, other: $type) -> Result<$type, Error> {
if other == 0 { Err(Error::Value("Division by zero".to_owned())) }
else { Ok(self.wrapping_rem(other)) }
}
@ -596,7 +596,7 @@ impl_integer!(u64);
macro_rules! impl_float {
($type: ident, $int_type: ident) => {
impl<E> Float<$type, E> for $type where E: UserError {
impl Float<$type> for $type {
fn abs(self) -> $type { self.abs() }
fn floor(self) -> $type { self.floor() }
fn ceil(self) -> $type { self.ceil() }

View File

@ -1,7 +1,7 @@
use std::fmt;
use parking_lot::RwLock;
use elements::{GlobalType, ValueType, TableElementType};
use interpreter::{Error, UserError};
use interpreter::Error;
use interpreter::value::RuntimeValue;
/// Variable type.
@ -20,35 +20,35 @@ pub enum VariableType {
}
/// Externally stored variable value.
pub trait ExternalVariableValue<E: UserError> {
pub trait ExternalVariableValue {
/// Get variable value.
fn get(&self) -> RuntimeValue;
/// Set variable value.
fn set(&mut self, value: RuntimeValue) -> Result<(), Error<E>>;
fn set(&mut self, value: RuntimeValue) -> Result<(), Error>;
}
/// Variable instance.
#[derive(Debug)]
pub struct VariableInstance<E: UserError> {
pub struct VariableInstance {
/// Is mutable?
is_mutable: bool,
/// Variable type.
variable_type: VariableType,
/// Global value.
value: RwLock<VariableValue<E>>,
value: RwLock<VariableValue>,
}
/// Enum variable value.
enum VariableValue<E: UserError> {
enum VariableValue {
/// Internal value.
Internal(RuntimeValue),
/// External value.
External(Box<ExternalVariableValue<E>>),
External(Box<ExternalVariableValue>),
}
impl<E> VariableInstance<E> where E: UserError {
impl VariableInstance {
/// New variable instance
pub fn new(is_mutable: bool, variable_type: VariableType, value: RuntimeValue) -> Result<Self, Error<E>> {
pub fn new(is_mutable: bool, variable_type: VariableType, value: RuntimeValue) -> Result<Self, Error> {
// TODO: there is nothing about null value in specification + there is nothing about initializing missing table elements? => runtime check for nulls
if !value.is_null() && value.variable_type() != Some(variable_type) {
return Err(Error::Variable(format!("trying to initialize variable of type {:?} with value of type {:?}", variable_type, value.variable_type())));
@ -62,12 +62,12 @@ impl<E> VariableInstance<E> where E: UserError {
}
/// New global variable
pub fn new_global(global_type: &GlobalType, value: RuntimeValue) -> Result<Self, Error<E>> {
pub fn new_global(global_type: &GlobalType, value: RuntimeValue) -> Result<Self, Error> {
Self::new(global_type.is_mutable(), global_type.content_type().into(), value)
}
/// New global with externally stored value.
pub fn new_external_global(is_mutable: bool, variable_type: VariableType, value: Box<ExternalVariableValue<E>>) -> Result<Self, Error<E>> {
pub fn new_external_global(is_mutable: bool, variable_type: VariableType, value: Box<ExternalVariableValue>) -> Result<Self, Error> {
// TODO: there is nothing about null value in specification + there is nothing about initializing missing table elements? => runtime check for nulls
let current_value = value.get();
if !current_value.is_null() && current_value.variable_type() != Some(variable_type) {
@ -97,7 +97,7 @@ impl<E> VariableInstance<E> where E: UserError {
}
/// Set the value of the variable instance
pub fn set(&self, value: RuntimeValue) -> Result<(), Error<E>> {
pub fn set(&self, value: RuntimeValue) -> Result<(), Error> {
if !self.is_mutable {
return Err(Error::Variable("trying to update immutable variable".into()));
}
@ -109,7 +109,7 @@ impl<E> VariableInstance<E> where E: UserError {
}
}
impl<E> VariableValue<E> where E: UserError {
impl VariableValue {
fn get(&self) -> RuntimeValue {
match *self {
VariableValue::Internal(ref value) => value.clone(),
@ -117,7 +117,7 @@ impl<E> VariableValue<E> where E: UserError {
}
}
fn set(&mut self, new_value: RuntimeValue) -> Result<(), Error<E>> {
fn set(&mut self, new_value: RuntimeValue) -> Result<(), Error> {
match *self {
VariableValue::Internal(ref mut value) => {
*value = new_value;
@ -147,7 +147,7 @@ impl From<TableElementType> for VariableType {
}
}
impl<E> fmt::Debug for VariableValue<E> where E: UserError {
impl fmt::Debug for VariableValue {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
VariableValue::Internal(ref value) => write!(f, "Variable.Internal({:?})", value),