1244: feat(interface-types) Update to last standard version r=MarkMcCaskey a=Hywan

WIP

Co-authored-by: Ivan Enderlin <ivan.enderlin@hoa-project.net>
This commit is contained in:
bors[bot] 2020-02-28 18:35:28 +00:00 committed by GitHub
commit 85a3bb7148
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 1761 additions and 2007 deletions

View File

@ -7,26 +7,29 @@ use std::str;
/// Represents the types supported by WIT. /// Represents the types supported by WIT.
#[derive(PartialEq, Debug)] #[derive(PartialEq, Debug)]
pub enum InterfaceType { pub enum InterfaceType {
/// An integer. /// A 8-bits signed integer.
Int, S8,
/// A float. /// A 16-bits signed integer.
Float, S16,
/// Opaque reference. /// A 32-bits signed integer.
Any, S32,
/// A string. /// A 64-bits signed integer.
String, S64,
/// A sequence. /// A 8-bits unsigned integer.
Seq, U8,
/// A 32-bits integer. /// A 16-bits unsigned integer.
I32, U16,
/// A 64-bits integer. /// A 32-bits unsigned integer.
I64, U32,
/// A 64-bits unsigned integer.
U64,
/// A 32-bits float. /// A 32-bits float.
F32, F32,
@ -34,37 +37,30 @@ pub enum InterfaceType {
/// A 64-bits float. /// A 64-bits float.
F64, F64,
/// A string.
String,
/// An `any` reference. /// An `any` reference.
AnyRef, Anyref,
/// A 32-bits integer (as defined in WebAssembly core).
I32,
/// A 64-bits integer (as defiend in WebAssembly core).
I64,
} }
/// Represents the kind of adapter. /// Represents a type signature.
#[derive(PartialEq, Debug)] #[derive(PartialEq, Debug)]
pub(crate) enum AdapterKind { pub struct Type {
/// An adapter defined for an imported function of a WebAssembly instance. /// Types for the parameters.
Import, pub inputs: Vec<InterfaceType>,
/// An adapter defined for an exported function of a WebAssembly instance. /// Types for the results.
Export, pub outputs: Vec<InterfaceType>,
/// A helper function.
HelperFunction,
} }
/// Represents an exported function signature. /// Represents an imported function.
#[derive(PartialEq, Debug)]
pub struct Export<'input> {
/// The function name.
pub name: &'input str,
/// The function input types.
pub input_types: Vec<InterfaceType>,
/// The function output types.
pub output_types: Vec<InterfaceType>,
}
/// Represents an imported function signature.
#[derive(PartialEq, Debug)] #[derive(PartialEq, Debug)]
pub struct Import<'input> { pub struct Import<'input> {
/// The function namespace. /// The function namespace.
@ -73,130 +69,65 @@ pub struct Import<'input> {
/// The function name. /// The function name.
pub name: &'input str, pub name: &'input str,
/// The function input types. /// The type signature.
pub input_types: Vec<InterfaceType>, pub signature_type: u32,
/// The function output types.
pub output_types: Vec<InterfaceType>,
} }
/// Represents a structural type. /// Represents an exported function signature.
#[derive(PartialEq, Debug)] #[derive(PartialEq, Debug)]
pub struct Type<'input> { pub struct Export<'input> {
/// The type name. /// The export name.
pub name: &'input str, pub name: &'input str,
/// The field names. /// The WIT function type being exported.
field_names: Vec<&'input str>, pub function_type: u32,
/// The field types.
field_types: Vec<InterfaceType>,
}
impl<'input> Type<'input> {
/// Creates a new `Type`.
///
/// The constructor panics if there is the length of `names` is
/// different than the length of `types`.
pub fn new(type_name: &'input str, names: Vec<&'input str>, types: Vec<InterfaceType>) -> Self {
assert_eq!(
names.len(),
types.len(),
"There must be the same number of field names than field types."
);
Self {
name: type_name,
field_names: names,
field_types: types,
}
}
/// Adds a new field to the type.
pub fn add_field(&mut self, name: &'input str, ty: InterfaceType) {
self.field_names.push(name);
self.field_types.push(ty);
}
/// Returns the field names.
pub fn field_names(&self) -> &Vec<&'input str> {
&self.field_names
}
/// Returns the field types.
pub fn field_types(&self) -> &Vec<InterfaceType> {
&self.field_types
}
} }
/// Represents an adapter. /// Represents an adapter.
#[derive(PartialEq, Debug)] #[derive(PartialEq, Debug)]
pub enum Adapter<'input> { pub struct Adapter<'input> {
/// An adapter for an imported function. /// The adapter function type.
Import { pub function_type: u32,
/// The function namespace.
namespace: &'input str,
/// The function name. /// The instructions.
name: &'input str, pub instructions: Vec<Instruction<'input>>,
/// The function input types.
input_types: Vec<InterfaceType>,
/// The function output types.
output_types: Vec<InterfaceType>,
/// The instructions of the adapter.
instructions: Vec<Instruction<'input>>,
},
/// An adapter for an exported function.
Export {
/// The function name.
name: &'input str,
/// The function input types.
input_types: Vec<InterfaceType>,
/// The function output types.
output_types: Vec<InterfaceType>,
/// The instructions of the adapter.
instructions: Vec<Instruction<'input>>,
},
/// An adapter for a helper function.
HelperFunction {
/// The helper name.
name: &'input str,
/// The helper input types.
input_types: Vec<InterfaceType>,
/// The helper output types.
output_types: Vec<InterfaceType>,
/// The instructions of the adapter.
instructions: Vec<Instruction<'input>>,
},
} }
/// Represented a forwarded export. /// Represents an implementation.
#[derive(PartialEq, Debug)] #[derive(PartialEq, Debug)]
pub struct Forward<'input> { pub struct Implementation {
/// The forwarded export name. /// The core function type.
pub name: &'input str, pub core_function_type: u32,
/// The adapter function type.
pub adapter_function_type: u32,
}
/// Represents the kind of interface.
#[derive(PartialEq, Debug)]
pub(crate) enum InterfaceKind {
/// A type.
Type,
/// An imported function.
Import,
/// An adapter.
Adapter,
/// An exported function.
Export,
/// An implementation.
Implementation,
} }
/// Represents a set of interfaces, i.e. it entirely describes a WIT /// Represents a set of interfaces, i.e. it entirely describes a WIT
/// definition. /// definition.
#[derive(PartialEq, Default, Debug)] #[derive(PartialEq, Default, Debug)]
pub struct Interfaces<'input> { pub struct Interfaces<'input> {
/// All the exported functions.
pub exports: Vec<Export<'input>>,
/// All the types. /// All the types.
pub types: Vec<Type<'input>>, pub types: Vec<Type>,
/// All the imported functions. /// All the imported functions.
pub imports: Vec<Import<'input>>, pub imports: Vec<Import<'input>>,
@ -204,6 +135,9 @@ pub struct Interfaces<'input> {
/// All the adapters. /// All the adapters.
pub adapters: Vec<Adapter<'input>>, pub adapters: Vec<Adapter<'input>>,
/// All the forwarded functions. /// All the exported functions.
pub forwards: Vec<Forward<'input>>, pub exports: Vec<Export<'input>>,
/// All the implementations.
pub implementations: Vec<Implementation>,
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,6 @@
//! Writes the AST into bytes representing WIT with its binary format. //! Writes the AST into bytes representing WIT with its binary format.
use crate::{ use crate::{ast::*, interpreter::Instruction};
ast::{Adapter, AdapterKind, Export, Forward, Import, InterfaceType, Interfaces, Type},
interpreter::Instruction,
};
use std::io::{self, Write}; use std::io::{self, Write};
/// A trait for converting a value to bytes. /// A trait for converting a value to bytes.
@ -97,61 +94,50 @@ where
{ {
fn to_bytes(&self, writer: &mut W) -> io::Result<()> { fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
match self { match self {
InterfaceType::Int => 0x7fff_u64.to_bytes(writer), InterfaceType::S8 => 0x00_u8.to_bytes(writer),
InterfaceType::Float => 0x7ffe_u64.to_bytes(writer), InterfaceType::S16 => 0x01_u8.to_bytes(writer),
InterfaceType::Any => 0x7ffd_u64.to_bytes(writer), InterfaceType::S32 => 0x02_u8.to_bytes(writer),
InterfaceType::String => 0x7ffc_u64.to_bytes(writer), InterfaceType::S64 => 0x03_u8.to_bytes(writer),
InterfaceType::Seq => 0x7ffb_u64.to_bytes(writer), InterfaceType::U8 => 0x04_u8.to_bytes(writer),
InterfaceType::I32 => 0x7f_u64.to_bytes(writer), InterfaceType::U16 => 0x05_u8.to_bytes(writer),
InterfaceType::I64 => 0x7e_u64.to_bytes(writer), InterfaceType::U32 => 0x06_u8.to_bytes(writer),
InterfaceType::F32 => 0x7d_u64.to_bytes(writer), InterfaceType::U64 => 0x07_u8.to_bytes(writer),
InterfaceType::F64 => 0x7c_u64.to_bytes(writer), InterfaceType::F32 => 0x08_u8.to_bytes(writer),
InterfaceType::AnyRef => 0x6f_u64.to_bytes(writer), InterfaceType::F64 => 0x09_u8.to_bytes(writer),
InterfaceType::String => 0x0a_u8.to_bytes(writer),
InterfaceType::Anyref => 0x0b_u8.to_bytes(writer),
InterfaceType::I32 => 0x0c_u8.to_bytes(writer),
InterfaceType::I64 => 0x0d_u8.to_bytes(writer),
} }
} }
} }
/// Encode an `AdapterKind` into bytes. /// Encode an `InterfaceKind` into bytes.
impl<W> ToBytes<W> for AdapterKind impl<W> ToBytes<W> for InterfaceKind
where where
W: Write, W: Write,
{ {
fn to_bytes(&self, writer: &mut W) -> io::Result<()> { fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
match self { match self {
AdapterKind::Import => 0x00_u8.to_bytes(writer), Self::Type => 0x00_u8.to_bytes(writer),
AdapterKind::Export => 0x01_u8.to_bytes(writer), Self::Import => 0x01_u8.to_bytes(writer),
AdapterKind::HelperFunction => 0x02_u8.to_bytes(writer), Self::Adapter => 0x02_u8.to_bytes(writer),
Self::Export => 0x03_u8.to_bytes(writer),
Self::Implementation => 0x04_u8.to_bytes(writer),
} }
} }
} }
/// Encode an `Export` into bytes.
///
/// Decoder is in `decoders::binary::exports`.
impl<W> ToBytes<W> for Export<'_>
where
W: Write,
{
fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
self.name.to_bytes(writer)?;
self.input_types.to_bytes(writer)?;
self.output_types.to_bytes(writer)?;
Ok(())
}
}
/// Encode a `Type` into bytes. /// Encode a `Type` into bytes.
/// ///
/// Decoder is in `decoders::binary::types`. /// Decoder is in `decoders::binary::types`.
impl<W> ToBytes<W> for Type<'_> impl<W> ToBytes<W> for Type
where where
W: Write, W: Write,
{ {
fn to_bytes(&self, writer: &mut W) -> io::Result<()> { fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
self.name.to_bytes(writer)?; self.inputs.to_bytes(writer)?;
self.field_names().to_bytes(writer)?; self.outputs.to_bytes(writer)?;
self.field_types().to_bytes(writer)?;
Ok(()) Ok(())
} }
@ -167,8 +153,7 @@ where
fn to_bytes(&self, writer: &mut W) -> io::Result<()> { fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
self.namespace.to_bytes(writer)?; self.namespace.to_bytes(writer)?;
self.name.to_bytes(writer)?; self.name.to_bytes(writer)?;
self.input_types.to_bytes(writer)?; (self.signature_type as u64).to_bytes(writer)?;
self.output_types.to_bytes(writer)?;
Ok(()) Ok(())
} }
@ -176,68 +161,46 @@ where
/// Encode an `Adapter` into bytes. /// Encode an `Adapter` into bytes.
/// ///
/// Decoder is in `decoders::binary::imports`. /// Decoder is in `decoders::binary::adapters`.
impl<W> ToBytes<W> for Adapter<'_> impl<W> ToBytes<W> for Adapter<'_>
where where
W: Write, W: Write,
{ {
fn to_bytes(&self, writer: &mut W) -> io::Result<()> { fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
match self { (self.function_type as u64).to_bytes(writer)?;
Adapter::Import { self.instructions.to_bytes(writer)?;
namespace,
name,
input_types,
output_types,
instructions,
} => {
AdapterKind::Import.to_bytes(writer)?;
namespace.to_bytes(writer)?;
name.to_bytes(writer)?;
input_types.to_bytes(writer)?;
output_types.to_bytes(writer)?;
instructions.to_bytes(writer)?;
}
Adapter::Export {
name,
input_types,
output_types,
instructions,
} => {
AdapterKind::Export.to_bytes(writer)?;
name.to_bytes(writer)?;
input_types.to_bytes(writer)?;
output_types.to_bytes(writer)?;
instructions.to_bytes(writer)?;
}
Adapter::HelperFunction {
name,
input_types,
output_types,
instructions,
} => {
AdapterKind::HelperFunction.to_bytes(writer)?;
name.to_bytes(writer)?;
input_types.to_bytes(writer)?;
output_types.to_bytes(writer)?;
instructions.to_bytes(writer)?;
}
}
Ok(()) Ok(())
} }
} }
/// Encode an `Forward` into bytes. /// Encode an `Export` into bytes.
/// ///
/// Decoder is `decoders::binary::forwards`. /// Decoder is in `decoders::binary::exports`.
impl<W> ToBytes<W> for Forward<'_> impl<W> ToBytes<W> for Export<'_>
where where
W: Write, W: Write,
{ {
fn to_bytes(&self, writer: &mut W) -> io::Result<()> { fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
self.name.to_bytes(writer) self.name.to_bytes(writer)?;
(self.function_type as u64).to_bytes(writer)?;
Ok(())
}
}
/// Encode an `Implementation` into bytes.
///
/// Decoder is in `decoders::binary::implementations`.
impl<W> ToBytes<W> for Implementation
where
W: Write,
{
fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
(self.core_function_type as u64).to_bytes(writer)?;
(self.adapter_function_type as u64).to_bytes(writer)?;
Ok(())
} }
} }
@ -249,11 +212,30 @@ where
W: Write, W: Write,
{ {
fn to_bytes(&self, writer: &mut W) -> io::Result<()> { fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
self.exports.to_bytes(writer)?; if !self.types.is_empty() {
self.types.to_bytes(writer)?; InterfaceKind::Type.to_bytes(writer)?;
self.imports.to_bytes(writer)?; self.types.to_bytes(writer)?;
self.adapters.to_bytes(writer)?; }
self.forwards.to_bytes(writer)?;
if !self.imports.is_empty() {
InterfaceKind::Import.to_bytes(writer)?;
self.imports.to_bytes(writer)?;
}
if !self.adapters.is_empty() {
InterfaceKind::Adapter.to_bytes(writer)?;
self.adapters.to_bytes(writer)?;
}
if !self.exports.is_empty() {
InterfaceKind::Export.to_bytes(writer)?;
self.exports.to_bytes(writer)?;
}
if !self.implementations.is_empty() {
InterfaceKind::Implementation.to_bytes(writer)?;
self.implementations.to_bytes(writer)?;
}
Ok(()) Ok(())
} }
@ -270,7 +252,7 @@ where
match self { match self {
Instruction::ArgumentGet { index } => { Instruction::ArgumentGet { index } => {
0x00_u8.to_bytes(writer)?; 0x00_u8.to_bytes(writer)?;
index.to_bytes(writer)?; (*index as u64).to_bytes(writer)?;
} }
Instruction::Call { function_index } => { Instruction::Call { function_index } => {
@ -290,76 +272,45 @@ where
allocator_name.to_bytes(writer)?; allocator_name.to_bytes(writer)?;
} }
Instruction::AsWasm(interface_type) => { Instruction::I32ToS8 => 0x07_u8.to_bytes(writer)?,
0x05_u8.to_bytes(writer)?; Instruction::I32ToS8X => 0x08_u8.to_bytes(writer)?,
interface_type.to_bytes(writer)?; Instruction::I32ToU8 => 0x09_u8.to_bytes(writer)?,
} Instruction::I32ToS16 => 0x0a_u8.to_bytes(writer)?,
Instruction::I32ToS16X => 0x0b_u8.to_bytes(writer)?,
Instruction::AsInterface(interface_type) => { Instruction::I32ToU16 => 0x0c_u8.to_bytes(writer)?,
0x06_u8.to_bytes(writer)?; Instruction::I32ToS32 => 0x0d_u8.to_bytes(writer)?,
interface_type.to_bytes(writer)?; Instruction::I32ToU32 => 0x0e_u8.to_bytes(writer)?,
} Instruction::I32ToS64 => 0x0f_u8.to_bytes(writer)?,
Instruction::I32ToU64 => 0x10_u8.to_bytes(writer)?,
Instruction::TableRefAdd => 0x07_u8.to_bytes(writer)?, Instruction::I64ToS8 => 0x11_u8.to_bytes(writer)?,
Instruction::I64ToS8X => 0x12_u8.to_bytes(writer)?,
Instruction::TableRefGet => 0x08_u8.to_bytes(writer)?, Instruction::I64ToU8 => 0x13_u8.to_bytes(writer)?,
Instruction::I64ToS16 => 0x14_u8.to_bytes(writer)?,
Instruction::CallMethod(function_index) => { Instruction::I64ToS16X => 0x15_u8.to_bytes(writer)?,
0x09_u8.to_bytes(writer)?; Instruction::I64ToU16 => 0x16_u8.to_bytes(writer)?,
function_index.to_bytes(writer)?; Instruction::I64ToS32 => 0x17_u8.to_bytes(writer)?,
} Instruction::I64ToS32X => 0x18_u8.to_bytes(writer)?,
Instruction::I64ToU32 => 0x19_u8.to_bytes(writer)?,
Instruction::MakeRecord(interface_type) => { Instruction::I64ToS64 => 0x1a_u8.to_bytes(writer)?,
0x0a_u8.to_bytes(writer)?; Instruction::I64ToU64 => 0x1b_u8.to_bytes(writer)?,
interface_type.to_bytes(writer)?; Instruction::S8ToI32 => 0x1c_u8.to_bytes(writer)?,
} Instruction::U8ToI32 => 0x1d_u8.to_bytes(writer)?,
Instruction::S16ToI32 => 0x1e_u8.to_bytes(writer)?,
Instruction::GetField(interface_type, field_index) => { Instruction::U16ToI32 => 0x1f_u8.to_bytes(writer)?,
0x0c_u8.to_bytes(writer)?; Instruction::S32ToI32 => 0x20_u8.to_bytes(writer)?,
interface_type.to_bytes(writer)?; Instruction::U32ToI32 => 0x21_u8.to_bytes(writer)?,
field_index.to_bytes(writer)?; Instruction::S64ToI32 => 0x22_u8.to_bytes(writer)?,
} Instruction::S64ToI32X => 0x23_u8.to_bytes(writer)?,
Instruction::U64ToI32 => 0x24_u8.to_bytes(writer)?,
Instruction::Const(interface_type, index) => { Instruction::U64ToI32X => 0x25_u8.to_bytes(writer)?,
0x0d_u8.to_bytes(writer)?; Instruction::S8ToI64 => 0x26_u8.to_bytes(writer)?,
interface_type.to_bytes(writer)?; Instruction::U8ToI64 => 0x27_u8.to_bytes(writer)?,
index.to_bytes(writer)?; Instruction::S16ToI64 => 0x28_u8.to_bytes(writer)?,
} Instruction::U16ToI64 => 0x29_u8.to_bytes(writer)?,
Instruction::S32ToI64 => 0x2a_u8.to_bytes(writer)?,
Instruction::FoldSeq(index) => { Instruction::U32ToI64 => 0x2b_u8.to_bytes(writer)?,
0x0e_u8.to_bytes(writer)?; Instruction::S64ToI64 => 0x2c_u8.to_bytes(writer)?,
index.to_bytes(writer)?; Instruction::U64ToI64 => 0x2d_u8.to_bytes(writer)?,
}
Instruction::Add(interface_type) => {
0x0f_u8.to_bytes(writer)?;
interface_type.to_bytes(writer)?;
}
Instruction::MemToSeq(interface_type, string) => {
0x10_u8.to_bytes(writer)?;
interface_type.to_bytes(writer)?;
string.to_bytes(writer)?;
}
Instruction::Load(interface_type, string) => {
0x11_u8.to_bytes(writer)?;
interface_type.to_bytes(writer)?;
string.to_bytes(writer)?;
}
Instruction::SeqNew(interface_type) => {
0x12_u8.to_bytes(writer)?;
interface_type.to_bytes(writer)?;
}
Instruction::ListPush => 0x13_u8.to_bytes(writer)?,
Instruction::RepeatUntil(index1, index2) => {
0x14_u8.to_bytes(writer)?;
index1.to_bytes(writer)?;
index2.to_bytes(writer)?;
}
} }
Ok(()) Ok(())
@ -444,23 +395,29 @@ mod tests {
#[test] #[test]
fn test_interface_type() { fn test_interface_type() {
assert_to_bytes!(InterfaceType::Int, &[0xff, 0xff, 0x01]); assert_to_bytes!(InterfaceType::S8, &[0x00]);
assert_to_bytes!(InterfaceType::Float, &[0xfe, 0xff, 0x01]); assert_to_bytes!(InterfaceType::S16, &[0x01]);
assert_to_bytes!(InterfaceType::Any, &[0xfd, 0xff, 0x01]); assert_to_bytes!(InterfaceType::S32, &[0x02]);
assert_to_bytes!(InterfaceType::String, &[0xfc, 0xff, 0x01]); assert_to_bytes!(InterfaceType::S64, &[0x03]);
assert_to_bytes!(InterfaceType::Seq, &[0xfb, 0xff, 0x01]); assert_to_bytes!(InterfaceType::U8, &[0x04]);
assert_to_bytes!(InterfaceType::I32, &[0x7f]); assert_to_bytes!(InterfaceType::U16, &[0x05]);
assert_to_bytes!(InterfaceType::I64, &[0x7e]); assert_to_bytes!(InterfaceType::U32, &[0x06]);
assert_to_bytes!(InterfaceType::F32, &[0x7d]); assert_to_bytes!(InterfaceType::U64, &[0x07]);
assert_to_bytes!(InterfaceType::F64, &[0x7c]); assert_to_bytes!(InterfaceType::F32, &[0x08]);
assert_to_bytes!(InterfaceType::AnyRef, &[0x6f]); 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]);
} }
#[test] #[test]
fn test_adapter_kind() { fn test_interface_kind() {
assert_to_bytes!(AdapterKind::Import, &[0x00]); assert_to_bytes!(InterfaceKind::Type, &[0x00]);
assert_to_bytes!(AdapterKind::Export, &[0x01]); assert_to_bytes!(InterfaceKind::Import, &[0x01]);
assert_to_bytes!(AdapterKind::HelperFunction, &[0x02]); assert_to_bytes!(InterfaceKind::Adapter, &[0x02]);
assert_to_bytes!(InterfaceKind::Export, &[0x03]);
assert_to_bytes!(InterfaceKind::Implementation, &[0x04]);
} }
#[test] #[test]
@ -468,19 +425,14 @@ mod tests {
assert_to_bytes!( assert_to_bytes!(
Export { Export {
name: "abc", name: "abc",
input_types: vec![InterfaceType::I32, InterfaceType::I64], function_type: 0,
output_types: vec![InterfaceType::I32]
}, },
&[ &[
0x03, // string of length 3 0x03, // string of length 3
0x61, // "a" 0x61, // "a"
0x62, // "b" 0x62, // "b"
0x63, // "c" 0x63, // "c"
0x02, // list of 2 items 0x00, // function type
0x7f, // I32
0x7e, // I64
0x01, // list of 1 items
0x7f, // I32
] ]
); );
} }
@ -488,22 +440,16 @@ mod tests {
#[test] #[test]
fn test_type() { fn test_type() {
assert_to_bytes!( assert_to_bytes!(
Type::new( Type {
"a", inputs: vec![InterfaceType::I32, InterfaceType::I64],
vec!["b", "c"], outputs: vec![InterfaceType::S32],
vec![InterfaceType::I32, InterfaceType::I64], },
),
&[ &[
0x01, // string of length 1
0x61, // "a"
0x02, // list of 2 items 0x02, // list of 2 items
0x01, // string of length 1 0x0c, // I32
0x62, // "b" 0x0d, // I64
0x01, // string of length 1 0x01, // list of 1 items
0x63, // "c" 0x02, // I64
0x02, // list of 2 items
0x7f, // I32
0x7e, // I64
] ]
); );
} }
@ -514,182 +460,91 @@ mod tests {
Import { Import {
namespace: "a", namespace: "a",
name: "b", name: "b",
input_types: vec![InterfaceType::I32, InterfaceType::I64], signature_type: 0,
output_types: vec![InterfaceType::I32],
}, },
&[ &[
0x01, // string of length 1 0x01, // string of length 1
0x61, // "a" 0x61, // "a"
0x01, // string of length 1 0x01, // string of length 1
0x62, // "b" 0x62, // "b"
0x02, // list of 2 items 0x00, // signature typr
0x7f, // I32
0x7e, // I64
0x01, // list of 1 items
0x7f, // I32
] ]
); );
} }
#[test] #[test]
fn test_adapter_import() { fn test_adapter() {
assert_to_bytes!( assert_to_bytes!(
Adapter::Import { Adapter {
namespace: "a", function_type: 0,
name: "b",
input_types: vec![InterfaceType::I32, InterfaceType::I64],
output_types: vec![InterfaceType::I32],
instructions: vec![Instruction::ArgumentGet { index: 1 }], instructions: vec![Instruction::ArgumentGet { index: 1 }],
}, },
&[ &[
0x00, // AdapterKind::Import 0x00, // function type
0x01, // string of length 1
0x61, // "a"
0x01, // string of length 1
0x62, // "b"
0x02, // list of 2 items
0x7f, // I32
0x7e, // I64
0x01, // list of 1 items
0x7f, // I32
0x01, // list of 1 item 0x01, // list of 1 item
0x00, 0x01, // ArgumentGet { index: 1 } 0x00, 0x01, // ArgumentGet { index: 1 }
] ]
); );
} }
#[test]
fn test_adapter_export() {
assert_to_bytes!(
Adapter::Export {
name: "a",
input_types: vec![InterfaceType::I32, InterfaceType::I64],
output_types: vec![InterfaceType::I32],
instructions: vec![Instruction::ArgumentGet { index: 1 }],
},
&[
0x01, // AdapterKind::Export
0x01, // string of length 1
0x61, // "a"
0x02, // list of 2 items
0x7f, // I32
0x7e, // I64
0x01, // list of 1 items
0x7f, // I32
0x01, // list of 1 item
0x00, 0x01, // ArgumentGet { index: 1 }
]
);
}
#[test]
fn test_adapter_helper_function() {
assert_to_bytes!(
Adapter::HelperFunction {
name: "a",
input_types: vec![InterfaceType::I32, InterfaceType::I64],
output_types: vec![InterfaceType::I32],
instructions: vec![Instruction::ArgumentGet { index: 1 }],
},
&[
0x02, // AdapterKind::HelperFunction
0x01, // string of length 1
0x61, // "a"
0x02, // list of 2 items
0x7f, // I32
0x7e, // I64
0x01, // list of 1 items
0x7f, // I32
0x01, // list of 1 item
0x00, 0x01, // ArgumentGet { index: 1 }
]
);
}
#[test]
fn test_forward() {
assert_to_bytes!(
Forward { name: "ab" },
&[
0x02, // string of length 2
0x61, // "a"
0x62, // "b"
]
);
}
#[test] #[test]
fn test_interfaces() { fn test_interfaces() {
assert_to_bytes!( assert_to_bytes!(
Interfaces { Interfaces {
exports: vec![Export { types: vec![Type {
name: "ab", inputs: vec![InterfaceType::S8],
input_types: vec![InterfaceType::I32], outputs: vec![InterfaceType::S16],
output_types: vec![InterfaceType::I32],
}], }],
types: vec![Type::new(
"ab",
vec!["cd", "e"],
vec![InterfaceType::I32, InterfaceType::I32],
)],
imports: vec![Import { imports: vec![Import {
namespace: "a", namespace: "ab",
name: "b", name: "c",
input_types: vec![InterfaceType::I32], signature_type: 0,
output_types: vec![InterfaceType::I64],
}], }],
adapters: vec![Adapter::Import { adapters: vec![Adapter {
namespace: "a", function_type: 0,
name: "b",
input_types: vec![InterfaceType::I32],
output_types: vec![InterfaceType::I32],
instructions: vec![Instruction::ArgumentGet { index: 1 }], instructions: vec![Instruction::ArgumentGet { index: 1 }],
}], }],
forwards: vec![Forward { name: "a" }], exports: vec![Export {
name: "ab",
function_type: 1,
}],
implementations: vec![Implementation {
core_function_type: 2,
adapter_function_type: 3,
}],
}, },
&[ &[
0x00, // type section
0x01, // 1 type
0x01, // list of 1 item
0x00, // S8
0x01, // list of 1 item
0x01, // S16
//
0x01, // import section
0x01, // 1 import
0x02, // string of 2 bytes
0x61, 0x62, // "a", "b"
0x01, // string of 1 byte
0x63, // "c"
0x00, // signature type
//
0x02, // adapter section
0x01, // 1 adapter
0x00, // function type
0x01, // list of 1 item
0x00, 0x01, // ArgumentGet { index: 1 }
//
0x03, // export section
0x01, // 1 export 0x01, // 1 export
0x02, // string of 2 bytes 0x02, // string of 2 bytes
0x61, 0x62, // "a", "b" 0x61, 0x62, // "a", "b"
0x01, // list of 1 item 0x01, // function type
0x7f, // I32 //
0x01, // list of 1 item 0x04, // implementation section
0x7f, // I32 0x01, // 1 implementation
0x01, // 1 type 0x02, // core function type
0x02, // string of 2 bytes 0x03, // adapter function type
0x61, 0x62, // "a", "b"
0x02, // list of 2 items
0x02, // string of 2 bytes
0x63, 0x64, // "c", "d"
0x01, // string of 1 byte
0x65, // "e"
0x02, // list of 2 items
0x7f, // I32
0x7f, // I32
0x01, // 1 import
0x01, // string of 1 byte
0x61, // "a"
0x01, // string of 1 byte
0x62, // "b"
0x01, // list of 1 item
0x7f, // I32
0x01, // list of 1 item
0x7e, // I64
0x01, // 1 adapter
0x00, // adapter kind: import
0x01, // string of 1 byte
0x61, // "a"
0x01, // string of 1 byte
0x62, // "b"
0x01, // list of 1 item
0x7f, // I32
0x01, // list of 1 item
0x7f, // I32
0x01, // list of 1 item
0x00, 0x01, // ArgumentGet { index: 1 }
0x01, // 1 adapter
0x01, // string of 1 byte
0x61, // "a"
] ]
); );
} }
@ -705,44 +560,92 @@ mod tests {
Instruction::WriteUtf8 { Instruction::WriteUtf8 {
allocator_name: "abc", allocator_name: "abc",
}, },
Instruction::AsWasm(InterfaceType::Int), Instruction::I32ToS8,
Instruction::AsInterface(InterfaceType::I64), Instruction::I32ToS8X,
Instruction::TableRefAdd, Instruction::I32ToU8,
Instruction::TableRefGet, Instruction::I32ToS16,
Instruction::CallMethod(1), Instruction::I32ToS16X,
Instruction::MakeRecord(InterfaceType::I32), Instruction::I32ToU16,
Instruction::GetField(InterfaceType::Int, 2), Instruction::I32ToS32,
Instruction::Const(InterfaceType::I32, 1), Instruction::I32ToU32,
Instruction::FoldSeq(1), Instruction::I32ToS64,
Instruction::Add(InterfaceType::I32), Instruction::I32ToU64,
Instruction::MemToSeq(InterfaceType::I32, "abc"), Instruction::I64ToS8,
Instruction::Load(InterfaceType::I32, "abc"), Instruction::I64ToS8X,
Instruction::SeqNew(InterfaceType::I32), Instruction::I64ToU8,
Instruction::ListPush, Instruction::I64ToS16,
Instruction::RepeatUntil(1, 2), Instruction::I64ToS16X,
Instruction::I64ToU16,
Instruction::I64ToS32,
Instruction::I64ToS32X,
Instruction::I64ToU32,
Instruction::I64ToS64,
Instruction::I64ToU64,
Instruction::S8ToI32,
Instruction::U8ToI32,
Instruction::S16ToI32,
Instruction::U16ToI32,
Instruction::S32ToI32,
Instruction::U32ToI32,
Instruction::S64ToI32,
Instruction::S64ToI32X,
Instruction::U64ToI32,
Instruction::U64ToI32X,
Instruction::S8ToI64,
Instruction::U8ToI64,
Instruction::S16ToI64,
Instruction::U16ToI64,
Instruction::S32ToI64,
Instruction::U32ToI64,
Instruction::S64ToI64,
Instruction::U64ToI64,
], ],
&[ &[
0x14, // list of 20 items 0x2c, // list of 44 items
0x00, 0x01, // ArgumentGet { index: 1 } 0x00, 0x01, // ArgumentGet { index: 1 }
0x01, 0x01, // Call { function_index: 1 } 0x01, 0x01, // Call { function_index: 1 }
0x02, 0x03, 0x61, 0x62, 0x63, // CallExport { export_name: "abc" } 0x02, 0x03, 0x61, 0x62, 0x63, // CallExport { export_name: "abc" }
0x03, // ReadUtf8 0x03, // ReadUtf8
0x04, 0x03, 0x61, 0x62, 0x63, // WriteUtf8 { allocator_name: "abc" } 0x04, 0x03, 0x61, 0x62, 0x63, // WriteUtf8 { allocator_name: "abc" }
0x05, 0xff, 0xff, 0x01, // AsWasm(Int) 0x07, // I32ToS8
0x06, 0x7e, // AsInterface(I64) 0x08, // I32ToS8X
0x07, // TableRefAdd 0x09, // I32ToU8
0x08, // TableRefGet 0x0a, // I32ToS16
0x09, 0x01, // CallMethod(1) 0x0b, // I32ToS16X
0x0a, 0x7f, // MakeRecord(I32) 0x0c, // I32ToU16
0x0c, 0xff, 0xff, 0x01, 0x02, // GetField(Int, 2) 0x0d, // I32ToS32
0x0d, 0x7f, 0x01, // Const(I32, 1) 0x0e, // I32ToU32
0x0e, 0x01, // FoldSeq(1) 0x0f, // I32ToS64
0x0f, 0x7f, // Add(I32) 0x10, // I32ToU64
0x10, 0x7f, 0x03, 0x61, 0x62, 0x63, // MemToSeq(I32, "abc") 0x11, // I64ToS8
0x11, 0x7f, 0x03, 0x61, 0x62, 0x63, // Load(I32, "abc") 0x12, // I64ToS8X
0x12, 0x7f, // SeqNew(I32) 0x13, // I64ToU8
0x13, // ListPush 0x14, // I64ToS16
0x14, 0x01, 0x02, // RepeatUntil(1, 2) 0x15, // I64ToS16X
0x16, // I64ToU16
0x17, // I64ToS32
0x18, // I64ToS32X
0x19, // I64ToU32
0x1a, // I64ToS64
0x1b, // I64ToU64
0x1c, // S8ToI32
0x1d, // U8ToI32
0x1e, // S16ToI32
0x1f, // U16ToI32
0x20, // S32ToI32
0x21, // U32ToI32
0x22, // S64ToI32
0x23, // S64ToI32X
0x24, // U64ToI32
0x25, // U64ToI32X
0x26, // S8ToI64
0x27, // U8ToI64
0x28, // S16ToI64
0x29, // U16ToI64
0x2a, // S32ToI64
0x2b, // U32ToI64
0x2c, // S64ToI64
0x2d, // U64ToI64
] ]
); );
} }

