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 {
|
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),
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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(),
|
|
|
|
(&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(),
|
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""#,
|
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
|
|
|
}
|