mirror of
https://github.com/fluencelabs/interface-types
synced 2024-12-04 15:20:20 +00:00
feat(interface-types) Continue the WAT encoder.
This commit is contained in:
parent
b64aef187d
commit
0352e39741
@ -1,6 +1,6 @@
|
||||
use std::str;
|
||||
|
||||
#[derive(PartialEq, Clone, Copy, Debug)]
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub enum InterfaceType {
|
||||
Int,
|
||||
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 {
|
||||
fn from(interface_type: InterfaceType) -> Self {
|
||||
impl From<&InterfaceType> for String {
|
||||
fn from(interface_type: &InterfaceType) -> Self {
|
||||
match interface_type {
|
||||
InterfaceType::Int => "Int".into(),
|
||||
InterfaceType::Float => "Float".into(),
|
||||
@ -17,14 +17,14 @@ impl From<InterfaceType> for String {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'input> From<Instruction<'input>> for String {
|
||||
fn from(instruction: Instruction) -> Self {
|
||||
impl<'input> From<&Instruction<'input>> for String {
|
||||
fn from(instruction: &Instruction) -> Self {
|
||||
match instruction {
|
||||
Instruction::ArgumentGet(index) => format!("arg.get {}", 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::WriteUtf8(string) => format!("write-utf8 \"{}\"", string),
|
||||
Instruction::WriteUtf8(string) => format!(r#"write-utf8 "{}""#, string),
|
||||
Instruction::AsWasm(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 from(export: Export) -> Self {
|
||||
fn input_types_to_param(input_types: &Vec<InterfaceType>) -> String {
|
||||
if input_types.is_empty() {
|
||||
"".into()
|
||||
} else {
|
||||
format!(
|
||||
"(@interface export \"{}\"{}{})",
|
||||
export.name,
|
||||
if export.input_types.is_empty() {
|
||||
"".into()
|
||||
} else {
|
||||
format!(
|
||||
" (param{})",
|
||||
export.input_types.iter().fold(
|
||||
String::new(),
|
||||
|mut accumulator, interface_type| {
|
||||
accumulator.push(' ');
|
||||
accumulator.push_str(&String::from(*interface_type));
|
||||
accumulator
|
||||
}
|
||||
)
|
||||
)
|
||||
},
|
||||
if export.output_types.is_empty() {
|
||||
"".into()
|
||||
} else {
|
||||
format!(
|
||||
" (result{})",
|
||||
export.output_types.iter().fold(
|
||||
String::new(),
|
||||
|mut accumulator, interface_type| {
|
||||
accumulator.push(' ');
|
||||
accumulator.push_str(&String::from(*interface_type));
|
||||
accumulator
|
||||
}
|
||||
)
|
||||
)
|
||||
},
|
||||
"\n (param{})",
|
||||
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!(
|
||||
"\n (result{})",
|
||||
output_types
|
||||
.iter()
|
||||
.fold(String::new(), |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]
|
||||
fn test_interface_types() {
|
||||
let inputs: Vec<String> = vec![
|
||||
InterfaceType::Int.into(),
|
||||
InterfaceType::Float.into(),
|
||||
InterfaceType::Any.into(),
|
||||
InterfaceType::String.into(),
|
||||
InterfaceType::Seq.into(),
|
||||
InterfaceType::I32.into(),
|
||||
InterfaceType::I64.into(),
|
||||
InterfaceType::F32.into(),
|
||||
InterfaceType::F64.into(),
|
||||
InterfaceType::AnyRef.into(),
|
||||
(&InterfaceType::Int).into(),
|
||||
(&InterfaceType::Float).into(),
|
||||
(&InterfaceType::Any).into(),
|
||||
(&InterfaceType::String).into(),
|
||||
(&InterfaceType::Seq).into(),
|
||||
(&InterfaceType::I32).into(),
|
||||
(&InterfaceType::I64).into(),
|
||||
(&InterfaceType::F32).into(),
|
||||
(&InterfaceType::F64).into(),
|
||||
(&InterfaceType::AnyRef).into(),
|
||||
];
|
||||
let outputs = vec![
|
||||
"Int", "Float", "Any", "String", "Seq", "i32", "i64", "f32", "f64", "anyref",
|
||||
@ -115,27 +198,27 @@ mod tests {
|
||||
#[test]
|
||||
fn test_instructions() {
|
||||
let inputs: Vec<String> = vec![
|
||||
Instruction::ArgumentGet(7).into(),
|
||||
Instruction::Call(7).into(),
|
||||
Instruction::CallExport("foo").into(),
|
||||
Instruction::ReadUtf8.into(),
|
||||
Instruction::WriteUtf8("foo").into(),
|
||||
Instruction::AsWasm(InterfaceType::Int).into(),
|
||||
Instruction::AsInterface(InterfaceType::AnyRef).into(),
|
||||
Instruction::TableRefAdd.into(),
|
||||
Instruction::TableRefGet.into(),
|
||||
Instruction::CallMethod(7).into(),
|
||||
Instruction::MakeRecord(InterfaceType::Int).into(),
|
||||
Instruction::GetField(InterfaceType::Int, 7).into(),
|
||||
Instruction::Const(InterfaceType::I32, 7).into(),
|
||||
Instruction::FoldSeq(7).into(),
|
||||
(&Instruction::ArgumentGet(7)).into(),
|
||||
(&Instruction::Call(7)).into(),
|
||||
(&Instruction::CallExport("foo")).into(),
|
||||
(&Instruction::ReadUtf8).into(),
|
||||
(&Instruction::WriteUtf8("foo")).into(),
|
||||
(&Instruction::AsWasm(InterfaceType::Int)).into(),
|
||||
(&Instruction::AsInterface(InterfaceType::AnyRef)).into(),
|
||||
(&Instruction::TableRefAdd).into(),
|
||||
(&Instruction::TableRefGet).into(),
|
||||
(&Instruction::CallMethod(7)).into(),
|
||||
(&Instruction::MakeRecord(InterfaceType::Int)).into(),
|
||||
(&Instruction::GetField(InterfaceType::Int, 7)).into(),
|
||||
(&Instruction::Const(InterfaceType::I32, 7)).into(),
|
||||
(&Instruction::FoldSeq(7)).into(),
|
||||
];
|
||||
let outputs = vec![
|
||||
"arg.get 7",
|
||||
"call 7",
|
||||
"call-export \"foo\"",
|
||||
r#"call-export "foo""#,
|
||||
"read-utf8",
|
||||
"write-utf8 \"foo\"",
|
||||
r#"write-utf8 "foo""#,
|
||||
"as-wasm Int",
|
||||
"as-interface anyref",
|
||||
"table-ref-add",
|
||||
@ -152,14 +235,184 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_exports() {
|
||||
let inputs: Vec<String> = vec![Export {
|
||||
name: "foo",
|
||||
input_types: vec![InterfaceType::I32, InterfaceType::F32],
|
||||
output_types: vec![InterfaceType::I32],
|
||||
}
|
||||
.into()];
|
||||
let outputs = vec!["(@interface export \"foo\" (param i32 f32) (result i32))"];
|
||||
let inputs: Vec<String> = vec![
|
||||
(&Export {
|
||||
name: "foo",
|
||||
input_types: vec![InterfaceType::I32, InterfaceType::F32],
|
||||
output_types: vec![InterfaceType::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);
|
||||
}
|
||||
|
||||
#[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…
Reference in New Issue
Block a user