Remove variable.rs

This commit is contained in:
Sergey Pepyakin
2017-12-13 18:15:13 +01:00
parent 47ec274700
commit 5eaf2ca183
7 changed files with 20 additions and 202 deletions

View File

@ -15,7 +15,7 @@ use parity_wasm::elements::{self, ValueType, GlobalType, MemoryType, TableType,
use parity_wasm::interpreter::{ use parity_wasm::interpreter::{
RuntimeValue, RuntimeValue,
ProgramInstance, ProgramInstance,
ItemIndex, ExportEntryType, ItemIndex,
Error as InterpreterError, Error as InterpreterError,
ImportResolver, ImportResolver,
Imports, Imports,
@ -278,7 +278,7 @@ pub fn spec(name: &str) {
let spec_expected = runtime_values(expected); let spec_expected = runtime_values(expected);
let actual_result = result.into_iter().collect::<Vec<parity_wasm::RuntimeValue>>(); let actual_result = result.into_iter().collect::<Vec<parity_wasm::RuntimeValue>>();
for (actual_result, spec_expected) in actual_result.iter().zip(spec_expected.iter()) { for (actual_result, spec_expected) in actual_result.iter().zip(spec_expected.iter()) {
assert_eq!(actual_result.variable_type(), spec_expected.variable_type()); assert_eq!(actual_result.value_type(), spec_expected.value_type());
// f32::NAN != f32::NAN // f32::NAN != f32::NAN
match spec_expected { match spec_expected {
&RuntimeValue::F32(val) if val.is_nan() => match actual_result { &RuntimeValue::F32(val) if val.is_nan() => match actual_result {

View File

@ -137,7 +137,6 @@ mod runner;
mod stack; mod stack;
mod table; mod table;
mod value; mod value;
mod variable;
mod store; mod store;
mod host; mod host;
mod imports; mod imports;
@ -146,11 +145,10 @@ mod imports;
mod tests; mod tests;
pub use self::memory::MemoryInstance; pub use self::memory::MemoryInstance;
pub use self::module::{ItemIndex, ExportEntryType, ExecutionParams}; pub use self::module::{ItemIndex, ExecutionParams};
pub use self::table::TableInstance; pub use self::table::TableInstance;
pub use self::program::ProgramInstance; pub use self::program::ProgramInstance;
pub use self::value::RuntimeValue; pub use self::value::RuntimeValue;
pub use self::variable::{VariableInstance, VariableType, ExternalVariableValue};
pub use self::host::{HostModule, HostModuleBuilder, Func1, AnyFunc, AsReturnVal, FromArg}; pub use self::host::{HostModule, HostModuleBuilder, Func1, AnyFunc, AsReturnVal, FromArg};
pub use self::imports::{ImportResolver, Imports}; pub use self::imports::{ImportResolver, Imports};
pub use self::store::{FuncInstance, ModuleInstance, GlobalInstance}; pub use self::store::{FuncInstance, ModuleInstance, GlobalInstance};

View File

@ -1,6 +1,5 @@
use elements::ResizableLimits; use elements::ResizableLimits;
use interpreter::Error; use interpreter::Error;
use interpreter::VariableType;
/// Execution context. /// Execution context.
pub struct ExecutionParams<'a, St: 'static> { pub struct ExecutionParams<'a, St: 'static> {
@ -8,15 +7,6 @@ pub struct ExecutionParams<'a, St: 'static> {
pub state: &'a mut St, pub state: &'a mut St,
} }
/// Export type.
#[derive(Debug, Clone)]
pub enum ExportEntryType {
/// Any type.
Any,
/// Type of global.
Global(VariableType),
}
/// Item index in items index space. /// Item index in items index space.
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub enum ItemIndex { pub enum ItemIndex {

View File

@ -1048,7 +1048,7 @@ impl FunctionContext {
self.is_initialized = true; self.is_initialized = true;
let locals = locals.iter() let locals = locals.iter()
.flat_map(|l| repeat(l.value_type().into()).take(l.count() as usize)) .flat_map(|l| repeat(l.value_type()).take(l.count() as usize))
.map(|vt| RuntimeValue::default(vt)) .map(|vt| RuntimeValue::default(vt))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
self.locals.extend(locals); self.locals.extend(locals);
@ -1152,7 +1152,7 @@ fn effective_address(address: u32, offset: u32) -> Result<u32, Error> {
pub fn prepare_function_args(function_type: &FunctionType, caller_stack: &mut StackWithLimit<RuntimeValue>) -> Result<Vec<RuntimeValue>, Error> { pub fn prepare_function_args(function_type: &FunctionType, caller_stack: &mut StackWithLimit<RuntimeValue>) -> Result<Vec<RuntimeValue>, 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.value_type();
let expected_type = (*param_type).into(); let expected_type = (*param_type).into();
if actual_type != Some(expected_type) { if actual_type != Some(expected_type) {
return Err(Error::Function(format!("invalid parameter type {:?} when expected {:?}", actual_type, expected_type))); return Err(Error::Function(format!("invalid parameter type {:?} when expected {:?}", actual_type, expected_type)));

View File

@ -5,7 +5,6 @@ use parking_lot::RwLock;
use elements::{TableType, ResizableLimits}; use elements::{TableType, ResizableLimits};
use interpreter::Error; use interpreter::Error;
use interpreter::module::check_limits; use interpreter::module::check_limits;
use interpreter::variable::VariableType;
use interpreter::store::FuncInstance; use interpreter::store::FuncInstance;
/// Table instance. /// Table instance.
@ -18,12 +17,12 @@ pub struct TableInstance {
} }
impl fmt::Debug for TableInstance { impl fmt::Debug for TableInstance {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("TableInstance") f.debug_struct("TableInstance")
.field("limits", &self.limits) .field("limits", &self.limits)
.field("buffer.len", &self.buffer.read().len()) .field("buffer.len", &self.buffer.read().len())
.finish() .finish()
} }
} }
impl TableInstance { impl TableInstance {
@ -43,11 +42,6 @@ impl TableInstance {
&self.limits &self.limits
} }
/// Get variable type for this table.
pub fn variable_type(&self) -> VariableType {
panic!("TODO")
}
/// Get the specific value in the table /// Get the specific value in the table
pub fn get(&self, offset: u32) -> Result<Rc<FuncInstance>, Error> { pub fn get(&self, offset: u32) -> Result<Rc<FuncInstance>, Error> {
let buffer = self.buffer.read(); let buffer = self.buffer.read();

View File

@ -2,15 +2,13 @@ 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; use interpreter::Error;
use interpreter::variable::VariableType; use elements::ValueType;
// TODO: Get rid of Null and AnyFunc. // TODO: Get rid of Null and AnyFunc.
/// Runtime value. /// Runtime value.
#[derive(Copy, Clone, Debug, PartialEq)] #[derive(Copy, Clone, Debug, PartialEq)]
pub enum RuntimeValue { pub enum RuntimeValue {
/// Null value.
Null,
/// 32b-length signed/unsigned int. /// 32b-length signed/unsigned int.
I32(i32), I32(i32),
/// 64b-length signed/unsigned int. /// 64b-length signed/unsigned int.
@ -113,12 +111,12 @@ pub trait Float<T>: ArithmeticOps<T> {
impl RuntimeValue { impl RuntimeValue {
/// Creates new default value of given type. /// Creates new default value of given type.
pub fn default(variable_type: VariableType) -> Self { pub fn default(value_type: ValueType) -> Self {
match variable_type { match value_type {
VariableType::I32 => RuntimeValue::I32(0), ValueType::I32 => RuntimeValue::I32(0),
VariableType::I64 => RuntimeValue::I64(0), ValueType::I64 => RuntimeValue::I64(0),
VariableType::F32 => RuntimeValue::F32(0f32), ValueType::F32 => RuntimeValue::F32(0f32),
VariableType::F64 => RuntimeValue::F64(0f64), ValueType::F64 => RuntimeValue::F64(0f64),
} }
} }
@ -132,22 +130,13 @@ impl RuntimeValue {
RuntimeValue::F64(f64_from_bits(val)) RuntimeValue::F64(f64_from_bits(val))
} }
/// Returns true if value is null.
pub fn is_null(&self) -> bool {
match *self {
RuntimeValue::Null => true,
_ => false,
}
}
/// Get variable type for this value. /// Get variable type for this value.
pub fn variable_type(&self) -> Option<VariableType> { pub fn value_type(&self) -> Option<ValueType> {
match *self { match *self {
RuntimeValue::Null => None, RuntimeValue::I32(_) => Some(ValueType::I32),
RuntimeValue::I32(_) => Some(VariableType::I32), RuntimeValue::I64(_) => Some(ValueType::I64),
RuntimeValue::I64(_) => Some(VariableType::I64), RuntimeValue::F32(_) => Some(ValueType::F32),
RuntimeValue::F32(_) => Some(VariableType::F32), RuntimeValue::F64(_) => Some(ValueType::F64),
RuntimeValue::F64(_) => Some(VariableType::F64),
} }
} }
} }

View File

@ -1,153 +0,0 @@
use std::fmt;
use parking_lot::RwLock;
use elements::{GlobalType, ValueType};
use interpreter::Error;
use interpreter::value::RuntimeValue;
/// Variable type.
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum VariableType {
/// i32 value.
I32,
/// i64 value.
I64,
/// f32 value.
F32,
/// f64 value.
F64,
}
/// Externally stored variable value.
///
/// WebAssembly specificaiton [requires][0] that if a global variable is immutable, then
/// it should remain unchanged. To comply with specification you should ensure this invariant holds.
///
/// [0]: https://webassembly.github.io/spec/appendix/properties.html#global-instance
pub trait ExternalVariableValue {
/// Get variable value.
fn get(&self) -> RuntimeValue;
/// Set variable value.
fn set(&mut self, value: RuntimeValue) -> Result<(), Error>;
}
/// Variable instance.
#[derive(Debug)]
pub struct VariableInstance {
/// Is mutable?
is_mutable: bool,
/// Variable type.
variable_type: VariableType,
/// Global value.
value: RwLock<VariableValue>,
}
/// Enum variable value.
enum VariableValue {
/// Internal value.
Internal(RuntimeValue),
/// External value.
External(Box<ExternalVariableValue>),
}
impl VariableInstance {
/// New variable instance
pub fn new(is_mutable: bool, variable_type: VariableType, value: RuntimeValue) -> Result<Self, Error> {
// TODO: there is nothing about null value in specification + there is nothing about initializing missing table elements? => runtime check for nulls
if !value.is_null() && value.variable_type() != Some(variable_type) {
return Err(Error::Variable(format!("trying to initialize variable of type {:?} with value of type {:?}", variable_type, value.variable_type())));
}
Ok(VariableInstance {
is_mutable: is_mutable,
variable_type: variable_type,
value: RwLock::new(VariableValue::Internal(value)),
})
}
/// New global variable
pub fn new_global(global_type: &GlobalType, value: RuntimeValue) -> Result<Self, Error> {
Self::new(global_type.is_mutable(), global_type.content_type().into(), value)
}
/// New global with externally stored value.
pub fn new_external_global(is_mutable: bool, variable_type: VariableType, value: Box<ExternalVariableValue>) -> Result<Self, Error> {
// TODO: there is nothing about null value in specification + there is nothing about initializing missing table elements? => runtime check for nulls
let current_value = value.get();
if !current_value.is_null() && current_value.variable_type() != Some(variable_type) {
return Err(Error::Variable(format!("trying to initialize variable of type {:?} with value of type {:?}", variable_type, current_value.variable_type())));
}
Ok(VariableInstance {
is_mutable: is_mutable,
variable_type: variable_type,
value: RwLock::new(VariableValue::External(value)),
})
}
/// Is mutable
pub fn is_mutable(&self) -> bool {
self.is_mutable
}
/// Get variable type.
pub fn variable_type(&self) -> VariableType {
self.variable_type
}
/// Get the value of the variable instance
pub fn get(&self) -> RuntimeValue {
self.value.read().get()
}
/// Set the value of the variable instance
pub fn set(&self, value: RuntimeValue) -> Result<(), Error> {
if !self.is_mutable {
return Err(Error::Variable("trying to update immutable variable".into()));
}
if value.variable_type() != Some(self.variable_type) {
return Err(Error::Variable(format!("trying to update variable of type {:?} with value of type {:?}", self.variable_type, value.variable_type())));
}
self.value.write().set(value)
}
}
impl VariableValue {
fn get(&self) -> RuntimeValue {
match *self {
VariableValue::Internal(ref value) => value.clone(),
VariableValue::External(ref value) => value.get(),
}
}
fn set(&mut self, new_value: RuntimeValue) -> Result<(), Error> {
match *self {
VariableValue::Internal(ref mut value) => {
*value = new_value;
Ok(())
},
VariableValue::External(ref mut value) => value.set(new_value),
}
}
}
impl From<ValueType> for VariableType {
fn from(vt: ValueType) -> VariableType {
match vt {
ValueType::I32 => VariableType::I32,
ValueType::I64 => VariableType::I64,
ValueType::F32 => VariableType::F32,
ValueType::F64 => VariableType::F64,
}
}
}
impl fmt::Debug for VariableValue {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
VariableValue::Internal(ref value) => write!(f, "Variable.Internal({:?})", value),
VariableValue::External(ref value) => write!(f, "Variable.External({:?})", value.get()),
}
}
}