mirror of
https://github.com/fluencelabs/parity-wasm
synced 2025-06-21 10:41:54 +00:00
Remove variable.rs
This commit is contained in:
@ -15,7 +15,7 @@ use parity_wasm::elements::{self, ValueType, GlobalType, MemoryType, TableType,
|
||||
use parity_wasm::interpreter::{
|
||||
RuntimeValue,
|
||||
ProgramInstance,
|
||||
ItemIndex, ExportEntryType,
|
||||
ItemIndex,
|
||||
Error as InterpreterError,
|
||||
ImportResolver,
|
||||
Imports,
|
||||
@ -278,7 +278,7 @@ pub fn spec(name: &str) {
|
||||
let spec_expected = runtime_values(expected);
|
||||
let actual_result = result.into_iter().collect::<Vec<parity_wasm::RuntimeValue>>();
|
||||
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
|
||||
match spec_expected {
|
||||
&RuntimeValue::F32(val) if val.is_nan() => match actual_result {
|
||||
|
@ -137,7 +137,6 @@ mod runner;
|
||||
mod stack;
|
||||
mod table;
|
||||
mod value;
|
||||
mod variable;
|
||||
mod store;
|
||||
mod host;
|
||||
mod imports;
|
||||
@ -146,11 +145,10 @@ mod imports;
|
||||
mod tests;
|
||||
|
||||
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::program::ProgramInstance;
|
||||
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::imports::{ImportResolver, Imports};
|
||||
pub use self::store::{FuncInstance, ModuleInstance, GlobalInstance};
|
||||
|
@ -1,6 +1,5 @@
|
||||
use elements::ResizableLimits;
|
||||
use interpreter::Error;
|
||||
use interpreter::VariableType;
|
||||
|
||||
/// Execution context.
|
||||
pub struct ExecutionParams<'a, St: 'static> {
|
||||
@ -8,15 +7,6 @@ pub struct ExecutionParams<'a, St: 'static> {
|
||||
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.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum ItemIndex {
|
||||
|
@ -1048,7 +1048,7 @@ impl FunctionContext {
|
||||
self.is_initialized = true;
|
||||
|
||||
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))
|
||||
.collect::<Vec<_>>();
|
||||
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> {
|
||||
let mut args = function_type.params().iter().rev().map(|param_type| {
|
||||
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();
|
||||
if actual_type != Some(expected_type) {
|
||||
return Err(Error::Function(format!("invalid parameter type {:?} when expected {:?}", actual_type, expected_type)));
|
||||
|
@ -5,7 +5,6 @@ use parking_lot::RwLock;
|
||||
use elements::{TableType, ResizableLimits};
|
||||
use interpreter::Error;
|
||||
use interpreter::module::check_limits;
|
||||
use interpreter::variable::VariableType;
|
||||
use interpreter::store::FuncInstance;
|
||||
|
||||
/// Table instance.
|
||||
@ -43,11 +42,6 @@ impl TableInstance {
|
||||
&self.limits
|
||||
}
|
||||
|
||||
/// Get variable type for this table.
|
||||
pub fn variable_type(&self) -> VariableType {
|
||||
panic!("TODO")
|
||||
}
|
||||
|
||||
/// Get the specific value in the table
|
||||
pub fn get(&self, offset: u32) -> Result<Rc<FuncInstance>, Error> {
|
||||
let buffer = self.buffer.read();
|
||||
|
@ -2,15 +2,13 @@ use std::{i32, i64, u32, u64, f32};
|
||||
use std::io;
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
use interpreter::Error;
|
||||
use interpreter::variable::VariableType;
|
||||
use elements::ValueType;
|
||||
|
||||
|
||||
// TODO: Get rid of Null and AnyFunc.
|
||||
/// Runtime value.
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub enum RuntimeValue {
|
||||
/// Null value.
|
||||
Null,
|
||||
/// 32b-length signed/unsigned int.
|
||||
I32(i32),
|
||||
/// 64b-length signed/unsigned int.
|
||||
@ -113,12 +111,12 @@ pub trait Float<T>: ArithmeticOps<T> {
|
||||
|
||||
impl RuntimeValue {
|
||||
/// Creates new default value of given type.
|
||||
pub fn default(variable_type: VariableType) -> Self {
|
||||
match variable_type {
|
||||
VariableType::I32 => RuntimeValue::I32(0),
|
||||
VariableType::I64 => RuntimeValue::I64(0),
|
||||
VariableType::F32 => RuntimeValue::F32(0f32),
|
||||
VariableType::F64 => RuntimeValue::F64(0f64),
|
||||
pub fn default(value_type: ValueType) -> Self {
|
||||
match value_type {
|
||||
ValueType::I32 => RuntimeValue::I32(0),
|
||||
ValueType::I64 => RuntimeValue::I64(0),
|
||||
ValueType::F32 => RuntimeValue::F32(0f32),
|
||||
ValueType::F64 => RuntimeValue::F64(0f64),
|
||||
}
|
||||
}
|
||||
|
||||
@ -132,22 +130,13 @@ impl RuntimeValue {
|
||||
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.
|
||||
pub fn variable_type(&self) -> Option<VariableType> {
|
||||
pub fn value_type(&self) -> Option<ValueType> {
|
||||
match *self {
|
||||
RuntimeValue::Null => None,
|
||||
RuntimeValue::I32(_) => Some(VariableType::I32),
|
||||
RuntimeValue::I64(_) => Some(VariableType::I64),
|
||||
RuntimeValue::F32(_) => Some(VariableType::F32),
|
||||
RuntimeValue::F64(_) => Some(VariableType::F64),
|
||||
RuntimeValue::I32(_) => Some(ValueType::I32),
|
||||
RuntimeValue::I64(_) => Some(ValueType::I64),
|
||||
RuntimeValue::F32(_) => Some(ValueType::F32),
|
||||
RuntimeValue::F64(_) => Some(ValueType::F64),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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()),
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user