This commit is contained in:
vms 2020-12-28 22:33:58 +03:00
parent 4b5da87cca
commit 3ca9734d2e
33 changed files with 919 additions and 861 deletions

18
Cargo.lock generated
View File

@ -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",

View File

@ -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"]

View File

@ -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)
}
}

View File

@ -0,0 +1,6 @@
mod errors;
mod types;
mod values;
pub use errors::WasmValueNativeCastError;
pub use values::NativeType;

View File

@ -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<IType, ParseError> {
let mut lookahead = parser.lookahead1();
if lookahead.peek::<keyword::s8>() {
parser.parse::<keyword::s8>()?;
Ok(IType::S8)
} else if lookahead.peek::<keyword::s16>() {
parser.parse::<keyword::s16>()?;
Ok(IType::S16)
} else if lookahead.peek::<keyword::s32>() {
parser.parse::<keyword::s32>()?;
Ok(IType::S32)
} else if lookahead.peek::<keyword::s64>() {
parser.parse::<keyword::s64>()?;
Ok(IType::S64)
} else if lookahead.peek::<keyword::u8>() {
parser.parse::<keyword::u8>()?;
Ok(IType::U8)
} else if lookahead.peek::<keyword::u16>() {
parser.parse::<keyword::u16>()?;
Ok(IType::U16)
} else if lookahead.peek::<keyword::u32>() {
parser.parse::<keyword::u32>()?;
Ok(IType::U32)
} else if lookahead.peek::<keyword::u64>() {
parser.parse::<keyword::u64>()?;
Ok(IType::U64)
} else if lookahead.peek::<keyword::f32>() {
parser.parse::<keyword::f32>()?;
Ok(IType::F32)
} else if lookahead.peek::<keyword::f64>() {
parser.parse::<keyword::f64>()?;
Ok(IType::F64)
} else if lookahead.peek::<keyword::string>() {
parser.parse::<keyword::string>()?;
Ok(IType::String)
} else if lookahead.peek::<keyword::array>() {
parser.parse::<keyword::array>()?;
let array_type = parser.parens(|p| p.parse())?;
Ok(IType::Array(Box::new(array_type)))
} else if lookahead.peek::<keyword::anyref>() {
parser.parse::<keyword::anyref>()?;
Ok(IType::Anyref)
} else if lookahead.peek::<keyword::i32>() {
parser.parse::<keyword::i32>()?;
Ok(IType::I32)
} else if lookahead.peek::<keyword::i64>() {
parser.parse::<keyword::i64>()?;
Ok(IType::I64)
} else if lookahead.peek::<keyword::record>() {
parser.parse::<keyword::record>()?;
Ok(IType::Record(parser.parse()?))
} else {
Err(lookahead.error())
}
}
}
impl Parse<'_> for IRecordType {
fn parse(parser: Parser<'_>) -> Result<Self, ParseError> {
parser.parse::<keyword::record>()?;
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::<keyword::field>()?;
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)
}
}

View File

@ -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<Self, Self::Error> {
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);

View File

@ -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;

View File

@ -1,4 +1,4 @@
//! `Vec1<T>` represents a non-empty `Vec<T>`.
//! `NEVec<T>` represents a non-empty `Vec<T>`.
use serde::{Deserialize, Serialize};
use std::{
@ -7,14 +7,14 @@ use std::{
ops,
};
/// `Vec1<T>` represents a non-empty `Vec<T>`. It derefs to `Vec<T>`
/// `NEVec<T>` represents a non-empty `Vec<T>`. It derefs to `Vec<T>`
/// directly.
#[derive(Clone, PartialEq, Eq, Serialize, Hash, Deserialize, Default)]
pub struct Vec1<T>(Vec<T>)
pub struct NEVec<T>(Vec<T>)
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<T> Vec1<T>
impl<T> NEVec<T>
where
T: Debug,
{
@ -41,13 +44,13 @@ where
}
}
/// Converts this Vec1 into Vec
/// Converts this NEVec into Vec
pub fn into_vec(self) -> Vec<T> {
self.0
}
}
impl<T> fmt::Debug for Vec1<T>
impl<T> fmt::Debug for NEVec<T>
where
T: Debug,
{
@ -56,7 +59,7 @@ where
}
}
impl<T> ops::Deref for Vec1<T>
impl<T> ops::Deref for NEVec<T>
where
T: Debug,
{

View File

@ -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<InterfaceType>),
Array(Box<IType>),
/// 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<RecordFieldType>,
pub fields: NEVec<RecordFieldType>,
}
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
}),
)
}
}

