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,
|
|
|
|
//! };
|
|
|
|
//!
|
|
|
|
//! let input: String = (&Interfaces {
|
2020-02-26 15:32:14 +01:00
|
|
|
//! types: vec![Type {
|
|
|
|
//! inputs: vec![InterfaceType::I32],
|
|
|
|
//! outputs: vec![InterfaceType::S8],
|
|
|
|
//! }],
|
|
|
|
//! imports: vec![Import {
|
|
|
|
//! namespace: "ns",
|
|
|
|
//! name: "foo",
|
|
|
|
//! signature_type: 0,
|
|
|
|
//! }],
|
|
|
|
//! adapters: vec![Adapter {
|
|
|
|
//! function_type: 0,
|
|
|
|
//! instructions: vec![Instruction::ArgumentGet { index: 42 }],
|
|
|
|
//! }],
|
|
|
|
//! exports: vec![Export {
|
|
|
|
//! name: "bar",
|
|
|
|
//! function_type: 0,
|
|
|
|
//! }],
|
|
|
|
//! implementations: vec![Implementation {
|
|
|
|
//! core_function_type: 0,
|
|
|
|
//! adapter_function_type: 1,
|
|
|
|
//! }],
|
2020-02-10 17:12:32 +01:00
|
|
|
//! })
|
2020-02-13 14:19:31 +01:00
|
|
|
//! .to_string();
|
2020-02-26 15:32:14 +01:00
|
|
|
//! let output = r#";; Types
|
|
|
|
//! (@interface type (func
|
|
|
|
//! (param i32)
|
|
|
|
//! (result s8)))
|
2020-02-10 17:12:32 +01:00
|
|
|
//!
|
2020-02-26 15:32:14 +01:00
|
|
|
//! ;; Imports
|
|
|
|
//! (@interface import "ns" "foo" (func (type 0)))
|
2020-02-10 17:12:32 +01:00
|
|
|
//!
|
2020-02-26 15:32:14 +01:00
|
|
|
//! ;; Adapters
|
|
|
|
//! (@interface func (type 0)
|
2020-02-10 17:12:32 +01:00
|
|
|
//! arg.get 42)
|
|
|
|
//!
|
2020-02-26 15:32:14 +01:00
|
|
|
//! ;; Exports
|
|
|
|
//! (@interface export "bar" (func 0))
|
|
|
|
//!
|
|
|
|
//! ;; Implementations
|
|
|
|
//! (@interface implement (func 0) (func 1))"#;
|
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),
|
2020-03-09 15:06:35 +01:00
|
|
|
Instruction::MemoryToString => "memory-to-string".into(),
|
2019-09-25 23:29:08 +02:00
|
|
|
Instruction::WriteUtf8 { allocator_name } => {
|
|
|
|
format!(r#"write-utf8 "{}""#, allocator_name)
|
|
|
|
}
|
2020-02-26 16:20:39 +01:00
|
|
|
Instruction::I32ToS8 => "i32-to-s8".into(),
|
|
|
|
Instruction::I32ToS8X => "i32-to-s8x".into(),
|
|
|
|
Instruction::I32ToU8 => "i32-to-u8".into(),
|
|
|
|
Instruction::I32ToS16 => "i32-to-s16".into(),
|
|
|
|
Instruction::I32ToS16X => "i32-to-s16x".into(),
|
|
|
|
Instruction::I32ToU16 => "i32-to-u16".into(),
|
|
|
|
Instruction::I32ToS32 => "i32-to-s32".into(),
|
|
|
|
Instruction::I32ToU32 => "i32-to-u32".into(),
|
|
|
|
Instruction::I32ToS64 => "i32-to-s64".into(),
|
|
|
|
Instruction::I32ToU64 => "i32-to-u64".into(),
|
|
|
|
Instruction::I64ToS8 => "i64-to-s8".into(),
|
|
|
|
Instruction::I64ToS8X => "i64-to-s8x".into(),
|
|
|
|
Instruction::I64ToU8 => "i64-to-u8".into(),
|
|
|
|
Instruction::I64ToS16 => "i64-to-s16".into(),
|
|
|
|
Instruction::I64ToS16X => "i64-to-s16x".into(),
|
|
|
|
Instruction::I64ToU16 => "i64-to-u16".into(),
|
|
|
|
Instruction::I64ToS32 => "i64-to-s32".into(),
|
|
|
|
Instruction::I64ToS32X => "i64-to-s32x".into(),
|
|
|
|
Instruction::I64ToU32 => "i64-to-u32".into(),
|
|
|
|
Instruction::I64ToS64 => "i64-to-s64".into(),
|
|
|
|
Instruction::I64ToU64 => "i64-to-u64".into(),
|
|
|
|
Instruction::S8ToI32 => "s8-to-i32".into(),
|
|
|
|
Instruction::U8ToI32 => "u8-to-i32".into(),
|
|
|
|
Instruction::S16ToI32 => "s16-to-i32".into(),
|
|
|
|
Instruction::U16ToI32 => "u16-to-i32".into(),
|
|
|
|
Instruction::S32ToI32 => "s32-to-i32".into(),
|
|
|
|
Instruction::U32ToI32 => "u32-to-i32".into(),
|
|
|
|
Instruction::S64ToI32 => "s64-to-i32".into(),
|
|
|
|
Instruction::S64ToI32X => "s64-to-i32x".into(),
|
|
|
|
Instruction::U64ToI32 => "u64-to-i32".into(),
|
|
|
|
Instruction::U64ToI32X => "u64-to-i32x".into(),
|
|
|
|
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(),
|
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 {
|
2020-02-26 15:32:14 +01:00
|
|
|
let mut output = String::new();
|
2019-09-18 18:02:05 +02:00
|
|
|
|
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-26 15:32:14 +01:00
|
|
|
accumulator.push('\n');
|
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-26 15:32:14 +01:00
|
|
|
accumulator.push('\n');
|
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| {
|
2020-02-26 15:32:14 +01:00
|
|
|
accumulator.push('\n');
|
2020-02-13 14:19:31 +01:00
|
|
|
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| {
|
2020-02-26 15:32:14 +01:00
|
|
|
accumulator.push('\n');
|
2020-02-24 18:12:01 +01:00
|
|
|
accumulator.push_str(&export.to_string());
|
|
|
|
accumulator
|
|
|
|
});
|
|
|
|
|
|
|
|
let implementations =
|
|
|
|
self.implementations
|
|
|
|
.iter()
|
|
|
|
.fold(String::new(), |mut accumulator, implementation| {
|
2020-02-26 15:32:14 +01:00
|
|
|
accumulator.push('\n');
|
2020-02-24 18:12:01 +01:00
|
|
|
accumulator.push_str(&implementation.to_string());
|
|
|
|
accumulator
|
|
|
|
});
|
|
|
|
|
2020-02-26 15:32:14 +01:00
|
|
|
let separator = |output: &mut String| {
|
|
|
|
if !output.is_empty() {
|
|
|
|
output.push_str("\n\n");
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
if !types.is_empty() {
|
|
|
|
output.push_str(";; Types");
|
|
|
|
output.push_str(&types);
|
|
|
|
}
|
|
|
|
|
|
|
|
separator(&mut output);
|
|
|
|
|
|
|
|
if !imports.is_empty() {
|
|
|
|
output.push_str(";; Imports");
|
|
|
|
output.push_str(&imports);
|
|
|
|
}
|
|
|
|
|
|
|
|
separator(&mut output);
|
|
|
|
|
|
|
|
if !adapters.is_empty() {
|
|
|
|
output.push_str(";; Adapters");
|
|
|
|
output.push_str(&adapters);
|
|
|
|
}
|
|
|
|
|
|
|
|
separator(&mut output);
|
|
|
|
|
|
|
|
if !exports.is_empty() {
|
|
|
|
output.push_str(";; Exports");
|
|
|
|
output.push_str(&exports);
|
|
|
|
}
|
|
|
|
|
|
|
|
separator(&mut output);
|
|
|
|
|
|
|
|
if !implementations.is_empty() {
|
|
|
|
output.push_str(";; Implementations");
|
|
|
|
output.push_str(&implementations);
|
|
|
|
}
|
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(),
|
2020-03-09 15:06:35 +01:00
|
|
|
(&Instruction::MemoryToString).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(),
|
2020-02-26 16:20:39 +01:00
|
|
|
(&Instruction::I32ToS8).to_string(),
|
|
|
|
(&Instruction::I32ToS8X).to_string(),
|
|
|
|
(&Instruction::I32ToU8).to_string(),
|
|
|
|
(&Instruction::I32ToS16).to_string(),
|
|
|
|
(&Instruction::I32ToS16X).to_string(),
|
|
|
|
(&Instruction::I32ToU16).to_string(),
|
|
|
|
(&Instruction::I32ToS32).to_string(),
|
|
|
|
(&Instruction::I32ToU32).to_string(),
|
|
|
|
(&Instruction::I32ToS64).to_string(),
|
|
|
|
(&Instruction::I32ToU64).to_string(),
|
|
|
|
(&Instruction::I64ToS8).to_string(),
|
|
|
|
(&Instruction::I64ToS8X).to_string(),
|
|
|
|
(&Instruction::I64ToU8).to_string(),
|
|
|
|
(&Instruction::I64ToS16).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(),
|
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""#,
|
2020-03-09 15:06:35 +01:00
|
|
|
"memory-to-string",
|
2019-09-18 16:37:57 +02:00
|
|
|
r#"write-utf8 "foo""#,
|
2020-02-26 16:20:39 +01:00
|
|
|
"i32-to-s8",
|
|
|
|
"i32-to-s8x",
|
|
|
|
"i32-to-u8",
|
|
|
|
"i32-to-s16",
|
|
|
|
"i32-to-s16x",
|
|
|
|
"i32-to-u16",
|
|
|
|
"i32-to-s32",
|
|
|
|
"i32-to-u32",
|
|
|
|
"i32-to-s64",
|
|
|
|
"i32-to-u64",
|
|
|
|
"i64-to-s8",
|
|
|
|
"i64-to-s8x",
|
|
|
|
"i64-to-u8",
|
|
|
|
"i64-to-s16",
|
|
|
|
"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",
|
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() {
|
2020-02-26 15:32:14 +01:00
|
|
|
let input = (&Export {
|
|
|
|
name: "foo",
|
|
|
|
function_type: 0,
|
|
|
|
})
|
|
|
|
.to_string();
|
|
|
|
let output = r#"(@interface export "foo" (func 0))"#;
|
2019-09-18 16:37:57 +02:00
|
|
|
|
2020-02-26 15:32:14 +01:00
|
|
|
assert_eq!(input, output);
|
2019-09-18 16:37:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2020-02-10 15:41:10 +01:00
|
|
|
fn test_imports() {
|
2020-02-26 15:32:14 +01:00
|
|
|
let input = (&Import {
|
|
|
|
namespace: "ns",
|
|
|
|
name: "foo",
|
|
|
|
signature_type: 0,
|
|
|
|
})
|
|
|
|
.to_string();
|
|
|
|
let output = r#"(@interface import "ns" "foo" (func (type 0)))"#;
|
2019-09-18 16:37:57 +02:00
|
|
|
|
2020-02-26 15:32:14 +01:00
|
|
|
assert_eq!(input, output);
|
2019-09-18 16:37:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2020-02-26 15:32:14 +01:00
|
|
|
fn test_adapter() {
|
|
|
|
let input = (&Adapter {
|
|
|
|
function_type: 0,
|
|
|
|
instructions: vec![Instruction::ArgumentGet { index: 42 }],
|
|
|
|
})
|
|
|
|
.to_string();
|
|
|
|
let output = r#"(@interface func (type 0)
|
|
|
|
arg.get 42)"#;
|
2019-09-13 15:40:23 +02:00
|
|
|
|
2020-02-26 15:32:14 +01:00
|
|
|
assert_eq!(input, output);
|
2019-09-13 15:40:23 +02:00
|
|
|
}
|
2019-09-18 16:37:57 +02:00
|
|
|
|
2019-09-18 18:02:05 +02:00
|
|
|
#[test]
|
|
|
|
fn test_interfaces() {
|
|
|
|
let input: String = (&Interfaces {
|
2020-02-26 15:32:14 +01:00
|
|
|
types: vec![Type {
|
|
|
|
inputs: vec![InterfaceType::I32],
|
|
|
|
outputs: vec![InterfaceType::S8],
|
|
|
|
}],
|
|
|
|
imports: vec![Import {
|
|
|
|
namespace: "ns",
|
|
|
|
name: "foo",
|
|
|
|
signature_type: 0,
|
|
|
|
}],
|
|
|
|
adapters: vec![Adapter {
|
|
|
|
function_type: 0,
|
|
|
|
instructions: vec![Instruction::ArgumentGet { index: 42 }],
|
|
|
|
}],
|
|
|
|
exports: vec![Export {
|
|
|
|
name: "bar",
|
|
|
|
function_type: 0,
|
|
|
|
}],
|
|
|
|
implementations: vec![Implementation {
|
|
|
|
core_function_type: 0,
|
|
|
|
adapter_function_type: 1,
|
|
|
|
}],
|
2019-09-18 18:02:05 +02:00
|
|
|
})
|
2020-02-13 14:19:31 +01:00
|
|
|
.to_string();
|
2020-02-26 15:32:14 +01:00
|
|
|
let output = r#";; Types
|
|
|
|
(@interface type (func
|
|
|
|
(param i32)
|
|
|
|
(result s8)))
|
2019-09-18 18:02:05 +02:00
|
|
|
|
2020-02-26 15:32:14 +01:00
|
|
|
;; Imports
|
|
|
|
(@interface import "ns" "foo" (func (type 0)))
|
2019-09-18 18:02:05 +02:00
|
|
|
|
2020-02-26 15:32:14 +01:00
|
|
|
;; Adapters
|
|
|
|
(@interface func (type 0)
|
2019-09-18 18:02:05 +02:00
|
|
|
arg.get 42)
|
|
|
|
|
2020-02-26 15:32:14 +01:00
|
|
|
;; Exports
|
|
|
|
(@interface export "bar" (func 0))
|
|
|
|
|
|
|
|
;; Implementations
|
|
|
|
(@interface implement (func 0) (func 1))"#;
|
2019-09-18 18:02:05 +02:00
|
|
|
|
|
|
|
assert_eq!(input, output);
|
|
|
|
}
|
2019-09-13 15:40:23 +02:00
|
|
|
}
|