2020-02-10 17:12:32 +01:00
|
|
|
//! Writes the AST into a string representing WIT with its textual format.
|
|
|
|
//!
|
|
|
|
//! # Example
|
|
|
|
//!
|
|
|
|
//! ```rust
|
|
|
|
//! use wasmer_interface_types::{
|
|
|
|
//! ast::*,
|
|
|
|
//! encoders::wat::*,
|
|
|
|
//! interpreter::Instruction,
|
|
|
|
//! };
|
|
|
|
//!
|
|
|
|
//! # fn main() {
|
|
|
|
//! let input: String = (&Interfaces {
|
|
|
|
//! exports: vec![
|
|
|
|
//! Export {
|
|
|
|
//! name: "foo",
|
|
|
|
//! input_types: vec![InterfaceType::I32],
|
|
|
|
//! output_types: vec![],
|
|
|
|
//! },
|
|
|
|
//! Export {
|
|
|
|
//! name: "bar",
|
|
|
|
//! input_types: vec![],
|
|
|
|
//! output_types: vec![],
|
|
|
|
//! },
|
|
|
|
//! ],
|
|
|
|
//! types: vec![],
|
|
|
|
//! imports: vec![
|
|
|
|
//! Import {
|
|
|
|
//! namespace: "ns",
|
|
|
|
//! name: "foo",
|
|
|
|
//! input_types: vec![],
|
|
|
|
//! output_types: vec![InterfaceType::I32],
|
|
|
|
//! },
|
|
|
|
//! 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 }],
|
|
|
|
//! },
|
|
|
|
//! ],
|
|
|
|
//! })
|
2020-02-13 14:19:31 +01:00
|
|
|
//! .to_string();
|
2020-02-10 17:12:32 +01:00
|
|
|
//! let output = r#";; Interfaces
|
|
|
|
//!
|
|
|
|
//! ;; 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)
|
|
|
|
//! arg.get 42)
|
|
|
|
//!
|
|
|
|
//! ;; Interface, Adapter bar
|
|
|
|
//! (@interface adapt (export "bar")
|
2020-02-24 15:56:11 +01:00
|
|
|
//! arg.get 42)"#;
|
2020-02-10 17:12:32 +01:00
|
|
|
//!
|
|
|
|
//! assert_eq!(input, output);
|
|
|
|
//! # }
|
|
|
|
//! ```
|
|
|
|
|
2020-02-24 18:12:01 +01:00
|
|
|
use crate::{ast::*, interpreter::Instruction};
|
2020-02-13 14:19:31 +01:00
|
|
|
use std::string::ToString;
|
2019-09-13 15:40:23 +02:00
|
|
|
|
2020-02-10 17:12:32 +01:00
|
|
|
/// Encode an `InterfaceType` into a string.
|
2020-02-13 14:19:31 +01:00
|
|
|
impl ToString for &InterfaceType {
|
|
|
|
fn to_string(&self) -> String {
|
|
|
|
match self {
|
feat(interface-types) Update interface types.
According to the last working notes, new interface types are s8, s16,
s32, s64, u8, u16, u32, u64, f32, f64, string, anyref, i32, and i64.
Their binary reprensentations are changing too, from 0x00 to 0x0d.
2020-02-24 15:37:03 +01:00
|
|
|
InterfaceType::S8 => "s8".into(),
|
|
|
|
InterfaceType::S16 => "s16".into(),
|
|
|
|
InterfaceType::S32 => "s32".into(),
|
|
|
|
InterfaceType::S64 => "s64".into(),
|
|
|
|
InterfaceType::U8 => "u8".into(),
|
|
|
|
InterfaceType::U16 => "u16".into(),
|
|
|
|
InterfaceType::U32 => "u32".into(),
|
|
|
|
InterfaceType::U64 => "u64".into(),
|
2019-09-13 15:40:23 +02:00
|
|
|
InterfaceType::F32 => "f32".into(),
|
|
|
|
InterfaceType::F64 => "f64".into(),
|
feat(interface-types) Update interface types.
According to the last working notes, new interface types are s8, s16,
s32, s64, u8, u16, u32, u64, f32, f64, string, anyref, i32, and i64.
Their binary reprensentations are changing too, from 0x00 to 0x0d.
2020-02-24 15:37:03 +01:00
|
|
|
InterfaceType::String => "string".into(),
|
|
|
|
InterfaceType::Anyref => "anyref".into(),
|
|
|
|
InterfaceType::I32 => "i32".into(),
|
|
|
|
InterfaceType::I64 => "i64".into(),
|
2019-09-13 15:40:23 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-10 17:12:32 +01:00
|
|
|
/// Encode an `Instruction` into a string.
|
2020-02-13 14:19:31 +01:00
|
|
|
impl<'input> ToString for &Instruction<'input> {
|
|
|
|
fn to_string(&self) -> String {
|
|
|
|
match self {
|
2019-09-25 23:29:08 +02:00
|
|
|
Instruction::ArgumentGet { index } => format!("arg.get {}", index),
|
|
|
|
Instruction::Call { function_index } => format!("call {}", function_index),
|
|
|
|
Instruction::CallExport { export_name } => format!(r#"call-export "{}""#, export_name),
|
2019-09-13 15:40:23 +02:00
|
|
|
Instruction::ReadUtf8 => "read-utf8".into(),
|
2019-09-25 23:29:08 +02:00
|
|
|
Instruction::WriteUtf8 { allocator_name } => {
|
|
|
|
format!(r#"write-utf8 "{}""#, allocator_name)
|
|
|
|
}
|
2019-09-13 15:40:23 +02:00
|
|
|
Instruction::AsWasm(interface_type) => {
|
2020-02-13 14:19:31 +01:00
|
|
|
format!("as-wasm {}", interface_type.to_string())
|
2019-09-13 15:40:23 +02:00
|
|
|
}
|
|
|
|
Instruction::AsInterface(interface_type) => {
|
2020-02-13 14:19:31 +01:00
|
|
|
format!("as-interface {}", interface_type.to_string())
|
2019-09-13 15:40:23 +02:00
|
|
|
}
|
|
|
|
Instruction::TableRefAdd => "table-ref-add".into(),
|
|
|
|
Instruction::TableRefGet => "table-ref-get".into(),
|
|
|
|
Instruction::CallMethod(index) => format!("call-method {}", index),
|
|
|
|
Instruction::MakeRecord(interface_type) => {
|
2020-02-13 14:19:31 +01:00
|
|
|
format!("make-record {}", interface_type.to_string())
|
2019-09-13 15:40:23 +02:00
|
|
|
}
|
|
|
|
Instruction::GetField(interface_type, field_index) => {
|
2020-02-13 14:19:31 +01:00
|
|
|
format!("get-field {} {}", interface_type.to_string(), field_index)
|
2019-09-13 15:40:23 +02:00
|
|
|
}
|
|
|
|
Instruction::Const(interface_type, value) => {
|
2020-02-13 14:19:31 +01:00
|
|
|
format!("const {} {}", interface_type.to_string(), value)
|
2019-09-13 15:40:23 +02:00
|
|
|
}
|
|
|
|
Instruction::FoldSeq(import_index) => format!("fold-seq {}", import_index),
|
2020-02-13 14:19:31 +01:00
|
|
|
Instruction::Add(interface_type) => format!("add {}", interface_type.to_string()),
|
|
|
|
Instruction::MemToSeq(interface_type, memory) => {
|
|
|
|
format!(r#"mem-to-seq {} "{}""#, interface_type.to_string(), memory)
|
|
|
|
}
|
2019-09-18 17:09:18 +02:00
|
|
|
Instruction::Load(interface_type, memory) => {
|
2020-02-13 14:19:31 +01:00
|
|
|
format!(r#"load {} "{}""#, interface_type.to_string(), memory)
|
2019-09-18 17:09:18 +02:00
|
|
|
}
|
|
|
|
Instruction::SeqNew(interface_type) => {
|
2020-02-13 14:19:31 +01:00
|
|
|
format!("seq.new {}", interface_type.to_string())
|
2019-09-18 17:09:18 +02:00
|
|
|
}
|
|
|
|
Instruction::ListPush => "list.push".into(),
|
2020-02-12 15:59:41 +01:00
|
|
|
Instruction::RepeatUntil(condition_index, step_index) => {
|
|
|
|
format!("repeat-until {} {}", condition_index, step_index)
|
2019-09-18 17:09:18 +02:00
|
|
|
}
|
2019-09-13 15:40:23 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-10 17:12:32 +01:00
|
|
|
/// Encode a list of `InterfaceType` representing inputs into a
|
|
|
|
/// string.
|
2019-09-20 12:02:11 +02:00
|
|
|
fn input_types_to_param(input_types: &[InterfaceType]) -> String {
|
2019-09-18 16:37:57 +02:00
|
|
|
if input_types.is_empty() {
|
|
|
|
"".into()
|
|
|
|
} else {
|
2019-09-13 15:40:23 +02:00
|
|
|
format!(
|
2019-09-18 16:37:57 +02:00
|
|
|
"\n (param{})",
|
|
|
|
input_types
|
|
|
|
.iter()
|
|
|
|
.fold(String::new(), |mut accumulator, interface_type| {
|
|
|
|
accumulator.push(' ');
|
2020-02-13 14:19:31 +01:00
|
|
|
accumulator.push_str(&interface_type.to_string());
|
2019-09-18 16:37:57 +02:00
|
|
|
accumulator
|
|
|
|
})
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-10 17:12:32 +01:00
|
|
|
/// Encode a list of `InterfaceType` representing outputs into a
|
|
|
|
/// string.
|
2019-09-20 12:02:11 +02:00
|
|
|
fn output_types_to_result(output_types: &[InterfaceType]) -> String {
|
2019-09-18 16:37:57 +02:00
|
|
|
if output_types.is_empty() {
|
|
|
|
"".into()
|
|
|
|
} else {
|
|
|
|
format!(
|
|
|
|
"\n (result{})",
|
|
|
|
output_types
|
|
|
|
.iter()
|
|
|
|
.fold(String::new(), |mut accumulator, interface_type| {
|
|
|
|
accumulator.push(' ');
|
2020-02-13 14:19:31 +01:00
|
|
|
accumulator.push_str(&interface_type.to_string());
|
2019-09-18 16:37:57 +02:00
|
|
|
accumulator
|
|
|
|
})
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-10 17:12:32 +01:00
|
|
|
/// Encode a `Type` into a string.
|
2020-02-24 16:23:31 +01:00
|
|
|
impl<'input> ToString for &Type {
|
2020-02-13 14:19:31 +01:00
|
|
|
fn to_string(&self) -> String {
|
2020-02-24 16:23:31 +01:00
|
|
|
format!(
|
|
|
|
r#"(@interface type (func{inputs}{outputs}))"#,
|
|
|
|
inputs = input_types_to_param(&self.inputs),
|
|
|
|
outputs = output_types_to_result(&self.outputs),
|
|
|
|
)
|
2019-09-18 16:37:57 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-10 17:12:32 +01:00
|
|
|
/// Encode an `Import` into a string.
|
2020-02-13 14:19:31 +01:00
|
|
|
impl<'input> ToString for &Import<'input> {
|
|
|
|
fn to_string(&self) -> String {
|
2019-09-18 16:37:57 +02:00
|
|
|
format!(
|
2020-02-24 18:12:01 +01:00
|
|
|
r#"(@interface import "{namespace}" "{name}" (func (type {type})))"#,
|
2020-02-13 14:19:31 +01:00
|
|
|
namespace = self.namespace,
|
|
|
|
name = self.name,
|
2020-02-24 18:12:01 +01:00
|
|
|
type = self.signature_type,
|
2019-09-18 16:37:57 +02:00
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-10 17:12:32 +01:00
|
|
|
/// Encode an `Adapter` into a string.
|
2020-02-13 14:19:31 +01:00
|
|
|
impl<'input> ToString for &Adapter<'input> {
|
|
|
|
fn to_string(&self) -> String {
|
2020-02-24 18:12:01 +01:00
|
|
|
format!(
|
|
|
|
r#"(@interface func (type {function_type}){instructions})"#,
|
|
|
|
function_type = self.function_type,
|
|
|
|
instructions =
|
|
|
|
self.instructions
|
|
|
|
.iter()
|
|
|
|
.fold(String::new(), |mut accumulator, instruction| {
|
|
|
|
accumulator.push_str("\n ");
|
|
|
|
accumulator.push_str(&instruction.to_string());
|
|
|
|
accumulator
|
|
|
|
}),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
2019-09-18 16:37:57 +02:00
|
|
|
|
2020-02-24 18:12:01 +01:00
|
|
|
/// Encode an `Export` into a string.
|
|
|
|
impl<'input> ToString for &Export<'input> {
|
|
|
|
fn to_string(&self) -> String {
|
|
|
|
format!(
|
|
|
|
r#"(@interface export "{name}" (func {type}))"#,
|
|
|
|
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,
|
|
|
|
)
|
2019-09-18 16:37:57 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-10 17:12:32 +01:00
|
|
|
/// Encode an `Interfaces` into a string.
|
2020-02-13 14:19:31 +01:00
|
|
|
impl<'input> ToString for &Interfaces<'input> {
|
|
|
|
fn to_string(&self) -> String {
|
2019-09-18 18:02:05 +02:00
|
|
|
let mut output = String::from(";; Interfaces");
|
|
|
|
|
2020-02-13 14:19:31 +01:00
|
|
|
let types = self
|
2019-09-18 18:02:05 +02:00
|
|
|
.types
|
|
|
|
.iter()
|
|
|
|
.fold(String::new(), |mut accumulator, ty| {
|
2020-02-13 14:19:31 +01:00
|
|
|
accumulator.push_str(&ty.to_string());
|
2019-09-18 18:02:05 +02:00
|
|
|
accumulator
|
|
|
|
});
|
|
|
|
|
2020-02-13 14:19:31 +01:00
|
|
|
let imports = self
|
2020-02-10 15:41:10 +01:00
|
|
|
.imports
|
|
|
|
.iter()
|
|
|
|
.fold(String::new(), |mut accumulator, import| {
|
2020-02-13 14:19:31 +01:00
|
|
|
accumulator.push_str(&import.to_string());
|
2019-09-18 18:02:05 +02:00
|
|
|
accumulator
|
2020-02-10 15:41:10 +01:00
|
|
|
});
|
2019-09-18 18:02:05 +02:00
|
|
|
|
2020-02-13 14:19:31 +01:00
|
|
|
let adapters = self
|
|
|
|
.adapters
|
|
|
|
.iter()
|
|
|
|
.fold(String::new(), |mut accumulator, adapter| {
|
|
|
|
accumulator.push_str(&adapter.to_string());
|
|
|
|
accumulator
|
|
|
|
});
|
|
|
|
|
2020-02-24 18:12:01 +01:00
|
|
|
let exports = self
|
|
|
|
.exports
|
|
|
|
.iter()
|
|
|
|
.fold(String::new(), |mut accumulator, export| {
|
|
|
|
accumulator.push_str(&export.to_string());
|
|
|
|
accumulator
|
|
|
|
});
|
|
|
|
|
|
|
|
let implementations =
|
|
|
|
self.implementations
|
|
|
|
.iter()
|
|
|
|
.fold(String::new(), |mut accumulator, implementation| {
|
|
|
|
accumulator.push_str(&implementation.to_string());
|
|
|
|
accumulator
|
|
|
|
});
|
|
|
|
|
2019-09-18 18:02:05 +02:00
|
|
|
output.push_str(&types);
|
2020-02-10 15:41:10 +01:00
|
|
|
output.push_str(&imports);
|
2019-09-18 18:02:05 +02:00
|
|
|
output.push_str(&adapters);
|
2020-02-24 18:12:01 +01:00
|
|
|
output.push_str(&exports);
|
|
|
|
output.push_str(&implementations);
|
2019-09-18 18:02:05 +02:00
|
|
|
|
|
|
|
output
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-13 15:40:23 +02:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
2019-09-26 14:14:46 +02:00
|
|
|
use crate::{ast::*, interpreter::Instruction};
|
2019-09-13 15:40:23 +02:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_interface_types() {
|
|
|
|
let inputs: Vec<String> = vec![
|
feat(interface-types) Update interface types.
According to the last working notes, new interface types are s8, s16,
s32, s64, u8, u16, u32, u64, f32, f64, string, anyref, i32, and i64.
Their binary reprensentations are changing too, from 0x00 to 0x0d.
2020-02-24 15:37:03 +01:00
|
|
|
(&InterfaceType::S8).to_string(),
|
|
|
|
(&InterfaceType::S16).to_string(),
|
|
|
|
(&InterfaceType::S32).to_string(),
|
|
|
|
(&InterfaceType::S64).to_string(),
|
|
|
|
(&InterfaceType::U8).to_string(),
|
|
|
|
(&InterfaceType::U16).to_string(),
|
|
|
|
(&InterfaceType::U32).to_string(),
|
|
|
|
(&InterfaceType::U64).to_string(),
|
|
|
|
(&InterfaceType::F32).to_string(),
|
|
|
|
(&InterfaceType::F64).to_string(),
|
2020-02-13 14:19:31 +01:00
|
|
|
(&InterfaceType::String).to_string(),
|
feat(interface-types) Update interface types.
According to the last working notes, new interface types are s8, s16,
s32, s64, u8, u16, u32, u64, f32, f64, string, anyref, i32, and i64.
Their binary reprensentations are changing too, from 0x00 to 0x0d.
2020-02-24 15:37:03 +01:00
|
|
|
(&InterfaceType::Anyref).to_string(),
|
2020-02-13 14:19:31 +01:00
|
|
|
(&InterfaceType::I32).to_string(),
|
|
|
|
(&InterfaceType::I64).to_string(),
|
2019-09-13 15:40:23 +02:00
|
|
|
];
|
|
|
|
let outputs = vec![
|
feat(interface-types) Update interface types.
According to the last working notes, new interface types are s8, s16,
s32, s64, u8, u16, u32, u64, f32, f64, string, anyref, i32, and i64.
Their binary reprensentations are changing too, from 0x00 to 0x0d.
2020-02-24 15:37:03 +01:00
|
|
|
"s8", "s16", "s32", "s64", "u8", "u16", "u32", "u64", "f32", "f64", "string", "anyref",
|
|
|
|
"i32", "i64",
|
2019-09-13 15:40:23 +02:00
|
|
|
];
|
|
|
|
|
|
|
|
assert_eq!(inputs, outputs);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_instructions() {
|
|
|
|
let inputs: Vec<String> = vec![
|
2020-02-13 14:19:31 +01:00
|
|
|
(&Instruction::ArgumentGet { index: 7 }).to_string(),
|
|
|
|
(&Instruction::Call { function_index: 7 }).to_string(),
|
|
|
|
(&Instruction::CallExport { export_name: "foo" }).to_string(),
|
|
|
|
(&Instruction::ReadUtf8).to_string(),
|
2019-09-25 23:29:08 +02:00
|
|
|
(&Instruction::WriteUtf8 {
|
|
|
|
allocator_name: "foo",
|
|
|
|
})
|
2020-02-13 14:19:31 +01:00
|
|
|
.to_string(),
|
feat(interface-types) Update interface types.
According to the last working notes, new interface types are s8, s16,
s32, s64, u8, u16, u32, u64, f32, f64, string, anyref, i32, and i64.
Their binary reprensentations are changing too, from 0x00 to 0x0d.
2020-02-24 15:37:03 +01:00
|
|
|
(&Instruction::AsWasm(InterfaceType::I32)).to_string(),
|
|
|
|
(&Instruction::AsInterface(InterfaceType::I32)).to_string(),
|
2020-02-13 14:19:31 +01:00
|
|
|
(&Instruction::TableRefAdd).to_string(),
|
|
|
|
(&Instruction::TableRefGet).to_string(),
|
|
|
|
(&Instruction::CallMethod(7)).to_string(),
|
feat(interface-types) Update interface types.
According to the last working notes, new interface types are s8, s16,
s32, s64, u8, u16, u32, u64, f32, f64, string, anyref, i32, and i64.
Their binary reprensentations are changing too, from 0x00 to 0x0d.
2020-02-24 15:37:03 +01:00
|
|
|
(&Instruction::MakeRecord(InterfaceType::I32)).to_string(),
|
|
|
|
(&Instruction::GetField(InterfaceType::I32, 7)).to_string(),
|
2020-02-13 14:19:31 +01:00
|
|
|
(&Instruction::Const(InterfaceType::I32, 7)).to_string(),
|
|
|
|
(&Instruction::FoldSeq(7)).to_string(),
|
feat(interface-types) Update interface types.
According to the last working notes, new interface types are s8, s16,
s32, s64, u8, u16, u32, u64, f32, f64, string, anyref, i32, and i64.
Their binary reprensentations are changing too, from 0x00 to 0x0d.
2020-02-24 15:37:03 +01:00
|
|
|
(&Instruction::Add(InterfaceType::I32)).to_string(),
|
|
|
|
(&Instruction::MemToSeq(InterfaceType::I32, "foo")).to_string(),
|
|
|
|
(&Instruction::Load(InterfaceType::I32, "foo")).to_string(),
|
|
|
|
(&Instruction::SeqNew(InterfaceType::I32)).to_string(),
|
2020-02-13 14:19:31 +01:00
|
|
|
(&Instruction::ListPush).to_string(),
|
|
|
|
(&Instruction::RepeatUntil(1, 2)).to_string(),
|
2019-09-13 15:40:23 +02:00
|
|
|
];
|
|
|
|
let outputs = vec![
|
|
|
|
"arg.get 7",
|
|
|
|
"call 7",
|
2019-09-18 16:37:57 +02:00
|
|
|
r#"call-export "foo""#,
|
2019-09-13 15:40:23 +02:00
|
|
|
"read-utf8",
|
2019-09-18 16:37:57 +02:00
|
|
|
r#"write-utf8 "foo""#,
|
feat(interface-types) Update interface types.
According to the last working notes, new interface types are s8, s16,
s32, s64, u8, u16, u32, u64, f32, f64, string, anyref, i32, and i64.
Their binary reprensentations are changing too, from 0x00 to 0x0d.
2020-02-24 15:37:03 +01:00
|
|
|
"as-wasm i32",
|
|
|
|
"as-interface i32",
|
2019-09-13 15:40:23 +02:00
|
|
|
"table-ref-add",
|
|
|
|
"table-ref-get",
|
|
|
|
"call-method 7",
|
feat(interface-types) Update interface types.
According to the last working notes, new interface types are s8, s16,
s32, s64, u8, u16, u32, u64, f32, f64, string, anyref, i32, and i64.
Their binary reprensentations are changing too, from 0x00 to 0x0d.
2020-02-24 15:37:03 +01:00
|
|
|
"make-record i32",
|
|
|
|
"get-field i32 7",
|
2019-09-13 15:40:23 +02:00
|
|
|
"const i32 7",
|
|
|
|
"fold-seq 7",
|
feat(interface-types) Update interface types.
According to the last working notes, new interface types are s8, s16,
s32, s64, u8, u16, u32, u64, f32, f64, string, anyref, i32, and i64.
Their binary reprensentations are changing too, from 0x00 to 0x0d.
2020-02-24 15:37:03 +01:00
|
|
|
"add i32",
|
|
|
|
r#"mem-to-seq i32 "foo""#,
|
|
|
|
r#"load i32 "foo""#,
|
|
|
|
"seq.new i32",
|
2019-09-18 17:09:18 +02:00
|
|
|
"list.push",
|
2020-02-12 15:59:41 +01:00
|
|
|
"repeat-until 1 2",
|
2019-09-13 15:40:23 +02:00
|
|
|
];
|
|
|
|
|
|
|
|
assert_eq!(inputs, outputs);
|
|
|
|
}
|
|
|
|
|
2020-02-24 16:23:31 +01:00
|
|
|
#[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);
|
|
|
|
}
|
|
|
|
|
2019-09-13 15:40:23 +02:00
|
|
|
#[test]
|
|
|
|
fn test_exports() {
|
2019-09-18 16:37:57 +02:00
|
|
|
let inputs: Vec<String> = vec![
|
|
|
|
(&Export {
|
|
|
|
name: "foo",
|
|
|
|
input_types: vec![InterfaceType::I32, InterfaceType::F32],
|
|
|
|
output_types: vec![InterfaceType::I32],
|
|
|
|
})
|
2020-02-13 14:19:31 +01:00
|
|
|
.to_string(),
|
2019-09-18 16:37:57 +02:00
|
|
|
(&Export {
|
|
|
|
name: "foo",
|
|
|
|
input_types: vec![InterfaceType::I32],
|
|
|
|
output_types: vec![],
|
|
|
|
})
|
2020-02-13 14:19:31 +01:00
|
|
|
.to_string(),
|
2019-09-18 16:37:57 +02:00
|
|
|
(&Export {
|
|
|
|
name: "foo",
|
|
|
|
input_types: vec![],
|
|
|
|
output_types: vec![InterfaceType::I32],
|
|
|
|
})
|
2020-02-13 14:19:31 +01:00
|
|
|
.to_string(),
|
2019-09-18 16:37:57 +02:00
|
|
|
(&Export {
|
|
|
|
name: "foo",
|
|
|
|
input_types: vec![],
|
|
|
|
output_types: vec![],
|
|
|
|
})
|
2020-02-13 14:19:31 +01:00
|
|
|
.to_string(),
|
2019-09-18 16:37:57 +02:00
|
|
|
];
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2020-02-10 15:41:10 +01:00
|
|
|
fn test_imports() {
|
2019-09-18 16:37:57 +02:00
|
|
|
let inputs: Vec<String> = vec![
|
2020-02-10 15:41:10 +01:00
|
|
|
(&Import {
|
2019-09-18 16:37:57 +02:00
|
|
|
namespace: "ns",
|
|
|
|
name: "foo",
|
feat(interface-types) Update interface types.
According to the last working notes, new interface types are s8, s16,
s32, s64, u8, u16, u32, u64, f32, f64, string, anyref, i32, and i64.
Their binary reprensentations are changing too, from 0x00 to 0x0d.
2020-02-24 15:37:03 +01:00
|
|
|
input_types: vec![InterfaceType::I32, InterfaceType::String],
|
2019-09-18 16:37:57 +02:00
|
|
|
output_types: vec![InterfaceType::String],
|
|
|
|
})
|
2020-02-13 14:19:31 +01:00
|
|
|
.to_string(),
|
2020-02-10 15:41:10 +01:00
|
|
|
(&Import {
|
2019-09-18 16:37:57 +02:00
|
|
|
namespace: "ns",
|
|
|
|
name: "foo",
|
|
|
|
input_types: vec![InterfaceType::String],
|
|
|
|
output_types: vec![],
|
|
|
|
})
|
2020-02-13 14:19:31 +01:00
|
|
|
.to_string(),
|
2020-02-10 15:41:10 +01:00
|
|
|
(&Import {
|
2019-09-18 16:37:57 +02:00
|
|
|
namespace: "ns",
|
|
|
|
name: "foo",
|
|
|
|
input_types: vec![],
|
|
|
|
output_types: vec![InterfaceType::String],
|
|
|
|
})
|
2020-02-13 14:19:31 +01:00
|
|
|
.to_string(),
|
2020-02-10 15:41:10 +01:00
|
|
|
(&Import {
|
2019-09-18 16:37:57 +02:00
|
|
|
namespace: "ns",
|
|
|
|
name: "foo",
|
|
|
|
input_types: vec![],
|
|
|
|
output_types: vec![],
|
|
|
|
})
|
2020-02-13 14:19:31 +01:00
|
|
|
.to_string(),
|
2019-09-18 16:37:57 +02:00
|
|
|
];
|
|
|
|
let outputs = vec![
|
|
|
|
r#"(@interface func $ns_foo (import "ns" "foo")
|
feat(interface-types) Update interface types.
According to the last working notes, new interface types are s8, s16,
s32, s64, u8, u16, u32, u64, f32, f64, string, anyref, i32, and i64.
Their binary reprensentations are changing too, from 0x00 to 0x0d.
2020-02-24 15:37:03 +01:00
|
|
|
(param i32 string)
|
|
|
|
(result string))"#,
|
2019-09-18 16:37:57 +02:00
|
|
|
r#"(@interface func $ns_foo (import "ns" "foo")
|
feat(interface-types) Update interface types.
According to the last working notes, new interface types are s8, s16,
s32, s64, u8, u16, u32, u64, f32, f64, string, anyref, i32, and i64.
Their binary reprensentations are changing too, from 0x00 to 0x0d.
2020-02-24 15:37:03 +01:00
|
|
|
(param string))"#,
|
2019-09-18 16:37:57 +02:00
|
|
|
r#"(@interface func $ns_foo (import "ns" "foo")
|
feat(interface-types) Update interface types.
According to the last working notes, new interface types are s8, s16,
s32, s64, u8, u16, u32, u64, f32, f64, string, anyref, i32, and i64.
Their binary reprensentations are changing too, from 0x00 to 0x0d.
2020-02-24 15:37:03 +01:00
|
|
|
(result string))"#,
|
2019-09-18 16:37:57 +02:00
|
|
|
r#"(@interface func $ns_foo (import "ns" "foo"))"#,
|
|
|
|
];
|
|
|
|
|
|
|
|
assert_eq!(inputs, outputs);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_adapters() {
|
|
|
|
let inputs: Vec<String> = vec![
|
|
|
|
(&Adapter::Import {
|
|
|
|
namespace: "ns",
|
|
|
|
name: "foo",
|
|
|
|
input_types: vec![InterfaceType::I32, InterfaceType::F32],
|
|
|
|
output_types: vec![InterfaceType::I32],
|
|
|
|
instructions: vec![
|
2019-09-25 23:29:08 +02:00
|
|
|
Instruction::ArgumentGet { index: 0 },
|
|
|
|
Instruction::WriteUtf8 {
|
|
|
|
allocator_name: "hello",
|
|
|
|
},
|
|
|
|
Instruction::CallExport { export_name: "f" },
|
2019-09-18 16:37:57 +02:00
|
|
|
],
|
|
|
|
})
|
2020-02-13 14:19:31 +01:00
|
|
|
.to_string(),
|
2019-09-18 16:37:57 +02:00
|
|
|
(&Adapter::Import {
|
|
|
|
namespace: "ns",
|
|
|
|
name: "foo",
|
|
|
|
input_types: vec![InterfaceType::I32],
|
|
|
|
output_types: vec![],
|
2019-09-25 23:29:08 +02:00
|
|
|
instructions: vec![Instruction::CallExport { export_name: "f" }],
|
2019-09-18 16:37:57 +02:00
|
|
|
})
|
2020-02-13 14:19:31 +01:00
|
|
|
.to_string(),
|
2019-09-18 16:37:57 +02:00
|
|
|
(&Adapter::Import {
|
|
|
|
namespace: "ns",
|
|
|
|
name: "foo",
|
|
|
|
input_types: vec![],
|
|
|
|
output_types: vec![InterfaceType::I32],
|
2019-09-25 23:29:08 +02:00
|
|
|
instructions: vec![Instruction::CallExport { export_name: "f" }],
|
2019-09-18 16:37:57 +02:00
|
|
|
})
|
2020-02-13 14:19:31 +01:00
|
|
|
.to_string(),
|
2019-09-18 16:37:57 +02:00
|
|
|
(&Adapter::Export {
|
|
|
|
name: "foo",
|
|
|
|
input_types: vec![InterfaceType::I32, InterfaceType::F32],
|
|
|
|
output_types: vec![InterfaceType::I32],
|
|
|
|
instructions: vec![
|
2019-09-25 23:29:08 +02:00
|
|
|
Instruction::ArgumentGet { index: 0 },
|
|
|
|
Instruction::WriteUtf8 {
|
|
|
|
allocator_name: "hello",
|
|
|
|
},
|
|
|
|
Instruction::CallExport { export_name: "f" },
|
2019-09-18 16:37:57 +02:00
|
|
|
],
|
|
|
|
})
|
2020-02-13 14:19:31 +01:00
|
|
|
.to_string(),
|
2019-09-18 16:37:57 +02:00
|
|
|
(&Adapter::Export {
|
|
|
|
name: "foo",
|
|
|
|
input_types: vec![InterfaceType::I32],
|
|
|
|
output_types: vec![],
|
2019-09-25 23:29:08 +02:00
|
|
|
instructions: vec![Instruction::CallExport { export_name: "f" }],
|
2019-09-18 16:37:57 +02:00
|
|
|
})
|
2020-02-13 14:19:31 +01:00
|
|
|
.to_string(),
|
2019-09-18 16:37:57 +02:00
|
|
|
(&Adapter::Export {
|
|
|
|
name: "foo",
|
|
|
|
input_types: vec![],
|
|
|
|
output_types: vec![InterfaceType::I32],
|
2019-09-25 23:29:08 +02:00
|
|
|
instructions: vec![Instruction::CallExport { export_name: "f" }],
|
2019-09-18 16:37:57 +02:00
|
|
|
})
|
2020-02-13 14:19:31 +01:00
|
|
|
.to_string(),
|
2019-09-18 16:37:57 +02:00
|
|
|
];
|
|
|
|
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")"#,
|
|
|
|
];
|
2019-09-13 15:40:23 +02:00
|
|
|
|
|
|
|
assert_eq!(inputs, outputs);
|
|
|
|
}
|
2019-09-18 16:37:57 +02:00
|
|
|
|
2019-09-18 18:02:05 +02:00
|
|
|
#[test]
|
|
|
|
fn test_interfaces() {
|
|
|
|
let input: String = (&Interfaces {
|
|
|
|
exports: vec![
|
|
|
|
Export {
|
|
|
|
name: "foo",
|
|
|
|
input_types: vec![InterfaceType::I32],
|
|
|
|
output_types: vec![],
|
|
|
|
},
|
|
|
|
Export {
|
|
|
|
name: "bar",
|
|
|
|
input_types: vec![],
|
|
|
|
output_types: vec![],
|
|
|
|
},
|
|
|
|
],
|
|
|
|
types: vec![],
|
2020-02-10 15:41:10 +01:00
|
|
|
imports: vec![
|
|
|
|
Import {
|
2019-09-18 18:02:05 +02:00
|
|
|
namespace: "ns",
|
|
|
|
name: "foo",
|
|
|
|
input_types: vec![],
|
|
|
|
output_types: vec![InterfaceType::I32],
|
|
|
|
},
|
2020-02-10 15:41:10 +01:00
|
|
|
Import {
|
2019-09-18 18:02:05 +02:00
|
|
|
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![],
|
2019-09-25 23:29:08 +02:00
|
|
|
instructions: vec![Instruction::ArgumentGet { index: 42 }],
|
2019-09-18 18:02:05 +02:00
|
|
|
},
|
|
|
|
Adapter::Export {
|
|
|
|
name: "bar",
|
|
|
|
input_types: vec![],
|
|
|
|
output_types: vec![],
|
2019-09-25 23:29:08 +02:00
|
|
|
instructions: vec![Instruction::ArgumentGet { index: 42 }],
|
2019-09-18 18:02:05 +02:00
|
|
|
},
|
|
|
|
],
|
|
|
|
})
|
2020-02-13 14:19:31 +01:00
|
|
|
.to_string();
|
2019-09-18 18:02:05 +02:00
|
|
|
let output = r#";; Interfaces
|
|
|
|
|
|
|
|
;; Interface, Export foo
|
|
|
|
(@interface export "foo"
|
|
|
|
(param i32))
|
|
|
|
|
|
|
|
;; Interface, Export bar
|
|
|
|
(@interface export "bar")
|
|
|
|
|
2020-02-10 15:41:10 +01:00
|
|
|
;; Interface, Import ns.foo
|
2019-09-18 18:02:05 +02:00
|
|
|
(@interface func $ns_foo (import "ns" "foo")
|
|
|
|
(result i32))
|
|
|
|
|
2020-02-10 15:41:10 +01:00
|
|
|
;; Interface, Import ns.bar
|
2019-09-18 18:02:05 +02:00
|
|
|
(@interface func $ns_bar (import "ns" "bar"))
|
|
|
|
|
|
|
|
;; Interface, Adapter ns.foo
|
|
|
|
(@interface adapt (import "ns" "foo")
|
|
|
|
(param i32)
|
|
|
|
arg.get 42)
|
|
|
|
|
|
|
|
;; Interface, Adapter bar
|
|
|
|
(@interface adapt (export "bar")
|
2020-02-24 15:56:11 +01:00
|
|
|
arg.get 42)"#;
|
2019-09-18 18:02:05 +02:00
|
|
|
|
|
|
|
assert_eq!(input, output);
|
|
|
|
}
|
2019-09-13 15:40:23 +02:00
|
|
|
}
|