View File

@ -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<InterfaceValue>),
Array(Vec<IValue>),
//Anyref(?),
/// A 32-bits integer (as defined in WebAssembly core).
@ -49,10 +49,10 @@ pub enum InterfaceValue {
I64(i64),
/// A record.
Record(Vec1<InterfaceValue>),
Record(NEVec<IValue>),
}
impl Default for InterfaceValue {
impl Default for IValue {
fn default() -> Self {
Self::I32(0)
}

View File

@ -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 {

View File

@ -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"

View File

@ -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;

View File

@ -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."),
},
))
}

View File

@ -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<IType> {
let mut lookahead = parser.lookahead1();
if lookahead.peek::<keyword::s8>() {
parser.parse::<keyword::s8>()?;
Ok(IType::S8)
} else if lookahead.peek::<keyword::s16>() {
parser.parse::<keyword::s16>()?;
Ok(IType::S16)
} else if lookahead.peek::<keyword::s32>() {
parser.parse::<keyword::s32>()?;
Ok(IType::S32)
} else if lookahead.peek::<keyword::s64>() {
parser.parse::<keyword::s64>()?;
Ok(IType::S64)
} else if lookahead.peek::<keyword::u8>() {
parser.parse::<keyword::u8>()?;
Ok(IType::U8)
} else if lookahead.peek::<keyword::u16>() {
parser.parse::<keyword::u16>()?;
Ok(IType::U16)
} else if lookahead.peek::<keyword::u32>() {
parser.parse::<keyword::u32>()?;
Ok(IType::U32)
} else if lookahead.peek::<keyword::u64>() {
parser.parse::<keyword::u64>()?;
Ok(IType::U64)
} else if lookahead.peek::<keyword::f32>() {
parser.parse::<keyword::f32>()?;
Ok(IType::F32)
} else if lookahead.peek::<keyword::f64>() {
parser.parse::<keyword::f64>()?;
Ok(IType::F64)
} else if lookahead.peek::<keyword::string>() {
parser.parse::<keyword::string>()?;
Ok(IType::String)
} else if lookahead.peek::<keyword::array>() {
parser.parse::<keyword::array>()?;
let array_type = parser.parens(|p| p.parse())?;
Ok(IType::Array(Box::new(array_type)))
} else if lookahead.peek::<keyword::anyref>() {
parser.parse::<keyword::anyref>()?;
Ok(IType::Anyref)
} else if lookahead.peek::<keyword::i32>() {
parser.parse::<keyword::i32>()?;
Ok(IType::I32)
} else if lookahead.peek::<keyword::i64>() {
parser.parse::<keyword::i64>()?;
Ok(IType::I64)
} else if lookahead.peek::<keyword::record>() {
parser.parse::<keyword::record>()?;
Ok(IType::Record(parser.parse()?))
} else {
Err(lookahead.error())
}
}
}
impl Parse<'_> for RecordTypeImpl {
fn parse(parser: Parser<'_>) -> Result<Self> {
parser.parse::<keyword::record>()?;
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::<keyword::field>()?;
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)]

View File

@ -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<W>
@ -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<W> ToBytes<W> for u8
where
@ -53,6 +64,72 @@ where
}
}
/// Encode an `IType` into bytes.
impl<W> ToBytes<W> 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<W> ToBytes<W> 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<W> ToBytes<W> 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::<Vec<_>>();
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<W> ToBytes<W> 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<W> ToBytes<W> 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<W> ToBytes<W> 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<W> ToBytes<W> 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::<Vec<_>>();
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",

View File

@ -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<String> = 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<String> = 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",

View File

@ -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<T> = Result<T, InstructionError>;
/// A type alias for the interpreter result.
pub type InterpreterResult<T> = Result<T, InstructionError>;
/// 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<InterfaceType>, Vec<InterfaceType>),
expected: (Vec<IType>, Vec<IType>),
/// The received signature.
received: (Vec<InterfaceType>, Vec<InterfaceType>),
received: (Vec<IType>, Vec<IType>),
},
/// Failed to call a local or import function.

View File

@ -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"
);

View File