View File

@ -9,105 +9,72 @@
//! interpreter::Instruction, //! interpreter::Instruction,
//! }; //! };
//! //!
//! # fn main() {
//! let input: String = (&Interfaces { //! let input: String = (&Interfaces {
//! exports: vec![ //! types: vec![Type {
//! Export { //! inputs: vec![InterfaceType::I32],
//! name: "foo", //! outputs: vec![InterfaceType::S8],
//! input_types: vec![InterfaceType::I32], //! }],
//! output_types: vec![], //! imports: vec![Import {
//! }, //! namespace: "ns",
//! Export { //! name: "foo",
//! name: "bar", //! signature_type: 0,
//! input_types: vec![], //! }],
//! output_types: vec![], //! adapters: vec![Adapter {
//! }, //! function_type: 0,
//! ], //! instructions: vec![Instruction::ArgumentGet { index: 42 }],
//! types: vec![], //! }],
//! imports: vec![ //! exports: vec![Export {
//! Import { //! name: "bar",
//! namespace: "ns", //! function_type: 0,
//! name: "foo", //! }],
//! input_types: vec![], //! implementations: vec![Implementation {
//! output_types: vec![InterfaceType::I32], //! core_function_type: 0,
//! }, //! adapter_function_type: 1,
//! Import { //! }],
//! namespace: "ns",
//! name: "bar",
//! input_types: vec![],
//! output_types: vec![],
//! },
//! ],
//! adapters: vec![
//! Adapter::Import {
//! namespace: "ns",
//! name: "foo",
//! input_types: vec![InterfaceType::I32],
//! output_types: vec![],
//! instructions: vec![Instruction::ArgumentGet { index: 42 }],
//! },
//! Adapter::Export {
//! name: "bar",
//! input_types: vec![],
//! output_types: vec![],
//! instructions: vec![Instruction::ArgumentGet { index: 42 }],
//! },
//! ],
//! forwards: vec![Forward { name: "main" }],
//! }) //! })
//! .to_string(); //! .to_string();
//! let output = r#";; Interfaces //! let output = r#";; Types
//! //! (@interface type (func
//! ;; Interface, Export foo
//! (@interface export "foo"
//! (param i32))
//!
//! ;; Interface, Export bar
//! (@interface export "bar")
//!
//! ;; Interface, Import ns.foo
//! (@interface func $ns_foo (import "ns" "foo")
//! (result i32))
//!
//! ;; Interface, Import ns.bar
//! (@interface func $ns_bar (import "ns" "bar"))
//!
//! ;; Interface, Adapter ns.foo
//! (@interface adapt (import "ns" "foo")
//! (param i32) //! (param i32)
//! (result s8)))
//!
//! ;; Imports
//! (@interface import "ns" "foo" (func (type 0)))
//!
//! ;; Adapters
//! (@interface func (type 0)
//! arg.get 42) //! arg.get 42)
//! //!
//! ;; Interface, Adapter bar //! ;; Exports
//! (@interface adapt (export "bar") //! (@interface export "bar" (func 0))
//! arg.get 42)
//! //!
//! ;; Interface, Forward main //! ;; Implementations
//! (@interface forward (export "main"))"#; //! (@interface implement (func 0) (func 1))"#;
//! //!
//! assert_eq!(input, output); //! assert_eq!(input, output);
//! # }
//! ``` //! ```
use crate::{ use crate::{ast::*, interpreter::Instruction};
ast::{Adapter, Export, Forward, Import, InterfaceType, Interfaces, Type},
interpreter::Instruction,
};
use std::string::ToString; use std::string::ToString;
/// Encode an `InterfaceType` into a string. /// Encode an `InterfaceType` into a string.
impl ToString for &InterfaceType { impl ToString for &InterfaceType {
fn to_string(&self) -> String { fn to_string(&self) -> String {
match self { match self {
InterfaceType::Int => "Int".into(), InterfaceType::S8 => "s8".into(),
InterfaceType::Float => "Float".into(), InterfaceType::S16 => "s16".into(),
InterfaceType::Any => "Any".into(), InterfaceType::S32 => "s32".into(),
InterfaceType::String => "String".into(), InterfaceType::S64 => "s64".into(),
InterfaceType::Seq => "Seq".into(), InterfaceType::U8 => "u8".into(),
InterfaceType::I32 => "i32".into(), InterfaceType::U16 => "u16".into(),
InterfaceType::I64 => "i64".into(), InterfaceType::U32 => "u32".into(),
InterfaceType::U64 => "u64".into(),
InterfaceType::F32 => "f32".into(), InterfaceType::F32 => "f32".into(),
InterfaceType::F64 => "f64".into(), InterfaceType::F64 => "f64".into(),
InterfaceType::AnyRef => "anyref".into(), InterfaceType::String => "string".into(),
InterfaceType::Anyref => "anyref".into(),
InterfaceType::I32 => "i32".into(),
InterfaceType::I64 => "i64".into(),
} }
} }
} }
@ -123,39 +90,45 @@ impl<'input> ToString for &Instruction<'input> {
Instruction::WriteUtf8 { allocator_name } => { Instruction::WriteUtf8 { allocator_name } => {
format!(r#"write-utf8 "{}""#, allocator_name) format!(r#"write-utf8 "{}""#, allocator_name)
} }
Instruction::AsWasm(interface_type) => { Instruction::I32ToS8 => "i32-to-s8".into(),
format!("as-wasm {}", interface_type.to_string()) Instruction::I32ToS8X => "i32-to-s8x".into(),
} Instruction::I32ToU8 => "i32-to-u8".into(),
Instruction::AsInterface(interface_type) => { Instruction::I32ToS16 => "i32-to-s16".into(),
format!("as-interface {}", interface_type.to_string()) Instruction::I32ToS16X => "i32-to-s16x".into(),
} Instruction::I32ToU16 => "i32-to-u16".into(),
Instruction::TableRefAdd => "table-ref-add".into(), Instruction::I32ToS32 => "i32-to-s32".into(),
Instruction::TableRefGet => "table-ref-get".into(), Instruction::I32ToU32 => "i32-to-u32".into(),
Instruction::CallMethod(index) => format!("call-method {}", index), Instruction::I32ToS64 => "i32-to-s64".into(),
Instruction::MakeRecord(interface_type) => { Instruction::I32ToU64 => "i32-to-u64".into(),
format!("make-record {}", interface_type.to_string()) Instruction::I64ToS8 => "i64-to-s8".into(),
} Instruction::I64ToS8X => "i64-to-s8x".into(),
Instruction::GetField(interface_type, field_index) => { Instruction::I64ToU8 => "i64-to-u8".into(),
format!("get-field {} {}", interface_type.to_string(), field_index) Instruction::I64ToS16 => "i64-to-s16".into(),
} Instruction::I64ToS16X => "i64-to-s16x".into(),
Instruction::Const(interface_type, value) => { Instruction::I64ToU16 => "i64-to-u16".into(),
format!("const {} {}", interface_type.to_string(), value) Instruction::I64ToS32 => "i64-to-s32".into(),
} Instruction::I64ToS32X => "i64-to-s32x".into(),
Instruction::FoldSeq(import_index) => format!("fold-seq {}", import_index), Instruction::I64ToU32 => "i64-to-u32".into(),
Instruction::Add(interface_type) => format!("add {}", interface_type.to_string()), Instruction::I64ToS64 => "i64-to-s64".into(),
Instruction::MemToSeq(interface_type, memory) => { Instruction::I64ToU64 => "i64-to-u64".into(),
format!(r#"mem-to-seq {} "{}""#, interface_type.to_string(), memory) Instruction::S8ToI32 => "s8-to-i32".into(),
} Instruction::U8ToI32 => "u8-to-i32".into(),
Instruction::Load(interface_type, memory) => { Instruction::S16ToI32 => "s16-to-i32".into(),
format!(r#"load {} "{}""#, interface_type.to_string(), memory) Instruction::U16ToI32 => "u16-to-i32".into(),
} Instruction::S32ToI32 => "s32-to-i32".into(),
Instruction::SeqNew(interface_type) => { Instruction::U32ToI32 => "u32-to-i32".into(),
format!("seq.new {}", interface_type.to_string()) Instruction::S64ToI32 => "s64-to-i32".into(),
} Instruction::S64ToI32X => "s64-to-i32x".into(),
Instruction::ListPush => "list.push".into(), Instruction::U64ToI32 => "u64-to-i32".into(),
Instruction::RepeatUntil(condition_index, step_index) => { Instruction::U64ToI32X => "u64-to-i32x".into(),
format!("repeat-until {} {}", condition_index, step_index) Instruction::S8ToI64 => "s8-to-i64".into(),
} Instruction::U8ToI64 => "u8-to-i64".into(),
Instruction::S16ToI64 => "s16-to-i64".into(),
Instruction::U16ToI64 => "u16-to-i64".into(),
Instruction::S32ToI64 => "s32-to-i64".into(),
Instruction::U32ToI64 => "u32-to-i64".into(),
Instruction::S64ToI64 => "s64-to-i64".into(),
Instruction::U64ToI64 => "u64-to-i64".into(),
} }
} }
} }
@ -198,34 +171,25 @@ fn output_types_to_result(output_types: &[InterfaceType]) -> String {
} }
} }
/// Encode an `Export` into a string. /// Encode a `Type` into a string.
impl<'input> ToString for &Export<'input> { impl<'input> ToString for &Type {
fn to_string(&self) -> String { fn to_string(&self) -> String {
format!( format!(
r#"(@interface export "{name}"{inputs}{outputs})"#, r#"(@interface type (func{inputs}{outputs}))"#,
name = self.name, inputs = input_types_to_param(&self.inputs),
inputs = input_types_to_param(&self.input_types), outputs = output_types_to_result(&self.outputs),
outputs = output_types_to_result(&self.output_types),
) )
} }
} }
/// Encode a `Type` into a string.
impl<'input> ToString for &Type<'input> {
fn to_string(&self) -> String {
todo!("To be implemented.")
}
}
/// Encode an `Import` into a string. /// Encode an `Import` into a string.
impl<'input> ToString for &Import<'input> { impl<'input> ToString for &Import<'input> {
fn to_string(&self) -> String { fn to_string(&self) -> String {
format!( format!(
r#"(@interface func ${namespace}_{name} (import "{namespace}" "{name}"){inputs}{outputs})"#, r#"(@interface import "{namespace}" "{name}" (func (type {type})))"#,
namespace = self.namespace, namespace = self.namespace,
name = self.name, name = self.name,
inputs = input_types_to_param(&self.input_types), type = self.signature_type,
outputs = output_types_to_result(&self.output_types),
) )
} }
} }
@ -233,60 +197,39 @@ impl<'input> ToString for &Import<'input> {
/// Encode an `Adapter` into a string. /// Encode an `Adapter` into a string.
impl<'input> ToString for &Adapter<'input> { impl<'input> ToString for &Adapter<'input> {
fn to_string(&self) -> String { fn to_string(&self) -> String {
match self { format!(
Adapter::Import { r#"(@interface func (type {function_type}){instructions})"#,
namespace, function_type = self.function_type,
name, instructions =
input_types, self.instructions
output_types, .iter()
instructions, .fold(String::new(), |mut accumulator, instruction| {
} => format!( accumulator.push_str("\n ");
r#"(@interface adapt (import "{namespace}" "{name}"){inputs}{outputs}{instructions})"#, accumulator.push_str(&instruction.to_string());
namespace = namespace, accumulator
name = name, }),
inputs = input_types_to_param(&input_types), )
outputs = output_types_to_result(&output_types),
instructions =
instructions
.iter()
.fold(String::new(), |mut accumulator, instruction| {
accumulator.push_str("\n ");
accumulator.push_str(&instruction.to_string());
accumulator
}),
),
Adapter::Export {
name,
input_types,
output_types,
instructions,
} => format!(
r#"(@interface adapt (export "{name}"){inputs}{outputs}{instructions})"#,
name = name,
inputs = input_types_to_param(&input_types),
outputs = output_types_to_result(&output_types),
instructions =
instructions
.iter()
.fold(String::new(), |mut accumulator, instruction| {
accumulator.push_str("\n ");
accumulator.push_str(&instruction.to_string());
accumulator
}),
),
_ => todo!("To be implemented."),
}
} }
} }
/// Encode a `Forward` into a string. /// Encode an `Export` into a string.
impl<'input> ToString for &Forward<'input> { impl<'input> ToString for &Export<'input> {
fn to_string(&self) -> String { fn to_string(&self) -> String {
format!( format!(
r#"(@interface forward (export "{name}"))"#, r#"(@interface export "{name}" (func {type}))"#,
name = self.name, name = self.name,
type = self.function_type,
)
}
}
/// Encode an `Implementation` into a string.
impl<'input> ToString for &Implementation {
fn to_string(&self) -> String {
format!(
r#"(@interface implement (func {core_function_type}) (func {adapter_function_type}))"#,
core_function_type = self.core_function_type,
adapter_function_type = self.adapter_function_type,
) )
} }
} }
@ -294,22 +237,13 @@ impl<'input> ToString for &Forward<'input> {
/// Encode an `Interfaces` into a string. /// Encode an `Interfaces` into a string.
impl<'input> ToString for &Interfaces<'input> { impl<'input> ToString for &Interfaces<'input> {
fn to_string(&self) -> String { fn to_string(&self) -> String {
let mut output = String::from(";; Interfaces"); let mut output = String::new();
let exports = self
.exports
.iter()
.fold(String::new(), |mut accumulator, export| {
accumulator.push_str(&format!("\n\n;; Interface, Export {}\n", export.name));
accumulator.push_str(&export.to_string());
accumulator
});
let types = self let types = self
.types .types
.iter() .iter()
.fold(String::new(), |mut accumulator, ty| { .fold(String::new(), |mut accumulator, ty| {
accumulator.push_str(&format!("\n\n;; Interface, Ty {}\n", ty.name)); accumulator.push('\n');
accumulator.push_str(&ty.to_string()); accumulator.push_str(&ty.to_string());
accumulator accumulator
}); });
@ -318,10 +252,7 @@ impl<'input> ToString for &Interfaces<'input> {
.imports .imports
.iter() .iter()
.fold(String::new(), |mut accumulator, import| { .fold(String::new(), |mut accumulator, import| {
accumulator.push_str(&format!( accumulator.push('\n');
"\n\n;; Interface, Import {}.{}\n",
import.namespace, import.name
));
accumulator.push_str(&import.to_string()); accumulator.push_str(&import.to_string());
accumulator accumulator
}); });
@ -330,38 +261,67 @@ impl<'input> ToString for &Interfaces<'input> {
.adapters .adapters
.iter() .iter()
.fold(String::new(), |mut accumulator, adapter| { .fold(String::new(), |mut accumulator, adapter| {
match adapter { accumulator.push('\n');
Adapter::Import {
namespace, name, ..
} => accumulator.push_str(&format!(
"\n\n;; Interface, Adapter {}.{}\n",
namespace, name
)),
Adapter::Export { name, .. } => {
accumulator.push_str(&format!("\n\n;; Interface, Adapter {}\n", name))
}
_ => todo!("To be implemented."),
}
accumulator.push_str(&adapter.to_string()); accumulator.push_str(&adapter.to_string());
accumulator accumulator
}); });
let forwards = self let exports = self
.forwards .exports
.iter() .iter()
.fold(String::new(), |mut accumulator, forward| { .fold(String::new(), |mut accumulator, export| {
accumulator.push_str(&format!("\n\n;; Interface, Forward {}\n", forward.name)); accumulator.push('\n');
accumulator.push_str(&forward.to_string()); accumulator.push_str(&export.to_string());
accumulator accumulator
}); });
output.push_str(&exports); let implementations =
output.push_str(&types); self.implementations
output.push_str(&imports); .iter()
output.push_str(&adapters); .fold(String::new(), |mut accumulator, implementation| {
output.push_str(&forwards); accumulator.push('\n');
accumulator.push_str(&implementation.to_string());
accumulator
});
let separator = |output: &mut String| {
if !output.is_empty() {
output.push_str("\n\n");
}
};
if !types.is_empty() {
output.push_str(";; Types");
output.push_str(&types);
}
separator(&mut output);
if !imports.is_empty() {
output.push_str(";; Imports");
output.push_str(&imports);
}
separator(&mut output);
if !adapters.is_empty() {
output.push_str(";; Adapters");
output.push_str(&adapters);
}
separator(&mut output);
if !exports.is_empty() {
output.push_str(";; Exports");
output.push_str(&exports);
}
separator(&mut output);
if !implementations.is_empty() {
output.push_str(";; Implementations");
output.push_str(&implementations);
}
output output
} }
@ -374,19 +334,24 @@ mod tests {
#[test] #[test]
fn test_interface_types() { fn test_interface_types() {
let inputs: Vec<String> = vec![ let inputs: Vec<String> = vec![
(&InterfaceType::Int).to_string(), (&InterfaceType::S8).to_string(),
(&InterfaceType::Float).to_string(), (&InterfaceType::S16).to_string(),
(&InterfaceType::Any).to_string(), (&InterfaceType::S32).to_string(),
(&InterfaceType::String).to_string(), (&InterfaceType::S64).to_string(),
(&InterfaceType::Seq).to_string(), (&InterfaceType::U8).to_string(),
(&InterfaceType::I32).to_string(), (&InterfaceType::U16).to_string(),
(&InterfaceType::I64).to_string(), (&InterfaceType::U32).to_string(),
(&InterfaceType::U64).to_string(),
(&InterfaceType::F32).to_string(), (&InterfaceType::F32).to_string(),
(&InterfaceType::F64).to_string(), (&InterfaceType::F64).to_string(),
(&InterfaceType::AnyRef).to_string(), (&InterfaceType::String).to_string(),
(&InterfaceType::Anyref).to_string(),
(&InterfaceType::I32).to_string(),
(&InterfaceType::I64).to_string(),
]; ];
let outputs = vec![ let outputs = vec![
"Int", "Float", "Any", "String", "Seq", "i32", "i64", "f32", "f64", "anyref", "s8", "s16", "s32", "s64", "u8", "u16", "u32", "u64", "f32", "f64", "string", "anyref",
"i32", "i64",
]; ];
assert_eq!(inputs, outputs); assert_eq!(inputs, outputs);
@ -403,21 +368,45 @@ mod tests {
allocator_name: "foo", allocator_name: "foo",
}) })
.to_string(), .to_string(),
(&Instruction::AsWasm(InterfaceType::Int)).to_string(), (&Instruction::I32ToS8).to_string(),
(&Instruction::AsInterface(InterfaceType::AnyRef)).to_string(), (&Instruction::I32ToS8X).to_string(),
(&Instruction::TableRefAdd).to_string(), (&Instruction::I32ToU8).to_string(),
(&Instruction::TableRefGet).to_string(), (&Instruction::I32ToS16).to_string(),
(&Instruction::CallMethod(7)).to_string(), (&Instruction::I32ToS16X).to_string(),
(&Instruction::MakeRecord(InterfaceType::Int)).to_string(), (&Instruction::I32ToU16).to_string(),
(&Instruction::GetField(InterfaceType::Int, 7)).to_string(), (&Instruction::I32ToS32).to_string(),
(&Instruction::Const(InterfaceType::I32, 7)).to_string(), (&Instruction::I32ToU32).to_string(),
(&Instruction::FoldSeq(7)).to_string(), (&Instruction::I32ToS64).to_string(),
(&Instruction::Add(InterfaceType::Int)).to_string(), (&Instruction::I32ToU64).to_string(),
(&Instruction::MemToSeq(InterfaceType::Int, "foo")).to_string(), (&Instruction::I64ToS8).to_string(),
(&Instruction::Load(InterfaceType::Int, "foo")).to_string(), (&Instruction::I64ToS8X).to_string(),
(&Instruction::SeqNew(InterfaceType::Int)).to_string(), (&Instruction::I64ToU8).to_string(),
(&Instruction::ListPush).to_string(), (&Instruction::I64ToS16).to_string(),
(&Instruction::RepeatUntil(1, 2)).to_string(), (&Instruction::I64ToS16X).to_string(),
(&Instruction::I64ToU16).to_string(),
(&Instruction::I64ToS32).to_string(),
(&Instruction::I64ToS32X).to_string(),
(&Instruction::I64ToU32).to_string(),
(&Instruction::I64ToS64).to_string(),
(&Instruction::I64ToU64).to_string(),
(&Instruction::S8ToI32).to_string(),
(&Instruction::U8ToI32).to_string(),
(&Instruction::S16ToI32).to_string(),
(&Instruction::U16ToI32).to_string(),
(&Instruction::S32ToI32).to_string(),
(&Instruction::U32ToI32).to_string(),
(&Instruction::S64ToI32).to_string(),
(&Instruction::S64ToI32X).to_string(),
(&Instruction::U64ToI32).to_string(),
(&Instruction::U64ToI32X).to_string(),
(&Instruction::S8ToI64).to_string(),
(&Instruction::U8ToI64).to_string(),
(&Instruction::S16ToI64).to_string(),
(&Instruction::U16ToI64).to_string(),
(&Instruction::S32ToI64).to_string(),
(&Instruction::U32ToI64).to_string(),
(&Instruction::S64ToI64).to_string(),
(&Instruction::U64ToI64).to_string(),
]; ];
let outputs = vec![ let outputs = vec![
"arg.get 7", "arg.get 7",
@ -425,21 +414,83 @@ mod tests {
r#"call-export "foo""#, r#"call-export "foo""#,
"read-utf8", "read-utf8",
r#"write-utf8 "foo""#, r#"write-utf8 "foo""#,
"as-wasm Int", "i32-to-s8",
"as-interface anyref", "i32-to-s8x",
"table-ref-add", "i32-to-u8",
"table-ref-get", "i32-to-s16",
"call-method 7", "i32-to-s16x",
"make-record Int", "i32-to-u16",
"get-field Int 7", "i32-to-s32",
"const i32 7", "i32-to-u32",
"fold-seq 7", "i32-to-s64",
"add Int", "i32-to-u64",
r#"mem-to-seq Int "foo""#, "i64-to-s8",
r#"load Int "foo""#, "i64-to-s8x",
"seq.new Int", "i64-to-u8",
"list.push", "i64-to-s16",
"repeat-until 1 2", "i64-to-s16x",
"i64-to-u16",
"i64-to-s32",
"i64-to-s32x",
"i64-to-u32",
"i64-to-s64",
"i64-to-u64",
"s8-to-i32",
"u8-to-i32",
"s16-to-i32",
"u16-to-i32",
"s32-to-i32",
"u32-to-i32",
"s64-to-i32",
"s64-to-i32x",
"u64-to-i32",
"u64-to-i32x",
"s8-to-i64",
"u8-to-i64",
"s16-to-i64",
"u16-to-i64",
"s32-to-i64",
"u32-to-i64",
"s64-to-i64",
"u64-to-i64",
];
assert_eq!(inputs, outputs);
}
#[test]
fn test_types() {
let inputs: Vec<String> = vec![
(&Type {
inputs: vec![InterfaceType::I32, InterfaceType::F32],
outputs: vec![InterfaceType::I32],
})
.to_string(),
(&Type {
inputs: vec![InterfaceType::I32],
outputs: vec![],
})
.to_string(),
(&Type {
inputs: vec![],
outputs: vec![InterfaceType::I32],
})
.to_string(),
(&Type {
inputs: vec![],
outputs: vec![],
})
.to_string(),
];
let outputs = vec![
r#"(@interface type (func
(param i32 f32)
(result i32)))"#,
r#"(@interface type (func
(param i32)))"#,
r#"(@interface type (func
(result i32)))"#,
r#"(@interface type (func))"#,
]; ];
assert_eq!(inputs, outputs); assert_eq!(inputs, outputs);
@ -447,187 +498,38 @@ mod tests {
#[test] #[test]
fn test_exports() { fn test_exports() {
let inputs: Vec<String> = vec![ let input = (&Export {
(&Export { name: "foo",
name: "foo", function_type: 0,
input_types: vec![InterfaceType::I32, InterfaceType::F32], })
output_types: vec![InterfaceType::I32], .to_string();
}) let output = r#"(@interface export "foo" (func 0))"#;
.to_string(),
(&Export {
name: "foo",
input_types: vec![InterfaceType::I32],
output_types: vec![],
})
.to_string(),
(&Export {
name: "foo",
input_types: vec![],
output_types: vec![InterfaceType::I32],
})
.to_string(),
(&Export {
name: "foo",
input_types: vec![],
output_types: vec![],
})
.to_string(),
];
let outputs = vec![
r#"(@interface export "foo"
(param i32 f32)
(result i32))"#,
r#"(@interface export "foo"
(param i32))"#,
r#"(@interface export "foo"
(result i32))"#,
r#"(@interface export "foo")"#,
];
assert_eq!(inputs, outputs); assert_eq!(input, output);
} }
#[test] #[test]
fn test_imports() { fn test_imports() {
let inputs: Vec<String> = vec![ let input = (&Import {
(&Import { namespace: "ns",
namespace: "ns", name: "foo",
name: "foo", signature_type: 0,
input_types: vec![InterfaceType::Int, InterfaceType::String], })
output_types: vec![InterfaceType::String], .to_string();
}) let output = r#"(@interface import "ns" "foo" (func (type 0)))"#;
.to_string(),
(&Import {
namespace: "ns",
name: "foo",
input_types: vec![InterfaceType::String],
output_types: vec![],
})
.to_string(),
(&Import {
namespace: "ns",
name: "foo",
input_types: vec![],
output_types: vec![InterfaceType::String],
})
.to_string(),
(&Import {
namespace: "ns",
name: "foo",
input_types: vec![],
output_types: vec![],
})
.to_string(),
];
let outputs = vec![
r#"(@interface func $ns_foo (import "ns" "foo")
(param Int String)
(result String))"#,
r#"(@interface func $ns_foo (import "ns" "foo")
(param String))"#,
r#"(@interface func $ns_foo (import "ns" "foo")
(result String))"#,
r#"(@interface func $ns_foo (import "ns" "foo"))"#,
];
assert_eq!(inputs, outputs); assert_eq!(input, output);
} }
#[test] #[test]
fn test_adapters() { fn test_adapter() {
let inputs: Vec<String> = vec![ let input = (&Adapter {
(&Adapter::Import { function_type: 0,
namespace: "ns", instructions: vec![Instruction::ArgumentGet { index: 42 }],
name: "foo", })
input_types: vec![InterfaceType::I32, InterfaceType::F32], .to_string();
output_types: vec![InterfaceType::I32], let output = r#"(@interface func (type 0)
instructions: vec![ arg.get 42)"#;
Instruction::ArgumentGet { index: 0 },
Instruction::WriteUtf8 {
allocator_name: "hello",
},
Instruction::CallExport { export_name: "f" },
],
})
.to_string(),
(&Adapter::Import {
namespace: "ns",
name: "foo",
input_types: vec![InterfaceType::I32],
output_types: vec![],
instructions: vec![Instruction::CallExport { export_name: "f" }],
})
.to_string(),
(&Adapter::Import {
namespace: "ns",
name: "foo",
input_types: vec![],
output_types: vec![InterfaceType::I32],
instructions: vec![Instruction::CallExport { export_name: "f" }],
})
.to_string(),
(&Adapter::Export {
name: "foo",
input_types: vec![InterfaceType::I32, InterfaceType::F32],
output_types: vec![InterfaceType::I32],
instructions: vec![
Instruction::ArgumentGet { index: 0 },
Instruction::WriteUtf8 {
allocator_name: "hello",
},
Instruction::CallExport { export_name: "f" },
],
})
.to_string(),
(&Adapter::Export {
name: "foo",
input_types: vec![InterfaceType::I32],
output_types: vec![],
instructions: vec![Instruction::CallExport { export_name: "f" }],
})
.to_string(),
(&Adapter::Export {
name: "foo",
input_types: vec![],
output_types: vec![InterfaceType::I32],
instructions: vec![Instruction::CallExport { export_name: "f" }],
})
.to_string(),
];
let outputs = vec![
r#"(@interface adapt (import "ns" "foo")
(param i32 f32)
(result i32)
arg.get 0
write-utf8 "hello"
call-export "f")"#,
r#"(@interface adapt (import "ns" "foo")
(param i32)
call-export "f")"#,
r#"(@interface adapt (import "ns" "foo")
(result i32)
call-export "f")"#,
r#"(@interface adapt (export "foo")
(param i32 f32)
(result i32)
arg.get 0
write-utf8 "hello"
call-export "f")"#,
r#"(@interface adapt (export "foo")
(param i32)
call-export "f")"#,
r#"(@interface adapt (export "foo")
(result i32)
call-export "f")"#,
];
assert_eq!(inputs, outputs);
}
#[test]
fn test_forward() {
let input: String = (&Forward { name: "main" }).to_string();
let output = r#"(@interface forward (export "main"))"#;
assert_eq!(input, output); assert_eq!(input, output);
} }
@ -635,78 +537,46 @@ mod tests {
#[test] #[test]
fn test_interfaces() { fn test_interfaces() {
let input: String = (&Interfaces { let input: String = (&Interfaces {
exports: vec![ types: vec![Type {
Export { inputs: vec![InterfaceType::I32],
name: "foo", outputs: vec![InterfaceType::S8],
input_types: vec![InterfaceType::I32], }],
output_types: vec![], imports: vec![Import {
}, namespace: "ns",
Export { name: "foo",
name: "bar", signature_type: 0,
input_types: vec![], }],
output_types: vec![], adapters: vec![Adapter {
}, function_type: 0,
], instructions: vec![Instruction::ArgumentGet { index: 42 }],
types: vec![], }],
imports: vec![ exports: vec![Export {
Import { name: "bar",
namespace: "ns", function_type: 0,
name: "foo", }],
input_types: vec![], implementations: vec![Implementation {
output_types: vec![InterfaceType::I32], core_function_type: 0,
}, adapter_function_type: 1,
Import { }],
namespace: "ns",
name: "bar",
input_types: vec![],
output_types: vec![],
},
],
adapters: vec![
Adapter::Import {
namespace: "ns",
name: "foo",
input_types: vec![InterfaceType::I32],
output_types: vec![],
instructions: vec![Instruction::ArgumentGet { index: 42 }],
},
Adapter::Export {
name: "bar",
input_types: vec![],
output_types: vec![],
instructions: vec![Instruction::ArgumentGet { index: 42 }],
},
],
forwards: vec![Forward { name: "main" }],
}) })
.to_string(); .to_string();
let output = r#";; Interfaces let output = r#";; Types
(@interface type (func
;; Interface, Export foo
(@interface export "foo"
(param i32))
;; Interface, Export bar
(@interface export "bar")
;; Interface, Import ns.foo
(@interface func $ns_foo (import "ns" "foo")
(result i32))
;; Interface, Import ns.bar
(@interface func $ns_bar (import "ns" "bar"))
;; Interface, Adapter ns.foo
(@interface adapt (import "ns" "foo")
(param i32) (param i32)
(result s8)))
;; Imports
(@interface import "ns" "foo" (func (type 0)))
;; Adapters
(@interface func (type 0)
arg.get 42) arg.get 42)
;; Interface, Adapter bar ;; Exports
(@interface adapt (export "bar") (@interface export "bar" (func 0))
arg.get 42)
;; Interface, Forward main ;; Implementations
(@interface forward (export "main"))"#; (@interface implement (func 0) (func 1))"#;
assert_eq!(input, output); assert_eq!(input, output);
} }

View File

@ -1,4 +1,4 @@
use crate::ast::InterfaceType; //use crate::ast::InterfaceType;
/// Represents all the possible WIT instructions. /// Represents all the possible WIT instructions.
#[derive(PartialEq, Debug)] #[derive(PartialEq, Debug)]
@ -6,7 +6,7 @@ pub enum Instruction<'input> {
/// The `arg.get` instruction. /// The `arg.get` instruction.
ArgumentGet { ArgumentGet {
/// The argument index. /// The argument index.
index: u64, index: u32,
}, },
/// The `call` instruction. /// The `call` instruction.
@ -30,48 +30,120 @@ pub enum Instruction<'input> {
allocator_name: &'input str, allocator_name: &'input str,
}, },
/// The `as-wasm` instruction. /// The `i32-to-s8,` instruction.
AsWasm(InterfaceType), I32ToS8,
/// The `as-interface` instruction. /// The `i32-to-s8x,` instruction.
AsInterface(InterfaceType), I32ToS8X,
/// The `table-ref-add` instruction. /// The `i32-to-u8,` instruction.
TableRefAdd, I32ToU8,
/// The `table-ref-get` instruction. /// The `i32-to-s16,` instruction.
TableRefGet, I32ToS16,
/// The `call-method` instruction. /// The `i32-to-s16x,` instruction.
CallMethod(u64), I32ToS16X,
/// The `make-record` instruction. /// The `i32-to-u16,` instruction.
MakeRecord(InterfaceType), I32ToU16,
/// The `get-field` instruction. /// The `i32-to-s32,` instruction.
GetField(InterfaceType, u64), I32ToS32,
/// The `const` instruction. /// The `i32-to-u32,` instruction.
Const(InterfaceType, u64), I32ToU32,
/// The `fold-seq` instruction. /// The `i32-to-s64,` instruction.
FoldSeq(u64), I32ToS64,
/// The `add` instruction. /// The `i32-to-u64,` instruction.
Add(InterfaceType), I32ToU64,
/// The `mem-to-seq` instruction. /// The `i64-to-s8,` instruction.
MemToSeq(InterfaceType, &'input str), I64ToS8,
/// The `load` instruction. /// The `i64-to-s8x,` instruction.
Load(InterfaceType, &'input str), I64ToS8X,
/// The `seq.new` instruction. /// The `i64-to-u8,` instruction.
SeqNew(InterfaceType), I64ToU8,
/// The `list.push` instruction. /// The `i64-to-s16,` instruction.
ListPush, I64ToS16,
/// The `repeat-until` instruction. /// The `i64-to-s16x,` instruction.
RepeatUntil(u64, u64), I64ToS16X,
/// The `i64-to-u16,` instruction.
I64ToU16,
/// The `i64-to-s32,` instruction.
I64ToS32,
/// The `i64-to-s32x,` instruction.
I64ToS32X,
/// The `i64-to-u32,` instruction.
I64ToU32,
/// The `i64-to-s64,` instruction.
I64ToS64,
/// The `i64-to-u64,` instruction.
I64ToU64,
/// The `s8-to-i32,` instruction.
S8ToI32,
/// The `u8-to-i32,` instruction.
U8ToI32,
/// The `s16-to-i32,` instruction.
S16ToI32,
/// The `u16-to-i32,` instruction.
U16ToI32,
/// The `s32-to-i32,` instruction.
S32ToI32,
/// The `u32-to-i32,` instruction.
U32ToI32,
/// The `s64-to-i32,` instruction.
S64ToI32,
/// The `s64-to-i32x,` instruction.
S64ToI32X,
/// The `u64-to-i32,` instruction.
U64ToI32,
/// The `u64-to-i32x,` instruction.
U64ToI32X,
/// The `s8-to-i64,` instruction.
S8ToI64,
/// The `u8-to-i64,` instruction.
U8ToI64,
/// The `s16-to-i64,` instruction.
S16ToI64,
/// The `u16-to-i64,` instruction.
U16ToI64,
/// The `s32-to-i64,` instruction.
S32ToI64,
/// The `u32-to-i64,` instruction.
U32ToI64,
/// The `s64-to-i64,` instruction.
S64ToI64,
/// The `u64-to-i64,` instruction.
U64ToI64,
} }

