mirror of
https://github.com/fluencelabs/wasmer
synced 2025-03-30 22:41:03 +00:00
feat(interface-types) Continue the WAT encoder.
This commit is contained in:
parent
40613d3d48
commit
6279b3e915
@ -1,6 +1,6 @@
|
|||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Copy, Debug)]
|
#[derive(PartialEq, Debug)]
|
||||||
pub enum InterfaceType {
|
pub enum InterfaceType {
|
||||||
Int,
|
Int,
|
||||||
Float,
|
Float,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::ast::{Export, Instruction, InterfaceType};
|
use crate::ast::{Adapter, Export, Forward, ImportedFunction, Instruction, InterfaceType, Type};
|
||||||
|
|
||||||
impl From<InterfaceType> for String {
|
impl From<&InterfaceType> for String {
|
||||||
fn from(interface_type: InterfaceType) -> Self {
|
fn from(interface_type: &InterfaceType) -> Self {
|
||||||
match interface_type {
|
match interface_type {
|
||||||
InterfaceType::Int => "Int".into(),
|
InterfaceType::Int => "Int".into(),
|
||||||
InterfaceType::Float => "Float".into(),
|
InterfaceType::Float => "Float".into(),
|
||||||
@ -17,14 +17,14 @@ impl From<InterfaceType> for String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'input> From<Instruction<'input>> for String {
|
impl<'input> From<&Instruction<'input>> for String {
|
||||||
fn from(instruction: Instruction) -> Self {
|
fn from(instruction: &Instruction) -> Self {
|
||||||
match instruction {
|
match instruction {
|
||||||
Instruction::ArgumentGet(index) => format!("arg.get {}", index),
|
Instruction::ArgumentGet(index) => format!("arg.get {}", index),
|
||||||
Instruction::Call(index) => format!("call {}", index),
|
Instruction::Call(index) => format!("call {}", index),
|
||||||
Instruction::CallExport(export_name) => format!("call-export \"{}\"", export_name),
|
Instruction::CallExport(export_name) => format!(r#"call-export "{}""#, export_name),
|
||||||
Instruction::ReadUtf8 => "read-utf8".into(),
|
Instruction::ReadUtf8 => "read-utf8".into(),
|
||||||
Instruction::WriteUtf8(string) => format!("write-utf8 \"{}\"", string),
|
Instruction::WriteUtf8(string) => format!(r#"write-utf8 "{}""#, string),
|
||||||
Instruction::AsWasm(interface_type) => {
|
Instruction::AsWasm(interface_type) => {
|
||||||
format!("as-wasm {}", String::from(interface_type))
|
format!("as-wasm {}", String::from(interface_type))
|
||||||
}
|
}
|
||||||
@ -48,41 +48,124 @@ impl<'input> From<Instruction<'input>> for String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'input> From<Export<'input>> for String {
|
fn input_types_to_param(input_types: &Vec<InterfaceType>) -> String {
|
||||||
fn from(export: Export) -> Self {
|
if input_types.is_empty() {
|
||||||
|
"".into()
|
||||||
|
} else {
|
||||||
format!(
|
format!(
|
||||||
"(@interface export \"{}\"{}{})",
|
"\n (param{})",
|
||||||
export.name,
|
input_types
|
||||||
if export.input_types.is_empty() {
|
.iter()
|
||||||
"".into()
|
.fold(String::new(), |mut accumulator, interface_type| {
|
||||||
} else {
|
accumulator.push(' ');
|
||||||
format!(
|
accumulator.push_str(&String::from(interface_type));
|
||||||
" (param{})",
|
accumulator
|
||||||
export.input_types.iter().fold(
|
})
|
||||||
String::new(),
|
)
|
||||||
|mut accumulator, interface_type| {
|
}
|
||||||
accumulator.push(' ');
|
}
|
||||||
accumulator.push_str(&String::from(*interface_type));
|
|
||||||
accumulator
|
fn output_types_to_result(output_types: &Vec<InterfaceType>) -> String {
|
||||||
}
|
if output_types.is_empty() {
|
||||||
)
|
"".into()
|
||||||
)
|
} else {
|
||||||
},
|
format!(
|
||||||
if export.output_types.is_empty() {
|
"\n (result{})",
|
||||||
"".into()
|
output_types
|
||||||
} else {
|
.iter()
|
||||||
format!(
|
.fold(String::new(), |mut accumulator, interface_type| {
|
||||||
" (result{})",
|
accumulator.push(' ');
|
||||||
export.output_types.iter().fold(
|
accumulator.push_str(&String::from(interface_type));
|
||||||
String::new(),
|
accumulator
|
||||||
|mut accumulator, interface_type| {
|
})
|
||||||
accumulator.push(' ');
|
)
|
||||||
accumulator.push_str(&String::from(*interface_type));
|
}
|
||||||
accumulator
|
}
|
||||||
}
|
|
||||||
)
|
impl<'input> From<&Export<'input>> for String {
|
||||||
)
|
fn from(export: &Export) -> Self {
|
||||||
},
|
format!(
|
||||||
|
r#"(@interface export "{name}"{inputs}{outputs})"#,
|
||||||
|
name = export.name,
|
||||||
|
inputs = input_types_to_param(&export.input_types),
|
||||||
|
outputs = output_types_to_result(&export.output_types),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'input> From<&Type<'input>> for String {
|
||||||
|
fn from(_ty: &Type) -> Self {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'input> From<&ImportedFunction<'input>> for String {
|
||||||
|
fn from(imported_function: &ImportedFunction) -> Self {
|
||||||
|
format!(
|
||||||
|
r#"(@interface func ${namespace}_{name} (import "{namespace}" "{name}"){inputs}{outputs})"#,
|
||||||
|
namespace = imported_function.namespace,
|
||||||
|
name = imported_function.name,
|
||||||
|
inputs = input_types_to_param(&imported_function.input_types),
|
||||||
|
outputs = output_types_to_result(&imported_function.output_types),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'input> From<&Adapter<'input>> for String {
|
||||||
|
fn from(adapter: &Adapter) -> Self {
|
||||||
|
match adapter {
|
||||||
|
Adapter::Import {
|
||||||
|
namespace,
|
||||||
|
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.iter().fold(
|
||||||
|
String::new(),
|
||||||
|
|mut accumulator, instruction| {
|
||||||
|
accumulator.push_str("\n ");
|
||||||
|
accumulator.push_str(&String::from(instruction));
|
||||||
|
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(&String::from(instruction));
|
||||||
|
accumulator
|
||||||
|
}
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
_ => unimplemented!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'input> From<&Forward<'input>> for String {
|
||||||
|
fn from(forward: &Forward) -> Self {
|
||||||
|
format!(
|
||||||
|
r#"(@interface forward (export "{name}"))"#,
|
||||||
|
name = forward.name,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -94,16 +177,16 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_interface_types() {
|
fn test_interface_types() {
|
||||||
let inputs: Vec<String> = vec![
|
let inputs: Vec<String> = vec![
|
||||||
InterfaceType::Int.into(),
|
(&InterfaceType::Int).into(),
|
||||||
InterfaceType::Float.into(),
|
(&InterfaceType::Float).into(),
|
||||||
InterfaceType::Any.into(),
|
(&InterfaceType::Any).into(),
|
||||||
InterfaceType::String.into(),
|
(&InterfaceType::String).into(),
|
||||||
InterfaceType::Seq.into(),
|
(&InterfaceType::Seq).into(),
|
||||||
InterfaceType::I32.into(),
|
(&InterfaceType::I32).into(),
|
||||||
InterfaceType::I64.into(),
|
(&InterfaceType::I64).into(),
|
||||||
InterfaceType::F32.into(),
|
(&InterfaceType::F32).into(),
|
||||||
InterfaceType::F64.into(),
|
(&InterfaceType::F64).into(),
|
||||||
InterfaceType::AnyRef.into(),
|
(&InterfaceType::AnyRef).into(),
|
||||||
];
|
];
|
||||||
let outputs = vec![
|
let outputs = vec![
|
||||||
"Int", "Float", "Any", "String", "Seq", "i32", "i64", "f32", "f64", "anyref",
|
"Int", "Float", "Any", "String", "Seq", "i32", "i64", "f32", "f64", "anyref",
|
||||||
@ -115,27 +198,27 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_instructions() {
|
fn test_instructions() {
|
||||||
let inputs: Vec<String> = vec![
|
let inputs: Vec<String> = vec![
|
||||||
Instruction::ArgumentGet(7).into(),
|
(&Instruction::ArgumentGet(7)).into(),
|
||||||
Instruction::Call(7).into(),
|
(&Instruction::Call(7)).into(),
|
||||||
Instruction::CallExport("foo").into(),
|
(&Instruction::CallExport("foo")).into(),
|
||||||
Instruction::ReadUtf8.into(),
|
(&Instruction::ReadUtf8).into(),
|
||||||
Instruction::WriteUtf8("foo").into(),
|
(&Instruction::WriteUtf8("foo")).into(),
|
||||||
Instruction::AsWasm(InterfaceType::Int).into(),
|
(&Instruction::AsWasm(InterfaceType::Int)).into(),
|
||||||
Instruction::AsInterface(InterfaceType::AnyRef).into(),
|
(&Instruction::AsInterface(InterfaceType::AnyRef)).into(),
|
||||||
Instruction::TableRefAdd.into(),
|
(&Instruction::TableRefAdd).into(),
|
||||||
Instruction::TableRefGet.into(),
|
(&Instruction::TableRefGet).into(),
|
||||||
Instruction::CallMethod(7).into(),
|
(&Instruction::CallMethod(7)).into(),
|
||||||
Instruction::MakeRecord(InterfaceType::Int).into(),
|
(&Instruction::MakeRecord(InterfaceType::Int)).into(),
|
||||||
Instruction::GetField(InterfaceType::Int, 7).into(),
|
(&Instruction::GetField(InterfaceType::Int, 7)).into(),
|
||||||
Instruction::Const(InterfaceType::I32, 7).into(),
|
(&Instruction::Const(InterfaceType::I32, 7)).into(),
|
||||||
Instruction::FoldSeq(7).into(),
|
(&Instruction::FoldSeq(7)).into(),
|
||||||
];
|
];
|
||||||
let outputs = vec![
|
let outputs = vec![
|
||||||
"arg.get 7",
|
"arg.get 7",
|
||||||
"call 7",
|
"call 7",
|
||||||
"call-export \"foo\"",
|
r#"call-export "foo""#,
|
||||||
"read-utf8",
|
"read-utf8",
|
||||||
"write-utf8 \"foo\"",
|
r#"write-utf8 "foo""#,
|
||||||
"as-wasm Int",
|
"as-wasm Int",
|
||||||
"as-interface anyref",
|
"as-interface anyref",
|
||||||
"table-ref-add",
|
"table-ref-add",
|
||||||
@ -152,14 +235,184 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_exports() {
|
fn test_exports() {
|
||||||
let inputs: Vec<String> = vec![Export {
|
let inputs: Vec<String> = vec![
|
||||||
name: "foo",
|
(&Export {
|
||||||
input_types: vec![InterfaceType::I32, InterfaceType::F32],
|
name: "foo",
|
||||||
output_types: vec![InterfaceType::I32],
|
input_types: vec![InterfaceType::I32, InterfaceType::F32],
|
||||||
}
|
output_types: vec![InterfaceType::I32],
|
||||||
.into()];
|
})
|
||||||
let outputs = vec!["(@interface export \"foo\" (param i32 f32) (result i32))"];
|
.into(),
|
||||||
|
(&Export {
|
||||||
|
name: "foo",
|
||||||
|
input_types: vec![InterfaceType::I32],
|
||||||
|
output_types: vec![],
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
(&Export {
|
||||||
|
name: "foo",
|
||||||
|
input_types: vec![],
|
||||||
|
output_types: vec![InterfaceType::I32],
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
(&Export {
|
||||||
|
name: "foo",
|
||||||
|
input_types: vec![],
|
||||||
|
output_types: vec![],
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
];
|
||||||
|
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!(inputs, outputs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_imported_functions() {
|
||||||
|
let inputs: Vec<String> = vec![
|
||||||
|
(&ImportedFunction {
|
||||||
|
namespace: "ns",
|
||||||
|
name: "foo",
|
||||||
|
input_types: vec![InterfaceType::Int, InterfaceType::String],
|
||||||
|
output_types: vec![InterfaceType::String],
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
(&ImportedFunction {
|
||||||
|
namespace: "ns",
|
||||||
|
name: "foo",
|
||||||
|
input_types: vec![InterfaceType::String],
|
||||||
|
output_types: vec![],
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
(&ImportedFunction {
|
||||||
|
namespace: "ns",
|
||||||
|
name: "foo",
|
||||||
|
input_types: vec![],
|
||||||
|
output_types: vec![InterfaceType::String],
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
(&ImportedFunction {
|
||||||
|
namespace: "ns",
|
||||||
|
name: "foo",
|
||||||
|
input_types: vec![],
|
||||||
|
output_types: vec![],
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
];
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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![
|
||||||
|
Instruction::ArgumentGet(0),
|
||||||
|
Instruction::WriteUtf8("hello"),
|
||||||
|
Instruction::CallExport("f"),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
(&Adapter::Import {
|
||||||
|
namespace: "ns",
|
||||||
|
name: "foo",
|
||||||
|
input_types: vec![InterfaceType::I32],
|
||||||
|
output_types: vec![],
|
||||||
|
instructions: vec![Instruction::CallExport("f")],
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
(&Adapter::Import {
|
||||||
|
namespace: "ns",
|
||||||
|
name: "foo",
|
||||||
|
input_types: vec![],
|
||||||
|
output_types: vec![InterfaceType::I32],
|
||||||
|
instructions: vec![Instruction::CallExport("f")],
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
(&Adapter::Export {
|
||||||
|
name: "foo",
|
||||||
|
input_types: vec![InterfaceType::I32, InterfaceType::F32],
|
||||||
|
output_types: vec![InterfaceType::I32],
|
||||||
|
instructions: vec![
|
||||||
|
Instruction::ArgumentGet(0),
|
||||||
|
Instruction::WriteUtf8("hello"),
|
||||||
|
Instruction::CallExport("f"),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
(&Adapter::Export {
|
||||||
|
name: "foo",
|
||||||
|
input_types: vec![InterfaceType::I32],
|
||||||
|
output_types: vec![],
|
||||||
|
instructions: vec![Instruction::CallExport("f")],
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
(&Adapter::Export {
|
||||||
|
name: "foo",
|
||||||
|
input_types: vec![],
|
||||||
|
output_types: vec![InterfaceType::I32],
|
||||||
|
instructions: vec![Instruction::CallExport("f")],
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
];
|
||||||
|
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" }).into();
|
||||||
|
let output = r#"(@interface forward (export "main"))"#;
|
||||||
|
|
||||||
|
assert_eq!(input, output);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user