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 builder::module;
use elements::{Module, ExportEntry, Internal, GlobalEntry, GlobalType, use elements::{Module, ExportEntry, Internal, GlobalEntry, GlobalType,
ValueType, InitExpr, Opcode, Opcodes}; ValueType, InitExpr, Opcode, Opcodes};
use interpreter::{Error, UserError}; use interpreter::Error;
use interpreter::env_native::NATIVE_INDEX_FUNC_MIN; use interpreter::env_native::NATIVE_INDEX_FUNC_MIN;
use interpreter::module::{ModuleInstanceInterface, ModuleInstance, ExecutionParams, use interpreter::module::{ModuleInstanceInterface, ModuleInstance, ExecutionParams,
ItemIndex, CallerContext, ExportEntryType, InternalFunctionReference, InternalFunction, FunctionSignature}; ItemIndex, CallerContext, ExportEntryType, InternalFunctionReference, InternalFunction, FunctionSignature};
@ -84,13 +84,13 @@ pub struct EnvParams {
pub static_size: Option<u32>, pub static_size: Option<u32>,
} }
pub struct EnvModuleInstance<E: UserError> { pub struct EnvModuleInstance {
_params: EnvParams, _params: EnvParams,
instance: ModuleInstance<E>, instance: ModuleInstance,
} }
impl<E> EnvModuleInstance<E> where E: UserError { impl EnvModuleInstance {
pub fn new(params: EnvParams, module: Module) -> Result<Self, Error<E>> { pub fn new(params: EnvParams, module: Module) -> Result<Self, Error> {
let mut instance = ModuleInstance::new(Weak::default(), "env".into(), module)?; let mut instance = ModuleInstance::new(Weak::default(), "env".into(), module)?;
instance.instantiate(None)?; instance.instantiate(None)?;
@ -101,52 +101,52 @@ impl<E> EnvModuleInstance<E> where E: UserError {
} }
} }
impl<E> ModuleInstanceInterface<E> for EnvModuleInstance<E> where E: UserError { impl ModuleInstanceInterface for EnvModuleInstance {
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> {
self.instance.execute_index(index, params) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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 // to make interpreter independent of *SCRIPTEN runtime, just make abort/assert = interpreter Error
match index { match index {
INDEX_FUNC_ABORT => self.global(ItemIndex::IndexSpace(INDEX_GLOBAL_ABORT), Some(VariableType::I32), None) 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 < params.total_memory);
debug_assert!((params.total_stack % LINEAR_MEMORY_PAGE_SIZE) == 0); debug_assert!((params.total_stack % LINEAR_MEMORY_PAGE_SIZE) == 0);
debug_assert!((params.total_memory % 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 std::borrow::Cow;
use parking_lot::RwLock; use parking_lot::RwLock;
use elements::{Internal, ValueType}; use elements::{Internal, ValueType};
use interpreter::{Error, UserError}; use interpreter::Error;
use interpreter::module::{ModuleInstanceInterface, ExecutionParams, ItemIndex, use interpreter::module::{ModuleInstanceInterface, ExecutionParams, ItemIndex,
CallerContext, ExportEntryType, InternalFunctionReference, InternalFunction, FunctionSignature}; CallerContext, ExportEntryType, InternalFunctionReference, InternalFunction, FunctionSignature};
use interpreter::memory::MemoryInstance; use interpreter::memory::MemoryInstance;
@ -17,9 +17,9 @@ pub const NATIVE_INDEX_FUNC_MIN: u32 = 10001;
pub const NATIVE_INDEX_GLOBAL_MIN: u32 = 20001; pub const NATIVE_INDEX_GLOBAL_MIN: u32 = 20001;
/// User functions executor. /// User functions executor.
pub trait UserFunctionExecutor<E: UserError> { pub trait UserFunctionExecutor {
/// Execute function with given name. /// 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 /// User function descriptor
@ -68,21 +68,21 @@ impl UserFunctionDescriptor {
} }
/// Set of user-defined module elements. /// Set of user-defined module elements.
pub struct UserDefinedElements<'a, E: 'a + UserError> { pub struct UserDefinedElements<'a> {
/// User globals list. /// User globals list.
pub globals: HashMap<String, Arc<VariableInstance<E>>>, pub globals: HashMap<String, Arc<VariableInstance>>,
/// User functions list. /// User functions list.
pub functions: Cow<'static, [UserFunctionDescriptor]>, pub functions: Cow<'static, [UserFunctionDescriptor]>,
/// Functions executor. /// Functions executor.
pub executor: Option<&'a mut UserFunctionExecutor<E>>, pub executor: Option<&'a mut UserFunctionExecutor>,
} }
/// Native module instance. /// Native module instance.
pub struct NativeModuleInstance<'a, E: 'a + UserError> { pub struct NativeModuleInstance<'a> {
/// Underllying module reference. /// Underllying module reference.
env: Arc<ModuleInstanceInterface<E>>, env: Arc<ModuleInstanceInterface>,
/// User function executor. /// User function executor.
executor: RwLock<Option<&'a mut UserFunctionExecutor<E>>>, executor: RwLock<Option<&'a mut UserFunctionExecutor>>,
/// By-name functions index. /// By-name functions index.
functions_by_name: HashMap<String, u32>, functions_by_name: HashMap<String, u32>,
/// User functions list. /// User functions list.
@ -90,12 +90,12 @@ pub struct NativeModuleInstance<'a, E: 'a + UserError> {
/// By-name functions index. /// By-name functions index.
globals_by_name: HashMap<String, u32>, globals_by_name: HashMap<String, u32>,
/// User globals list. /// 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 /// 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() { 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())); 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 { impl<'a> ModuleInstanceInterface for NativeModuleInstance<'a> {
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> {
self.env.execute_index(index, params) 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) 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) { if let Some(index) = self.functions_by_name.get(name) {
let composite_index = NATIVE_INDEX_FUNC_MIN + *index; let composite_index = NATIVE_INDEX_FUNC_MIN + *index;
match required_type { 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) 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) 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) 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 { let index = match global_index {
ItemIndex::IndexSpace(index) | ItemIndex::Internal(index) => index, ItemIndex::IndexSpace(index) | ItemIndex::Internal(index) => index,
ItemIndex::External(_) => unreachable!("trying to get global, exported by native env module"), 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))) .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 { let index = match function_index {
ItemIndex::IndexSpace(index) | ItemIndex::Internal(index) => index, ItemIndex::IndexSpace(index) | ItemIndex::Internal(index) => index,
ItemIndex::External(_) => unreachable!("trying to call function, exported by native env module"), 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)))?)) .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)) 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) 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) 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) 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 { if index < NATIVE_INDEX_FUNC_MIN || index >= NATIVE_INDEX_GLOBAL_MIN {
return self.env.call_internal_function(outer, index); 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. /// 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) NativeModuleInstance::new(env, user_elements)
} }