View File

@ -1,9 +1,9 @@
executable_instruction!( executable_instruction!(
argument_get(index: u64, instruction_name: String) -> _ { argument_get(index: u32, instruction_name: String) -> _ {
move |runtime| -> _ { move |runtime| -> _ {
let invocation_inputs = runtime.invocation_inputs; let invocation_inputs = runtime.invocation_inputs;
if index >= (invocation_inputs.len() as u64) { if index >= (invocation_inputs.len() as u32) {
return Err(format!( return Err(format!(
"`{}` cannot access argument #{} because it doesn't exist.", "`{}` cannot access argument #{} because it doesn't exist.",
instruction_name, index instruction_name, index

View File

@ -66,7 +66,6 @@ pub(crate) type ExecutableInstruction<Instance, Export, LocalImport, Memory, Mem
/// Instruction, Interpreter, /// Instruction, Interpreter,
/// }; /// };
/// ///
/// # fn main() {
/// // 1. Creates an interpreter from a set of instructions. They will /// // 1. Creates an interpreter from a set of instructions. They will
/// // be transformed into executable instructions. /// // be transformed into executable instructions.
/// let interpreter: Interpreter<Instance, Export, LocalImport, Memory, MemoryView> = (&vec![ /// let interpreter: Interpreter<Instance, Export, LocalImport, Memory, MemoryView> = (&vec![
@ -116,7 +115,6 @@ pub(crate) type ExecutableInstruction<Instance, Export, LocalImport, Memory, Mem
/// ///
/// // 5. Read the stack to get the result. /// // 5. Read the stack to get the result.
/// assert_eq!(stack.as_slice(), &[InterfaceValue::I32(7)]); /// assert_eq!(stack.as_slice(), &[InterfaceValue::I32(7)]);
/// # }
/// ``` /// ```
pub struct Interpreter<Instance, Export, LocalImport, Memory, MemoryView> pub struct Interpreter<Instance, Export, LocalImport, Memory, MemoryView>
where where

View File

@ -6,29 +6,39 @@ pub use crate::ast::InterfaceType;
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum InterfaceValue { pub enum InterfaceValue {
Int(isize), S8(i8),
Float(f64), S16(i16),
Any(isize), S32(i32),
String(String), S64(i64),
// Seq(…), U8(u8),
I32(i32), U16(u16),
I64(i64), U32(u32),
U64(u64),
F32(f32), F32(f32),
F64(f64), F64(f64),
// AnyRef(…), String(String),
//Anyref(?),
I32(i32),
I64(i64),
} }
impl From<&InterfaceValue> for InterfaceType { impl From<&InterfaceValue> for InterfaceType {
fn from(value: &InterfaceValue) -> Self { fn from(value: &InterfaceValue) -> Self {
match value { match value {
InterfaceValue::Int(_) => Self::Int, InterfaceValue::S8(_) => Self::S8,
InterfaceValue::Float(_) => Self::Float, InterfaceValue::S16(_) => Self::S16,
InterfaceValue::Any(_) => Self::Any, InterfaceValue::S32(_) => Self::S32,
InterfaceValue::String(_) => Self::String, InterfaceValue::S64(_) => Self::S64,
InterfaceValue::I32(_) => Self::I32, InterfaceValue::U8(_) => Self::U8,
InterfaceValue::I64(_) => Self::I64, InterfaceValue::U16(_) => Self::U16,
InterfaceValue::U32(_) => Self::U32,
InterfaceValue::U64(_) => Self::U64,
InterfaceValue::F32(_) => Self::F32, InterfaceValue::F32(_) => Self::F32,
InterfaceValue::F64(_) => Self::F64, InterfaceValue::F64(_) => Self::F64,
InterfaceValue::String(_) => Self::String,
//InterfaceValue::Anyref(_) => Self::Anyref,
InterfaceValue::I32(_) => Self::I32,
InterfaceValue::I64(_) => Self::I64,
} }
} }
} }
@ -60,8 +70,14 @@ macro_rules! from_x_for_interface_value {
}; };
} }
from_x_for_interface_value!(i8, S8);
from_x_for_interface_value!(i16, S16);
from_x_for_interface_value!(u8, U8);
from_x_for_interface_value!(u16, U16);
from_x_for_interface_value!(u32, U32);
from_x_for_interface_value!(u64, U64);
from_x_for_interface_value!(f32, F32);
from_x_for_interface_value!(f64, F64);
from_x_for_interface_value!(String, String); from_x_for_interface_value!(String, String);
from_x_for_interface_value!(i32, I32); from_x_for_interface_value!(i32, I32);
from_x_for_interface_value!(i64, I64); from_x_for_interface_value!(i64, I64);
from_x_for_interface_value!(f32, F32);
from_x_for_interface_value!(f64, F64);

View File

@ -5,6 +5,11 @@ macro_rules! consume {
let (next_input, $parser_output) = $parser_expression; let (next_input, $parser_output) = $parser_expression;
$input = next_input; $input = next_input;
}; };
(($input:ident, mut $parser_output:ident) = $parser_expression:expr) => {
let (next_input, mut $parser_output) = $parser_expression;
$input = next_input;
};
} }
/// This macro creates an executable instruction for the interpreter. /// This macro creates an executable instruction for the interpreter.

View File

@ -6,30 +6,33 @@ use wasmer_interface_types::{
#[test] #[test]
fn test_binary_encoding_decoding_roundtrip() { fn test_binary_encoding_decoding_roundtrip() {
let original_ast = Interfaces { let original_ast = Interfaces {
exports: vec![Export { types: vec![
name: "ab", Type {
input_types: vec![InterfaceType::I32], inputs: vec![],
output_types: vec![InterfaceType::I32], outputs: vec![],
}], },
types: vec![Type::new( Type {
"ab", inputs: vec![InterfaceType::I32, InterfaceType::I32],
vec!["cd", "e"], outputs: vec![InterfaceType::S32],
vec![InterfaceType::I32, InterfaceType::I32], },
)], ],
imports: vec![Import { imports: vec![Import {
namespace: "a", namespace: "a",
name: "b", name: "b",
input_types: vec![InterfaceType::I32], signature_type: 0,
output_types: vec![InterfaceType::I64],
}], }],
adapters: vec![Adapter::Import { adapters: vec![Adapter {
namespace: "a", function_type: 0,
name: "b",
input_types: vec![InterfaceType::I32],
output_types: vec![InterfaceType::I32],
instructions: vec![Instruction::ArgumentGet { index: 1 }], instructions: vec![Instruction::ArgumentGet { index: 1 }],
}], }],
forwards: vec![Forward { name: "a" }], exports: vec![Export {
name: "ab",
function_type: 1,
}],
implementations: vec![Implementation {
core_function_type: 0,
adapter_function_type: 0,
}],
}; };
let mut binary = vec![]; let mut binary = vec![];