From 3ca9734d2e50fe9574ada5441ef104532dfa7aa0 Mon Sep 17 00:00:00 2001 From: vms Date: Mon, 28 Dec 2020 22:33:58 +0300 Subject: [PATCH] update --- Cargo.lock | 18 +- crates/it-types/Cargo.toml | 7 + crates/it-types/src/impls/errors.rs | 29 +++ crates/it-types/src/impls/mod.rs | 6 + crates/it-types/src/impls/types.rs | 161 +++++++++++++ crates/it-types/src/impls/values.rs | 51 +++++ crates/it-types/src/lib.rs | 15 +- crates/it-types/src/{vec1.rs => ne_vec.rs} | 21 +- crates/it-types/src/types.rs | 60 ++++- crates/it-types/src/values.rs | 10 +- tests/binary.rs | 6 +- wasmer-it/Cargo.toml | 2 +- wasmer-it/src/ast.rs | 7 +- wasmer-it/src/decoders/binary.rs | 18 +- wasmer-it/src/decoders/wat.rs | 139 +----------- wasmer-it/src/encoders/binary.rs | 214 ++++++++++-------- wasmer-it/src/encoders/wat.rs | 119 +++------- wasmer-it/src/errors.rs | 41 +--- .../interpreter/instructions/argument_get.rs | 14 +- .../src/interpreter/instructions/arrays.rs | 135 +++++------ .../src/interpreter/instructions/call_core.rs | 34 +-- wasmer-it/src/interpreter/instructions/mod.rs | 126 ++++++----- .../src/interpreter/instructions/numbers.rs | 148 ++++++------ .../src/interpreter/instructions/records.rs | 135 +++++------ .../src/interpreter/instructions/strings.rs | 66 +++--- .../src/interpreter/instructions/utils.rs | 14 +- wasmer-it/src/interpreter/mod.rs | 30 ++- wasmer-it/src/interpreter/wasm/structures.rs | 25 +- wasmer-it/src/lib.rs | 11 +- wasmer-it/src/macros.rs | 12 +- wasmer-it/src/serde/de.rs | 8 +- wasmer-it/src/serde/ser.rs | 45 ++-- wasmer-it/src/values.rs | 53 +---- 33 files changed, 919 insertions(+), 861 deletions(-) create mode 100644 crates/it-types/src/impls/errors.rs create mode 100644 crates/it-types/src/impls/mod.rs create mode 100644 crates/it-types/src/impls/types.rs create mode 100644 crates/it-types/src/impls/values.rs rename crates/it-types/src/{vec1.rs => ne_vec.rs} (70%) diff --git a/Cargo.lock b/Cargo.lock index 481211e..3c185a1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -22,14 +22,16 @@ checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" name = "fluence-it-types" version = "0.1.0" dependencies = [ + "nom", "serde", + "wast", ] [[package]] name = "itoa" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" +checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" [[package]] name = "leb128" @@ -87,9 +89,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" +checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df" dependencies = [ "proc-macro2", ] @@ -128,9 +130,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.59" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcac07dbffa1c65e7f816ab9eba78eb142c6d44410f4eeba1e26e4f5dfa56b95" +checksum = "1500e84d27fe482ed1dc791a56eddc2f230046a040fa908c08bda1d9fb615779" dependencies = [ "itoa", "ryu", @@ -145,9 +147,9 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "syn" -version = "1.0.48" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc371affeffc477f42a221a1e4297aedcea33d47d19b61455588bd9d8f6b19ac" +checksum = "a9802ddde94170d186eeee5005b798d9c159fa970403f1be19976d0cfb939b72" dependencies = [ "proc-macro2", "quote", diff --git a/crates/it-types/Cargo.toml b/crates/it-types/Cargo.toml index ca30c9f..64019ad 100644 --- a/crates/it-types/Cargo.toml +++ b/crates/it-types/Cargo.toml @@ -4,6 +4,13 @@ version = "0.1.0" description = "Definitions of IValue and IType" authors = ["Fluence Labs"] edition = "2018" +license = "Apache-2.0" [dependencies] serde = { version = "1.0.118", features = ["derive", "rc"]} + +nom = { version = "5.1", optional = true } +wast = { version = "8.0", optional = true } + +[features] +impls = ["nom", "wast"] diff --git a/crates/it-types/src/impls/errors.rs b/crates/it-types/src/impls/errors.rs new file mode 100644 index 0000000..4f77bd0 --- /dev/null +++ b/crates/it-types/src/impls/errors.rs @@ -0,0 +1,29 @@ +use crate::IType; +use crate::IValue; + +use std::error::Error; +use std::fmt::Display; +use std::fmt::Formatter; +use std::fmt::Result; + +/// Structure to represent errors when casting from an `IType` +/// to a native value. +#[derive(Debug)] +pub struct WasmValueNativeCastError { + /// The initial type. + pub from: IValue, + + /// The targeted type. + /// + /// `IType` is used to represent the native type by + /// associativity. + pub to: IType, +} + +impl Error for WasmValueNativeCastError {} + +impl Display for WasmValueNativeCastError { + fn fmt(&self, formatter: &mut Formatter) -> Result { + write!(formatter, "{:?}", self) + } +} diff --git a/crates/it-types/src/impls/mod.rs b/crates/it-types/src/impls/mod.rs new file mode 100644 index 0000000..b6eb852 --- /dev/null +++ b/crates/it-types/src/impls/mod.rs @@ -0,0 +1,6 @@ +mod errors; +mod types; +mod values; + +pub use errors::WasmValueNativeCastError; +pub use values::NativeType; diff --git a/crates/it-types/src/impls/types.rs b/crates/it-types/src/impls/types.rs new file mode 100644 index 0000000..ea74054 --- /dev/null +++ b/crates/it-types/src/impls/types.rs @@ -0,0 +1,161 @@ +use crate::ne_vec::NEVec; +use crate::IRecordFieldType; +use crate::IRecordType; +use crate::IType; + +use wast::parser::Parse; +use wast::parser::Parser; +use wast::Error as ParseError; + +mod keyword { + pub use wast::{ + custom_keyword, + kw::{anyref, export, f32, f64, func, i32, i64, import, param, result}, + }; + + // New keywords. + custom_keyword!(record); + custom_keyword!(field); + + // New types. + custom_keyword!(s8); + custom_keyword!(s16); + custom_keyword!(s32); + custom_keyword!(s64); + custom_keyword!(u8); + custom_keyword!(u16); + custom_keyword!(u32); + custom_keyword!(u64); + custom_keyword!(string); + custom_keyword!(array); +} + +impl Parse<'_> for IType { + fn parse(parser: Parser<'_>) -> Result { + let mut lookahead = parser.lookahead1(); + if lookahead.peek::() { + parser.parse::()?; + + Ok(IType::S8) + } else if lookahead.peek::() { + parser.parse::()?; + + Ok(IType::S16) + } else if lookahead.peek::() { + parser.parse::()?; + + Ok(IType::S32) + } else if lookahead.peek::() { + parser.parse::()?; + + Ok(IType::S64) + } else if lookahead.peek::() { + parser.parse::()?; + + Ok(IType::U8) + } else if lookahead.peek::() { + parser.parse::()?; + + Ok(IType::U16) + } else if lookahead.peek::() { + parser.parse::()?; + + Ok(IType::U32) + } else if lookahead.peek::() { + parser.parse::()?; + + Ok(IType::U64) + } else if lookahead.peek::() { + parser.parse::()?; + + Ok(IType::F32) + } else if lookahead.peek::() { + parser.parse::()?; + + Ok(IType::F64) + } else if lookahead.peek::() { + parser.parse::()?; + + Ok(IType::String) + } else if lookahead.peek::() { + parser.parse::()?; + + let array_type = parser.parens(|p| p.parse())?; + + Ok(IType::Array(Box::new(array_type))) + } else if lookahead.peek::() { + parser.parse::()?; + + Ok(IType::Anyref) + } else if lookahead.peek::() { + parser.parse::()?; + + Ok(IType::I32) + } else if lookahead.peek::() { + parser.parse::()?; + + Ok(IType::I64) + } else if lookahead.peek::() { + parser.parse::()?; + + Ok(IType::Record(parser.parse()?)) + } else { + Err(lookahead.error()) + } + } +} + +impl Parse<'_> for IRecordType { + fn parse(parser: Parser<'_>) -> Result { + parser.parse::()?; + + let record_name = parser + .step(|cursor| { + cursor + .id() + .ok_or_else(|| cursor.error("expecting argument identifier")) + })? + .to_string(); + + let mut fields = vec![]; + + parser.parens(|parser| { + while !parser.is_empty() { + parser.parse::()?; + + let name = parser + .step(|cursor| { + cursor + .id() + .ok_or_else(|| cursor.error("expecting argument identifier")) + })? + .to_string(); + + if !name.ends_with(':') { + parser.step(|cursor| { + if let Some((":", rest)) = cursor.reserved() { + return Ok(("", rest)); + } + Err(cursor.error("expected : between an argument and a type")) + })?; + } + + let ty = parser.parse()?; + let record_field_type = IRecordFieldType { + name: name.trim_end_matches(':').to_string(), + ty, + }; + + fields.push(record_field_type); + } + Ok(()) + })?; + + let record_type = IRecordType { + name: record_name, + fields: NEVec::new(fields).expect("Record must have at least one field, zero given."), + }; + + Ok(record_type) + } +} diff --git a/crates/it-types/src/impls/values.rs b/crates/it-types/src/impls/values.rs new file mode 100644 index 0000000..3d99b2e --- /dev/null +++ b/crates/it-types/src/impls/values.rs @@ -0,0 +1,51 @@ +use crate::IType; +use crate::IValue; +use crate::WasmValueNativeCastError; + +use std::convert::TryFrom; + +/// Represents a native type supported by WIT. +pub trait NativeType { + /// The associated interface type that maps to the native type. + const INTERFACE_TYPE: IType; +} + +macro_rules! native { + ($native_type:ty, $variant:ident) => { + impl NativeType for $native_type { + const INTERFACE_TYPE: IType = IType::$variant; + } + + impl From<$native_type> for IValue { + fn from(n: $native_type) -> Self { + IValue::$variant(n) + } + } + + impl TryFrom<&IValue> for $native_type { + type Error = WasmValueNativeCastError; + + fn try_from(w: &IValue) -> Result { + match w { + IValue::$variant(n) => Ok(n.clone()), + _ => Err(WasmValueNativeCastError { + from: w.clone(), + to: <$native_type>::INTERFACE_TYPE, + }), + } + } + } + }; +} + +native!(i8, S8); +native!(i16, S16); +native!(i32, I32); +native!(i64, I64); +native!(u8, U8); +native!(u16, U16); +native!(u32, U32); +native!(u64, U64); +native!(f32, F32); +native!(f64, F64); +native!(String, String); diff --git a/crates/it-types/src/lib.rs b/crates/it-types/src/lib.rs index 893c264..f304e07 100644 --- a/crates/it-types/src/lib.rs +++ b/crates/it-types/src/lib.rs @@ -1,11 +1,20 @@ +#[cfg(feature = "impls")] +mod impls; +pub mod ne_vec; mod types; mod values; -pub mod vec1; // types -pub use types::InterfaceType as IType; +pub use types::IType; pub use types::RecordFieldType as IRecordFieldType; pub use types::RecordType as IRecordType; +#[cfg(feature = "impls")] +pub use impls::NativeType; + // values -pub use values::InterfaceValue as IValue; +pub use values::IValue; + +// errors +#[cfg(feature = "impls")] +pub use impls::WasmValueNativeCastError; diff --git a/crates/it-types/src/vec1.rs b/crates/it-types/src/ne_vec.rs similarity index 70% rename from crates/it-types/src/vec1.rs rename to crates/it-types/src/ne_vec.rs index 360a3e3..a7ce992 100644 --- a/crates/it-types/src/vec1.rs +++ b/crates/it-types/src/ne_vec.rs @@ -1,4 +1,4 @@ -//! `Vec1` represents a non-empty `Vec`. +//! `NEVec` represents a non-empty `Vec`. use serde::{Deserialize, Serialize}; use std::{ @@ -7,14 +7,14 @@ use std::{ ops, }; -/// `Vec1` represents a non-empty `Vec`. It derefs to `Vec` +/// `NEVec` represents a non-empty `Vec`. It derefs to `Vec` /// directly. #[derive(Clone, PartialEq, Eq, Serialize, Hash, Deserialize, Default)] -pub struct Vec1(Vec) +pub struct NEVec(Vec) where T: Debug; -/// Represents the only error that can be emitted by `Vec1`, i.e. when +/// Represents the only error that can be emitted by `NEVec`, i.e. when /// the number of items is zero. #[derive(Debug)] pub struct EmptyVec; @@ -23,11 +23,14 @@ impl error::Error for EmptyVec {} impl fmt::Display for EmptyVec { fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(formatter, "Vec1 must as least contain one item, zero given") + write!( + formatter, + "NEVec must as least contain one item, zero given" + ) } } -impl Vec1 +impl NEVec where T: Debug, { @@ -41,13 +44,13 @@ where } } - /// Converts this Vec1 into Vec + /// Converts this NEVec into Vec pub fn into_vec(self) -> Vec { self.0 } } -impl fmt::Debug for Vec1 +impl fmt::Debug for NEVec where T: Debug, { @@ -56,7 +59,7 @@ where } } -impl ops::Deref for Vec1 +impl ops::Deref for NEVec where T: Debug, { diff --git a/crates/it-types/src/types.rs b/crates/it-types/src/types.rs index 3310ebe..70ca577 100644 --- a/crates/it-types/src/types.rs +++ b/crates/it-types/src/types.rs @@ -1,13 +1,13 @@ //! This module defines the WIT types. -use crate::vec1::Vec1; +use crate::ne_vec::NEVec; use serde::Deserialize; use serde::Serialize; /// Represents the types supported by WIT. #[derive(PartialEq, Eq, Debug, Clone, Hash, Serialize, Deserialize)] -pub enum InterfaceType { +pub enum IType { /// A 8-bits signed integer. S8, @@ -42,7 +42,7 @@ pub enum InterfaceType { String, /// An array of values of the same type. - Array(Box), + Array(Box), /// An `any` reference. Anyref, @@ -65,7 +65,7 @@ pub struct RecordFieldType { pub name: String, /// A field type. - pub ty: InterfaceType, + pub ty: IType, } /// Represents a record type. @@ -77,18 +77,64 @@ pub struct RecordType { /// Types and names representing the fields. /// A record must have at least one field, hence the /// [`Vec1`][crate::vec1::Vec1]. - pub fields: Vec1, + pub fields: NEVec, } impl Default for RecordType { fn default() -> Self { Self { name: String::new(), - fields: Vec1::new(vec![RecordFieldType { + fields: NEVec::new(vec![RecordFieldType { name: String::new(), - ty: InterfaceType::S8, + ty: IType::S8, }]) .unwrap(), } } } + +/// Encode an `IType` into a string. +// TODO: consider change to impl Display +impl ToString for &IType { + fn to_string(&self) -> String { + match &self { + IType::S8 => "s8".to_string(), + IType::S16 => "s16".to_string(), + IType::S32 => "s32".to_string(), + IType::S64 => "s64".to_string(), + IType::U8 => "u8".to_string(), + IType::U16 => "u16".to_string(), + IType::U32 => "u32".to_string(), + IType::U64 => "u64".to_string(), + IType::F32 => "f32".to_string(), + IType::F64 => "f64".to_string(), + IType::String => "string".to_string(), + IType::Array(ty) => format!("array ({})", ty.as_ref().to_string()), + IType::Anyref => "anyref".to_string(), + IType::I32 => "i32".to_string(), + IType::I64 => "i64".to_string(), + IType::Record(record_type_id) => format!("record {}", record_type_id), + } + } +} + +impl ToString for &RecordType { + fn to_string(&self) -> String { + format!( + "record ${} (\n{fields})", + self.name, + fields = self + .fields + .iter() + .fold(String::new(), |mut accumulator, field_type| { + accumulator.push(' '); + accumulator.push_str(&format!( + "field ${}: {}\n", + field_type.name, + (&field_type.ty).to_string() + )); + accumulator + }), + ) + } +} diff --git a/crates/it-types/src/values.rs b/crates/it-types/src/values.rs index 7b765f4..a2835f2 100644 --- a/crates/it-types/src/values.rs +++ b/crates/it-types/src/values.rs @@ -1,10 +1,10 @@ //! Defines WIT values and associated operations. -use crate::vec1::Vec1; +use crate::ne_vec::NEVec; /// A WIT value. #[derive(Debug, Clone, PartialEq)] -pub enum InterfaceValue { +pub enum IValue { /// A 8-bits signed integer. S8(i8), @@ -39,7 +39,7 @@ pub enum InterfaceValue { String(String), /// A byte array. - Array(Vec), + Array(Vec), //Anyref(?), /// A 32-bits integer (as defined in WebAssembly core). @@ -49,10 +49,10 @@ pub enum InterfaceValue { I64(i64), /// A record. - Record(Vec1), + Record(NEVec), } -impl Default for InterfaceValue { +impl Default for IValue { fn default() -> Self { Self::I32(0) } diff --git a/tests/binary.rs b/tests/binary.rs index 8198c04..271585b 100644 --- a/tests/binary.rs +++ b/tests/binary.rs @@ -13,11 +13,11 @@ fn test_binary_encoding_decoding_roundtrip() { outputs: vec![], }, Type::Function { - inputs: vec![InterfaceType::I32, InterfaceType::I32], - outputs: vec![InterfaceType::S32], + inputs: vec![IType::I32, IType::I32], + outputs: vec![IType::S32], }, Type::Record(RecordType { - fields: vec1![InterfaceType::String, InterfaceType::I32], + fields: vec1![IType::String, IType::I32], }), ], imports: vec![Import { diff --git a/wasmer-it/Cargo.toml b/wasmer-it/Cargo.toml index fd39247..7a7131a 100644 --- a/wasmer-it/Cargo.toml +++ b/wasmer-it/Cargo.toml @@ -8,7 +8,7 @@ repository = "https://github.com/wasmerio/wasmer" edition = "2018" [dependencies] -fluence-it-types = { path = "../crates/it-types", version = "0.1.0" } +fluence-it-types = { path = "../crates/it-types", version = "0.1.0", features = ["impls"] } nom = "5.1" wast = "8.0" diff --git a/wasmer-it/src/ast.rs b/wasmer-it/src/ast.rs index 28ad538..e332ce0 100644 --- a/wasmer-it/src/ast.rs +++ b/wasmer-it/src/ast.rs @@ -1,12 +1,7 @@ //! Represents the WIT language as a tree. This is the central //! representation of the language. -use crate::{ - interpreter::Instruction, - IValue, - IType, - IRecordType -}; +use crate::{interpreter::Instruction, IRecordType, IType}; use serde::Deserialize; use serde::Serialize; diff --git a/wasmer-it/src/decoders/binary.rs b/wasmer-it/src/decoders/binary.rs index 4ff3c3a..77482ff 100644 --- a/wasmer-it/src/decoders/binary.rs +++ b/wasmer-it/src/decoders/binary.rs @@ -1,9 +1,9 @@ //! Parse the WIT binary representation into an [AST](crate::ast). +use crate::IRecordFieldType; +use crate::IRecordType; use crate::IType; -use crate::RecordFieldType; -use crate::RecordType; -use crate::{ast::*, interpreter::Instruction, types::*}; +use crate::{ast::*, interpreter::Instruction}; use nom::{ error::{make_error, ErrorKind, ParseError}, Err, IResult, @@ -76,7 +76,7 @@ fn uleb<'input, E: ParseError<&'input [u8]>>(input: &'input [u8]) -> IResult<&'i fn record_field<'input, E: ParseError<&'input [u8]>>( mut input: &'input [u8], -) -> IResult<&'input [u8], RecordFieldType, E> { +) -> IResult<&'input [u8], IRecordFieldType, E> { if input.is_empty() { return Err(Err::Error(make_error(input, ErrorKind::Eof))); } @@ -84,7 +84,7 @@ fn record_field<'input, E: ParseError<&'input [u8]>>( consume!((input, name) = owned_string(input)?); consume!((input, ty) = ty(input)?); - Ok((input, RecordFieldType { name, ty })) + Ok((input, IRecordFieldType { name, ty })) } fn function_arg<'input, E: ParseError<&'input [u8]>>( @@ -144,17 +144,17 @@ fn ty<'input, E: ParseError<&'input [u8]>>( /// Parse a record type. fn record_type<'input, E: ParseError<&'input [u8]>>( input: &'input [u8], -) -> IResult<&'input [u8], RecordType, E> { - use crate::vec1::Vec1; +) -> IResult<&'input [u8], IRecordType, E> { + use crate::NEVec; let (output, name) = owned_string(input)?; let (output, fields) = list(output, record_field)?; Ok(( output, - RecordType { + IRecordType { name, - fields: Vec1::new(fields).expect("Record must have at least one field, zero given."), + fields: NEVec::new(fields).expect("Record must have at least one field, zero given."), }, )) } diff --git a/wasmer-it/src/decoders/wat.rs b/wasmer-it/src/decoders/wat.rs index 8fe9071..668a30f 100644 --- a/wasmer-it/src/decoders/wat.rs +++ b/wasmer-it/src/decoders/wat.rs @@ -1,12 +1,7 @@ //! Parse the WIT textual representation into an [AST](crate::ast). use crate::IType; -use crate::ITypeImpl; -use crate::RecordFieldType; -use crate::RecordFieldTypeImpl; -use crate::RecordType; -use crate::RecordTypeImpl; -use crate::{ast::*, interpreter::Instruction, types::*, vec1::Vec1}; +use crate::{ast::*, interpreter::Instruction}; use std::rc::Rc; pub use wast::parser::ParseBuffer as Buffer; use wast::parser::{self, Cursor, Parse, Parser, Peek, Result}; @@ -89,138 +84,6 @@ mod keyword { custom_keyword!(swap2 = "swap2"); } -impl Parse<'_> for ITypeImpl { - fn parse(parser: Parser<'_>) -> Result { - let mut lookahead = parser.lookahead1(); - if lookahead.peek::() { - parser.parse::()?; - - Ok(IType::S8) - } else if lookahead.peek::() { - parser.parse::()?; - - Ok(IType::S16) - } else if lookahead.peek::() { - parser.parse::()?; - - Ok(IType::S32) - } else if lookahead.peek::() { - parser.parse::()?; - - Ok(IType::S64) - } else if lookahead.peek::() { - parser.parse::()?; - - Ok(IType::U8) - } else if lookahead.peek::() { - parser.parse::()?; - - Ok(IType::U16) - } else if lookahead.peek::() { - parser.parse::()?; - - Ok(IType::U32) - } else if lookahead.peek::() { - parser.parse::()?; - - Ok(IType::U64) - } else if lookahead.peek::() { - parser.parse::()?; - - Ok(IType::F32) - } else if lookahead.peek::() { - parser.parse::()?; - - Ok(IType::F64) - } else if lookahead.peek::() { - parser.parse::()?; - - Ok(IType::String) - } else if lookahead.peek::() { - parser.parse::()?; - - let array_type = parser.parens(|p| p.parse())?; - - Ok(IType::Array(Box::new(array_type))) - } else if lookahead.peek::() { - parser.parse::()?; - - Ok(IType::Anyref) - } else if lookahead.peek::() { - parser.parse::()?; - - Ok(IType::I32) - } else if lookahead.peek::() { - parser.parse::()?; - - Ok(IType::I64) - } else if lookahead.peek::() { - parser.parse::()?; - - Ok(IType::Record(parser.parse()?)) - } else { - Err(lookahead.error()) - } - } -} - -impl Parse<'_> for RecordTypeImpl { - fn parse(parser: Parser<'_>) -> Result { - parser.parse::()?; - - let record_name = parser - .step(|cursor| { - cursor - .id() - .ok_or_else(|| cursor.error("expecting argument identifier")) - })? - .to_string(); - - let mut fields = vec![]; - - parser.parens(|parser| { - while !parser.is_empty() { - parser.parse::()?; - - let name = parser - .step(|cursor| { - cursor - .id() - .ok_or_else(|| cursor.error("expecting argument identifier")) - })? - .to_string(); - - if !name.ends_with(':') { - parser.step(|cursor| { - if let Some((":", rest)) = cursor.reserved() { - return Ok(("", rest)); - } - Err(cursor.error("expected : between an argument and a type")) - })?; - } - - let ty = parser.parse()?; - let record_field_type = RecordFieldType { - name: name.trim_end_matches(":").to_string(), - ty, - }; - let record_field_type = RecordFieldTypeImpl(record_field_type); - - fields.push(record_field_type); - } - Ok(()) - })?; - - let record_type = RecordType { - name: record_name, - fields: Vec1::new(fields).expect("Record must have at least one field, zero given."), - }; - let record_type = RecordTypeImpl(record_type); - - Ok(record_type) - } -} - #[allow(clippy::suspicious_else_formatting)] impl<'a> Parse<'a> for Instruction { #[allow(clippy::cognitive_complexity)] diff --git a/wasmer-it/src/encoders/binary.rs b/wasmer-it/src/encoders/binary.rs index 3cade0e..c55dcba 100644 --- a/wasmer-it/src/encoders/binary.rs +++ b/wasmer-it/src/encoders/binary.rs @@ -1,12 +1,14 @@ //! Writes the AST into bytes representing WIT with its binary format. -use crate::{ast::*, interpreter::Instruction, types::*}; -use std::io::{self, Write}; +use crate::{ast::*, interpreter::Instruction}; +use crate::IRecordFieldType; +use crate::IRecordType; use crate::IType; -use crate::ITypeImpl; -use crate::RecordFieldTypeImpl; -use crate::RecordTypeImpl; + +use std::io; +use std::io::Write; +use std::ops::Deref; /// A trait for converting a value to bytes. pub trait ToBytes @@ -17,6 +19,15 @@ where fn to_bytes(&self, writer: &mut W) -> io::Result<()>; } +/// Miscellaneous IType wrapper to pass the orphan rule. +pub struct ITypeImpl<'a>(pub &'a IType); + +/// Miscellaneous IRecordType wrapper to pass the orphan rule. +pub struct IRecordTypeImpl<'a>(pub &'a IRecordType); + +/// Miscellaneous IRecordFieldType wrapper to pass the orphan rule. +pub struct IRecordFieldTypeImpl<'a>(pub &'a IRecordFieldType); + /// Encode a `u8` into a byte (well, it's already a byte!). impl ToBytes for u8 where @@ -53,6 +64,72 @@ where } } +/// Encode an `IType` into bytes. +impl ToBytes for ITypeImpl<'_> +where + W: Write, +{ + fn to_bytes(&self, writer: &mut W) -> io::Result<()> { + match &self.0 { + IType::S8 => 0x00_u8.to_bytes(writer), + IType::S16 => 0x01_u8.to_bytes(writer), + IType::S32 => 0x02_u8.to_bytes(writer), + IType::S64 => 0x03_u8.to_bytes(writer), + IType::U8 => 0x04_u8.to_bytes(writer), + IType::U16 => 0x05_u8.to_bytes(writer), + IType::U32 => 0x06_u8.to_bytes(writer), + IType::U64 => 0x07_u8.to_bytes(writer), + IType::F32 => 0x08_u8.to_bytes(writer), + IType::F64 => 0x09_u8.to_bytes(writer), + IType::String => 0x0a_u8.to_bytes(writer), + IType::Array(ty) => { + 0x36_u8.to_bytes(writer)?; + let itype_impl = ITypeImpl(ty); + itype_impl.to_bytes(writer) + } + IType::Anyref => 0x0b_u8.to_bytes(writer), + IType::I32 => 0x0c_u8.to_bytes(writer), + IType::I64 => 0x0d_u8.to_bytes(writer), + IType::Record(record_id) => { + 0x0e_u8.to_bytes(writer)?; + record_id.to_bytes(writer) + } + } + } +} + +/// Encode a `RecordType` into bytes. +impl ToBytes for IRecordFieldTypeImpl<'_> +where + W: Write, +{ + fn to_bytes(&self, writer: &mut W) -> io::Result<()> { + let record_field_type = &self.0; + record_field_type.name.as_str().to_bytes(writer)?; + let itype_impl = ITypeImpl(&record_field_type.ty); + itype_impl.to_bytes(writer) + } +} + +/// Encode a `RecordType` into bytes. +impl ToBytes for IRecordTypeImpl<'_> +where + W: Write, +{ + fn to_bytes(&self, writer: &mut W) -> io::Result<()> { + let record_type = self.0; + record_type.name.as_str().to_bytes(writer)?; + let record_type_impl = record_type + .fields + .deref() + .iter() + .map(|r| IRecordFieldTypeImpl(r)) + .collect::>(); + + record_type_impl.to_bytes(writer) + } +} + /// Encode a `str` into bytes. /// /// Decoder is `decoders::binary::string`. @@ -110,63 +187,6 @@ where } } -/// Encode an `InterfaceType` into bytes. -impl ToBytes for ITypeImpl -where - W: Write, -{ - fn to_bytes(&self, writer: &mut W) -> io::Result<()> { - match self.0 { - IType::S8 => 0x00_u8.to_bytes(writer), - IType::S16 => 0x01_u8.to_bytes(writer), - IType::S32 => 0x02_u8.to_bytes(writer), - IType::S64 => 0x03_u8.to_bytes(writer), - IType::U8 => 0x04_u8.to_bytes(writer), - IType::U16 => 0x05_u8.to_bytes(writer), - IType::U32 => 0x06_u8.to_bytes(writer), - IType::U64 => 0x07_u8.to_bytes(writer), - IType::F32 => 0x08_u8.to_bytes(writer), - IType::F64 => 0x09_u8.to_bytes(writer), - IType::String => 0x0a_u8.to_bytes(writer), - IType::Array(ty) => { - 0x36_u8.to_bytes(writer)?; - ty.to_bytes(writer) - } - IType::Anyref => 0x0b_u8.to_bytes(writer), - IType::I32 => 0x0c_u8.to_bytes(writer), - IType::I64 => 0x0d_u8.to_bytes(writer), - IType::Record(record_id) => { - 0x0e_u8.to_bytes(writer)?; - record_id.to_bytes(writer) - } - } - } -} - -/// Encode a `RecordType` into bytes. -impl ToBytes for RecordFieldTypeImpl -where - W: Write, -{ - fn to_bytes(&self, writer: &mut W) -> io::Result<()> { - let record_field_type = &self.0; - record_field_type.name.as_str().to_bytes(writer)?; - record_field_type.ty.to_bytes(writer) - } -} - -/// Encode a `RecordType` into bytes. -impl ToBytes for RecordTypeImpl -where - W: Write, -{ - fn to_bytes(&self, writer: &mut W) -> io::Result<()> { - let record_type = &self.0; - record_type.name.as_str().to_bytes(writer)?; - record_type.fields.to_bytes(writer) - } -} - /// Encode a `TypeKind` into bytes. impl ToBytes for TypeKind where @@ -202,7 +222,8 @@ where { fn to_bytes(&self, writer: &mut W) -> io::Result<()> { self.name.to_bytes(writer)?; - self.ty.to_bytes(writer) + let itype_impl = ITypeImpl(&self.ty); + itype_impl.to_bytes(writer) } } @@ -221,12 +242,17 @@ where } => { TypeKind::Function.to_bytes(writer)?; arguments.to_bytes(writer)?; + let output_types = output_types + .iter() + .map(|t| ITypeImpl(t)) + .collect::>(); output_types.to_bytes(writer)?; } Type::Record(record_type) => { TypeKind::Record.to_bytes(writer)?; - record_type.to_bytes(writer)?; + let record_impl = IRecordTypeImpl(record_type.deref()); + record_impl.to_bytes(writer)?; } } @@ -390,11 +416,13 @@ where Instruction::ArrayLiftMemory { value_type } => { 0x37_u8.to_bytes(writer)?; - value_type.to_bytes(writer)? + let value_type_impl = ITypeImpl(value_type); + value_type_impl.to_bytes(writer)? } Instruction::ArrayLowerMemory { value_type } => { 0x38_u8.to_bytes(writer)?; - value_type.to_bytes(writer)? + let value_type_impl = ITypeImpl(value_type); + value_type_impl.to_bytes(writer)? } /* Instruction::ArraySize => 0x39_u8.to_bytes(writer)?, @@ -505,23 +533,23 @@ mod tests { #[test] fn test_interface_type() { - assert_to_bytes!(InterfaceType::S8, &[0x00]); - assert_to_bytes!(InterfaceType::S16, &[0x01]); - assert_to_bytes!(InterfaceType::S32, &[0x02]); - assert_to_bytes!(InterfaceType::S64, &[0x03]); - assert_to_bytes!(InterfaceType::U8, &[0x04]); - assert_to_bytes!(InterfaceType::U16, &[0x05]); - assert_to_bytes!(InterfaceType::U32, &[0x06]); - assert_to_bytes!(InterfaceType::U64, &[0x07]); - assert_to_bytes!(InterfaceType::F32, &[0x08]); - assert_to_bytes!(InterfaceType::F64, &[0x09]); - assert_to_bytes!(InterfaceType::String, &[0x0a]); - assert_to_bytes!(InterfaceType::Anyref, &[0x0b]); - assert_to_bytes!(InterfaceType::I32, &[0x0c]); - assert_to_bytes!(InterfaceType::I64, &[0x0d]); + assert_to_bytes!(IType::S8, &[0x00]); + assert_to_bytes!(IType::S16, &[0x01]); + assert_to_bytes!(IType::S32, &[0x02]); + assert_to_bytes!(IType::S64, &[0x03]); + assert_to_bytes!(IType::U8, &[0x04]); + assert_to_bytes!(IType::U16, &[0x05]); + assert_to_bytes!(IType::U32, &[0x06]); + assert_to_bytes!(IType::U64, &[0x07]); + assert_to_bytes!(IType::F32, &[0x08]); + assert_to_bytes!(IType::F64, &[0x09]); + assert_to_bytes!(IType::String, &[0x0a]); + assert_to_bytes!(IType::Anyref, &[0x0b]); + assert_to_bytes!(IType::I32, &[0x0c]); + assert_to_bytes!(IType::I64, &[0x0d]); assert_to_bytes!( - InterfaceType::Record(RecordType { - fields: vec1![InterfaceType::String] + IType::Record(RecordType { + fields: vec1![IType::String] }), &[0x0e, 0x01, 0x0a] ); @@ -531,7 +559,7 @@ mod tests { fn test_record_type() { assert_to_bytes!( RecordType { - fields: vec1![InterfaceType::String] + fields: vec1![IType::String] }, &[ 0x01, // 1 field @@ -540,7 +568,7 @@ mod tests { ); assert_to_bytes!( RecordType { - fields: vec1![InterfaceType::String, InterfaceType::I32] + fields: vec1![IType::String, IType::I32] }, &[ 0x02, // 2 fields @@ -551,11 +579,11 @@ mod tests { assert_to_bytes!( RecordType { fields: vec1![ - InterfaceType::String, - InterfaceType::Record(RecordType { - fields: vec1![InterfaceType::I32, InterfaceType::I32], + IType::String, + IType::Record(RecordType { + fields: vec1![IType::I32, IType::I32], }), - InterfaceType::F64, + IType::F64, ], }, &[ @@ -600,8 +628,8 @@ mod tests { fn test_type_function() { assert_to_bytes!( Type::Function { - inputs: vec![InterfaceType::I32, InterfaceType::I64], - outputs: vec![InterfaceType::S32], + inputs: vec![IType::I32, IType::I64], + outputs: vec![IType::S32], }, &[ 0x00, // function type @@ -618,7 +646,7 @@ mod tests { fn test_type_record() { assert_to_bytes!( Type::Record(RecordType { - fields: vec1![InterfaceType::I32, InterfaceType::I64], + fields: vec1![IType::I32, IType::I64], }), &[ 0x01, // record type @@ -667,8 +695,8 @@ mod tests { assert_to_bytes!( Interfaces { types: vec![Type::Function { - inputs: vec![InterfaceType::S8], - outputs: vec![InterfaceType::S16], + inputs: vec![IType::S8], + outputs: vec![IType::S16], }], imports: vec![Import { namespace: "ab", diff --git a/wasmer-it/src/encoders/wat.rs b/wasmer-it/src/encoders/wat.rs index c921c8f..cff8aa1 100644 --- a/wasmer-it/src/encoders/wat.rs +++ b/wasmer-it/src/encoders/wat.rs @@ -7,13 +7,13 @@ //! ast::{Adapter, Export, Implementation, Import, Interfaces, Type}, //! encoders::wat::*, //! interpreter::Instruction, -//! types::InterfaceType, +//! types::IType, //! }; //! //! let input: String = (&Interfaces { //! types: vec![Type::Function { -//! inputs: vec![InterfaceType::I32], -//! outputs: vec![InterfaceType::S8], +//! inputs: vec![IType::I32], +//! outputs: vec![IType::S8], //! }], //! imports: vec![Import { //! namespace: "ns", @@ -56,58 +56,9 @@ //! ``` use crate::IType; -use crate::ITypeImpl; -use crate::RecordTypeImpl; -use crate::{ast::*, interpreter::Instruction, types::*}; +use crate::{ast::*, interpreter::Instruction}; use std::string::ToString; -/// Encode an `InterfaceType` into a string. -impl ToString for &ITypeImpl { - fn to_string(&self) -> String { - match &self.0 { - IType::S8 => "s8".to_string(), - IType::S16 => "s16".to_string(), - IType::S32 => "s32".to_string(), - IType::S64 => "s64".to_string(), - IType::U8 => "u8".to_string(), - IType::U16 => "u16".to_string(), - IType::U32 => "u32".to_string(), - IType::U64 => "u64".to_string(), - IType::F32 => "f32".to_string(), - IType::F64 => "f64".to_string(), - IType::String => "string".to_string(), - IType::Array(ty) => format!("array ({})", ty.as_ref().to_string()), - IType::Anyref => "anyref".to_string(), - IType::I32 => "i32".to_string(), - IType::I64 => "i64".to_string(), - IType::Record(record_type_id) => format!("record {}", record_type_id), - } - } -} - -impl ToString for &RecordTypeImpl { - fn to_string(&self) -> String { - let record_type = &self.0; - format!( - "record ${} (\n{fields})", - record_type.name, - fields = - record_type - .fields - .iter() - .fold(String::new(), |mut accumulator, field_type| { - accumulator.push(' '); - accumulator.push_str(&format!( - "field ${}: {}\n", - field_type.name, - (&field_type.ty).to_string() - )); - accumulator - }), - ) - } -} - /// Encode an `Instruction` into a string. impl ToString for &Instruction { fn to_string(&self) -> String { @@ -172,7 +123,7 @@ impl ToString for &Instruction { } } -/// Encode a list of `InterfaceType` representing inputs into a +/// Encode a list of `IType` representing inputs into a /// string. fn encode_function_arguments(arguments: &[FunctionArg]) -> String { // here we know that arg_names and arg_types have the same length @@ -195,7 +146,7 @@ fn encode_function_arguments(arguments: &[FunctionArg]) -> String { } } -/// Encode a list of `InterfaceType` representing outputs into a +/// Encode a list of `IType` representing outputs into a /// string. fn output_types_to_result(output_types: &[IType]) -> String { if output_types.is_empty() { @@ -389,22 +340,22 @@ mod tests { #[test] fn test_interface_types() { let inputs: Vec = vec![ - (&InterfaceType::S8).to_string(), - (&InterfaceType::S16).to_string(), - (&InterfaceType::S32).to_string(), - (&InterfaceType::S64).to_string(), - (&InterfaceType::U8).to_string(), - (&InterfaceType::U16).to_string(), - (&InterfaceType::U32).to_string(), - (&InterfaceType::U64).to_string(), - (&InterfaceType::F32).to_string(), - (&InterfaceType::F64).to_string(), - (&InterfaceType::String).to_string(), - (&InterfaceType::Anyref).to_string(), - (&InterfaceType::I32).to_string(), - (&InterfaceType::I64).to_string(), - (&InterfaceType::Record(RecordType { - fields: vec1![InterfaceType::String], + (&IType::S8).to_string(), + (&IType::S16).to_string(), + (&IType::S32).to_string(), + (&IType::S64).to_string(), + (&IType::U8).to_string(), + (&IType::U16).to_string(), + (&IType::U32).to_string(), + (&IType::U64).to_string(), + (&IType::F32).to_string(), + (&IType::F64).to_string(), + (&IType::String).to_string(), + (&IType::Anyref).to_string(), + (&IType::I32).to_string(), + (&IType::I64).to_string(), + (&IType::Record(RecordType { + fields: vec1![IType::String], })) .to_string(), ]; @@ -433,20 +384,20 @@ mod tests { fn test_record_type() { let inputs = vec![ (&RecordType { - fields: vec1![InterfaceType::String], + fields: vec1![IType::String], }) .to_string(), (&RecordType { - fields: vec1![InterfaceType::String, InterfaceType::I32], + fields: vec1![IType::String, IType::I32], }) .to_string(), (&RecordType { fields: vec1![ - InterfaceType::String, - InterfaceType::Record(RecordType { - fields: vec1![InterfaceType::I32, InterfaceType::I32], + IType::String, + IType::Record(RecordType { + fields: vec1![IType::I32, IType::I32], }), - InterfaceType::F64, + IType::F64, ], }) .to_string(), @@ -554,18 +505,18 @@ mod tests { fn test_types() { let inputs: Vec = vec![ (&Type::Function { - inputs: vec![InterfaceType::I32, InterfaceType::F32], - outputs: vec![InterfaceType::I32], + inputs: vec![IType::I32, IType::F32], + outputs: vec![IType::I32], }) .to_string(), (&Type::Function { - inputs: vec![InterfaceType::I32], + inputs: vec![IType::I32], outputs: vec![], }) .to_string(), (&Type::Function { inputs: vec![], - outputs: vec![InterfaceType::I32], + outputs: vec![IType::I32], }) .to_string(), (&Type::Function { @@ -574,7 +525,7 @@ mod tests { }) .to_string(), (&Type::Record(RecordType { - fields: vec1![InterfaceType::String, InterfaceType::I32], + fields: vec1![IType::String, IType::I32], })) .to_string(), ]; @@ -635,8 +586,8 @@ mod tests { fn test_interfaces() { let input: String = (&Interfaces { types: vec![Type::Function { - inputs: vec![InterfaceType::I32], - outputs: vec![InterfaceType::S8], + inputs: vec![IType::I32], + outputs: vec![IType::S8], }], imports: vec![Import { namespace: "ns", diff --git a/wasmer-it/src/errors.rs b/wasmer-it/src/errors.rs index 845a4f0..215e291 100644 --- a/wasmer-it/src/errors.rs +++ b/wasmer-it/src/errors.rs @@ -1,8 +1,9 @@ //! The error module contains all the data structures that represent //! an error. -use crate::values::InterfaceValue; -use crate::{ast::TypeKind, interpreter::Instruction, types::InterfaceType}; +use crate::IType; +use crate::IValue; +use crate::{ast::TypeKind, interpreter::Instruction}; use std::{ error::Error, fmt::{self, Display, Formatter}, @@ -11,34 +12,14 @@ use std::{ string::{self, ToString}, }; +pub use fluence_it_types::WasmValueNativeCastError; + /// A type alias for instruction's results. pub type InstructionResult = Result; /// A type alias for the interpreter result. pub type InterpreterResult = Result; -/// Structure to represent errors when casting from an `InterfaceType` -/// to a native value. -#[derive(Debug)] -pub struct WasmValueNativeCastError { - /// The initial type. - pub from: InterfaceValue, - - /// The targeted type. - /// - /// `InterfaceType` is used to represent the native type by - /// associativity. - pub to: InterfaceType, -} - -impl Error for WasmValueNativeCastError {} - -impl Display for WasmValueNativeCastError { - fn fmt(&self, formatter: &mut Formatter) -> fmt::Result { - write!(formatter, "{:?}", self) - } -} - /// Structure to represent the errors for instructions. #[derive(Debug)] pub struct InstructionError { @@ -86,20 +67,20 @@ pub enum InstructionErrorKind { /// Failed to cast from `from` to `to`. LoweringLifting { /// The initial type. - from: InterfaceType, + from: IType, /// The targeted type. - to: InterfaceType, + to: IType, }, /// Read a value from the stack, but it doesn't have the expected /// type. InvalidValueOnTheStack { /// The expected type. - expected_type: InterfaceType, + expected_type: IType, /// The received type. - received_value: InterfaceValue, + received_value: IValue, }, /// Need to read some values from the stack, but it doesn't @@ -122,10 +103,10 @@ pub enum InstructionErrorKind { function_index: u32, /// The expected signature. - expected: (Vec, Vec), + expected: (Vec, Vec), /// The received signature. - received: (Vec, Vec), + received: (Vec, Vec), }, /// Failed to call a local or import function. diff --git a/wasmer-it/src/interpreter/instructions/argument_get.rs b/wasmer-it/src/interpreter/instructions/argument_get.rs index f8a8c7e..35825e4 100644 --- a/wasmer-it/src/interpreter/instructions/argument_get.rs +++ b/wasmer-it/src/interpreter/instructions/argument_get.rs @@ -29,9 +29,9 @@ mod tests { test_executable_instruction!( test_argument_get = instructions: [Instruction::ArgumentGet { index: 0 }], - invocation_inputs: [InterfaceValue::I32(42)], + invocation_inputs: [IValue::I32(42)], instance: Instance::new(), - stack: [InterfaceValue::I32(42)], + stack: [IValue::I32(42)], ); test_executable_instruction!( @@ -41,20 +41,20 @@ mod tests { Instruction::ArgumentGet { index: 1 }, ], invocation_inputs: [ - InterfaceValue::I32(7), - InterfaceValue::I32(42), + IValue::I32(7), + IValue::I32(42), ], instance: Instance::new(), stack: [ - InterfaceValue::I32(7), - InterfaceValue::I32(42), + IValue::I32(7), + IValue::I32(42), ], ); test_executable_instruction!( test_argument_get__invalid_index = instructions: [Instruction::ArgumentGet { index: 1 }], - invocation_inputs: [InterfaceValue::I32(42)], + invocation_inputs: [IValue::I32(42)], instance: Instance::new(), error: "`arg.get 1` cannot access invocation inputs #1 because it doesn't exist" ); diff --git a/wasmer-it/src/interpreter/instructions/arrays.rs b/wasmer-it/src/interpreter/instructions/arrays.rs index 87198c7..32482e0 100644 --- a/wasmer-it/src/interpreter/instructions/arrays.rs +++ b/wasmer-it/src/interpreter/instructions/arrays.rs @@ -6,19 +6,18 @@ use crate::interpreter::instructions::to_native; use crate::{ errors::{InstructionError, InstructionErrorKind}, interpreter::Instruction, - types::InterfaceType, - values::InterfaceValue, + IType, IValue, }; use std::convert::TryInto; pub(super) fn array_lift_memory_<'instance, Instance, Export, LocalImport, Memory, MemoryView>( instance: &'instance Instance, - value_type: &InterfaceType, + value_type: &IType, offset: usize, size: usize, instruction: Instruction, -) -> Result, InstructionError> +) -> Result, InstructionError> where Export: crate::interpreter::wasm::structures::Export, LocalImport: crate::interpreter::wasm::structures::LocalImport, @@ -38,74 +37,58 @@ where let data = read_from_instance_mem(instance, instruction.clone(), offset, size)?; let result_array = match value_type { - InterfaceType::S8 => { + IType::S8 => { let data = transmute_vec::(data).unwrap(); - data.into_iter().map(InterfaceValue::S8).collect::>() + data.into_iter().map(IValue::S8).collect::>() } - InterfaceType::S16 => { + IType::S16 => { let data = transmute_many::(&data).unwrap(); - data.iter() - .map(|v| InterfaceValue::S16(*v)) - .collect::>() + data.iter().map(|v| IValue::S16(*v)).collect::>() } - InterfaceType::S32 => { + IType::S32 => { let data = transmute_many::(&data).unwrap(); - data.iter() - .map(|v| InterfaceValue::S32(*v)) - .collect::>() + data.iter().map(|v| IValue::S32(*v)).collect::>() } - InterfaceType::S64 => { + IType::S64 => { let data = transmute_many::(&data).unwrap(); - data.iter() - .map(|v| InterfaceValue::S64(*v)) - .collect::>() + data.iter().map(|v| IValue::S64(*v)).collect::>() } - InterfaceType::I32 => { + IType::I32 => { let data = transmute_many::(&data).unwrap(); - data.iter() - .map(|v| InterfaceValue::I32(*v)) - .collect::>() + data.iter().map(|v| IValue::I32(*v)).collect::>() } - InterfaceType::I64 => { + IType::I64 => { let data = transmute_many::(&data).unwrap(); - data.iter() - .map(|v| InterfaceValue::S64(*v)) - .collect::>() + data.iter().map(|v| IValue::S64(*v)).collect::>() } - InterfaceType::U8 => data.into_iter().map(InterfaceValue::U8).collect::>(), - InterfaceType::U16 => { + IType::U8 => data.into_iter().map(IValue::U8).collect::>(), + IType::U16 => { let data = transmute_many::(&data).unwrap(); - data.iter() - .map(|v| InterfaceValue::U16(*v)) - .collect::>() + data.iter().map(|v| IValue::U16(*v)).collect::>() } - InterfaceType::U32 => { + IType::U32 => { + let data = transmute_many::(&data).unwrap(); + data.iter().map(|v| IValue::U32(*v)).collect::>() + } + IType::U64 => { + let data = transmute_many::(&data).unwrap(); + data.iter().map(|v| IValue::U64(*v)).collect::>() + } + IType::F32 => { let data = transmute_many::(&data).unwrap(); data.iter() - .map(|v| InterfaceValue::U32(*v)) + .map(|v| IValue::F32(f32::from_bits(*v))) .collect::>() } - InterfaceType::U64 => { + IType::F64 => { let data = transmute_many::(&data).unwrap(); data.iter() - .map(|v| InterfaceValue::U64(*v)) + .map(|v| IValue::F64(f64::from_bits(*v))) .collect::>() } - InterfaceType::F32 => { - let data = transmute_many::(&data).unwrap(); - data.iter() - .map(|v| InterfaceValue::F32(f32::from_bits(*v))) - .collect::>() - } - InterfaceType::F64 => { - let data = transmute_many::(&data).unwrap(); - data.iter() - .map(|v| InterfaceValue::F64(f64::from_bits(*v))) - .collect::>() - } - InterfaceType::Anyref => unimplemented!(), - InterfaceType::String => { + IType::Anyref => unimplemented!(), + IType::String => { let data = transmute_many::(&data).unwrap(); if data.is_empty() { @@ -134,12 +117,12 @@ where // TODO: check let string = String::from_utf8(string_mem).unwrap(); - result.push(InterfaceValue::String(string)); + result.push(IValue::String(string)); } result } - InterfaceType::Array(ty) => { + IType::Array(ty) => { let data = transmute_many::(&data).unwrap(); if data.is_empty() { @@ -167,12 +150,12 @@ where instruction.clone(), )?; - result.push(InterfaceValue::Array(value)); + result.push(IValue::Array(value)); } result } - InterfaceType::Record(record_type_id) => { + IType::Record(record_type_id) => { let record_type = instance.wit_record_by_id(*record_type_id).ok_or_else(|| { InstructionError::new( instruction.clone(), @@ -205,7 +188,7 @@ where pub(crate) fn array_lift_memory( instruction: Instruction, - value_type: InterfaceType, + value_type: IType, ) -> crate::interpreter::ExecutableInstruction where Export: crate::interpreter::wasm::structures::Export, @@ -253,7 +236,7 @@ where )?; log::trace!("array.lift_memory: pushing {:?} on the stack", array); - runtime.stack.push(InterfaceValue::Array(array)); + runtime.stack.push(IValue::Array(array)); Ok(()) } @@ -263,7 +246,7 @@ where pub(super) fn array_lower_memory_( instance: &mut Instance, instruction: Instruction, - array_values: Vec, + array_values: Vec, ) -> Result<(usize, usize), InstructionError> where Export: crate::interpreter::wasm::structures::Export, @@ -278,19 +261,19 @@ where // here it's known that all interface values have the same type for value in array_values { match value { - InterfaceValue::S8(value) => result.push(value as _), - InterfaceValue::S16(value) => result.push(value as _), - InterfaceValue::S32(value) => result.push(value as _), - InterfaceValue::S64(value) => result.push(value as _), - InterfaceValue::U8(value) => result.push(value as _), - InterfaceValue::U16(value) => result.push(value as _), - InterfaceValue::U32(value) => result.push(value as _), - InterfaceValue::U64(value) => result.push(value as _), - InterfaceValue::I32(value) => result.push(value as _), - InterfaceValue::I64(value) => result.push(value as _), - InterfaceValue::F32(value) => result.push(value as _), - InterfaceValue::F64(value) => result.push(value.to_bits()), - InterfaceValue::String(value) => { + IValue::S8(value) => result.push(value as _), + IValue::S16(value) => result.push(value as _), + IValue::S32(value) => result.push(value as _), + IValue::S64(value) => result.push(value as _), + IValue::U8(value) => result.push(value as _), + IValue::U16(value) => result.push(value as _), + IValue::U32(value) => result.push(value as _), + IValue::U64(value) => result.push(value as _), + IValue::I32(value) => result.push(value as _), + IValue::I64(value) => result.push(value as _), + IValue::F32(value) => result.push(value as _), + IValue::F64(value) => result.push(value.to_bits()), + IValue::String(value) => { let string_pointer = if !value.is_empty() { write_to_instance_mem(instance, instruction.clone(), value.as_bytes())? } else { @@ -301,7 +284,7 @@ where result.push(value.len() as _); } - InterfaceValue::Array(values) => { + IValue::Array(values) => { let (array_offset, array_size) = if !values.is_empty() { array_lower_memory_(instance, instruction.clone(), values)? } else { @@ -312,7 +295,7 @@ where result.push(array_size as _); } - InterfaceValue::Record(values) => { + IValue::Record(values) => { let record_offset = super::record_lower_memory_(instance, instruction.clone(), values)?; result.push(record_offset as _); @@ -328,7 +311,7 @@ where pub(crate) fn array_lower_memory( instruction: Instruction, - value_type: InterfaceType, + value_type: IType, ) -> crate::interpreter::ExecutableInstruction where Export: crate::interpreter::wasm::structures::Export, @@ -351,7 +334,7 @@ where })?; match stack_value { - InterfaceValue::Array(values) => { + IValue::Array(values) => { log::trace!("array.lower_memory: obtained {:?} values on the stack for interface type {:?}", values, value_type); for value in values.iter() { @@ -371,15 +354,15 @@ where offset, size ); - runtime.stack.push(InterfaceValue::I32(offset as _)); - runtime.stack.push(InterfaceValue::I32(size as _)); + runtime.stack.push(IValue::I32(offset as _)); + runtime.stack.push(IValue::I32(size as _)); Ok(()) } _ => Err(InstructionError::new( instruction.clone(), InstructionErrorKind::InvalidValueOnTheStack { - expected_type: InterfaceType::Array(Box::new(value_type.clone())), + expected_type: IType::Array(Box::new(value_type.clone())), received_value: stack_value.clone(), }, )), diff --git a/wasmer-it/src/interpreter/instructions/call_core.rs b/wasmer-it/src/interpreter/instructions/call_core.rs index 1785a7e..4703249 100644 --- a/wasmer-it/src/interpreter/instructions/call_core.rs +++ b/wasmer-it/src/interpreter/instructions/call_core.rs @@ -63,11 +63,11 @@ mod tests { Instruction::CallCore { function_index: 42 }, ], invocation_inputs: [ - InterfaceValue::I32(3), - InterfaceValue::I32(4), + IValue::I32(3), + IValue::I32(4), ], instance: Instance::new(), - stack: [InterfaceValue::I32(12)], + stack: [IValue::I32(12)], ); test_executable_instruction!( @@ -76,8 +76,8 @@ mod tests { Instruction::CallCore { function_index: 42 }, ], invocation_inputs: [ - InterfaceValue::I32(3), - InterfaceValue::I32(4), + IValue::I32(3), + IValue::I32(4), ], instance: Default::default(), error: r#"`call-core 42` the local or import function `42` doesn't exist"#, @@ -91,8 +91,8 @@ mod tests { // ^^ `42` expects 2 values on the stack, only one is present ], invocation_inputs: [ - InterfaceValue::I32(3), - InterfaceValue::I32(4), + IValue::I32(3), + IValue::I32(4), ], instance: Instance::new(), error: r#"`call-core 42` needed to read `2` value(s) from the stack, but it doesn't contain enough data"#, @@ -106,8 +106,8 @@ mod tests { Instruction::CallCore { function_index: 42 }, ], invocation_inputs: [ - InterfaceValue::I32(3), - InterfaceValue::I64(4), + IValue::I32(3), + IValue::I64(4), // ^^^ mismatch with `42` signature ], instance: Instance::new(), @@ -122,8 +122,8 @@ mod tests { Instruction::CallCore { function_index: 42 }, ], invocation_inputs: [ - InterfaceValue::I32(3), - InterfaceValue::I32(4), + IValue::I32(3), + IValue::I32(4), ], instance: Instance { locals_or_imports: { @@ -131,8 +131,8 @@ mod tests { hashmap.insert( 42, LocalImport { - inputs: vec![InterfaceType::I32, InterfaceType::I32], - outputs: vec![InterfaceType::I32], + inputs: vec![IType::I32, IType::I32], + outputs: vec![IType::I32], function: |_| Err(()), // ^^^^^^^ function fails }, @@ -153,8 +153,8 @@ mod tests { Instruction::CallCore { function_index: 42 }, ], invocation_inputs: [ - InterfaceValue::I32(3), - InterfaceValue::I32(4), + IValue::I32(3), + IValue::I32(4), ], instance: Instance { locals_or_imports: { @@ -162,8 +162,8 @@ mod tests { hashmap.insert( 42, LocalImport { - inputs: vec![InterfaceType::I32, InterfaceType::I32], - outputs: vec![InterfaceType::I32], + inputs: vec![IType::I32, IType::I32], + outputs: vec![IType::I32], function: |_| Ok(vec![]), // ^^^^^^^^^^ void }, diff --git a/wasmer-it/src/interpreter/instructions/mod.rs b/wasmer-it/src/interpreter/instructions/mod.rs index 994bfce..aaf5d46 100644 --- a/wasmer-it/src/interpreter/instructions/mod.rs +++ b/wasmer-it/src/interpreter/instructions/mod.rs @@ -8,27 +8,29 @@ mod strings; mod swap2; mod utils; -use crate::interpreter::wasm; -use crate::types::InterfaceType; -use crate::vec1::Vec1; -use crate::{ - errors::{InstructionError, InstructionErrorKind, InstructionResult, WasmValueNativeCastError}, - values::{InterfaceValue, NativeType}, +use crate::errors::{ + InstructionError, InstructionErrorKind, InstructionResult, WasmValueNativeCastError, }; +use crate::interpreter::wasm; +use crate::IType; +use crate::IValue; +use crate::NEVec; pub(crate) use argument_get::argument_get; pub(crate) use arrays::*; pub(crate) use call_core::call_core; pub(crate) use dup::dup; pub(crate) use numbers::*; pub(crate) use records::*; -use std::convert::TryFrom; pub(crate) use strings::*; pub(crate) use swap2::swap2; pub(self) use utils::*; +use fluence_it_types::NativeType; use serde::Deserialize; use serde::Serialize; +use std::convert::TryFrom; + pub(self) const ALLOCATE_FUNC_INDEX: u32 = 0; pub(self) const DEALLOCATE_FUNC_INDEX: u32 = 1; @@ -155,13 +157,13 @@ pub enum Instruction { /// The `array.lift_memory` instruction. ArrayLiftMemory { /// Array value type. - value_type: InterfaceType, + value_type: IType, }, /// The `array.lower_memory` instruction. ArrayLowerMemory { /// Array value type. - value_type: InterfaceType, + value_type: IType, }, /* @@ -198,13 +200,13 @@ pub enum Instruction { } /// Just a short helper to map the error of a cast from an -/// `InterfaceValue` to a native value. +/// `IValue` to a native value. pub(crate) fn to_native<'a, T>( - wit_value: &'a InterfaceValue, + wit_value: &'a IValue, instruction: Instruction, ) -> InstructionResult where - T: NativeType + TryFrom<&'a InterfaceValue, Error = WasmValueNativeCastError>, + T: NativeType + TryFrom<&'a IValue, Error = WasmValueNativeCastError>, { T::try_from(wit_value) .map_err(|error| InstructionError::new(instruction, InstructionErrorKind::ToNative(error))) @@ -220,7 +222,7 @@ pub(crate) fn check_function_signature< >( instance: &'instance Instance, local_import: &LocalImport, - values: &[InterfaceValue], + values: &[IValue], instruction: Instruction, ) -> Result<(), InstructionError> where @@ -249,8 +251,8 @@ pub(crate) fn is_value_compatible_to_type< MemoryView, >( instance: &'instance Instance, - interface_type: &InterfaceType, - interface_value: &InterfaceValue, + interface_type: &IType, + interface_value: &IValue, instruction: Instruction, ) -> Result<(), InstructionError> where @@ -261,27 +263,27 @@ where Instance: wasm::structures::Instance, { match (&interface_type, interface_value) { - (InterfaceType::S8, InterfaceValue::S8(_)) => Ok(()), - (InterfaceType::S16, InterfaceValue::S16(_)) => Ok(()), - (InterfaceType::S32, InterfaceValue::S32(_)) => Ok(()), - (InterfaceType::S64, InterfaceValue::S64(_)) => Ok(()), - (InterfaceType::U8, InterfaceValue::U8(_)) => Ok(()), - (InterfaceType::U16, InterfaceValue::U16(_)) => Ok(()), - (InterfaceType::U32, InterfaceValue::U32(_)) => Ok(()), - (InterfaceType::U64, InterfaceValue::U64(_)) => Ok(()), - (InterfaceType::I32, InterfaceValue::I32(_)) => Ok(()), - (InterfaceType::I64, InterfaceValue::I64(_)) => Ok(()), - (InterfaceType::F32, InterfaceValue::F32(_)) => Ok(()), - (InterfaceType::F64, InterfaceValue::F64(_)) => Ok(()), - (InterfaceType::String, InterfaceValue::String(_)) => Ok(()), - (InterfaceType::Array(ty), InterfaceValue::Array(values)) => { + (IType::S8, IValue::S8(_)) => Ok(()), + (IType::S16, IValue::S16(_)) => Ok(()), + (IType::S32, IValue::S32(_)) => Ok(()), + (IType::S64, IValue::S64(_)) => Ok(()), + (IType::U8, IValue::U8(_)) => Ok(()), + (IType::U16, IValue::U16(_)) => Ok(()), + (IType::U32, IValue::U32(_)) => Ok(()), + (IType::U64, IValue::U64(_)) => Ok(()), + (IType::I32, IValue::I32(_)) => Ok(()), + (IType::I64, IValue::I64(_)) => Ok(()), + (IType::F32, IValue::F32(_)) => Ok(()), + (IType::F64, IValue::F64(_)) => Ok(()), + (IType::String, IValue::String(_)) => Ok(()), + (IType::Array(ty), IValue::Array(values)) => { for value in values { is_value_compatible_to_type(instance, ty, value, instruction.clone())? } Ok(()) } - (InterfaceType::Record(ref record_type_id), InterfaceValue::Record(record_fields)) => { + (IType::Record(ref record_type_id), IValue::Record(record_fields)) => { is_record_fields_compatible_to_type( instance, *record_type_id, @@ -311,7 +313,7 @@ pub(crate) fn is_record_fields_compatible_to_type< >( instance: &'instance Instance, record_type_id: u64, - record_fields: &[InterfaceValue], + record_fields: &[IValue], instruction: Instruction, ) -> Result<(), InstructionError> where @@ -332,9 +334,9 @@ where return Err(InstructionError::new( instruction.clone(), InstructionErrorKind::InvalidValueOnTheStack { - expected_type: InterfaceType::Record(record_type_id), + expected_type: IType::Record(record_type_id), // unwrap is safe here - len's been already checked - received_value: InterfaceValue::Record(Vec1::new(record_fields.to_vec()).unwrap()), + received_value: IValue::Record(NEVec::new(record_fields.to_vec()).unwrap()), }, )); } @@ -359,9 +361,9 @@ pub(crate) mod tests { use std::{cell::Cell, collections::HashMap, convert::TryInto, ops::Deref, rc::Rc}; pub(crate) struct Export { - pub(crate) inputs: Vec, - pub(crate) outputs: Vec, - pub(crate) function: fn(arguments: &[InterfaceValue]) -> Result, ()>, + pub(crate) inputs: Vec, + pub(crate) outputs: Vec, + pub(crate) function: fn(arguments: &[IValue]) -> Result, ()>, } impl wasm::structures::Export for Export { @@ -373,23 +375,23 @@ pub(crate) mod tests { self.outputs.len() } - fn arguments(&self) -> &[InterfaceType] { + fn arguments(&self) -> &[IType] { &self.inputs } - fn outputs(&self) -> &[InterfaceType] { + fn outputs(&self) -> &[IType] { &self.outputs } - fn call(&self, arguments: &[InterfaceValue]) -> Result, ()> { + fn call(&self, arguments: &[IValue]) -> Result, ()> { (self.function)(arguments) } } pub(crate) struct LocalImport { - pub(crate) inputs: Vec, - pub(crate) outputs: Vec, - pub(crate) function: fn(arguments: &[InterfaceValue]) -> Result, ()>, + pub(crate) inputs: Vec, + pub(crate) outputs: Vec, + pub(crate) function: fn(arguments: &[IValue]) -> Result, ()>, } impl wasm::structures::LocalImport for LocalImport { @@ -401,15 +403,15 @@ pub(crate) mod tests { self.outputs.len() } - fn arguments(&self) -> &[InterfaceType] { + fn arguments(&self) -> &[IType] { &self.inputs } - fn outputs(&self) -> &[InterfaceType] { + fn outputs(&self) -> &[IType] { &self.outputs } - fn call(&self, arguments: &[InterfaceValue]) -> Result, ()> { + fn call(&self, arguments: &[IValue]) -> Result, ()> { (self.function)(arguments) } } @@ -462,13 +464,13 @@ pub(crate) mod tests { hashmap.insert( "sum".into(), Export { - inputs: vec![InterfaceType::I32, InterfaceType::I32], - outputs: vec![InterfaceType::I32], - function: |arguments: &[InterfaceValue]| { + inputs: vec![IType::I32, IType::I32], + outputs: vec![IType::I32], + function: |arguments: &[IValue]| { let a: i32 = (&arguments[0]).try_into().unwrap(); let b: i32 = (&arguments[1]).try_into().unwrap(); - Ok(vec![InterfaceValue::I32(a + b)]) + Ok(vec![IValue::I32(a + b)]) }, }, ); @@ -481,13 +483,13 @@ pub(crate) mod tests { hashmap.insert( 42, LocalImport { - inputs: vec![InterfaceType::I32, InterfaceType::I32], - outputs: vec![InterfaceType::I32], - function: |arguments: &[InterfaceValue]| { + inputs: vec![IType::I32, IType::I32], + outputs: vec![IType::I32], + function: |arguments: &[IValue]| { let a: i32 = (&arguments[0]).try_into().unwrap(); let b: i32 = (&arguments[1]).try_into().unwrap(); - Ok(vec![InterfaceValue::I32(a * b)]) + Ok(vec![IValue::I32(a * b)]) }, }, ); @@ -495,12 +497,12 @@ pub(crate) mod tests { hashmap.insert( 43, LocalImport { - inputs: vec![InterfaceType::I32], - outputs: vec![InterfaceType::I32], - function: |arguments: &[InterfaceValue]| { + inputs: vec![IType::I32], + outputs: vec![IType::I32], + function: |arguments: &[IValue]| { let _size: i32 = (&arguments[0]).try_into().unwrap(); - Ok(vec![InterfaceValue::I32(0)]) + Ok(vec![IValue::I32(0)]) }, }, ); @@ -513,27 +515,27 @@ pub(crate) mod tests { fields: vec1![ RecordFieldType { name: String::from("field_0"), - ty: InterfaceType::I32, + ty: IType::I32, }, RecordFieldType { name: String::from("field_1"), - ty: InterfaceType::Record(RecordType { + ty: IType::Record(RecordType { name: String::from("RecordType1"), fields: vec1![ RecordFieldType { name: String::from("field_0"), - ty: InterfaceType::String, + ty: IType::String, }, RecordFieldType { name: String::from("field1"), - ty: InterfaceType::F32 + ty: IType::F32 } ], }), }, RecordFieldType { name: String::from("field_2"), - ty: InterfaceType::I64, + ty: IType::I64, } ], })], diff --git a/wasmer-it/src/interpreter/instructions/numbers.rs b/wasmer-it/src/interpreter/instructions/numbers.rs index 0d3d0f7..a85c109 100644 --- a/wasmer-it/src/interpreter/instructions/numbers.rs +++ b/wasmer-it/src/interpreter/instructions/numbers.rs @@ -1,8 +1,8 @@ +use crate::IType; +use crate::IValue; use crate::{ errors::{InstructionError, InstructionErrorKind}, interpreter::Instruction, - types::InterfaceType, - values::InterfaceValue, }; use std::convert::TryInto; @@ -12,17 +12,17 @@ macro_rules! lowering_lifting { $instruction_function_name(instruction: Instruction) -> _ { move |runtime| -> _ { match runtime.stack.pop1() { - Some(InterfaceValue::$from_variant(value)) => { + Some(IValue::$from_variant(value)) => { runtime .stack .push({ - let converted_value = InterfaceValue::$to_variant(value.try_into().map_err( + let converted_value = IValue::$to_variant(value.try_into().map_err( |_| { InstructionError::new( instruction.clone(), InstructionErrorKind::LoweringLifting { - from: InterfaceType::$from_variant, - to: InterfaceType::$to_variant + from: IType::$from_variant, + to: IType::$to_variant }, ) }, @@ -37,7 +37,7 @@ macro_rules! lowering_lifting { return Err(InstructionError::new( instruction.clone(), InstructionErrorKind::InvalidValueOnTheStack { - expected_type: InterfaceType::$from_variant, + expected_type: IType::$from_variant, received_value: wrong_value, } )) @@ -96,7 +96,7 @@ mod tests { test_executable_instruction!( test_convert_fails = instructions: [Instruction::ArgumentGet { index: 0}, Instruction::S8FromI32], - invocation_inputs: [InterfaceValue::I32(128)], + invocation_inputs: [IValue::I32(128)], instance: Instance::new(), error: "`s8.from_i32` failed to cast `I32` to `S8`" ); @@ -104,7 +104,7 @@ mod tests { test_executable_instruction!( test_type_mismatch = instructions: [Instruction::ArgumentGet { index: 0}, Instruction::S8FromI32], - invocation_inputs: [InterfaceValue::I64(42)], + invocation_inputs: [IValue::I64(42)], instance: Instance::new(), error: "`s8.from_i32` read a value of type `I64` from the stack, but the type `I32` was expected" ); @@ -112,7 +112,7 @@ mod tests { test_executable_instruction!( test_no_value_on_the_stack = instructions: [Instruction::S8FromI32], - invocation_inputs: [InterfaceValue::I32(42)], + invocation_inputs: [IValue::I32(42)], instance: Instance::new(), error: "`s8.from_i32` needed to read `1` value(s) from the stack, but it doesn't contain enough data" ); @@ -120,256 +120,256 @@ mod tests { test_executable_instruction!( test_s8_from_i32 = instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::S8FromI32], - invocation_inputs: [InterfaceValue::I32(42)], + invocation_inputs: [IValue::I32(42)], instance: Instance::new(), - stack: [InterfaceValue::S8(42)], + stack: [IValue::S8(42)], ); test_executable_instruction!( test_s8_from_i64 = instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::S8FromI64], - invocation_inputs: [InterfaceValue::I64(42)], + invocation_inputs: [IValue::I64(42)], instance: Instance::new(), - stack: [InterfaceValue::S8(42)], + stack: [IValue::S8(42)], ); test_executable_instruction!( test_s16_from_i32 = instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::S16FromI32], - invocation_inputs: [InterfaceValue::I32(42)], + invocation_inputs: [IValue::I32(42)], instance: Instance::new(), - stack: [InterfaceValue::S16(42)], + stack: [IValue::S16(42)], ); test_executable_instruction!( test_s16_from_i64 = instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::S16FromI64], - invocation_inputs: [InterfaceValue::I64(42)], + invocation_inputs: [IValue::I64(42)], instance: Instance::new(), - stack: [InterfaceValue::S16(42)], + stack: [IValue::S16(42)], ); test_executable_instruction!( test_s32_from_i32 = instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::S32FromI32], - invocation_inputs: [InterfaceValue::I32(42)], + invocation_inputs: [IValue::I32(42)], instance: Instance::new(), - stack: [InterfaceValue::S32(42)], + stack: [IValue::S32(42)], ); test_executable_instruction!( test_s32_from_i64 = instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::S32FromI64], - invocation_inputs: [InterfaceValue::I64(42)], + invocation_inputs: [IValue::I64(42)], instance: Instance::new(), - stack: [InterfaceValue::S32(42)], + stack: [IValue::S32(42)], ); test_executable_instruction!( test_s64_from_i32 = instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::S64FromI32], - invocation_inputs: [InterfaceValue::I32(42)], + invocation_inputs: [IValue::I32(42)], instance: Instance::new(), - stack: [InterfaceValue::S64(42)], + stack: [IValue::S64(42)], ); test_executable_instruction!( test_s64_from_i64 = instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::S64FromI64], - invocation_inputs: [InterfaceValue::I64(42)], + invocation_inputs: [IValue::I64(42)], instance: Instance::new(), - stack: [InterfaceValue::S64(42)], + stack: [IValue::S64(42)], ); test_executable_instruction!( test_i32_from_s8 = instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I32FromS8], - invocation_inputs: [InterfaceValue::S8(42)], + invocation_inputs: [IValue::S8(42)], instance: Instance::new(), - stack: [InterfaceValue::I32(42)], + stack: [IValue::I32(42)], ); test_executable_instruction!( test_i32_from_s16 = instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I32FromS16], - invocation_inputs: [InterfaceValue::S16(42)], + invocation_inputs: [IValue::S16(42)], instance: Instance::new(), - stack: [InterfaceValue::I32(42)], + stack: [IValue::I32(42)], ); test_executable_instruction!( test_i32_from_s32 = instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I32FromS32], - invocation_inputs: [InterfaceValue::S32(42)], + invocation_inputs: [IValue::S32(42)], instance: Instance::new(), - stack: [InterfaceValue::I32(42)], + stack: [IValue::I32(42)], ); test_executable_instruction!( test_i32_from_s64 = instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I32FromS64], - invocation_inputs: [InterfaceValue::S64(42)], + invocation_inputs: [IValue::S64(42)], instance: Instance::new(), - stack: [InterfaceValue::I32(42)], + stack: [IValue::I32(42)], ); test_executable_instruction!( test_i64_from_s8 = instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I64FromS8], - invocation_inputs: [InterfaceValue::S8(42)], + invocation_inputs: [IValue::S8(42)], instance: Instance::new(), - stack: [InterfaceValue::I64(42)], + stack: [IValue::I64(42)], ); test_executable_instruction!( test_i64_from_s16 = instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I64FromS16], - invocation_inputs: [InterfaceValue::S16(42)], + invocation_inputs: [IValue::S16(42)], instance: Instance::new(), - stack: [InterfaceValue::I64(42)], + stack: [IValue::I64(42)], ); test_executable_instruction!( test_i64_from_s32 = instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I64FromS32], - invocation_inputs: [InterfaceValue::S32(42)], + invocation_inputs: [IValue::S32(42)], instance: Instance::new(), - stack: [InterfaceValue::I64(42)], + stack: [IValue::I64(42)], ); test_executable_instruction!( test_i64_from_s64 = instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I64FromS64], - invocation_inputs: [InterfaceValue::S64(42)], + invocation_inputs: [IValue::S64(42)], instance: Instance::new(), - stack: [InterfaceValue::I64(42)], + stack: [IValue::I64(42)], ); test_executable_instruction!( test_u8_from_i32 = instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::U8FromI32], - invocation_inputs: [InterfaceValue::I32(42)], + invocation_inputs: [IValue::I32(42)], instance: Instance::new(), - stack: [InterfaceValue::U8(42)], + stack: [IValue::U8(42)], ); test_executable_instruction!( test_u8_from_i64 = instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::U8FromI64], - invocation_inputs: [InterfaceValue::I64(42)], + invocation_inputs: [IValue::I64(42)], instance: Instance::new(), - stack: [InterfaceValue::U8(42)], + stack: [IValue::U8(42)], ); test_executable_instruction!( test_u16_from_i32 = instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::U16FromI32], - invocation_inputs: [InterfaceValue::I32(42)], + invocation_inputs: [IValue::I32(42)], instance: Instance::new(), - stack: [InterfaceValue::U16(42)], + stack: [IValue::U16(42)], ); test_executable_instruction!( test_u16_from_i64 = instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::U16FromI64], - invocation_inputs: [InterfaceValue::I64(42)], + invocation_inputs: [IValue::I64(42)], instance: Instance::new(), - stack: [InterfaceValue::U16(42)], + stack: [IValue::U16(42)], ); test_executable_instruction!( test_u32_from_i32 = instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::U32FromI32], - invocation_inputs: [InterfaceValue::I32(42)], + invocation_inputs: [IValue::I32(42)], instance: Instance::new(), - stack: [InterfaceValue::U32(42)], + stack: [IValue::U32(42)], ); test_executable_instruction!( test_u32_from_i64 = instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::U32FromI64], - invocation_inputs: [InterfaceValue::I64(42)], + invocation_inputs: [IValue::I64(42)], instance: Instance::new(), - stack: [InterfaceValue::U32(42)], + stack: [IValue::U32(42)], ); test_executable_instruction!( test_u64_from_i32 = instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::U64FromI32], - invocation_inputs: [InterfaceValue::I32(42)], + invocation_inputs: [IValue::I32(42)], instance: Instance::new(), - stack: [InterfaceValue::U64(42)], + stack: [IValue::U64(42)], ); test_executable_instruction!( test_u64_from_i64 = instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::U64FromI64], - invocation_inputs: [InterfaceValue::I64(42)], + invocation_inputs: [IValue::I64(42)], instance: Instance::new(), - stack: [InterfaceValue::U64(42)], + stack: [IValue::U64(42)], ); test_executable_instruction!( test_i32_from_u8 = instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I32FromU8], - invocation_inputs: [InterfaceValue::U8(42)], + invocation_inputs: [IValue::U8(42)], instance: Instance::new(), - stack: [InterfaceValue::I32(42)], + stack: [IValue::I32(42)], ); test_executable_instruction!( test_i32_from_u16 = instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I32FromU16], - invocation_inputs: [InterfaceValue::U16(42)], + invocation_inputs: [IValue::U16(42)], instance: Instance::new(), - stack: [InterfaceValue::I32(42)], + stack: [IValue::I32(42)], ); test_executable_instruction!( test_i32_from_u32 = instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I32FromU32], - invocation_inputs: [InterfaceValue::U32(42)], + invocation_inputs: [IValue::U32(42)], instance: Instance::new(), - stack: [InterfaceValue::I32(42)], + stack: [IValue::I32(42)], ); test_executable_instruction!( test_i32_from_u64 = instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I32FromU64], - invocation_inputs: [InterfaceValue::U64(42)], + invocation_inputs: [IValue::U64(42)], instance: Instance::new(), - stack: [InterfaceValue::I32(42)], + stack: [IValue::I32(42)], ); test_executable_instruction!( test_i64_from_u8 = instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I64FromU8], - invocation_inputs: [InterfaceValue::U8(42)], + invocation_inputs: [IValue::U8(42)], instance: Instance::new(), - stack: [InterfaceValue::I64(42)], + stack: [IValue::I64(42)], ); test_executable_instruction!( test_i64_from_u16 = instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I64FromU16], - invocation_inputs: [InterfaceValue::U16(42)], + invocation_inputs: [IValue::U16(42)], instance: Instance::new(), - stack: [InterfaceValue::I64(42)], + stack: [IValue::I64(42)], ); test_executable_instruction!( test_i64_from_u32 = instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I64FromU32], - invocation_inputs: [InterfaceValue::U32(42)], + invocation_inputs: [IValue::U32(42)], instance: Instance::new(), - stack: [InterfaceValue::I64(42)], + stack: [IValue::I64(42)], ); test_executable_instruction!( test_i64_from_u64 = instructions: [Instruction::ArgumentGet { index: 0 }, Instruction::I64FromU64], - invocation_inputs: [InterfaceValue::U64(42)], + invocation_inputs: [IValue::U64(42)], instance: Instance::new(), - stack: [InterfaceValue::I64(42)], + stack: [IValue::I64(42)], ); } diff --git a/wasmer-it/src/interpreter/instructions/records.rs b/wasmer-it/src/interpreter/instructions/records.rs index 4092d35..99f3b38 100644 --- a/wasmer-it/src/interpreter/instructions/records.rs +++ b/wasmer-it/src/interpreter/instructions/records.rs @@ -2,18 +2,19 @@ use super::read_from_instance_mem; use super::write_to_instance_mem; use crate::interpreter::instructions::{is_record_fields_compatible_to_type, to_native}; +use crate::IRecordType; +use crate::IType; +use crate::IValue; +use crate::NEVec; use crate::{ errors::{InstructionError, InstructionErrorKind}, interpreter::Instruction, - types::{InterfaceType, RecordType}, - values::InterfaceValue, - vec1::Vec1, }; use std::convert::TryInto; /* -/// Build an `InterfaceValue::Record` based on values on the stack. +/// Build an `IValue::Record` based on values on the stack. /// /// To fill a record, every field `field_1` to `field_n` must get its /// value from the stack with `value_1` to `value_n`. It is not @@ -27,14 +28,14 @@ use std::convert::TryInto; /// is possible to access to last positions). So a `VecDeque` type is /// used: it is a double-ended queue. fn record_lift_( - stack: &mut Stack, + stack: &mut Stack, record_type: &RecordType, -) -> Result { +) -> Result { let length = record_type.fields.len(); let mut values = VecDeque::with_capacity(length); for field in record_type.fields.iter().rev() { match field { - InterfaceType::Record(record_type) => { + IType::Record(record_type) => { values.push_front(record_lift_(stack, &record_type)?) } ty => { @@ -50,8 +51,8 @@ fn record_lift_( } } } - Ok(InterfaceValue::Record( - Vec1::new(values.into_iter().collect()) + Ok(IValue::Record( + NEVec::new(values.into_iter().collect()) .expect("Record must have at least one field, zero given"), )) } @@ -101,10 +102,10 @@ where pub(super) fn record_lift_memory_<'instance, Instance, Export, LocalImport, Memory, MemoryView>( instance: &'instance Instance, - record_type: &RecordType, + record_type: &IRecordType, offset: usize, instruction: Instruction, -) -> Result +) -> Result where Export: crate::interpreter::wasm::structures::Export, LocalImport: crate::interpreter::wasm::structures::LocalImport, @@ -113,12 +114,12 @@ where Instance: crate::interpreter::wasm::structures::Instance + 'instance, { - fn record_size(record_type: &RecordType) -> usize { + fn record_size(record_type: &IRecordType) -> usize { let mut record_size = 0; for field_type in record_type.fields.iter() { let params_count = match field_type.ty { - InterfaceType::String | InterfaceType::Array(_) => 2, + IType::String | IType::Array(_) => 2, _ => 1, }; @@ -140,42 +141,42 @@ where for field in (*record_type.fields).iter() { let value = data[field_id]; match &field.ty { - InterfaceType::S8 => { - values.push(InterfaceValue::S8(value as _)); + IType::S8 => { + values.push(IValue::S8(value as _)); } - InterfaceType::S16 => { - values.push(InterfaceValue::S16(value as _)); + IType::S16 => { + values.push(IValue::S16(value as _)); } - InterfaceType::S32 => { - values.push(InterfaceValue::S32(value as _)); + IType::S32 => { + values.push(IValue::S32(value as _)); } - InterfaceType::S64 => { - values.push(InterfaceValue::S64(value as _)); + IType::S64 => { + values.push(IValue::S64(value as _)); } - InterfaceType::I32 => { - values.push(InterfaceValue::I32(value as _)); + IType::I32 => { + values.push(IValue::I32(value as _)); } - InterfaceType::I64 => { - values.push(InterfaceValue::I64(value as _)); + IType::I64 => { + values.push(IValue::I64(value as _)); } - InterfaceType::U8 => { - values.push(InterfaceValue::U8(value as _)); + IType::U8 => { + values.push(IValue::U8(value as _)); } - InterfaceType::U16 => { - values.push(InterfaceValue::U16(value as _)); + IType::U16 => { + values.push(IValue::U16(value as _)); } - InterfaceType::U32 => { - values.push(InterfaceValue::U32(value as _)); + IType::U32 => { + values.push(IValue::U32(value as _)); } - InterfaceType::U64 => { - values.push(InterfaceValue::U64(value as _)); + IType::U64 => { + values.push(IValue::U64(value as _)); } - InterfaceType::F32 => { - values.push(InterfaceValue::F32(value as _)); + IType::F32 => { + values.push(IValue::F32(value as _)); } - InterfaceType::F64 => values.push(InterfaceValue::F64(f64::from_bits(value))), - InterfaceType::Anyref => {} - InterfaceType::String => { + IType::F64 => values.push(IValue::F64(f64::from_bits(value))), + IType::Anyref => {} + IType::String => { let string_offset = value; field_id += 1; let string_size = data[field_id]; @@ -190,12 +191,12 @@ where // TODO: check let string = String::from_utf8(string_mem).unwrap(); - values.push(InterfaceValue::String(string)); + values.push(IValue::String(string)); } else { - values.push(InterfaceValue::String(String::new())); + values.push(IValue::String(String::new())); } } - InterfaceType::Array(ty) => { + IType::Array(ty) => { let array_offset = value; field_id += 1; let array_size = data[field_id]; @@ -208,12 +209,12 @@ where array_size as _, instruction.clone(), )?; - values.push(InterfaceValue::Array(array)); + values.push(IValue::Array(array)); } else { - values.push(InterfaceValue::Array(vec![])); + values.push(IValue::Array(vec![])); } } - InterfaceType::Record(record_type_id) => { + IType::Record(record_type_id) => { let offset = value; let record_type = instance.wit_record_by_id(*record_type_id).ok_or_else(|| { @@ -238,8 +239,8 @@ where super::deallocate(instance, instruction, offset as _, size as _)?; - Ok(InterfaceValue::Record( - Vec1::new(values.into_iter().collect()) + Ok(IValue::Record( + NEVec::new(values.into_iter().collect()) .expect("Record must have at least one field, zero given"), )) } @@ -301,7 +302,7 @@ where pub(super) fn record_lower_memory_( instance: &mut Instance, instruction: Instruction, - values: Vec1, + values: NEVec, ) -> Result where Export: crate::interpreter::wasm::structures::Export, @@ -315,19 +316,19 @@ where for value in values.into_vec() { match value { - InterfaceValue::S8(value) => result.push(value as _), - InterfaceValue::S16(value) => result.push(value as _), - InterfaceValue::S32(value) => result.push(value as _), - InterfaceValue::S64(value) => result.push(value as _), - InterfaceValue::U8(value) => result.push(value as _), - InterfaceValue::U16(value) => result.push(value as _), - InterfaceValue::U32(value) => result.push(value as _), - InterfaceValue::U64(value) => result.push(value as _), - InterfaceValue::I32(value) => result.push(value as _), - InterfaceValue::I64(value) => result.push(value as _), - InterfaceValue::F32(value) => result.push(value as _), - InterfaceValue::F64(value) => result.push(value.to_bits()), - InterfaceValue::String(value) => { + IValue::S8(value) => result.push(value as _), + IValue::S16(value) => result.push(value as _), + IValue::S32(value) => result.push(value as _), + IValue::S64(value) => result.push(value as _), + IValue::U8(value) => result.push(value as _), + IValue::U16(value) => result.push(value as _), + IValue::U32(value) => result.push(value as _), + IValue::U64(value) => result.push(value as _), + IValue::I32(value) => result.push(value as _), + IValue::I64(value) => result.push(value as _), + IValue::F32(value) => result.push(value as _), + IValue::F64(value) => result.push(value.to_bits()), + IValue::String(value) => { let string_pointer = if !value.is_empty() { write_to_instance_mem(instance, instruction.clone(), value.as_bytes())? } else { @@ -338,7 +339,7 @@ where result.push(value.len() as _); } - InterfaceValue::Array(values) => { + IValue::Array(values) => { let (offset, size) = if !values.is_empty() { super::array_lower_memory_(instance, instruction.clone(), values)? } else { @@ -349,7 +350,7 @@ where result.push(size as _); } - InterfaceValue::Record(values) => { + IValue::Record(values) => { let record_ptr = record_lower_memory_(instance, instruction.clone(), values)?; result.push(record_ptr as _); @@ -382,7 +383,7 @@ where let instance = &mut runtime.wasm_instance; match runtime.stack.pop1() { - Some(InterfaceValue::Record(record_fields)) => { + Some(IValue::Record(record_fields)) => { is_record_fields_compatible_to_type( &**instance, record_type_id, @@ -396,14 +397,14 @@ where record_lower_memory_(*instance, instruction.clone(), record_fields)?; log::debug!("record.lower_memory: pushing {} on the stack", offset); - runtime.stack.push(InterfaceValue::I32(offset)); + runtime.stack.push(IValue::I32(offset)); Ok(()) } Some(value) => Err(InstructionError::new( instruction.clone(), InstructionErrorKind::InvalidValueOnTheStack { - expected_type: InterfaceType::Record(record_type_id), + expected_type: IType::Record(record_type_id), received_value: value, }, )), @@ -452,7 +453,7 @@ where } }; match runtime.stack.pop1() { - Some(InterfaceValue::Record(record_values)) + Some(IValue::Record(record_values)) if record_type == &(&*record_values).into() => { let values = FlattenIValueIterator::new(&record_values); @@ -464,7 +465,7 @@ where Some(value) => Err(InstructionError::new( instruction.clone(), InstructionErrorKind::InvalidValueOnTheStack { - expected_type: InterfaceType::Record(record_type.clone()), + expected_type: IType::Record(record_type.clone()), received_type: (&value).into(), }, )), diff --git a/wasmer-it/src/interpreter/instructions/strings.rs b/wasmer-it/src/interpreter/instructions/strings.rs index d6ede4d..d8ffed6 100644 --- a/wasmer-it/src/interpreter/instructions/strings.rs +++ b/wasmer-it/src/interpreter/instructions/strings.rs @@ -1,9 +1,9 @@ use super::to_native; +use crate::IType; +use crate::IValue; use crate::{ errors::{InstructionError, InstructionErrorKind}, interpreter::Instruction, - types::InterfaceType, - values::InterfaceValue, }; use std::{cell::Cell, convert::TryInto}; @@ -39,7 +39,7 @@ executable_instruction!( let memory_view = memory.view(); if length == 0 { - runtime.stack.push(InterfaceValue::String("".into())); + runtime.stack.push(IValue::String("".into())); return Ok(()) } @@ -63,7 +63,7 @@ executable_instruction!( .map_err(|error| InstructionError::new(instruction.clone(), InstructionErrorKind::String(error)))?; log::debug!("string.lift_memory: pushing {:?} on the stack", string); - runtime.stack.push(InterfaceValue::String(string)); + runtime.stack.push(IValue::String(string)); Ok(()) } @@ -110,8 +110,8 @@ executable_instruction!( } log::debug!("string.lower_memory: pushing {}, {} on the stack", string_pointer, string_length); - runtime.stack.push(InterfaceValue::I32(string_pointer as i32)); - runtime.stack.push(InterfaceValue::I32(string_length)); + runtime.stack.push(IValue::I32(string_pointer as i32)); + runtime.stack.push(IValue::I32(string_length)); Ok(()) } @@ -122,11 +122,11 @@ executable_instruction!( string_size(instruction: Instruction) -> _ { move |runtime| -> _ { match runtime.stack.pop1() { - Some(InterfaceValue::String(string)) => { + Some(IValue::String(string)) => { let length = string.len() as i32; log::debug!("string.size: pushing {} on the stack", length); - runtime.stack.push(InterfaceValue::I32(length)); + runtime.stack.push(IValue::I32(length)); Ok(()) }, @@ -134,7 +134,7 @@ executable_instruction!( Some(value) => Err(InstructionError::new( instruction.clone(), InstructionErrorKind::InvalidValueOnTheStack { - expected_type: InterfaceType::String, + expected_type: IType::String, received_value: (&value).clone(), }, )), @@ -158,16 +158,16 @@ mod tests { Instruction::StringLiftMemory, ], invocation_inputs: [ - InterfaceValue::I32(0), + IValue::I32(0), // ^^^^^^ pointer - InterfaceValue::I32(13), + IValue::I32(13), // ^^^^^^^ length ], instance: Instance { memory: Memory::new("Hello, World!".as_bytes().iter().map(|u| Cell::new(*u)).collect()), ..Default::default() }, - stack: [InterfaceValue::String("Hello, World!".into())], + stack: [IValue::String("Hello, World!".into())], ); test_executable_instruction!( @@ -178,14 +178,14 @@ mod tests { Instruction::StringLiftMemory, ], invocation_inputs: [ - InterfaceValue::I32(0), - InterfaceValue::I32(0), + IValue::I32(0), + IValue::I32(0), ], instance: Instance { memory: Memory::new(vec![]), ..Default::default() }, - stack: [InterfaceValue::String("".into())], + stack: [IValue::String("".into())], ); test_executable_instruction!( @@ -196,8 +196,8 @@ mod tests { Instruction::StringLiftMemory, ], invocation_inputs: [ - InterfaceValue::I32(-42), - InterfaceValue::I32(13), + IValue::I32(-42), + IValue::I32(13), ], instance: Instance { memory: Memory::new("Hello!".as_bytes().iter().map(|u| Cell::new(*u)).collect()), @@ -214,8 +214,8 @@ mod tests { Instruction::StringLiftMemory, ], invocation_inputs: [ - InterfaceValue::I32(0), - InterfaceValue::I32(-1), + IValue::I32(0), + IValue::I32(-1), ], instance: Instance { memory: Memory::new("Hello!".as_bytes().iter().map(|u| Cell::new(*u)).collect()), @@ -232,9 +232,9 @@ mod tests { Instruction::StringLiftMemory, ], invocation_inputs: [ - InterfaceValue::I32(0), + IValue::I32(0), // ^^^^^^ pointer - InterfaceValue::I32(13), + IValue::I32(13), // ^^^^^^^ length is too long ], instance: Instance { @@ -252,9 +252,9 @@ mod tests { Instruction::StringLiftMemory, ], invocation_inputs: [ - InterfaceValue::I32(0), + IValue::I32(0), // ^^^^^^ pointer - InterfaceValue::I32(4), + IValue::I32(4), // ^^^^^^ length is too long ], instance: Instance { @@ -272,8 +272,8 @@ mod tests { // ^^^^^^^^^^^^^^^^ `string.lift_memory` expects 2 values on the stack, only one is present. ], invocation_inputs: [ - InterfaceValue::I32(0), - InterfaceValue::I32(13), + IValue::I32(0), + IValue::I32(13), ], instance: Instance::new(), error: r#"`string.lift_memory` needed to read `2` value(s) from the stack, but it doesn't contain enough data"#, @@ -289,12 +289,12 @@ mod tests { Instruction::StringLowerMemory, ], - invocation_inputs: [InterfaceValue::String("Hello, World!".into())], + invocation_inputs: [IValue::String("Hello, World!".into())], instance: Instance::new(), stack: [ - InterfaceValue::I32(0), + IValue::I32(0), // ^^^^^^ pointer - InterfaceValue::I32(13), + IValue::I32(13), // ^^^^^^^ length ] ); @@ -309,9 +309,9 @@ mod tests { Instruction::StringLowerMemory, Instruction::StringLiftMemory, ], - invocation_inputs: [InterfaceValue::String("Hello, World!".into())], + invocation_inputs: [IValue::String("Hello, World!".into())], instance: Instance::new(), - stack: [InterfaceValue::String("Hello, World!".into())], + stack: [IValue::String("Hello, World!".into())], ); test_executable_instruction!( @@ -330,9 +330,9 @@ mod tests { Instruction::ArgumentGet { index: 0 }, Instruction::StringSize, ], - invocation_inputs: [InterfaceValue::String("Hello, World!".into())], + invocation_inputs: [IValue::String("Hello, World!".into())], instance: Instance::new(), - stack: [InterfaceValue::I32(13)], + stack: [IValue::I32(13)], ); test_executable_instruction!( @@ -351,7 +351,7 @@ mod tests { Instruction::ArgumentGet { index: 0 }, Instruction::StringSize, ], - invocation_inputs: [InterfaceValue::I32(42)], + invocation_inputs: [IValue::I32(42)], instance: Instance::new(), error: r#"`string.size` read a value of type `I32` from the stack, but the type `String` was expected"#, ); diff --git a/wasmer-it/src/interpreter/instructions/utils.rs b/wasmer-it/src/interpreter/instructions/utils.rs index ac099ae..0e7fd18 100644 --- a/wasmer-it/src/interpreter/instructions/utils.rs +++ b/wasmer-it/src/interpreter/instructions/utils.rs @@ -4,11 +4,11 @@ use crate::interpreter::wasm; use crate::interpreter::wasm::structures::{FunctionIndex, TypedIndex}; use crate::interpreter::instructions::to_native; +use crate::IType; +use crate::IValue; use crate::{ errors::{InstructionError, InstructionErrorKind}, interpreter::Instruction, - types::InterfaceType, - values::InterfaceValue, }; pub(super) fn read_from_instance_mem<'instance, Instance, Export, LocalImport, Memory, MemoryView>( @@ -115,14 +115,14 @@ where instance, ALLOCATE_FUNC_INDEX, instruction.clone(), - vec![InterfaceValue::I32(size as _)], + vec![IValue::I32(size as _)], )?; if values.len() != 1 { return Err(InstructionError::new( instruction, InstructionErrorKind::LocalOrImportSignatureMismatch { function_index: ALLOCATE_FUNC_INDEX, - expected: (vec![InterfaceType::I32], vec![]), + expected: (vec![IType::I32], vec![]), received: (vec![], vec![]), }, )); @@ -147,7 +147,7 @@ where instance, DEALLOCATE_FUNC_INDEX, instruction, - vec![InterfaceValue::I32(mem_ptr), InterfaceValue::I32(size)], + vec![IValue::I32(mem_ptr), IValue::I32(size)], )?; Ok(()) @@ -157,8 +157,8 @@ fn call_core<'instance, Instance, Export, LocalImport, Memory, MemoryView>( instance: &'instance Instance, function_index: u32, instruction: Instruction, - inputs: Vec, -) -> Result, InstructionError> + inputs: Vec, +) -> Result, InstructionError> where Export: wasm::structures::Export + 'instance, LocalImport: wasm::structures::LocalImport + 'instance, diff --git a/wasmer-it/src/interpreter/mod.rs b/wasmer-it/src/interpreter/mod.rs index 37a106e..9c023aa 100644 --- a/wasmer-it/src/interpreter/mod.rs +++ b/wasmer-it/src/interpreter/mod.rs @@ -4,10 +4,8 @@ mod instructions; pub mod stack; pub mod wasm; -use crate::{ - errors::{InstructionResult, InterpreterResult}, - values::InterfaceValue, -}; +use crate::errors::{InstructionResult, InterpreterResult}; +use crate::IValue; pub use instructions::Instruction; use stack::Stack; use std::{convert::TryFrom, marker::PhantomData}; @@ -24,10 +22,10 @@ where { /// The invocation inputs are all the arguments received by an /// adapter. - invocation_inputs: &'invocation [InterfaceValue], + invocation_inputs: &'invocation [IValue], /// Each runtime (so adapter) has its own stack instance. - stack: Stack, + stack: Stack, /// The WebAssembly module instance. It is used by adapter's /// instructions. @@ -68,8 +66,8 @@ pub(crate) type ExecutableInstruction where @@ -158,9 +156,9 @@ where /// returns the stack. pub fn run( &self, - invocation_inputs: &[InterfaceValue], + invocation_inputs: &[IValue], wasm_instance: &mut Instance, - ) -> InterpreterResult> { + ) -> InterpreterResult> { let mut runtime = Runtime { invocation_inputs, stack: Stack::new(), diff --git a/wasmer-it/src/interpreter/wasm/structures.rs b/wasmer-it/src/interpreter/wasm/structures.rs index cb7c92e..4666a75 100644 --- a/wasmer-it/src/interpreter/wasm/structures.rs +++ b/wasmer-it/src/interpreter/wasm/structures.rs @@ -1,8 +1,9 @@ #![allow(missing_docs)] use crate::ast::FunctionArg; -use crate::types::RecordType; -use crate::{types::InterfaceType, values::InterfaceValue}; +use crate::IRecordType; +use crate::IType; +use crate::IValue; use std::rc::Rc; use std::{cell::Cell, ops::Deref}; @@ -47,8 +48,8 @@ pub trait Export { fn inputs_cardinality(&self) -> usize; fn outputs_cardinality(&self) -> usize; fn arguments(&self) -> &[FunctionArg]; - fn outputs(&self) -> &[InterfaceType]; - fn call(&self, arguments: &[InterfaceValue]) -> Result, ()>; + fn outputs(&self) -> &[IType]; + fn call(&self, arguments: &[IValue]) -> Result, ()>; } pub trait LocalImport { @@ -56,8 +57,8 @@ pub trait LocalImport { fn inputs_cardinality(&self) -> usize; fn outputs_cardinality(&self) -> usize; fn arguments(&self) -> &[FunctionArg]; - fn outputs(&self) -> &[InterfaceType]; - fn call(&self, arguments: &[InterfaceValue]) -> Result, ()>; + fn outputs(&self) -> &[IType]; + fn call(&self, arguments: &[IValue]) -> Result, ()>; } pub trait MemoryView: Deref]> {} @@ -79,7 +80,7 @@ where fn export(&self, export_name: &str) -> Option<&E>; fn local_or_import(&self, index: I) -> Option<&LI>; fn memory(&self, index: usize) -> Option<&M>; - fn wit_record_by_id(&self, index: u64) -> Option<&Rc>; + fn wit_record_by_id(&self, index: u64) -> Option<&Rc>; } impl Export for () { @@ -99,11 +100,11 @@ impl Export for () { &[] } - fn outputs(&self) -> &[InterfaceType] { + fn outputs(&self) -> &[IType] { &[] } - fn call(&self, _arguments: &[InterfaceValue]) -> Result, ()> { + fn call(&self, _arguments: &[IValue]) -> Result, ()> { Err(()) } } @@ -125,11 +126,11 @@ impl LocalImport for () { &[] } - fn outputs(&self) -> &[InterfaceType] { + fn outputs(&self) -> &[IType] { &[] } - fn call(&self, _arguments: &[InterfaceValue]) -> Result, ()> { + fn call(&self, _arguments: &[IValue]) -> Result, ()> { Err(()) } } @@ -171,7 +172,7 @@ where None } - fn wit_record_by_id(&self, _index: u64) -> Option<&Rc> { + fn wit_record_by_id(&self, _index: u64) -> Option<&Rc> { None } } diff --git a/wasmer-it/src/lib.rs b/wasmer-it/src/lib.rs index 783f940..21eb67a 100644 --- a/wasmer-it/src/lib.rs +++ b/wasmer-it/src/lib.rs @@ -64,13 +64,14 @@ pub mod interpreter; mod serde; mod values; -pub use fluence_it_types::vec1::Vec1; +pub use fluence_it_types::ne_vec::NEVec; pub use fluence_it_types::IRecordFieldType; pub use fluence_it_types::IRecordType; pub use fluence_it_types::IType; pub use fluence_it_types::IValue; -pub(crate) struct ITypeImpl(pub IType); -pub(crate) struct RecordTypeImpl(pub IRecordType); -pub(crate) struct RecordFieldTypeImpl(pub IRecordFieldType); -pub(crate) struct IValueImpl(pub IValue); +#[cfg(feature = "serde")] +pub use crate::serde::de::from_interface_values; + +#[cfg(feature = "serde")] +pub use crate::serde::ser::to_interface_value; diff --git a/wasmer-it/src/macros.rs b/wasmer-it/src/macros.rs index 08f57c9..baf976e 100644 --- a/wasmer-it/src/macros.rs +++ b/wasmer-it/src/macros.rs @@ -14,13 +14,13 @@ macro_rules! vec1 { ($item:expr; $length:expr) => { { - crate::vec1::Vec1::new(vec![$item; $length]).unwrap() + crate::vec1::NEVec::new(vec![$item; $length]).unwrap() } }; ($($item:expr),+ $(,)?) => { { - crate::vec1::Vec1::new(vec![$($item),*]).unwrap() + crate::vec1::NEVec::new(vec![$($item),*]).unwrap() } }; } @@ -104,8 +104,8 @@ macro_rules! test_executable_instruction { stack::Stackable, Instruction, Interpreter, }, - types::InterfaceType, - values::InterfaceValue, + types::IType, + values::IValue, }; use std::{cell::Cell, collections::HashMap, convert::TryInto}; @@ -146,8 +146,8 @@ macro_rules! test_executable_instruction { stack::Stackable, Instruction, Interpreter, }, - types::InterfaceType, - values::InterfaceValue, + types::IType, + values::IValue, }; use std::{cell::Cell, collections::HashMap, convert::TryInto}; diff --git a/wasmer-it/src/serde/de.rs b/wasmer-it/src/serde/de.rs index b489f07..2729615 100644 --- a/wasmer-it/src/serde/de.rs +++ b/wasmer-it/src/serde/de.rs @@ -33,9 +33,9 @@ use std::{ /// y: f32, /// }; /// -/// let values = vec![IValue::Record(Vec1::new(vec![ +/// let values = vec![IValue::Record(NEVec::new(vec![ /// IValue::String("abc".to_string()), -/// IValue::Record(Vec1::new(vec![IValue::I32(1), IValue::I64(2)]).unwrap()), +/// IValue::Record(NEVec::new(vec![IValue::I32(1), IValue::I64(2)]).unwrap()), /// IValue::F32(3.), /// ]).unwrap())]; /// let t = from_interface_values::(&values).unwrap(); @@ -62,14 +62,14 @@ where } } -/// The deserializer. The iterator iterates over `InterfaceValue`s, +/// The deserializer. The iterator iterates over `IValue`s, /// all flatten, see `FlattenIValueIterator`. struct Deserializer<'de> { iterator: Peekable>, } impl<'de> Deserializer<'de> { - pub fn new(input: &'de [InterfaceValue]) -> Deserializer<'de> { + pub fn new(input: &'de [IValue]) -> Deserializer<'de> { Deserializer { iterator: FlattenIValueIterator::new(input).peekable(), } diff --git a/wasmer-it/src/serde/ser.rs b/wasmer-it/src/serde/ser.rs index add64dd..06c353b 100644 --- a/wasmer-it/src/serde/ser.rs +++ b/wasmer-it/src/serde/ser.rs @@ -1,8 +1,7 @@ //! Provides a serializer from Rust value to WIT values. use crate::IValue; -use crate::IValueImpl; -use crate::Vec1; +use crate::NEVec; use serde::{ser, Serialize}; use std::fmt::{self, Display}; @@ -39,9 +38,9 @@ use std::fmt::{self, Display}; /// /// assert_eq!( /// to_interface_value(&input).unwrap(), -/// IValue::Record(Vec1::new(vec![ +/// IValue::Record(NEVec::new(vec![ /// IValue::String("abc".to_string()), -/// IValue::Record(Vec1::new(vec![IValue::I32(1), IValue::I64(2)]).unwrap()), +/// IValue::Record(NEVec::new(vec![IValue::I32(1), IValue::I64(2)]).unwrap()), /// IValue::F32(3.), /// ]).unwrap()), /// ); @@ -51,7 +50,6 @@ where T: Serialize, { let mut serializer = Serializer::new(); - let value = ValueImpl(value); value.serialize(&mut serializer)?; if serializer.values.len() != 1 { @@ -64,14 +62,14 @@ where } else { let first_value = first_values.pop().unwrap(); // this `unwrap` is safe because we are sure the length is 1. - Ok(first_value.0) + Ok(first_value) } } } /// The serializer. struct Serializer { - values: Vec>, + values: Vec>, } impl Serializer { @@ -81,7 +79,7 @@ impl Serializer { } } - fn last(&mut self) -> &mut Vec { + fn last(&mut self) -> &mut Vec { self.values.last_mut().unwrap() } @@ -89,7 +87,7 @@ impl Serializer { self.values.push(Vec::with_capacity(capacity)); } - fn pop(&mut self) -> Result, SerializeError> { + fn pop(&mut self) -> Result, SerializeError> { // The first `vec` contains the final result. It is forbidden // to `pop` it as is. if self.values.len() < 2 { @@ -364,10 +362,7 @@ impl<'a> ser::SerializeSeq for &'a mut Serializer { } fn end(self) -> Result { - let values = self.pop()?.into_iter().map(|v| v.0).collect::>(); - - let record = IValue::Array(values); - let record = IValueImpl(record); + let record = IValue::Array(self.pop()?); self.last().push(record); Ok(()) @@ -402,11 +397,9 @@ impl<'a> ser::SerializeTupleStruct for &'a mut Serializer { } fn end(self) -> Result { - let values = self.pop()?.into_iter().map(|v| v.0).collect::>(); - - let record = - IValue::Record(Vec1::new(values).map_err(|_| Self::Error::RecordNeedsAtLeastOneField)?); - let record = ValueImpl(record); + let record = IValue::Record( + NEVec::new(self.pop()?).map_err(|_| Self::Error::RecordNeedsAtLeastOneField)?, + ); self.last().push(record); Ok(()) @@ -448,11 +441,9 @@ impl<'a> ser::SerializeMap for &'a mut Serializer { } fn end(self) -> Result { - let values = self.pop()?.into_iter().map(|v| v.0).collect::>(); - - let record = - IValue::Record(Vec1::new(values).map_err(|_| Self::Error::RecordNeedsAtLeastOneField)?); - let record = ValueImpl(record); + let record = IValue::Record( + NEVec::new(self.pop()?).map_err(|_| Self::Error::RecordNeedsAtLeastOneField)?, + ); self.last().push(record); Ok(()) @@ -471,11 +462,9 @@ impl<'a> ser::SerializeStruct for &'a mut Serializer { } fn end(self) -> Result { - let values = self.pop()?.into_iter().map(|v| v.0).collect::>(); - - let record = - IValue::Record(Vec1::new(values).map_err(|_| Self::Error::RecordNeedsAtLeastOneField)?); - let record = ValueImpl(record); + let record = IValue::Record( + NEVec::new(self.pop()?).map_err(|_| Self::Error::RecordNeedsAtLeastOneField)?, + ); self.last().push(record); Ok(()) diff --git a/wasmer-it/src/values.rs b/wasmer-it/src/values.rs index db652d7..9885d65 100644 --- a/wasmer-it/src/values.rs +++ b/wasmer-it/src/values.rs @@ -1,59 +1,10 @@ -use crate::IType; use crate::IValue; -use crate::IValueImpl; -use crate::{errors::WasmValueNativeCastError, types::IType, vec1::Vec1}; -use std::{convert::TryFrom, slice::Iter}; + +use std::slice::Iter; #[cfg(feature = "serde")] pub use crate::serde::{de::from_interface_values, ser::to_interface_value}; -/// Represents a native type supported by WIT. -pub trait NativeType { - /// The associated interface type that maps to the native type. - const INTERFACE_TYPE: IType; -} - -macro_rules! native { - ($native_type:ty, $variant:ident) => { - impl NativeType for $native_type { - const INTERFACE_TYPE: IType = IType::$variant; - } - - impl From<$native_type> for IValueImpl { - fn from(n: $native_type) -> Self { - let ivalue = IValue::$variant(n); - Self(ivalue) - } - } - - impl TryFrom<&IValueImpl> for $native_type { - type Error = WasmValueNativeCastError; - - fn try_from(w: &IValue) -> Result { - match w { - IValue::$variant(n) => Ok(n.clone()), - _ => Err(WasmValueNativeCastError { - from: w.clone(), - to: <$native_type>::INTERFACE_TYPE, - }), - } - } - } - }; -} - -native!(i8, S8); -native!(i16, S16); -native!(i32, I32); -native!(i64, I64); -native!(u8, U8); -native!(u16, U16); -native!(u32, U32); -native!(u64, U64); -native!(f32, F32); -native!(f64, F64); -native!(String, String); - /// Iterates over a vector of `IValues` but flatten all the /// values. So `I32(1), Record([I32(2), I32(3)]), I32(4)` will be /// iterated like `I32(1), I32(2), I32(3), I32(4)`.