View File

@ -1,7 +1,7 @@
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
use std::collections::HashMap; use std::collections::HashMap;
use elements::{ImportSection, ImportEntry, External, Internal}; use elements::{ImportSection, ImportEntry, External, Internal};
use interpreter::{Error, UserError}; use interpreter::Error;
use interpreter::memory::MemoryInstance; use interpreter::memory::MemoryInstance;
use interpreter::module::{ModuleInstanceInterface, ItemIndex, ExportEntryType, FunctionSignature}; use interpreter::module::{ModuleInstanceInterface, ItemIndex, ExportEntryType, FunctionSignature};
use interpreter::program::ProgramInstanceEssence; use interpreter::program::ProgramInstanceEssence;
@ -9,9 +9,9 @@ use interpreter::table::TableInstance;
use interpreter::variable::{VariableInstance, VariableType}; use interpreter::variable::{VariableInstance, VariableType};
/// Module imports. /// Module imports.
pub struct ModuleImports<E: UserError> { pub struct ModuleImports {
/// Program instance. /// Program instance.
program: Weak<ProgramInstanceEssence<E>>, program: Weak<ProgramInstanceEssence>,
/// External functions. /// External functions.
functions: Vec<usize>, functions: Vec<usize>,
/// External tables. /// External tables.
@ -22,9 +22,9 @@ pub struct ModuleImports<E: UserError> {
globals: Vec<usize>, globals: Vec<usize>,
} }
impl<E> ModuleImports<E> where E: UserError { impl ModuleImports {
/// Create new imports for given import section. /// 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 functions = Vec::new();
let mut tables = Vec::new(); let mut tables = Vec::new();
let mut memory = Vec::new(); let mut memory = Vec::new();
@ -104,7 +104,7 @@ impl<E> ModuleImports<E> where E: UserError {
} }
/// Get module reference. /// 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(externals) = externals {
if let Some(module) = externals.get(name).cloned() { if let Some(module) = externals.get(name).cloned() {
return Ok(module); return Ok(module);
@ -118,7 +118,7 @@ impl<E> ModuleImports<E> where E: UserError {
} }
/// Get function index. /// 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))?; 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 { if let Internal::Function(external_index) = export {
return Ok(external_index); return Ok(external_index);
@ -128,7 +128,7 @@ impl<E> ModuleImports<E> where E: UserError {
} }
/// Get table reference. /// 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)?; let (module, export) = self.external_export(externals, import, &ExportEntryType::Any)?;
if let Internal::Table(external_index) = export { if let Internal::Table(external_index) = export {
return module.table(ItemIndex::Internal(external_index)); return module.table(ItemIndex::Internal(external_index));
@ -138,7 +138,7 @@ impl<E> ModuleImports<E> where E: UserError {
} }
/// Get memory reference. /// 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)?; let (module, export) = self.external_export(externals, import, &ExportEntryType::Any)?;
if let Internal::Memory(external_index) = export { if let Internal::Memory(external_index) = export {
return module.memory(ItemIndex::Internal(external_index)); return module.memory(ItemIndex::Internal(external_index));
@ -148,7 +148,7 @@ impl<E> ModuleImports<E> where E: UserError {
} }
/// Get global reference. /// 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))?; 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 { if let Internal::Global(external_index) = export {
return module.global(ItemIndex::Internal(external_index), required_type, externals); 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()))) 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()) self.module(externals, import.module())
.and_then(|m| .and_then(|m|
m.export_entry(import.field(), required_type) m.export_entry(import.field(), required_type)

View File

@ -4,7 +4,7 @@ use std::ops::Range;
use std::cmp; use std::cmp;
use parking_lot::RwLock; use parking_lot::RwLock;
use elements::{MemoryType, ResizableLimits}; use elements::{MemoryType, ResizableLimits};
use interpreter::{Error, UserError}; use interpreter::Error;
use interpreter::module::check_limits; use interpreter::module::check_limits;
/// Linear memory page size. /// Linear memory page size.
@ -13,15 +13,13 @@ pub const LINEAR_MEMORY_PAGE_SIZE: u32 = 65536;
const LINEAR_MEMORY_MAX_PAGES: u32 = 65536; const LINEAR_MEMORY_MAX_PAGES: u32 = 65536;
/// Linear memory instance. /// Linear memory instance.
pub struct MemoryInstance<E: UserError> { pub struct MemoryInstance {
/// Memofy limits. /// Memofy limits.
limits: ResizableLimits, limits: ResizableLimits,
/// Linear memory buffer. /// Linear memory buffer.
buffer: RwLock<Vec<u8>>, buffer: RwLock<Vec<u8>>,
/// Maximum buffer size. /// Maximum buffer size.
maximum_size: u32, 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>> { 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. /// 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())?; check_limits(memory_type.limits())?;
let maximum_size = match memory_type.limits().maximum() { let maximum_size = match memory_type.limits().maximum() {
@ -65,7 +63,6 @@ impl<E> MemoryInstance<E> where E: UserError {
limits: memory_type.limits().clone(), limits: memory_type.limits().clone(),
buffer: RwLock::new(vec![0; initial_size as usize]), buffer: RwLock::new(vec![0; initial_size as usize]),
maximum_size: maximum_size, maximum_size: maximum_size,
_dummy: Default::default(),
}; };
Ok(Arc::new(memory)) Ok(Arc::new(memory))
@ -82,7 +79,7 @@ impl<E> MemoryInstance<E> where E: UserError {
} }
/// Get data at given offset. /// 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 buffer = self.buffer.read();
let region = self.checked_region(&buffer, offset as usize, size)?; 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 /// 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 buffer = self.buffer.read();
let region = self.checked_region(&buffer, offset as usize, target.len())?; 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. /// 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 mut buffer = self.buffer.write();
let range = self.checked_region(&buffer, offset as usize, value.len())?.range(); 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. /// Increases the size of the linear memory by given number of pages.
/// Returns -1 if allocation fails or previous memory size, if succeeds. /// 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 mut buffer = self.buffer.write();
let old_size = buffer.len() as u32; let old_size = buffer.len() as u32;
match calculate_memory_size(old_size, pages, self.maximum_size) { 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>> where B: ::std::ops::Deref<Target=Vec<u8>>
{ {
let end = offset.checked_add(size) let end = offset.checked_add(size)
@ -141,7 +138,7 @@ impl<E> MemoryInstance<E> where E: UserError {
} }
/// Copy memory region. Semantically equivalent to `memmove`. /// 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 buffer = self.buffer.write();
let read_region = self.checked_region(&buffer, src_offset, len)?; 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`, /// Copy memory region, non-overlapping version. Semantically equivalent to `memcpy`,
/// but returns Error if source overlaping with destination. /// 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 buffer = self.buffer.write();
let read_region = self.checked_region(&buffer, src_offset, len)?; 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`. /// 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 mut buffer = self.buffer.write();
let range = self.checked_region(&buffer, offset, len)?.range(); let range = self.checked_region(&buffer, offset, len)?.range();
@ -187,7 +184,7 @@ impl<E> MemoryInstance<E> where E: UserError {
} }
/// Zero memory region /// 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) self.clear(offset, 0, len)
} }
} }

View File

@ -30,7 +30,7 @@ impl UserError {
/// Internal interpreter error. /// Internal interpreter error.
#[derive(Debug)] #[derive(Debug)]
pub enum Error<E> where E: UserError { pub enum Error {
/// Program-level error. /// Program-level error.
Program(String), Program(String),
/// Validation error. /// Validation error.
@ -63,10 +63,9 @@ pub enum Error<E> where E: UserError {
Trap(String), Trap(String),
/// Custom user error. /// Custom user error.
User(Box<UserError>), User(Box<UserError>),
Other(E),
} }
impl<E> Into<String> for Error<E> where E: UserError { impl Into<String> for Error {
fn into(self) -> String { fn into(self) -> String {
match self { match self {
Error::Program(s) => s, Error::Program(s) => s,
@ -85,12 +84,11 @@ impl<E> Into<String> for Error<E> where E: UserError {
Error::Native(s) => s, Error::Native(s) => s,
Error::Trap(s) => format!("trap: {}", s), Error::Trap(s) => format!("trap: {}", s),
Error::User(e) => format!("user: {}", e), 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> { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
match *self { match *self {
Error::Program(ref s) => write!(f, "Program: {}", s), 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::Native(ref s) => write!(f, "Native: {}", s),
Error::Trap(ref s) => write!(f, "Trap: {}", s), Error::Trap(ref s) => write!(f, "Trap: {}", s),
Error::User(ref e) => write!(f, "User: {}", e), 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(()) } 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 { fn from(e: U) -> Self {
Error::User(Box::new(e)) Error::User(Box::new(e))
} }
@ -157,16 +154,20 @@ pub use self::env_native::{env_native_module, UserDefinedElements, UserFunctionE
pub use self::env::EnvParams; pub use self::env::EnvParams;
/// Default type of Error if you do not need any custom user errors. /// 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. /// Default type of ProgramInstance if you do not need any custom user errors.
/// To work with custom user errors or interpreter internals, use CustomProgramInstance. /// 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. /// Default type of ModuleInstance if you do not need any custom user errors.
/// To work with custom user errors or interpreter internals, use CustomModuleInstance. /// 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. /// Default type of ModuleInstanceInterface if you do not need any custom user errors.
/// To work with custom user errors or interpreter internals, use CustomModuleInstanceInterface. /// 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::sync::{Arc, Weak};
use std::fmt; use std::fmt;
use elements::{Module, InitExpr, Opcode, Type, FunctionType, Internal, External, BlockType, ResizableLimits, Local, ValueType}; 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::env_native::UserFunctionDescriptor;
use interpreter::imports::ModuleImports; use interpreter::imports::ModuleImports;
use interpreter::memory::MemoryInstance; use interpreter::memory::MemoryInstance;
@ -22,11 +22,11 @@ const DEFAULT_FRAME_STACK_LIMIT: usize = 1024;
/// Execution context. /// Execution context.
#[derive(Clone)] #[derive(Clone)]
pub struct ExecutionParams<'a, E: UserError> { pub struct ExecutionParams<'a> {
/// Arguments. /// Arguments.
pub args: Vec<RuntimeValue>, pub args: Vec<RuntimeValue>,
/// Execution-local external modules. /// Execution-local external modules.
pub externals: HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>, pub externals: HashMap<String, Arc<ModuleInstanceInterface + 'a>>,
} }
/// Export type. /// Export type.
@ -50,31 +50,31 @@ pub enum FunctionSignature<'a> {
} }
/// Module instance API. /// Module instance API.
pub trait ModuleInstanceInterface<E: UserError> { pub trait ModuleInstanceInterface {
/// Execute function with the given index. /// 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. /// 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. /// 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. /// 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. /// 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. /// 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. /// 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. /// 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. /// 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. /// 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. /// 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. /// 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. /// Item index in items index space.
@ -89,7 +89,7 @@ pub enum ItemIndex {
} }
/// Module instance. /// Module instance.
pub struct ModuleInstance<E: UserError> { pub struct ModuleInstance {
/// Module name. /// Module name.
name: String, name: String,
/// Module. /// Module.
@ -97,48 +97,39 @@ pub struct ModuleInstance<E: UserError> {
/// Function labels. /// Function labels.
functions_labels: HashMap<u32, HashMap<usize, usize>>, functions_labels: HashMap<u32, HashMap<usize, usize>>,
/// Module imports. /// Module imports.
imports: ModuleImports<E>, imports: ModuleImports,
/// Module exports. /// Module exports.
exports: HashMap<String, Vec<Internal>>, exports: HashMap<String, Vec<Internal>>,
/// Tables. /// Tables.
tables: Vec<Arc<TableInstance<E>>>, tables: Vec<Arc<TableInstance>>,
/// Linear memory regions. /// Linear memory regions.
memory: Vec<Arc<MemoryInstance<E>>>, memory: Vec<Arc<MemoryInstance>>,
/// Globals. /// Globals.
globals: Vec<Arc<VariableInstance<E>>>, globals: Vec<Arc<VariableInstance>>,
} }
/// Caller context. /// Caller context.
pub struct CallerContext<'a, E: 'a + UserError> { pub struct CallerContext<'a> {
/// Value stack limit /// Value stack limit
pub value_stack_limit: usize, pub value_stack_limit: usize,
/// Frame stack limit /// Frame stack limit
pub frame_stack_limit: usize, pub frame_stack_limit: usize,
/// Stack of the input parameters /// Stack of the input parameters
pub value_stack: &'a mut StackWithLimit<RuntimeValue, E>, pub value_stack: &'a mut StackWithLimit<RuntimeValue>,
/// Execution-local external modules. /// Execution-local external modules.
pub externals: &'a HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>, pub externals: &'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>,
} }
/// Internal function reference. /// Internal function reference.
pub struct InternalFunctionReference<'a, E: UserError> { #[derive(Clone)]
pub struct InternalFunctionReference<'a> {
/// Module reference. /// Module reference.
pub module: Arc<ModuleInstanceInterface<E> + 'a>, pub module: Arc<ModuleInstanceInterface + 'a>,
/// Internal function index. /// Internal function index.
pub internal_index: u32, pub internal_index: u32,
} }
// TODO: This impl should be removed once `E` not needed anymore. impl<'a> fmt::Debug for InternalFunctionReference<'a> {
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 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "InternalFunctionReference") write!(f, "InternalFunctionReference")
} }
@ -154,9 +145,9 @@ pub struct InternalFunction<'a> {
pub labels: &'a HashMap<usize, usize>, 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. /// 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(); let mut externals = HashMap::new();
externals.insert(name, module); externals.insert(name, module);
ExecutionParams { 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 { fn default() -> Self {
ExecutionParams { ExecutionParams {
args: Vec::default(), 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 { impl<'a> From<Vec<RuntimeValue>> for ExecutionParams<'a> {
fn from(args: Vec<RuntimeValue>) -> ExecutionParams<'a, E> { fn from(args: Vec<RuntimeValue>) -> ExecutionParams<'a> {
ExecutionParams { ExecutionParams {
args: args, args: args,
externals: HashMap::new(), 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. /// 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 // load entries from import section
let imports = ModuleImports::new(program, module.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. /// 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 // validate start section
if let Some(start_function) = self.module.start_section() { if let Some(start_function) = self.module.start_section() {
let func_type_index = self.require_function(ItemIndex::IndexSpace(start_function))?; 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]. /// 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) // execute start function (if any)
if let Some(start_function) = self.module.start_section() { if let Some(start_function) = self.module.start_section() {
self.execute_index(start_function, ExecutionParams::default())?; self.execute_index(start_function, ExecutionParams::default())?;
@ -450,11 +441,11 @@ impl<E> ModuleInstance<E> where E: UserError {
Ok(()) 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) 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) { match self.imports.parse_function_index(index) {
ItemIndex::IndexSpace(_) => unreachable!("parse_function_index resolves IndexSpace option"), ItemIndex::IndexSpace(_) => unreachable!("parse_function_index resolves IndexSpace option"),
ItemIndex::Internal(index) => self.module.function_section() 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 { impl ModuleInstanceInterface for ModuleInstance {
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> {
let ExecutionParams { args, externals } = params; let ExecutionParams { args, externals } = params;
let mut args = StackWithLimit::with_data(args, DEFAULT_VALUE_STACK_LIMIT); let mut args = StackWithLimit::with_data(args, DEFAULT_VALUE_STACK_LIMIT);
let function_reference = self.function_reference(ItemIndex::IndexSpace(index), Some(&externals))?; 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) 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) let index = self.exports.get(name)
.ok_or(Error::Function(format!("missing executable export with name {}", name))) .ok_or(Error::Function(format!("missing executable export with name {}", name)))
.and_then(|l| l.iter() .and_then(|l| l.iter()
@ -500,7 +491,7 @@ impl<E> ModuleInstanceInterface<E> for ModuleInstance<E> where E: UserError {
self.execute_index(index, params) 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) self.exports.get(name)
.ok_or(Error::Function(format!("missing export entry with name {}", name))) .ok_or(Error::Function(format!("missing export entry with name {}", name)))
.and_then(|l| l.iter() .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)))) .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) { match self.imports.parse_table_index(index) {
ItemIndex::IndexSpace(_) => unreachable!("parse_table_index resolves IndexSpace option"), ItemIndex::IndexSpace(_) => unreachable!("parse_table_index resolves IndexSpace option"),
ItemIndex::Internal(index) => self.tables.get(index as usize).cloned() 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) { match self.imports.parse_memory_index(index) {
ItemIndex::IndexSpace(_) => unreachable!("parse_memory_index resolves IndexSpace option"), ItemIndex::IndexSpace(_) => unreachable!("parse_memory_index resolves IndexSpace option"),
ItemIndex::Internal(index) => self.memory.get(index as usize).cloned() 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) { match self.imports.parse_global_index(index) {
ItemIndex::IndexSpace(_) => unreachable!("parse_global_index resolves IndexSpace option"), ItemIndex::IndexSpace(_) => unreachable!("parse_global_index resolves IndexSpace option"),
ItemIndex::Internal(index) => self.globals.get(index as usize).cloned() 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) { match self.imports.parse_function_index(function_index) {
ItemIndex::IndexSpace(_) => unreachable!("parse_function_index resolves IndexSpace option"), ItemIndex::IndexSpace(_) => unreachable!("parse_function_index resolves IndexSpace option"),
ItemIndex::Internal(index) => self.require_function(ItemIndex::Internal(index)) 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() self.module.type_section()
.ok_or(Error::Validation(format!("type reference {} exists in module without type section", type_index))) .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) { .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) .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) { match self.imports.parse_function_index(index) {
ItemIndex::IndexSpace(_) => unreachable!("parse_function_index resolves IndexSpace option"), ItemIndex::IndexSpace(_) => unreachable!("parse_function_index resolves IndexSpace option"),
ItemIndex::Internal(index) => Ok(InternalFunctionReference { 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 table = self.table(ItemIndex::IndexSpace(table_idx))?;
let (module, index) = match table.get(func_idx)? { let (module, index) = match table.get(func_idx)? {
RuntimeValue::AnyFunc(module, index) => (module.clone(), index), 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) 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 let function_body = self.module
.code_section() .code_section()
.ok_or(Error::Function(format!("trying to call function with index {} in module without code section", internal_index))) .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 function_type = self.function_type(ItemIndex::Internal(index))?;
let args = prepare_function_args(&function_type, outer.value_stack)?; let args = prepare_function_args(&function_type, outer.value_stack)?;
let function_ref = InternalFunctionReference { module: self.self_ref(Some(outer.externals))?, internal_index: index }; 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 /// 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 { CallerContext {
value_stack_limit: DEFAULT_VALUE_STACK_LIMIT, value_stack_limit: DEFAULT_VALUE_STACK_LIMIT,
frame_stack_limit: DEFAULT_FRAME_STACK_LIMIT, frame_stack_limit: DEFAULT_FRAME_STACK_LIMIT,
@ -666,7 +657,7 @@ impl<'a, E> CallerContext<'a, E> where E: UserError {
} }
/// Nested context /// Nested context
pub fn nested(outer: &'a mut FunctionContext<E>) -> Self { pub fn nested(outer: &'a mut FunctionContext) -> Self {
CallerContext { CallerContext {
value_stack_limit: outer.value_stack().limit() - outer.value_stack().len(), value_stack_limit: outer.value_stack().limit() - outer.value_stack().len(),
frame_stack_limit: outer.frame_stack().limit() - outer.frame_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 let Some(maximum) = limits.maximum() {
if maximum < limits.initial() { if maximum < limits.initial() {
return Err(Error::Validation(format!("maximum limit {} is lesser than minimum {}", 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(()) 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() { let first_opcode = match expr.code().len() {
1 => &expr.code()[0], 1 => &expr.code()[0],
2 if expr.code().len() == 2 && expr.code()[1] == Opcode::End => &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 std::collections::HashMap;
use parking_lot::RwLock; use parking_lot::RwLock;
use elements::Module; use elements::Module;
use interpreter::{Error, UserError}; use interpreter::Error;
use interpreter::env::{self, env_module}; use interpreter::env::{self, env_module};
use interpreter::module::{ModuleInstance, ModuleInstanceInterface}; use interpreter::module::{ModuleInstance, ModuleInstanceInterface};
/// Program instance. Program is a set of instantiated modules. /// Program instance. Program is a set of instantiated modules.
pub struct ProgramInstance<E: UserError> { pub struct ProgramInstance {
/// Shared data reference. /// Shared data reference.
essence: Arc<ProgramInstanceEssence<E>>, essence: Arc<ProgramInstanceEssence>,
} }
/// Program instance essence. /// Program instance essence.
pub struct ProgramInstanceEssence<E: UserError> { pub struct ProgramInstanceEssence {
/// Loaded modules. /// 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. /// Create new program instance.
pub fn new() -> Result<Self, Error<E>> { pub fn new() -> Result<Self, Error> {
ProgramInstance::with_env_params(env::EnvParams::default()) ProgramInstance::with_env_params(env::EnvParams::default())
} }
/// Create new program instance with custom env module params (mostly memory) /// 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 { Ok(ProgramInstance {
essence: Arc::new(ProgramInstanceEssence::with_env_params(params)?), essence: Arc::new(ProgramInstanceEssence::with_env_params(params)?),
}) })
} }
/// Create a new program instance with a custom env module /// 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 { ProgramInstance {
essence: Arc::new(ProgramInstanceEssence::with_env_module(env_module)), essence: Arc::new(ProgramInstanceEssence::with_env_module(env_module)),
} }
} }
/// Instantiate module with validation. /// 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)?; let mut module_instance = ModuleInstance::new(Arc::downgrade(&self.essence), name.into(), module)?;
module_instance.instantiate(externals)?; module_instance.instantiate(externals)?;
@ -50,30 +50,30 @@ impl<E> ProgramInstance<E> where E: UserError {
} }
/// Insert instantiated module. /// 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 // replace existing module with the same name with new one
self.essence.modules.write().insert(name.into(), module_instance.clone()); self.essence.modules.write().insert(name.into(), module_instance.clone());
Ok(module_instance) Ok(module_instance)
} }
/// Get one of the modules by name /// 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) self.essence.module(name)
} }
} }
impl<E> ProgramInstanceEssence<E> where E: UserError { impl ProgramInstanceEssence {
/// Create new program essence. /// Create new program essence.
pub fn new() -> Result<Self, Error<E>> { pub fn new() -> Result<Self, Error> {
ProgramInstanceEssence::with_env_params(env::EnvParams::default()) 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)?; let env_mod = env_module(env_params)?;
Ok(ProgramInstanceEssence::with_env_module(Arc::new(env_mod))) 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(); let mut modules = HashMap::new();
modules.insert("env".into(), env_module); modules.insert("env".into(), env_module);
ProgramInstanceEssence { ProgramInstanceEssence {
@ -83,7 +83,7 @@ impl<E> ProgramInstanceEssence<E> where E: UserError {
/// Get module reference. /// 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() self.modules.read().get(name).cloned()
} }
} }

View File

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

View File

@ -1,32 +1,28 @@
use std::collections::VecDeque; use std::collections::VecDeque;
use interpreter::{Error, UserError}; use interpreter::Error;
use interpreter::value::{RuntimeValue, TryInto}; use interpreter::value::{RuntimeValue, TryInto};
/// Stack with limit. /// Stack with limit.
#[derive(Debug)] #[derive(Debug)]
pub struct StackWithLimit<T, E> where T: Clone, E: UserError { pub struct StackWithLimit<T> where T: Clone {
/// Stack values. /// Stack values.
values: VecDeque<T>, values: VecDeque<T>,
/// Stack limit (maximal stack len). /// Stack limit (maximal stack len).
limit: usize, 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 { pub fn with_data(data: Vec<T>, limit: usize) -> Self {
StackWithLimit { StackWithLimit {
values: data.into_iter().collect(), values: data.into_iter().collect(),
limit: limit, limit: limit
_dummy: Default::default(),
} }
} }
pub fn with_limit(limit: usize) -> Self { pub fn with_limit(limit: usize) -> Self {
StackWithLimit { StackWithLimit {
values: VecDeque::new(), values: VecDeque::new(),
limit: limit, limit: limit
_dummy: Default::default(),
} }
} }
@ -46,19 +42,19 @@ impl<T, E> StackWithLimit<T, E> where T: Clone, E: UserError {
&self.values &self.values
} }
pub fn top(&self) -> Result<&T, Error<E>> { pub fn top(&self) -> Result<&T, Error> {
self.values self.values
.back() .back()
.ok_or(Error::Stack("non-empty stack expected".into())) .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 self.values
.back_mut() .back_mut()
.ok_or(Error::Stack("non-empty stack expected".into())) .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() { if index >= self.values.len() {
return Err(Error::Stack(format!("trying to get value at position {} on stack of size {}", 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")) 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 { if self.values.len() >= self.limit {
return Err(Error::Stack(format!("exceeded stack limit {}", 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(()) 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() { if self.values.is_empty() {
return Err(Error::Stack("trying to insert penultimate element into empty stack".into())); 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(()) Ok(())
} }
pub fn pop(&mut self) -> Result<T, Error<E>> { pub fn pop(&mut self) -> Result<T, Error> {
self.values self.values
.pop_back() .pop_back()
.ok_or(Error::Stack("non-empty stack expected".into())) .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 { impl StackWithLimit<RuntimeValue> {
pub fn pop_as<T>(&mut self) -> Result<T, Error<E>> pub fn pop_as<T>(&mut self) -> Result<T, Error>
where RuntimeValue: TryInto<T, Error<E>> { where RuntimeValue: TryInto<T, Error> {
self.pop().and_then(TryInto::try_into) 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 right = self.pop()?;
let left = self.pop()?; let left = self.pop()?;
Ok((left, right)) Ok((left, right))
} }
pub fn pop_pair_as<T>(&mut self) -> Result<(T, T), Error<E>> pub fn pop_pair_as<T>(&mut self) -> Result<(T, T), Error>
where RuntimeValue: TryInto<T, Error<E>> { where RuntimeValue: TryInto<T, Error> {
let right = self.pop_as()?; let right = self.pop_as()?;
let left = self.pop_as()?; let left = self.pop_as()?;
Ok((left, right)) 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 right = self.pop()?;
let mid = self.pop()?; let mid = self.pop()?;
let left = self.pop()?; let left = self.pop()?;

View File

@ -2,29 +2,29 @@ use std::u32;
use std::sync::Arc; use std::sync::Arc;
use parking_lot::RwLock; use parking_lot::RwLock;
use elements::{TableType, ResizableLimits}; use elements::{TableType, ResizableLimits};
use interpreter::{Error, UserError}; use interpreter::Error;
use interpreter::module::check_limits; use interpreter::module::check_limits;
use interpreter::variable::{VariableInstance, VariableType}; use interpreter::variable::{VariableInstance, VariableType};
use interpreter::value::RuntimeValue; use interpreter::value::RuntimeValue;
/// Table instance. /// Table instance.
pub struct TableInstance<E: UserError> { pub struct TableInstance {
/// Table limits. /// Table limits.
limits: ResizableLimits, limits: ResizableLimits,
/// Table variables type. /// Table variables type.
variable_type: VariableType, variable_type: VariableType,
/// Table memory buffer. /// Table memory buffer.
buffer: RwLock<Vec<TableElement<E>>>, buffer: RwLock<Vec<TableElement>>,
} }
/// Table element. Cloneable wrapper around VariableInstance. /// Table element. Cloneable wrapper around VariableInstance.
struct TableElement<E: UserError> { struct TableElement {
pub var: VariableInstance<E>, pub var: VariableInstance,
} }
impl<E> TableInstance<E> where E: UserError { impl TableInstance {
/// New instance of the table /// 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())?; check_limits(table_type.limits())?;
let variable_type = table_type.elem_type().into(); 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 /// 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 = self.buffer.read();
let buffer_len = buffer.len(); let buffer_len = buffer.len();
buffer.get(offset as usize) buffer.get(offset as usize)
@ -57,7 +57,7 @@ impl<E> TableInstance<E> where E: UserError {
} }
/// Set the table value from raw slice /// 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 { for val in value {
match self.variable_type { match self.variable_type {
VariableType::AnyFunc => self.set(offset, RuntimeValue::AnyFunc(module_name.clone(), *val))?, 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 /// 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 mut buffer = self.buffer.write();
let buffer_len = buffer.len(); let buffer_len = buffer.len();
buffer.get_mut(offset as usize) buffer.get_mut(offset as usize)
@ -78,15 +78,15 @@ impl<E> TableInstance<E> where E: UserError {
} }
} }
impl<E> TableElement<E> where E: UserError { impl TableElement {
pub fn new(var: VariableInstance<E>) -> Self { pub fn new(var: VariableInstance) -> Self {
TableElement { TableElement {
var: var, var: var,
} }
} }
} }
impl<E> Clone for TableElement<E> where E: UserError { impl Clone for TableElement {
fn clone(&self) -> Self { fn clone(&self) -> Self {
TableElement::new(VariableInstance::new(self.var.is_mutable(), self.var.variable_type(), self.var.get()) 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")) .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::sync::Arc;
use std::collections::HashMap; use std::collections::HashMap;
use elements::{Opcode, BlockType, ValueType}; use elements::{Opcode, BlockType, ValueType};
use interpreter::{Error, UserError}; use interpreter::Error;
use interpreter::runner::{DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDEX}; use interpreter::runner::{DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDEX};
use interpreter::module::{ModuleInstance, ModuleInstanceInterface, ItemIndex, FunctionSignature}; use interpreter::module::{ModuleInstance, ModuleInstanceInterface, ItemIndex, FunctionSignature};
use interpreter::stack::StackWithLimit; use interpreter::stack::StackWithLimit;
@ -12,19 +12,19 @@ use interpreter::variable::VariableType;
const NATURAL_ALIGNMENT: u32 = 0xFFFFFFFF; const NATURAL_ALIGNMENT: u32 = 0xFFFFFFFF;
/// Function validation context. /// Function validation context.
pub struct FunctionValidationContext<'a, E: 'a + UserError> { pub struct FunctionValidationContext<'a> {
/// Wasm module instance (in process of instantiation). /// Wasm module instance (in process of instantiation).
module_instance: &'a ModuleInstance<E>, module_instance: &'a ModuleInstance,
/// Native externals. /// Native externals.
externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>>, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>,
/// Current instruction position. /// Current instruction position.
position: usize, position: usize,
/// Local variables. /// Local variables.
locals: &'a [ValueType], locals: &'a [ValueType],
/// Value stack. /// Value stack.
value_stack: StackWithLimit<StackValueType, E>, value_stack: StackWithLimit<StackValueType>,
/// Frame stack. /// Frame stack.
frame_stack: StackWithLimit<BlockFrame, E>, frame_stack: StackWithLimit<BlockFrame>,
/// Function return type. None if validating expression. /// Function return type. None if validating expression.
return_type: Option<BlockType>, return_type: Option<BlockType>,
/// Labels positions. /// Labels positions.
@ -75,9 +75,7 @@ pub enum BlockFrameType {
} }
/// Function validator. /// Function validator.
pub struct Validator<E: UserError> { pub struct Validator;
_dummy: ::std::marker::PhantomData<E>,
}
/// Instruction outcome. /// Instruction outcome.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -88,8 +86,8 @@ pub enum InstructionOutcome {
Unreachable, Unreachable,
} }
impl<E> Validator<E> where E: UserError { impl Validator {
pub fn validate_function(context: &mut FunctionValidationContext<E>, block_type: BlockType, body: &[Opcode]) -> Result<(), Error<E>> { pub fn validate_function(context: &mut FunctionValidationContext, block_type: BlockType, body: &[Opcode]) -> Result<(), Error> {
context.push_label(BlockFrameType::Function, block_type)?; context.push_label(BlockFrameType::Function, block_type)?;
Validator::validate_function_block(context, body)?; Validator::validate_function_block(context, body)?;
while !context.frame_stack.is_empty() { while !context.frame_stack.is_empty() {
@ -99,7 +97,7 @@ impl<E> Validator<E> where E: UserError {
Ok(()) 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(); let body_len = body.len();
if body_len == 0 { if body_len == 0 {
return Err(Error::Validation("Non-empty function body expected".into())); 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); debug!(target: "validator", "validating {:?}", opcode);
match opcode { match opcode {
&Opcode::Unreachable => Ok(InstructionOutcome::Unreachable), &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)?; context.push_value(value_type)?;
Ok(InstructionOutcome::ValidateNextInstruction) 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.pop_value(value_type)?;
context.push_value(value_type)?; context.push_value(value_type)?;
Ok(InstructionOutcome::ValidateNextInstruction) 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.pop_value(value_type)?; context.pop_value(value_type)?;
context.push_value(value_type)?; context.push_value(value_type)?;
Ok(InstructionOutcome::ValidateNextInstruction) 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.pop_value(value_type)?;
context.push_value(ValueType::I32.into())?; context.push_value(ValueType::I32.into())?;
Ok(InstructionOutcome::ValidateNextInstruction) 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.pop_value(value_type)?; context.pop_value(value_type)?;
context.push_value(ValueType::I32.into())?; context.push_value(ValueType::I32.into())?;
Ok(InstructionOutcome::ValidateNextInstruction) 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.pop_value(value_type1)?;
context.push_value(value_type2)?; context.push_value(value_type2)?;
Ok(InstructionOutcome::ValidateNextInstruction) 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(|_| ())?; context.pop_any_value().map(|_| ())?;
Ok(InstructionOutcome::ValidateNextInstruction) 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())?; context.pop_value(ValueType::I32.into())?;
let select_type = context.pop_any_value()?; let select_type = context.pop_any_value()?;
context.pop_value(select_type)?; context.pop_value(select_type)?;
@ -364,13 +362,13 @@ impl<E> Validator<E> where E: UserError {
Ok(InstructionOutcome::ValidateNextInstruction) 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)?; let local_type = context.require_local(index)?;
context.push_value(local_type)?; context.push_value(local_type)?;
Ok(InstructionOutcome::ValidateNextInstruction) 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 local_type = context.require_local(index)?;
let value_type = context.pop_any_value()?; let value_type = context.pop_any_value()?;
if local_type != value_type { if local_type != value_type {
@ -379,7 +377,7 @@ impl<E> Validator<E> where E: UserError {
Ok(InstructionOutcome::ValidateNextInstruction) 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 local_type = context.require_local(index)?;
let value_type = context.tee_any_value()?; let value_type = context.tee_any_value()?;
if local_type != value_type { if local_type != value_type {
@ -388,13 +386,13 @@ impl<E> Validator<E> where E: UserError {
Ok(InstructionOutcome::ValidateNextInstruction) 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)?; let global_type = context.require_global(index, None)?;
context.push_value(global_type)?; context.push_value(global_type)?;
Ok(InstructionOutcome::ValidateNextInstruction) 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 global_type = context.require_global(index, Some(true))?;
let value_type = context.pop_any_value()?; let value_type = context.pop_any_value()?;
if global_type != value_type { if global_type != value_type {
@ -403,7 +401,7 @@ impl<E> Validator<E> where E: UserError {
Ok(InstructionOutcome::ValidateNextInstruction) 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 align != NATURAL_ALIGNMENT {
if 1u32.checked_shl(align).unwrap_or(u32::MAX) > max_align { 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))); 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) 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 align != NATURAL_ALIGNMENT {
if 1u32.checked_shl(align).unwrap_or(u32::MAX) > max_align { 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))); 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) 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) 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) 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.pop_value(ValueType::I32.into())?;
context.push_label(BlockFrameType::IfTrue, block_type).map(|_| InstructionOutcome::ValidateNextInstruction) 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 block_type = {
let top_frame = context.top_label()?; let top_frame = context.top_label()?;
if top_frame.frame_type != BlockFrameType::IfTrue { 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) 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()?; let top_frame = context.top_label()?;
if top_frame.frame_type == BlockFrameType::IfTrue { if top_frame.frame_type == BlockFrameType::IfTrue {
@ -471,7 +469,7 @@ impl<E> Validator<E> where E: UserError {
context.pop_label().map(|_| InstructionOutcome::ValidateNextInstruction) 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_type, frame_block_type) = {
let frame = context.require_label(idx)?; let frame = context.require_label(idx)?;
(frame.frame_type, frame.block_type) (frame.frame_type, frame.block_type)
@ -485,7 +483,7 @@ impl<E> Validator<E> where E: UserError {
Ok(InstructionOutcome::Unreachable) 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())?; context.pop_value(ValueType::I32.into())?;
if let BlockType::Value(value_type) = context.require_label(idx)?.block_type { if let BlockType::Value(value_type) = context.require_label(idx)?.block_type {
context.tee_value(value_type.into())?; context.tee_value(value_type.into())?;
@ -493,7 +491,7 @@ impl<E> Validator<E> where E: UserError {
Ok(InstructionOutcome::ValidateNextInstruction) 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; let mut required_block_type = None;
{ {
@ -525,14 +523,14 @@ impl<E> Validator<E> where E: UserError {
Ok(InstructionOutcome::Unreachable) 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()? { if let BlockType::Value(value_type) = context.return_type()? {
context.tee_value(value_type.into())?; context.tee_value(value_type.into())?;
} }
Ok(InstructionOutcome::Unreachable) 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)?; let (argument_types, return_type) = context.require_function(idx)?;
for argument_type in argument_types.iter().rev() { for argument_type in argument_types.iter().rev() {
context.pop_value((*argument_type).into())?; context.pop_value((*argument_type).into())?;
@ -543,7 +541,7 @@ impl<E> Validator<E> where E: UserError {
Ok(InstructionOutcome::ValidateNextInstruction) 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.require_table(DEFAULT_TABLE_INDEX, VariableType::AnyFunc)?;
context.pop_value(ValueType::I32.into())?; context.pop_value(ValueType::I32.into())?;
@ -557,13 +555,13 @@ impl<E> Validator<E> where E: UserError {
Ok(InstructionOutcome::ValidateNextInstruction) 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.require_memory(DEFAULT_MEMORY_INDEX)?;
context.push_value(ValueType::I32.into())?; context.push_value(ValueType::I32.into())?;
Ok(InstructionOutcome::ValidateNextInstruction) 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.require_memory(DEFAULT_MEMORY_INDEX)?;
context.pop_value(ValueType::I32.into())?; context.pop_value(ValueType::I32.into())?;
context.push_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( pub fn new(
module_instance: &'a ModuleInstance<E>, module_instance: &'a ModuleInstance,
externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface<E> + 'a>>>, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>,
locals: &'a [ValueType], locals: &'a [ValueType],
value_stack_limit: usize, value_stack_limit: usize,
frame_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()) 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()?; self.check_stack_access()?;
match self.value_stack.pop()? { match self.value_stack.pop()? {
StackValueType::Specific(stack_value_type) if stack_value_type == value_type => Ok(()), 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()?; self.check_stack_access()?;
match *self.value_stack.top()? { match *self.value_stack.top()? {
StackValueType::Specific(stack_value_type) if stack_value_type == value_type => Ok(()), 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()?; self.check_stack_access()?;
match self.value_stack.pop()? { match self.value_stack.pop()? {
StackValueType::Specific(stack_value_type) => Ok(StackValueType::Specific(stack_value_type)), 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.check_stack_access()?;
self.value_stack.top().map(Clone::clone) 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) 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() 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 { self.frame_stack.push(BlockFrame {
frame_type: frame_type, frame_type: frame_type,
block_type: block_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 frame = self.frame_stack.pop()?;
let actual_value_type = if self.value_stack.len() > frame.value_stack_len { let actual_value_type = if self.value_stack.len() > frame.value_stack_len {
Some(self.value_stack.pop()?) Some(self.value_stack.pop()?)
@ -678,22 +676,22 @@ impl<'a, E> FunctionValidationContext<'a, E> where E: UserError {
Ok(InstructionOutcome::ValidateNextInstruction) 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) 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())) 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) self.locals.get(idx as usize)
.cloned() .cloned()
.map(Into::into) .map(Into::into)
.ok_or(Error::Validation(format!("Trying to access local with index {} when there are only {} locals", idx, self.locals.len()))) .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 self.module_instance
.global(ItemIndex::IndexSpace(idx), None, self.externals.clone()) .global(ItemIndex::IndexSpace(idx), None, self.externals.clone())
.and_then(|g| match mutability { .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 self.module_instance
.memory(ItemIndex::IndexSpace(idx)) .memory(ItemIndex::IndexSpace(idx))
.map(|_| ()) .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 self.module_instance
.table(ItemIndex::IndexSpace(idx)) .table(ItemIndex::IndexSpace(idx))
.and_then(|t| if t.variable_type() == variable_type { .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)) self.module_instance.function_type(ItemIndex::IndexSpace(idx))
.map(|ft| (ft.params().to_vec(), ft.return_type().map(BlockType::Value).unwrap_or(BlockType::NoResult))) .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) self.module_instance.function_type_by_index(idx)
.map(|ft| (ft.params().to_vec(), ft.return_type().map(BlockType::Value).unwrap_or(BlockType::NoResult))) .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 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; 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 { if self.value_stack.len() > value_stack_min {
Ok(()) Ok(())

View File

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

View File

@ -1,7 +1,7 @@
use std::fmt; use std::fmt;
use parking_lot::RwLock; use parking_lot::RwLock;
use elements::{GlobalType, ValueType, TableElementType}; use elements::{GlobalType, ValueType, TableElementType};
use interpreter::{Error, UserError}; use interpreter::Error;
use interpreter::value::RuntimeValue; use interpreter::value::RuntimeValue;
/// Variable type. /// Variable type.
@ -20,35 +20,35 @@ pub enum VariableType {
} }
/// Externally stored variable value. /// Externally stored variable value.
pub trait ExternalVariableValue<E: UserError> { pub trait ExternalVariableValue {
/// Get variable value. /// Get variable value.
fn get(&self) -> RuntimeValue; fn get(&self) -> RuntimeValue;
/// Set variable value. /// Set variable value.
fn set(&mut self, value: RuntimeValue) -> Result<(), Error<E>>; fn set(&mut self, value: RuntimeValue) -> Result<(), Error>;
} }
/// Variable instance. /// Variable instance.
#[derive(Debug)] #[derive(Debug)]
pub struct VariableInstance<E: UserError> { pub struct VariableInstance {
/// Is mutable? /// Is mutable?
is_mutable: bool, is_mutable: bool,
/// Variable type. /// Variable type.
variable_type: VariableType, variable_type: VariableType,
/// Global value. /// Global value.
value: RwLock<VariableValue<E>>, value: RwLock<VariableValue>,
} }
/// Enum variable value. /// Enum variable value.
enum VariableValue<E: UserError> { enum VariableValue {
/// Internal value. /// Internal value.
Internal(RuntimeValue), Internal(RuntimeValue),
/// External value. /// External value.
External(Box<ExternalVariableValue<E>>), External(Box<ExternalVariableValue>),
} }
impl<E> VariableInstance<E> where E: UserError { impl VariableInstance {
/// New variable instance /// 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 // 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) { 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()))); 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 /// 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) Self::new(global_type.is_mutable(), global_type.content_type().into(), value)
} }
/// New global with externally stored 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 // 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(); let current_value = value.get();
if !current_value.is_null() && current_value.variable_type() != Some(variable_type) { 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 /// 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 { if !self.is_mutable {
return Err(Error::Variable("trying to update immutable variable".into())); 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 { fn get(&self) -> RuntimeValue {
match *self { match *self {
VariableValue::Internal(ref value) => value.clone(), 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 { match *self {
VariableValue::Internal(ref mut value) => { VariableValue::Internal(ref mut value) => {
*value = new_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 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self { match *self {
VariableValue::Internal(ref value) => write!(f, "Variable.Internal({:?})", value), VariableValue::Internal(ref value) => write!(f, "Variable.Internal({:?})", value),