@ -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<Vec<InterfaceValue>, InstructionError>
) -> Result<Vec<IValue>, 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::<u8, i8>(data).unwrap();
data.into_iter().map(InterfaceValue::S8).collect::<Vec<_>>()
data.into_iter().map(IValue::S8).collect::<Vec<_>>()
}
InterfaceType::S16 => {
IType::S16 => {
let data = transmute_many::<i16, AllOrNothingGuard>(&data).unwrap();
data.iter()
.map(|v| InterfaceValue::S16(*v))
.collect::<Vec<_>>()
data.iter().map(|v| IValue::S16(*v)).collect::<Vec<_>>()
}
InterfaceType::S32 => {
IType::S32 => {
let data = transmute_many::<i32, AllOrNothingGuard>(&data).unwrap();
data.iter()
.map(|v| InterfaceValue::S32(*v))
.collect::<Vec<_>>()
data.iter().map(|v| IValue::S32(*v)).collect::<Vec<_>>()
}
InterfaceType::S64 => {
IType::S64 => {
let data = transmute_many::<i64, AllOrNothingGuard>(&data).unwrap();
data.iter()
.map(|v| InterfaceValue::S64(*v))
.collect::<Vec<_>>()
data.iter().map(|v| IValue::S64(*v)).collect::<Vec<_>>()
}
InterfaceType::I32 => {
IType::I32 => {
let data = transmute_many::<i32, AllOrNothingGuard>(&data).unwrap();
data.iter()
.map(|v| InterfaceValue::I32(*v))
.collect::<Vec<_>>()
data.iter().map(|v| IValue::I32(*v)).collect::<Vec<_>>()
}
InterfaceType::I64 => {
IType::I64 => {
let data = transmute_many::<i64, AllOrNothingGuard>(&data).unwrap();
data.iter()
.map(|v| InterfaceValue::S64(*v))
.collect::<Vec<_>>()
data.iter().map(|v| IValue::S64(*v)).collect::<Vec<_>>()
}
InterfaceType::U8 => data.into_iter().map(InterfaceValue::U8).collect::<Vec<_>>(),
InterfaceType::U16 => {
IType::U8 => data.into_iter().map(IValue::U8).collect::<Vec<_>>(),
IType::U16 => {
let data = transmute_many::<u16, AllOrNothingGuard>(&data).unwrap();
data.iter()
.map(|v| InterfaceValue::U16(*v))
.collect::<Vec<_>>()
data.iter().map(|v| IValue::U16(*v)).collect::<Vec<_>>()
}
InterfaceType::U32 => {
IType::U32 => {
let data = transmute_many::<u32, AllOrNothingGuard>(&data).unwrap();
data.iter().map(|v| IValue::U32(*v)).collect::<Vec<_>>()
}
IType::U64 => {
let data = transmute_many::<u64, AllOrNothingGuard>(&data).unwrap();
data.iter().map(|v| IValue::U64(*v)).collect::<Vec<_>>()
}
IType::F32 => {
let data = transmute_many::<u32, AllOrNothingGuard>(&data).unwrap();
data.iter()
.map(|v| InterfaceValue::U32(*v))
.map(|v| IValue::F32(f32::from_bits(*v)))
.collect::<Vec<_>>()
}
InterfaceType::U64 => {
IType::F64 => {
let data = transmute_many::<u64, AllOrNothingGuard>(&data).unwrap();
data.iter()
.map(|v| InterfaceValue::U64(*v))
.map(|v| IValue::F64(f64::from_bits(*v)))
.collect::<Vec<_>>()
}
InterfaceType::F32 => {
let data = transmute_many::<u32, AllOrNothingGuard>(&data).unwrap();
data.iter()
.map(|v| InterfaceValue::F32(f32::from_bits(*v)))
.collect::<Vec<_>>()
}
InterfaceType::F64 => {
let data = transmute_many::<u64, AllOrNothingGuard>(&data).unwrap();
data.iter()
.map(|v| InterfaceValue::F64(f64::from_bits(*v)))
.collect::<Vec<_>>()
}
InterfaceType::Anyref => unimplemented!(),
InterfaceType::String => {
IType::Anyref => unimplemented!(),
IType::String => {
let data = transmute_many::<u32, AllOrNothingGuard>(&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::<u32, AllOrNothingGuard>(&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<Instance, Export, LocalImport, Memory, MemoryView>(
instruction: Instruction,
value_type: InterfaceType,
value_type: IType,
) -> crate::interpreter::ExecutableInstruction<Instance, Export, LocalImport, Memory, MemoryView>
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, Export, LocalImport, Memory, MemoryView>(
instance: &mut Instance,
instruction: Instruction,
array_values: Vec<InterfaceValue>,
array_values: Vec<IValue>,
) -> 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<Instance, Export, LocalImport, Memory, MemoryView>(
instruction: Instruction,
value_type: InterfaceType,
value_type: IType,
) -> crate::interpreter::ExecutableInstruction<Instance, Export, LocalImport, Memory, MemoryView>
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(),
},
)),

View File

@ -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
},

View File

@ -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<T>
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<Export, LocalImport, Memory, MemoryView>,
{
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<InterfaceType>,
pub(crate) outputs: Vec<InterfaceType>,
pub(crate) function: fn(arguments: &[InterfaceValue]) -> Result<Vec<InterfaceValue>, ()>,
pub(crate) inputs: Vec<IType>,
pub(crate) outputs: Vec<IType>,
pub(crate) function: fn(arguments: &[IValue]) -> Result<Vec<IValue>, ()>,
}
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<Vec<InterfaceValue>, ()> {
fn call(&self, arguments: &[IValue]) -> Result<Vec<IValue>, ()> {
(self.function)(arguments)
}
}
pub(crate) struct LocalImport {
pub(crate) inputs: Vec<InterfaceType>,
pub(crate) outputs: Vec<InterfaceType>,
pub(crate) function: fn(arguments: &[InterfaceValue]) -> Result<Vec<InterfaceValue>, ()>,
pub(crate) inputs: Vec<IType>,
pub(crate) outputs: Vec<IType>,
pub(crate) function: fn(arguments: &[IValue]) -> Result<Vec<IValue>, ()>,
}
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<Vec<InterfaceValue>, ()> {
fn call(&self, arguments: &[IValue]) -> Result<Vec<IValue>, ()> {
(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,
}
],
})],

View File

@ -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)],
);
}

View File

@ -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<InterfaceValue>,
stack: &mut Stack<IValue>,
record_type: &RecordType,
) -> Result<InterfaceValue, InstructionErrorKind> {
) -> Result<IValue, InstructionErrorKind> {
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<InterfaceValue, InstructionError>
) -> Result<IValue, InstructionError>
where
Export: crate::interpreter::wasm::structures::Export,
LocalImport: crate::interpreter::wasm::structures::LocalImport,
@ -113,12 +114,12 @@ where
Instance: crate::interpreter::wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>
+ '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, Export, LocalImport, Memory, MemoryView>(
instance: &mut Instance,
instruction: Instruction,
values: Vec1<InterfaceValue>,
values: NEVec<IValue>,
) -> Result<i32, InstructionError>
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(),
},
)),

