mirror of
https://github.com/fluencelabs/wasmer
synced 2025-04-25 10:22:19 +00:00
Merge #1244
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:
commit
85a3bb7148
@ -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
@ -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() {
|
||||||
|
InterfaceKind::Type.to_bytes(writer)?;
|
||||||
self.types.to_bytes(writer)?;
|
self.types.to_bytes(writer)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.imports.is_empty() {
|
||||||
|
InterfaceKind::Import.to_bytes(writer)?;
|
||||||
self.imports.to_bytes(writer)?;
|
self.imports.to_bytes(writer)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.adapters.is_empty() {
|
||||||
|
InterfaceKind::Adapter.to_bytes(writer)?;
|
||||||
self.adapters.to_bytes(writer)?;
|
self.adapters.to_bytes(writer)?;
|
||||||
self.forwards.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
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
//! },
|
|
||||||
//! Export {
|
|
||||||
//! name: "bar",
|
|
||||||
//! input_types: vec![],
|
|
||||||
//! output_types: vec![],
|
|
||||||
//! },
|
|
||||||
//! ],
|
|
||||||
//! types: vec![],
|
|
||||||
//! imports: vec![
|
|
||||||
//! Import {
|
|
||||||
//! namespace: "ns",
|
//! namespace: "ns",
|
||||||
//! name: "foo",
|
//! name: "foo",
|
||||||
//! input_types: vec![],
|
//! signature_type: 0,
|
||||||
//! output_types: vec![InterfaceType::I32],
|
//! }],
|
||||||
//! },
|
//! adapters: vec![Adapter {
|
||||||
//! Import {
|
//! function_type: 0,
|
||||||
//! 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 }],
|
//! instructions: vec![Instruction::ArgumentGet { index: 42 }],
|
||||||
//! },
|
//! }],
|
||||||
//! Adapter::Export {
|
//! exports: vec![Export {
|
||||||
//! name: "bar",
|
//! name: "bar",
|
||||||
//! input_types: vec![],
|
//! function_type: 0,
|
||||||
//! output_types: vec![],
|
//! }],
|
||||||
//! instructions: vec![Instruction::ArgumentGet { index: 42 }],
|
//! implementations: vec![Implementation {
|
||||||
//! },
|
//! core_function_type: 0,
|
||||||
//! ],
|
//! adapter_function_type: 1,
|
||||||
//! 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,
|
|
||||||
input_types,
|
|
||||||
output_types,
|
|
||||||
instructions,
|
|
||||||
} => format!(
|
|
||||||
r#"(@interface adapt (import "{namespace}" "{name}"){inputs}{outputs}{instructions})"#,
|
|
||||||
namespace = namespace,
|
|
||||||
name = name,
|
|
||||||
inputs = input_types_to_param(&input_types),
|
|
||||||
outputs = output_types_to_result(&output_types),
|
|
||||||
instructions =
|
instructions =
|
||||||
instructions
|
self.instructions
|
||||||
.iter()
|
.iter()
|
||||||
.fold(String::new(), |mut accumulator, instruction| {
|
.fold(String::new(), |mut accumulator, instruction| {
|
||||||
accumulator.push_str("\n ");
|
accumulator.push_str("\n ");
|
||||||
accumulator.push_str(&instruction.to_string());
|
accumulator.push_str(&instruction.to_string());
|
||||||
accumulator
|
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 =
|
||||||
|
self.implementations
|
||||||
|
.iter()
|
||||||
|
.fold(String::new(), |mut accumulator, implementation| {
|
||||||
|
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);
|
output.push_str(&types);
|
||||||
|
}
|
||||||
|
|
||||||
|
separator(&mut output);
|
||||||
|
|
||||||
|
if !imports.is_empty() {
|
||||||
|
output.push_str(";; Imports");
|
||||||
output.push_str(&imports);
|
output.push_str(&imports);
|
||||||
|
}
|
||||||
|
|
||||||
|
separator(&mut output);
|
||||||
|
|
||||||
|
if !adapters.is_empty() {
|
||||||
|
output.push_str(";; Adapters");
|
||||||
output.push_str(&adapters);
|
output.push_str(&adapters);
|
||||||
output.push_str(&forwards);
|
}
|
||||||
|
|
||||||
|
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",
|
||||||
input_types: vec![InterfaceType::I32, InterfaceType::F32],
|
function_type: 0,
|
||||||
output_types: vec![InterfaceType::I32],
|
|
||||||
})
|
})
|
||||||
.to_string(),
|
.to_string();
|
||||||
(&Export {
|
let output = r#"(@interface export "foo" (func 0))"#;
|
||||||
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",
|
||||||
input_types: vec![InterfaceType::Int, InterfaceType::String],
|
signature_type: 0,
|
||||||
output_types: vec![InterfaceType::String],
|
|
||||||
})
|
})
|
||||||
.to_string(),
|
.to_string();
|
||||||
(&Import {
|
let output = r#"(@interface import "ns" "foo" (func (type 0)))"#;
|
||||||
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],
|
|
||||||
output_types: vec![InterfaceType::I32],
|
|
||||||
instructions: vec![
|
|
||||||
Instruction::ArgumentGet { index: 0 },
|
|
||||||
Instruction::WriteUtf8 {
|
|
||||||
allocator_name: "hello",
|
|
||||||
},
|
|
||||||
Instruction::CallExport { export_name: "f" },
|
|
||||||
],
|
|
||||||
})
|
})
|
||||||
.to_string(),
|
.to_string();
|
||||||
(&Adapter::Import {
|
let output = r#"(@interface func (type 0)
|
||||||
namespace: "ns",
|
arg.get 42)"#;
|
||||||
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 {
|
||||||
},
|
|
||||||
Export {
|
|
||||||
name: "bar",
|
|
||||||
input_types: vec![],
|
|
||||||
output_types: vec![],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
types: vec![],
|
|
||||||
imports: vec![
|
|
||||||
Import {
|
|
||||||
namespace: "ns",
|
namespace: "ns",
|
||||||
name: "foo",
|
name: "foo",
|
||||||
input_types: vec![],
|
signature_type: 0,
|
||||||
output_types: vec![InterfaceType::I32],
|
}],
|
||||||
},
|
adapters: vec![Adapter {
|
||||||
Import {
|
function_type: 0,
|
||||||
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 }],
|
instructions: vec![Instruction::ArgumentGet { index: 42 }],
|
||||||
},
|
}],
|
||||||
Adapter::Export {
|
exports: vec![Export {
|
||||||
name: "bar",
|
name: "bar",
|
||||||
input_types: vec![],
|
function_type: 0,
|
||||||
output_types: vec![],
|
}],
|
||||||
instructions: vec![Instruction::ArgumentGet { index: 42 }],
|
implementations: vec![Implementation {
|
||||||
},
|
core_function_type: 0,
|
||||||
],
|
adapter_function_type: 1,
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
|
||||||
|
@ -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.
|
||||||
|
@ -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![];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user