feat(interface-types) Encode Interfaces to WAT.

This commit is contained in:
Ivan Enderlin 2019-09-18 18:02:05 +02:00
parent 6ec35c8bdc
commit fc9389d932
2 changed files with 204 additions and 2 deletions

View File

@ -1,4 +1,6 @@
use crate::ast::{Adapter, Export, Forward, ImportedFunction, Instruction, InterfaceType, Type};
use crate::ast::{
Adapter, Export, Forward, ImportedFunction, Instruction, InterfaceType, Interfaces, Type,
};
impl From<&InterfaceType> for String {
fn from(interface_type: &InterfaceType) -> Self {
@ -186,6 +188,83 @@ impl<'input> From<&Forward<'input>> for String {
}
}
impl<'input> From<&Interfaces<'input>> for String {
fn from(interfaces: &Interfaces) -> Self {
let mut output = String::from(";; Interfaces");
let exports = interfaces
.exports
.iter()
.fold(String::new(), |mut accumulator, export| {
accumulator.push_str(&format!("\n\n;; Interface, Export {}\n", export.name));
accumulator.push_str(&String::from(export));
accumulator
});
let types = interfaces
.types
.iter()
.fold(String::new(), |mut accumulator, ty| {
accumulator.push_str(&format!("\n\n;; Interface, Ty {}\n", ty.name));
accumulator.push_str(&String::from(ty));
accumulator
});
let imported_functions = interfaces.imported_functions.iter().fold(
String::new(),
|mut accumulator, imported_function| {
accumulator.push_str(&format!(
"\n\n;; Interface, Imported function {}.{}\n",
imported_function.namespace, imported_function.name
));
accumulator.push_str(&String::from(imported_function));
accumulator
},
);
let adapters =
interfaces
.adapters
.iter()
.fold(String::new(), |mut accumulator, adapter| {
match adapter {
Adapter::Import {
namespace, name, ..
} => accumulator.push_str(&format!(
"\n\n;; Interface, Adapter {}.{}\n",
namespace, name
)),
Adapter::Export { name, .. } => {
accumulator.push_str(&format!("\n\n;; Interface, Adapter {}\n", name))
}
_ => unimplemented!(),
}
accumulator.push_str(&String::from(adapter));
accumulator
});
let forwards =
interfaces
.forwards
.iter()
.fold(String::new(), |mut accumulator, forward| {
accumulator.push_str(&format!("\n\n;; Interface, Forward {}\n", forward.name));
accumulator.push_str(&String::from(forward));
accumulator
});
output.push_str(&exports);
output.push_str(&types);
output.push_str(&imported_functions);
output.push_str(&adapters);
output.push_str(&forwards);
output
}
}
#[cfg(test)]
mod tests {
use crate::ast::*;
@ -443,4 +522,83 @@ mod tests {
assert_eq!(input, output);
}
#[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![],
imported_functions: vec![
ImportedFunction {
namespace: "ns",
name: "foo",
input_types: vec![],
output_types: vec![InterfaceType::I32],
},
ImportedFunction {
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(42)],
},
Adapter::Export {
name: "bar",
input_types: vec![],
output_types: vec![],
instructions: vec![Instruction::ArgumentGet(42)],
},
],
forwards: vec![Forward { name: "main" }],
})
.into();
let output = r#";; Interfaces
;; Interface, Export foo
(@interface export "foo"
(param i32))
;; Interface, Export bar
(@interface export "bar")
;; Interface, Imported function ns.foo
(@interface func $ns_foo (import "ns" "foo")
(result i32))
;; Interface, Imported function 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")
arg.get 42)
;; Interface, Forward main
(@interface forward (export "main"))"#;
assert_eq!(input, output);
}
}

View File

@ -8,7 +8,7 @@ pub use decoders::binary::parse as parse_binary;
#[cfg(test)]
mod tests {
use crate::{ast::*, parse_binary};
use crate::{ast::*, encoders::wat::*, parse_binary};
use std::fs;
use wasmer_clif_backend::CraneliftCompiler;
use wasmer_runtime_core as runtime;
@ -103,6 +103,50 @@ mod tests {
forwards: vec![Forward { name: "main" }]
}
);
let wat = String::from(&interfaces);
assert_eq!(
wat,
r#";; Interfaces
;; Interface, Export strlen
(@interface export "strlen"
(param i32)
(result i32))
;; Interface, Export write_null_byte
(@interface export "write_null_byte"
(param i32 i32)
(result i32))
;; Interface, Imported function host.console_log
(@interface func $host_console_log (import "host" "console_log")
(param String))
;; Interface, Imported function host.document_title
(@interface func $host_document_title (import "host" "document_title")
(result String))
;; Interface, Adapter host.console_log
(@interface adapt (import "host" "console_log")
(param i32)
arg.get 0
arg.get 0
call-export "strlen"
read-utf8
call 0)
;; Interface, Adapter host.document_title
(@interface adapt (import "host" "document_title")
(result i32)
call 1
write-utf8 "alloc"
call-export "write_null_byte")
;; Interface, Forward main
(@interface forward (export "main"))"#,
);
}
Err(_) => assert!(false),