View File

@ -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"#,
);

View File

@ -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<InterfaceValue>,
) -> Result<Vec<InterfaceValue>, InstructionError>
inputs: Vec<IValue>,
) -> Result<Vec<IValue>, InstructionError>
where
Export: wasm::structures::Export + 'instance,
LocalImport: wasm::structures::LocalImport + 'instance,

View File

@ -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<InterfaceValue>,
stack: Stack<IValue>,
/// The WebAssembly module instance. It is used by adapter's
/// instructions.
@ -68,8 +66,8 @@ pub(crate) type ExecutableInstruction<Instance, Export, LocalImport, Memory, Mem
/// stack::Stackable,
/// Instruction, Interpreter,
/// },
/// types::InterfaceType,
/// values::InterfaceValue,
/// types::IType,
/// values::IValue,
/// };
///
/// // 1. Creates an interpreter from a set of instructions. They will
@ -83,7 +81,7 @@ pub(crate) type ExecutableInstruction<Instance, Export, LocalImport, Memory, Mem
/// .unwrap();
///
/// // 2. Defines the arguments of the adapter.
/// let invocation_inputs = vec![InterfaceValue::I32(3), InterfaceValue::I32(4)];
/// let invocation_inputs = vec![IValue::I32(3), IValue::I32(4)];
///
/// // 3. Creates a WebAssembly instance.
/// let mut instance = Instance {
@ -94,17 +92,17 @@ pub(crate) type ExecutableInstruction<Instance, Export, LocalImport, Memory, Mem
/// 42,
/// LocalImport {
/// // Defines the argument types of the function.
/// inputs: vec![InterfaceType::I32, InterfaceType::I32],
/// inputs: vec![IType::I32, IType::I32],
///
/// // Defines the result types.
/// outputs: vec![InterfaceType::I32],
/// outputs: vec![IType::I32],
///
/// // Defines the function implementation.
/// function: |arguments: &[InterfaceValue]| {
/// 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)])
/// },
/// },
/// );
@ -120,7 +118,7 @@ pub(crate) type ExecutableInstruction<Instance, Export, LocalImport, Memory, Mem
/// let stack = run.unwrap();
///
/// // 5. Read the stack to get the result.
/// assert_eq!(stack.as_slice(), &[InterfaceValue::I32(7)]);
/// assert_eq!(stack.as_slice(), &[IValue::I32(7)]);
/// ```
pub struct Interpreter<Instance, Export, LocalImport, Memory, MemoryView>
where
@ -158,9 +156,9 @@ where
/// returns the stack.
pub fn run(
&self,
invocation_inputs: &[InterfaceValue],
invocation_inputs: &[IValue],
wasm_instance: &mut Instance,
) -> InterpreterResult<Stack<InterfaceValue>> {
) -> InterpreterResult<Stack<IValue>> {
let mut runtime = Runtime {
invocation_inputs,
stack: Stack::new(),

View File

@ -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<Vec<InterfaceValue>, ()>;
fn outputs(&self) -> &[IType];
fn call(&self, arguments: &[IValue]) -> Result<Vec<IValue>, ()>;
}
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<Vec<InterfaceValue>, ()>;
fn outputs(&self) -> &[IType];
fn call(&self, arguments: &[IValue]) -> Result<Vec<IValue>, ()>;
}
pub trait MemoryView: Deref<Target = [Cell<u8>]> {}
@ -79,7 +80,7 @@ where
fn export(&self, export_name: &str) -> Option<&E>;
fn local_or_import<I: TypedIndex + LocalImportIndex>(&self, index: I) -> Option<&LI>;
fn memory(&self, index: usize) -> Option<&M>;
fn wit_record_by_id(&self, index: u64) -> Option<&Rc<RecordType>>;
fn wit_record_by_id(&self, index: u64) -> Option<&Rc<IRecordType>>;
}
impl Export for () {
@ -99,11 +100,11 @@ impl Export for () {
&[]
}
fn outputs(&self) -> &[InterfaceType] {
fn outputs(&self) -> &[IType] {
&[]
}
fn call(&self, _arguments: &[InterfaceValue]) -> Result<Vec<InterfaceValue>, ()> {
fn call(&self, _arguments: &[IValue]) -> Result<Vec<IValue>, ()> {
Err(())
}
}
@ -125,11 +126,11 @@ impl LocalImport for () {
&[]
}
fn outputs(&self) -> &[InterfaceType] {
fn outputs(&self) -> &[IType] {
&[]
}
fn call(&self, _arguments: &[InterfaceValue]) -> Result<Vec<InterfaceValue>, ()> {
fn call(&self, _arguments: &[IValue]) -> Result<Vec<IValue>, ()> {
Err(())
}
}
@ -171,7 +172,7 @@ where
None
}
fn wit_record_by_id(&self, _index: u64) -> Option<&Rc<RecordType>> {
fn wit_record_by_id(&self, _index: u64) -> Option<&Rc<IRecordType>> {
None
}
}

View File

@ -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;

View File

@ -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};

View File

@ -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::<T>(&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<FlattenIValueIterator<'de>>,
}
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(),
}

View File

@ -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<Vec<IValueImpl>>,
values: Vec<Vec<IValue>>,
}
impl Serializer {
@ -81,7 +79,7 @@ impl Serializer {
}
}
fn last(&mut self) -> &mut Vec<IValueImpl> {
fn last(&mut self) -> &mut Vec<IValue> {
self.values.last_mut().unwrap()
}
@ -89,7 +87,7 @@ impl Serializer {
self.values.push(Vec::with_capacity(capacity));
}
fn pop(&mut self) -> Result<Vec<IValueImpl>, SerializeError> {
fn pop(&mut self) -> Result<Vec<IValue>, 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<Self::Ok, Self::Error> {
let values = self.pop()?.into_iter().map(|v| v.0).collect::<Vec<_>>();
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<Self::Ok, Self::Error> {
let values = self.pop()?.into_iter().map(|v| v.0).collect::<Vec<_>>();
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<Self::Ok, Self::Error> {
let values = self.pop()?.into_iter().map(|v| v.0).collect::<Vec<_>>();
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<Self::Ok, Self::Error> {
let values = self.pop()?.into_iter().map(|v| v.0).collect::<Vec<_>>();
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(())

View File

@ -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<Self, Self::Error> {
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)`.