mirror of
https://github.com/fluencelabs/wasmer
synced 2025-03-31 23:11:04 +00:00
feat(interface-types) Re-implement interface kinds.
Adopt a flat structure: Flat resolved imports, flat resolved exports, flat resolved types etc. Also, use the latest textual format for adapters & co.
This commit is contained in:
parent
c64febdad6
commit
0c5d46eec9
@ -50,16 +50,6 @@ pub enum InterfaceType {
|
|||||||
I64,
|
I64,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents the kind of adapter.
|
|
||||||
#[derive(PartialEq, Debug)]
|
|
||||||
pub(crate) enum AdapterKind {
|
|
||||||
/// An adapter defined for an imported function of a WebAssembly instance.
|
|
||||||
Import,
|
|
||||||
|
|
||||||
/// An adapter defined for an exported function of a WebAssembly instance.
|
|
||||||
Export,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Represents a type signature.
|
/// Represents a type signature.
|
||||||
#[derive(PartialEq, Debug)]
|
#[derive(PartialEq, Debug)]
|
||||||
pub struct Type {
|
pub struct Type {
|
||||||
@ -70,20 +60,7 @@ pub struct Type {
|
|||||||
pub outputs: Vec<InterfaceType>,
|
pub outputs: Vec<InterfaceType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents an exported function signature.
|
/// Represents an imported function.
|
||||||
#[derive(PartialEq, Debug)]
|
|
||||||
pub struct Export<'input> {
|
|
||||||
/// The function name.
|
|
||||||
pub name: &'input str,
|
|
||||||
|
|
||||||
/// The function input types.
|
|
||||||
pub input_types: Vec<InterfaceType>,
|
|
||||||
|
|
||||||
/// The function output types.
|
|
||||||
pub output_types: Vec<InterfaceType>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Represents an imported function signature.
|
|
||||||
#[derive(PartialEq, Debug)]
|
#[derive(PartialEq, Debug)]
|
||||||
pub struct Import<'input> {
|
pub struct Import<'input> {
|
||||||
/// The function namespace.
|
/// The function namespace.
|
||||||
@ -92,48 +69,57 @@ pub struct Import<'input> {
|
|||||||
/// The function name.
|
/// The function name.
|
||||||
pub name: &'input str,
|
pub name: &'input str,
|
||||||
|
|
||||||
/// The function input types.
|
/// The type signature.
|
||||||
pub input_types: Vec<InterfaceType>,
|
pub signature_type: u32,
|
||||||
|
}
|
||||||
|
|
||||||
/// The function output types.
|
/// Represents an exported function signature.
|
||||||
pub output_types: Vec<InterfaceType>,
|
#[derive(PartialEq, Debug)]
|
||||||
|
pub struct Export<'input> {
|
||||||
|
/// The export name.
|
||||||
|
pub name: &'input str,
|
||||||
|
|
||||||
|
/// The WIT function type being exported.
|
||||||
|
pub function_type: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Represents an implementation.
|
||||||
|
#[derive(PartialEq, Debug)]
|
||||||
|
pub struct Implementation {
|
||||||
|
/// The core function type.
|
||||||
|
pub core_function_type: u32,
|
||||||
|
|
||||||
|
/// The adapter function type.
|
||||||
|
pub adapter_function_type: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents an adapter.
|
/// Represents an adapter.
|
||||||
#[derive(PartialEq, Debug)]
|
#[derive(PartialEq, Debug)]
|
||||||
pub enum Adapter<'input> {
|
pub struct Adapter<'input> {
|
||||||
/// An adapter for an imported function.
|
/// The adapter function type.
|
||||||
Import {
|
pub function_type: u32,
|
||||||
/// The function namespace.
|
|
||||||
namespace: &'input str,
|
|
||||||
|
|
||||||
/// The function name.
|
/// The instructions.
|
||||||
name: &'input str,
|
pub instructions: Vec<Instruction<'input>>,
|
||||||
|
}
|
||||||
|
|
||||||
/// The function input types.
|
/// Represents the kind of interface.
|
||||||
input_types: Vec<InterfaceType>,
|
#[derive(PartialEq, Debug)]
|
||||||
|
pub(crate) enum InterfaceKind {
|
||||||
|
/// A type.
|
||||||
|
Type,
|
||||||
|
|
||||||
/// The function output types.
|
/// An imported function.
|
||||||
output_types: Vec<InterfaceType>,
|
Import,
|
||||||
|
|
||||||
/// The instructions of the adapter.
|
/// An adapter.
|
||||||
instructions: Vec<Instruction<'input>>,
|
Adapter,
|
||||||
},
|
|
||||||
|
|
||||||
/// An adapter for an exported function.
|
/// An exported function.
|
||||||
Export {
|
Export,
|
||||||
/// The function name.
|
|
||||||
name: &'input str,
|
|
||||||
|
|
||||||
/// The function input types.
|
/// An implementation.
|
||||||
input_types: Vec<InterfaceType>,
|
Implementation,
|
||||||
|
|
||||||
/// The function output types.
|
|
||||||
output_types: Vec<InterfaceType>,
|
|
||||||
|
|
||||||
/// The instructions of the adapter.
|
|
||||||
instructions: Vec<Instruction<'input>>,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents a set of interfaces, i.e. it entirely describes a WIT
|
/// Represents a set of interfaces, i.e. it entirely describes a WIT
|
||||||
@ -143,12 +129,15 @@ pub struct Interfaces<'input> {
|
|||||||
/// All the types.
|
/// All the types.
|
||||||
pub types: Vec<Type>,
|
pub types: Vec<Type>,
|
||||||
|
|
||||||
/// All the exported functions.
|
|
||||||
pub exports: Vec<Export<'input>>,
|
|
||||||
|
|
||||||
/// All the imported functions.
|
/// All the imported functions.
|
||||||
pub imports: Vec<Import<'input>>,
|
pub imports: Vec<Import<'input>>,
|
||||||
|
|
||||||
/// All the adapters.
|
/// All the adapters.
|
||||||
pub adapters: Vec<Adapter<'input>>,
|
pub adapters: Vec<Adapter<'input>>,
|
||||||
|
|
||||||
|
/// All the exported functions.
|
||||||
|
pub exports: Vec<Export<'input>>,
|
||||||
|
|
||||||
|
/// All the implementations.
|
||||||
|
pub implementations: Vec<Implementation>,
|
||||||
}
|
}
|
||||||
|
@ -32,15 +32,18 @@ impl TryFrom<u8> for InterfaceType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse an adapter kind.
|
/// Parse an interface kind.
|
||||||
impl TryFrom<u8> for AdapterKind {
|
impl TryFrom<u8> for InterfaceKind {
|
||||||
type Error = &'static str;
|
type Error = &'static str;
|
||||||
|
|
||||||
fn try_from(code: u8) -> Result<Self, Self::Error> {
|
fn try_from(code: u8) -> Result<Self, Self::Error> {
|
||||||
Ok(match code {
|
Ok(match code {
|
||||||
0x0 => Self::Import,
|
0x00 => Self::Type,
|
||||||
0x1 => Self::Export,
|
0x01 => Self::Import,
|
||||||
_ => return Err("Unknown adapter kind code."),
|
0x02 => Self::Adapter,
|
||||||
|
0x03 => Self::Export,
|
||||||
|
0x04 => Self::Implementation,
|
||||||
|
_ => return Err("Unknown interface kind code."),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -263,29 +266,6 @@ fn instruction<'input, E: ParseError<&'input [u8]>>(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a list of exports.
|
|
||||||
fn exports<'input, E: ParseError<&'input [u8]>>(
|
|
||||||
mut input: &'input [u8],
|
|
||||||
) -> IResult<&'input [u8], Vec<Export>, E> {
|
|
||||||
consume!((input, number_of_exports) = uleb(input)?);
|
|
||||||
|
|
||||||
let mut exports = Vec::with_capacity(number_of_exports as usize);
|
|
||||||
|
|
||||||
for _ in 0..number_of_exports {
|
|
||||||
consume!((input, export_name) = string(input)?);
|
|
||||||
consume!((input, export_input_types) = list(input, ty)?);
|
|
||||||
consume!((input, export_output_types) = list(input, ty)?);
|
|
||||||
|
|
||||||
exports.push(Export {
|
|
||||||
name: export_name,
|
|
||||||
input_types: export_input_types,
|
|
||||||
output_types: export_output_types,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok((input, exports))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parse a list of types.
|
/// Parse a list of types.
|
||||||
fn types<'input, E: ParseError<&'input [u8]>>(
|
fn types<'input, E: ParseError<&'input [u8]>>(
|
||||||
mut input: &'input [u8],
|
mut input: &'input [u8],
|
||||||
@ -313,16 +293,14 @@ fn imports<'input, E: ParseError<&'input [u8]>>(
|
|||||||
let mut imports = Vec::with_capacity(number_of_imports as usize);
|
let mut imports = Vec::with_capacity(number_of_imports as usize);
|
||||||
|
|
||||||
for _ in 0..number_of_imports {
|
for _ in 0..number_of_imports {
|
||||||
consume!((input, import_namespace) = string(input)?);
|
consume!((input, namespace) = string(input)?);
|
||||||
consume!((input, import_name) = string(input)?);
|
consume!((input, name) = string(input)?);
|
||||||
consume!((input, import_input_types) = list(input, ty)?);
|
consume!((input, signature_type) = uleb(input)?);
|
||||||
consume!((input, import_output_types) = list(input, ty)?);
|
|
||||||
|
|
||||||
imports.push(Import {
|
imports.push(Import {
|
||||||
namespace: import_namespace,
|
namespace,
|
||||||
name: import_name,
|
name,
|
||||||
input_types: import_input_types,
|
signature_type: signature_type as u32,
|
||||||
output_types: import_output_types,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -338,64 +316,112 @@ fn adapters<'input, E: ParseError<&'input [u8]>>(
|
|||||||
let mut adapters = Vec::with_capacity(number_of_adapters as usize);
|
let mut adapters = Vec::with_capacity(number_of_adapters as usize);
|
||||||
|
|
||||||
for _ in 0..number_of_adapters {
|
for _ in 0..number_of_adapters {
|
||||||
consume!((input, adapter_kind) = byte(input)?);
|
consume!((input, function_type) = uleb(input)?);
|
||||||
let adapter_kind = AdapterKind::try_from(adapter_kind)
|
consume!((input, instructions) = list(input, instruction)?);
|
||||||
.map_err(|_| Err::Error(make_error(input, ErrorKind::ParseTo)))?;
|
|
||||||
|
|
||||||
match adapter_kind {
|
adapters.push(Adapter {
|
||||||
AdapterKind::Import => {
|
function_type: function_type as u32,
|
||||||
consume!((input, adapter_namespace) = string(input)?);
|
instructions,
|
||||||
consume!((input, adapter_name) = string(input)?);
|
|
||||||
consume!((input, adapter_input_types) = list(input, ty)?);
|
|
||||||
consume!((input, adapter_output_types) = list(input, ty)?);
|
|
||||||
consume!((input, adapter_instructions) = list(input, instruction)?);
|
|
||||||
|
|
||||||
adapters.push(Adapter::Import {
|
|
||||||
namespace: adapter_namespace,
|
|
||||||
name: adapter_name,
|
|
||||||
input_types: adapter_input_types,
|
|
||||||
output_types: adapter_output_types,
|
|
||||||
instructions: adapter_instructions,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
AdapterKind::Export => {
|
|
||||||
consume!((input, adapter_name) = string(input)?);
|
|
||||||
consume!((input, adapter_input_types) = list(input, ty)?);
|
|
||||||
consume!((input, adapter_output_types) = list(input, ty)?);
|
|
||||||
consume!((input, adapter_instructions) = list(input, instruction)?);
|
|
||||||
|
|
||||||
adapters.push(Adapter::Export {
|
|
||||||
name: adapter_name,
|
|
||||||
input_types: adapter_input_types,
|
|
||||||
output_types: adapter_output_types,
|
|
||||||
instructions: adapter_instructions,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok((input, adapters))
|
Ok((input, adapters))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse a list of exports.
|
||||||
|
fn exports<'input, E: ParseError<&'input [u8]>>(
|
||||||
|
mut input: &'input [u8],
|
||||||
|
) -> IResult<&'input [u8], Vec<Export>, E> {
|
||||||
|
consume!((input, number_of_exports) = uleb(input)?);
|
||||||
|
|
||||||
|
let mut exports = Vec::with_capacity(number_of_exports as usize);
|
||||||
|
|
||||||
|
for _ in 0..number_of_exports {
|
||||||
|
consume!((input, name) = string(input)?);
|
||||||
|
consume!((input, function_type) = uleb(input)?);
|
||||||
|
|
||||||
|
exports.push(Export {
|
||||||
|
name,
|
||||||
|
function_type: function_type as u32,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok((input, exports))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse a list of implementations.
|
||||||
|
fn implementations<'input, E: ParseError<&'input [u8]>>(
|
||||||
|
mut input: &'input [u8],
|
||||||
|
) -> IResult<&'input [u8], Vec<Implementation>, E> {
|
||||||
|
consume!((input, number_of_implementations) = uleb(input)?);
|
||||||
|
|
||||||
|
let mut implementations = Vec::with_capacity(number_of_implementations as usize);
|
||||||
|
|
||||||
|
for _ in 0..number_of_implementations {
|
||||||
|
consume!((input, core_function_type) = uleb(input)?);
|
||||||
|
consume!((input, adapter_function_type) = uleb(input)?);
|
||||||
|
|
||||||
|
implementations.push(Implementation {
|
||||||
|
core_function_type: core_function_type as u32,
|
||||||
|
adapter_function_type: adapter_function_type as u32,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok((input, implementations))
|
||||||
|
}
|
||||||
|
|
||||||
/// Parse complete interfaces.
|
/// Parse complete interfaces.
|
||||||
fn interfaces<'input, E: ParseError<&'input [u8]>>(
|
fn interfaces<'input, E: ParseError<&'input [u8]>>(
|
||||||
bytes: &'input [u8],
|
bytes: &'input [u8],
|
||||||
) -> IResult<&'input [u8], Interfaces, E> {
|
) -> IResult<&'input [u8], Interfaces, E> {
|
||||||
let mut input = bytes;
|
let mut input = bytes;
|
||||||
|
|
||||||
consume!((input, exports) = exports(input)?);
|
consume!((input, interface_kind) = byte(input)?);
|
||||||
consume!((input, types) = types(input)?);
|
|
||||||
consume!((input, imports) = imports(input)?);
|
let interface_kind = InterfaceKind::try_from(interface_kind)
|
||||||
consume!((input, adapters) = adapters(input)?);
|
.map_err(|_| Err::Error(make_error(input, ErrorKind::ParseTo)))?;
|
||||||
|
|
||||||
|
let mut all_types = vec![];
|
||||||
|
let mut all_imports = vec![];
|
||||||
|
let mut all_adapters = vec![];
|
||||||
|
let mut all_exports = vec![];
|
||||||
|
let mut all_implementations = vec![];
|
||||||
|
|
||||||
|
match interface_kind {
|
||||||
|
InterfaceKind::Type => {
|
||||||
|
consume!((input, mut new_types) = types(input)?);
|
||||||
|
all_types.append(&mut new_types);
|
||||||
|
}
|
||||||
|
|
||||||
|
InterfaceKind::Import => {
|
||||||
|
consume!((input, mut new_imports) = imports(input)?);
|
||||||
|
all_imports.append(&mut new_imports);
|
||||||
|
}
|
||||||
|
|
||||||
|
InterfaceKind::Adapter => {
|
||||||
|
consume!((input, mut new_adapters) = adapters(input)?);
|
||||||
|
all_adapters.append(&mut new_adapters);
|
||||||
|
}
|
||||||
|
|
||||||
|
InterfaceKind::Export => {
|
||||||
|
consume!((input, mut new_exports) = exports(input)?);
|
||||||
|
all_exports.append(&mut new_exports);
|
||||||
|
}
|
||||||
|
|
||||||
|
InterfaceKind::Implementation => {
|
||||||
|
consume!((input, mut new_implementations) = implementations(input)?);
|
||||||
|
all_implementations.append(&mut new_implementations)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
input,
|
input,
|
||||||
Interfaces {
|
Interfaces {
|
||||||
exports,
|
types: all_types,
|
||||||
types,
|
imports: all_imports,
|
||||||
imports,
|
adapters: all_adapters,
|
||||||
adapters,
|
exports: all_exports,
|
||||||
|
implementations: all_implementations,
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@ -792,6 +818,7 @@ mod tests {
|
|||||||
assert_eq!(imports::<()>(input), output);
|
assert_eq!(imports::<()>(input), output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
#[test]
|
#[test]
|
||||||
fn test_adapters() {
|
fn test_adapters() {
|
||||||
let input = &[
|
let input = &[
|
||||||
@ -838,6 +865,7 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(adapters::<()>(input), output);
|
assert_eq!(adapters::<()>(input), output);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse() {
|
fn test_parse() {
|
||||||
@ -863,6 +891,7 @@ mod tests {
|
|||||||
0x0c, // I32
|
0x0c, // I32
|
||||||
0x01, // list of 1 item
|
0x01, // list of 1 item
|
||||||
0x0d, // I64
|
0x0d, // I64
|
||||||
|
/*
|
||||||
0x01, // 1 adapter
|
0x01, // 1 adapter
|
||||||
0x00, // adapter kind: import
|
0x00, // adapter kind: import
|
||||||
0x01, // string of 1 byte
|
0x01, // string of 1 byte
|
||||||
@ -875,6 +904,7 @@ mod tests {
|
|||||||
0x0c, // I32
|
0x0c, // I32
|
||||||
0x01, // list of 1 item
|
0x01, // list of 1 item
|
||||||
0x00, 0x01, // ArgumentGet { index: 1 }
|
0x00, 0x01, // ArgumentGet { index: 1 }
|
||||||
|
*/
|
||||||
];
|
];
|
||||||
let output = Ok((
|
let output = Ok((
|
||||||
&[] as &[u8],
|
&[] as &[u8],
|
||||||
@ -894,13 +924,13 @@ mod tests {
|
|||||||
input_types: vec![InterfaceType::I32],
|
input_types: vec![InterfaceType::I32],
|
||||||
output_types: vec![InterfaceType::I64],
|
output_types: vec![InterfaceType::I64],
|
||||||
}],
|
}],
|
||||||
adapters: vec![Adapter::Import {
|
adapters: vec![/*Adapter::Import {
|
||||||
namespace: "a",
|
namespace: "a",
|
||||||
name: "b",
|
name: "b",
|
||||||
input_types: vec![InterfaceType::I32],
|
input_types: vec![InterfaceType::I32],
|
||||||
output_types: vec![InterfaceType::I32],
|
output_types: vec![InterfaceType::I32],
|
||||||
instructions: vec![Instruction::ArgumentGet { index: 1 }],
|
instructions: vec![Instruction::ArgumentGet { index: 1 }],
|
||||||
}],
|
}*/],
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -2,10 +2,7 @@
|
|||||||
|
|
||||||
use crate::{ast::*, interpreter::Instruction};
|
use crate::{ast::*, interpreter::Instruction};
|
||||||
pub use wast::parser::ParseBuffer as Buffer;
|
pub use wast::parser::ParseBuffer as Buffer;
|
||||||
use wast::{
|
use wast::parser::{self, Cursor, Parse, Parser, Peek, Result};
|
||||||
parser::{self, Cursor, Parse, Parser, Peek, Result},
|
|
||||||
Id, LParen,
|
|
||||||
};
|
|
||||||
|
|
||||||
mod keyword {
|
mod keyword {
|
||||||
pub use wast::{
|
pub use wast::{
|
||||||
@ -14,7 +11,7 @@ mod keyword {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// New keywords.
|
// New keywords.
|
||||||
custom_keyword!(adapt);
|
custom_keyword!(implement);
|
||||||
custom_keyword!(r#type = "type");
|
custom_keyword!(r#type = "type");
|
||||||
|
|
||||||
// New types.
|
// New types.
|
||||||
@ -283,10 +280,11 @@ impl Parse<'_> for FunctionType {
|
|||||||
|
|
||||||
#[derive(PartialEq, Debug)]
|
#[derive(PartialEq, Debug)]
|
||||||
enum Interface<'a> {
|
enum Interface<'a> {
|
||||||
Export(Export<'a>),
|
|
||||||
Type(Type),
|
Type(Type),
|
||||||
Import(Import<'a>),
|
Import(Import<'a>),
|
||||||
Adapter(Adapter<'a>),
|
Adapter(Adapter<'a>),
|
||||||
|
Export(Export<'a>),
|
||||||
|
Implementation(Implementation),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Parse<'a> for Interface<'a> {
|
impl<'a> Parse<'a> for Interface<'a> {
|
||||||
@ -299,14 +297,16 @@ impl<'a> Parse<'a> for Interface<'a> {
|
|||||||
|
|
||||||
let mut lookahead = parser.lookahead1();
|
let mut lookahead = parser.lookahead1();
|
||||||
|
|
||||||
if lookahead.peek::<keyword::export>() {
|
if lookahead.peek::<keyword::r#type>() {
|
||||||
Ok(Interface::Export(parser.parse()?))
|
|
||||||
} else if lookahead.peek::<keyword::func>() {
|
|
||||||
Ok(Interface::Import(parser.parse()?))
|
|
||||||
} else if lookahead.peek::<keyword::adapt>() {
|
|
||||||
Ok(Interface::Adapter(parser.parse()?))
|
|
||||||
} else if lookahead.peek::<keyword::r#type>() {
|
|
||||||
Ok(Interface::Type(parser.parse()?))
|
Ok(Interface::Type(parser.parse()?))
|
||||||
|
} else if lookahead.peek::<keyword::import>() {
|
||||||
|
Ok(Interface::Import(parser.parse()?))
|
||||||
|
} else if lookahead.peek::<keyword::func>() {
|
||||||
|
Ok(Interface::Adapter(parser.parse()?))
|
||||||
|
} else if lookahead.peek::<keyword::export>() {
|
||||||
|
Ok(Interface::Export(parser.parse()?))
|
||||||
|
} else if lookahead.peek::<keyword::implement>() {
|
||||||
|
Ok(Interface::Implementation(parser.parse()?))
|
||||||
} else {
|
} else {
|
||||||
Err(lookahead.error())
|
Err(lookahead.error())
|
||||||
}
|
}
|
||||||
@ -343,113 +343,92 @@ impl<'a> Parse<'a> for Type {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Parse<'a> for Export<'a> {
|
|
||||||
fn parse(parser: Parser<'a>) -> Result<Self> {
|
|
||||||
parser.parse::<keyword::export>()?;
|
|
||||||
let name = parser.parse()?;
|
|
||||||
|
|
||||||
let mut input_types = vec![];
|
|
||||||
let mut output_types = vec![];
|
|
||||||
|
|
||||||
while !parser.is_empty() {
|
|
||||||
let function_type = parser.parse::<FunctionType>()?;
|
|
||||||
|
|
||||||
match function_type {
|
|
||||||
FunctionType::Input(mut inputs) => input_types.append(&mut inputs),
|
|
||||||
FunctionType::Output(mut outputs) => output_types.append(&mut outputs),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Export {
|
|
||||||
name,
|
|
||||||
input_types,
|
|
||||||
output_types,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Parse<'a> for Import<'a> {
|
impl<'a> Parse<'a> for Import<'a> {
|
||||||
fn parse(parser: Parser<'a>) -> Result<Self> {
|
fn parse(parser: Parser<'a>) -> Result<Self> {
|
||||||
parser.parse::<keyword::func>()?;
|
|
||||||
parser.parse::<Id>()?;
|
|
||||||
|
|
||||||
let (namespace, name) = parser.parens(|parser| {
|
|
||||||
parser.parse::<keyword::import>()?;
|
parser.parse::<keyword::import>()?;
|
||||||
|
|
||||||
Ok((parser.parse()?, parser.parse()?))
|
let namespace = parser.parse()?;
|
||||||
|
let name = parser.parse()?;
|
||||||
|
|
||||||
|
let signature_type = parser.parens(|parser| {
|
||||||
|
parser.parse::<keyword::func>()?;
|
||||||
|
|
||||||
|
parser.parens(|parser| {
|
||||||
|
parser.parse::<keyword::r#type>()?;
|
||||||
|
|
||||||
|
parser.parse()
|
||||||
|
})
|
||||||
})?;
|
})?;
|
||||||
let mut input_types = vec![];
|
|
||||||
let mut output_types = vec![];
|
|
||||||
|
|
||||||
while !parser.is_empty() {
|
|
||||||
let function_type = parser.parse::<FunctionType>()?;
|
|
||||||
|
|
||||||
match function_type {
|
|
||||||
FunctionType::Input(mut inputs) => input_types.append(&mut inputs),
|
|
||||||
FunctionType::Output(mut outputs) => output_types.append(&mut outputs),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Import {
|
Ok(Import {
|
||||||
namespace,
|
namespace,
|
||||||
name,
|
name,
|
||||||
input_types,
|
signature_type,
|
||||||
output_types,
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Parse<'a> for Export<'a> {
|
||||||
|
fn parse(parser: Parser<'a>) -> Result<Self> {
|
||||||
|
parser.parse::<keyword::export>()?;
|
||||||
|
|
||||||
|
let name = parser.parse()?;
|
||||||
|
|
||||||
|
let function_type = parser.parens(|parser| {
|
||||||
|
parser.parse::<keyword::func>()?;
|
||||||
|
|
||||||
|
parser.parse()
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(Export {
|
||||||
|
name,
|
||||||
|
function_type,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Parse<'a> for Implementation {
|
||||||
|
fn parse(parser: Parser<'a>) -> Result<Self> {
|
||||||
|
parser.parse::<keyword::implement>()?;
|
||||||
|
|
||||||
|
let core_function_type = parser.parens(|parser| {
|
||||||
|
parser.parse::<keyword::func>()?;
|
||||||
|
|
||||||
|
parser.parse()
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let adapter_function_type = parser.parens(|parser| {
|
||||||
|
parser.parse::<keyword::func>()?;
|
||||||
|
|
||||||
|
parser.parse()
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(Implementation {
|
||||||
|
core_function_type,
|
||||||
|
adapter_function_type,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Parse<'a> for Adapter<'a> {
|
impl<'a> Parse<'a> for Adapter<'a> {
|
||||||
fn parse(parser: Parser<'a>) -> Result<Self> {
|
fn parse(parser: Parser<'a>) -> Result<Self> {
|
||||||
parser.parse::<keyword::adapt>()?;
|
parser.parse::<keyword::func>()?;
|
||||||
|
|
||||||
let (kind, namespace, name) = parser.parens(|parser| {
|
let function_type = parser.parens(|parser| {
|
||||||
let mut lookahead = parser.lookahead1();
|
parser.parse::<keyword::r#type>()?;
|
||||||
|
|
||||||
if lookahead.peek::<keyword::import>() {
|
parser.parse()
|
||||||
parser.parse::<keyword::import>()?;
|
|
||||||
|
|
||||||
Ok((AdapterKind::Import, parser.parse()?, parser.parse()?))
|
|
||||||
} else if lookahead.peek::<keyword::export>() {
|
|
||||||
parser.parse::<keyword::export>()?;
|
|
||||||
|
|
||||||
Ok((AdapterKind::Export, "", parser.parse()?))
|
|
||||||
} else {
|
|
||||||
Err(lookahead.error())
|
|
||||||
}
|
|
||||||
})?;
|
})?;
|
||||||
let mut input_types = vec![];
|
|
||||||
let mut output_types = vec![];
|
|
||||||
let mut instructions = vec![];
|
let mut instructions = vec![];
|
||||||
|
|
||||||
while !parser.is_empty() {
|
while !parser.is_empty() {
|
||||||
if parser.peek::<LParen>() {
|
|
||||||
let function_type = parser.parse::<FunctionType>()?;
|
|
||||||
|
|
||||||
match function_type {
|
|
||||||
FunctionType::Input(mut inputs) => input_types.append(&mut inputs),
|
|
||||||
FunctionType::Output(mut outputs) => output_types.append(&mut outputs),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
instructions.push(parser.parse()?);
|
instructions.push(parser.parse()?);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Ok(match kind {
|
Ok(Adapter {
|
||||||
AdapterKind::Import => Adapter::Import {
|
function_type,
|
||||||
namespace,
|
|
||||||
name,
|
|
||||||
input_types,
|
|
||||||
output_types,
|
|
||||||
instructions,
|
instructions,
|
||||||
},
|
|
||||||
|
|
||||||
AdapterKind::Export => Adapter::Export {
|
|
||||||
name,
|
|
||||||
input_types,
|
|
||||||
output_types,
|
|
||||||
instructions,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -462,10 +441,13 @@ impl<'a> Parse<'a> for Interfaces<'a> {
|
|||||||
let interface = parser.parse::<Interface>()?;
|
let interface = parser.parse::<Interface>()?;
|
||||||
|
|
||||||
match interface {
|
match interface {
|
||||||
Interface::Export(export) => interfaces.exports.push(export),
|
|
||||||
Interface::Type(ty) => interfaces.types.push(ty),
|
Interface::Type(ty) => interfaces.types.push(ty),
|
||||||
Interface::Import(import) => interfaces.imports.push(import),
|
Interface::Import(import) => interfaces.imports.push(import),
|
||||||
Interface::Adapter(adapter) => interfaces.adapters.push(adapter),
|
Interface::Adapter(adapter) => interfaces.adapters.push(adapter),
|
||||||
|
Interface::Export(export) => interfaces.exports.push(export),
|
||||||
|
Interface::Implementation(implementation) => {
|
||||||
|
interfaces.implementations.push(implementation)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
//! Writes the AST into bytes representing WIT with its binary format.
|
//! Writes the AST into bytes representing WIT with its binary format.
|
||||||
|
|
||||||
use crate::{
|
use crate::{ast::*, interpreter::Instruction};
|
||||||
ast::{Adapter, AdapterKind, Export, Import, InterfaceType, Interfaces, Type},
|
|
||||||
interpreter::Instruction,
|
|
||||||
};
|
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
|
|
||||||
/// A trait for converting a value to bytes.
|
/// A trait for converting a value to bytes.
|
||||||
@ -115,35 +112,22 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Encode an `AdapterKind` into bytes.
|
/// Encode an `InterfaceKind` into bytes.
|
||||||
impl<W> ToBytes<W> for AdapterKind
|
impl<W> ToBytes<W> for InterfaceKind
|
||||||
where
|
where
|
||||||
W: Write,
|
W: Write,
|
||||||
{
|
{
|
||||||
fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
|
fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
|
||||||
match self {
|
match self {
|
||||||
AdapterKind::Import => 0x00_u8.to_bytes(writer),
|
Self::Type => 0x00_u8.to_bytes(writer),
|
||||||
AdapterKind::Export => 0x01_u8.to_bytes(writer),
|
Self::Import => 0x01_u8.to_bytes(writer),
|
||||||
|
Self::Adapter => 0x02_u8.to_bytes(writer),
|
||||||
|
Self::Export => 0x03_u8.to_bytes(writer),
|
||||||
|
Self::Implementation => 0x04_u8.to_bytes(writer),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Encode an `Export` into bytes.
|
|
||||||
///
|
|
||||||
/// Decoder is in `decoders::binary::exports`.
|
|
||||||
impl<W> ToBytes<W> for Export<'_>
|
|
||||||
where
|
|
||||||
W: Write,
|
|
||||||
{
|
|
||||||
fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
|
|
||||||
self.name.to_bytes(writer)?;
|
|
||||||
self.input_types.to_bytes(writer)?;
|
|
||||||
self.output_types.to_bytes(writer)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Encode a `Type` into bytes.
|
/// Encode a `Type` into bytes.
|
||||||
///
|
///
|
||||||
/// Decoder is in `decoders::binary::types`.
|
/// Decoder is in `decoders::binary::types`.
|
||||||
@ -169,8 +153,7 @@ where
|
|||||||
fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
|
fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
|
||||||
self.namespace.to_bytes(writer)?;
|
self.namespace.to_bytes(writer)?;
|
||||||
self.name.to_bytes(writer)?;
|
self.name.to_bytes(writer)?;
|
||||||
self.input_types.to_bytes(writer)?;
|
(self.signature_type as u64).to_bytes(writer)?;
|
||||||
self.output_types.to_bytes(writer)?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -178,41 +161,44 @@ where
|
|||||||
|
|
||||||
/// Encode an `Adapter` into bytes.
|
/// Encode an `Adapter` into bytes.
|
||||||
///
|
///
|
||||||
/// Decoder is in `decoders::binary::imports`.
|
/// Decoder is in `decoders::binary::adapters`.
|
||||||
impl<W> ToBytes<W> for Adapter<'_>
|
impl<W> ToBytes<W> for Adapter<'_>
|
||||||
where
|
where
|
||||||
W: Write,
|
W: Write,
|
||||||
{
|
{
|
||||||
fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
|
fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
|
||||||
match self {
|
(self.function_type as u64).to_bytes(writer)?;
|
||||||
Adapter::Import {
|
self.instructions.to_bytes(writer)?;
|
||||||
namespace,
|
|
||||||
name,
|
|
||||||
input_types,
|
|
||||||
output_types,
|
|
||||||
instructions,
|
|
||||||
} => {
|
|
||||||
AdapterKind::Import.to_bytes(writer)?;
|
|
||||||
namespace.to_bytes(writer)?;
|
|
||||||
name.to_bytes(writer)?;
|
|
||||||
input_types.to_bytes(writer)?;
|
|
||||||
output_types.to_bytes(writer)?;
|
|
||||||
instructions.to_bytes(writer)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Adapter::Export {
|
Ok(())
|
||||||
name,
|
|
||||||
input_types,
|
|
||||||
output_types,
|
|
||||||
instructions,
|
|
||||||
} => {
|
|
||||||
AdapterKind::Export.to_bytes(writer)?;
|
|
||||||
name.to_bytes(writer)?;
|
|
||||||
input_types.to_bytes(writer)?;
|
|
||||||
output_types.to_bytes(writer)?;
|
|
||||||
instructions.to_bytes(writer)?;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Encode an `Export` into bytes.
|
||||||
|
///
|
||||||
|
/// Decoder is in `decoders::binary::exports`.
|
||||||
|
impl<W> ToBytes<W> for Export<'_>
|
||||||
|
where
|
||||||
|
W: Write,
|
||||||
|
{
|
||||||
|
fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
|
||||||
|
self.name.to_bytes(writer)?;
|
||||||
|
(self.function_type as u64).to_bytes(writer)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Encode an `Implementation` into bytes.
|
||||||
|
///
|
||||||
|
/// Decoder is in `decoders::binary::implementations`.
|
||||||
|
impl<W> ToBytes<W> for Implementation
|
||||||
|
where
|
||||||
|
W: Write,
|
||||||
|
{
|
||||||
|
fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
|
||||||
|
(self.core_function_type as u64).to_bytes(writer)?;
|
||||||
|
(self.adapter_function_type as u64).to_bytes(writer)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -226,10 +212,32 @@ where
|
|||||||
W: Write,
|
W: Write,
|
||||||
{
|
{
|
||||||
fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
|
fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
|
||||||
self.exports.to_bytes(writer)?;
|
if !self.types.is_empty() {
|
||||||
|
InterfaceKind::Type.to_bytes(writer)?;
|
||||||
self.types.to_bytes(writer)?;
|
self.types.to_bytes(writer)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.imports.is_empty() {
|
||||||
|
InterfaceKind::Import.to_bytes(writer)?;
|
||||||
self.imports.to_bytes(writer)?;
|
self.imports.to_bytes(writer)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.adapters.is_empty() {
|
||||||
|
InterfaceKind::Adapter.to_bytes(writer)?;
|
||||||
self.adapters.to_bytes(writer)?;
|
self.adapters.to_bytes(writer)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.exports.is_empty() {
|
||||||
|
InterfaceKind::Export.to_bytes(writer)?;
|
||||||
|
self.exports.to_bytes(writer)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.implementations.is_empty() {
|
||||||
|
InterfaceKind::Implementation.to_bytes(writer)?;
|
||||||
|
self.implementations.to_bytes(writer)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
//self.adapters.to_bytes(writer)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -437,9 +445,12 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_adapter_kind() {
|
fn test_interface_kind() {
|
||||||
assert_to_bytes!(AdapterKind::Import, &[0x00]);
|
assert_to_bytes!(InterfaceKind::Type, &[0x00]);
|
||||||
assert_to_bytes!(AdapterKind::Export, &[0x01]);
|
assert_to_bytes!(InterfaceKind::Import, &[0x01]);
|
||||||
|
assert_to_bytes!(InterfaceKind::Function, &[0x02]);
|
||||||
|
assert_to_bytes!(InterfaceKind::Export, &[0x03]);
|
||||||
|
assert_to_bytes!(InterfaceKind::Implementation, &[0x04]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -515,7 +526,7 @@ mod tests {
|
|||||||
instructions: vec![Instruction::ArgumentGet { index: 1 }],
|
instructions: vec![Instruction::ArgumentGet { index: 1 }],
|
||||||
},
|
},
|
||||||
&[
|
&[
|
||||||
0x00, // AdapterKind::Import
|
0x01, // InterfaceKind::Import
|
||||||
0x01, // string of length 1
|
0x01, // string of length 1
|
||||||
0x61, // "a"
|
0x61, // "a"
|
||||||
0x01, // string of length 1
|
0x01, // string of length 1
|
||||||
@ -541,7 +552,7 @@ mod tests {
|
|||||||
instructions: vec![Instruction::ArgumentGet { index: 1 }],
|
instructions: vec![Instruction::ArgumentGet { index: 1 }],
|
||||||
},
|
},
|
||||||
&[
|
&[
|
||||||
0x01, // AdapterKind::Export
|
0x03, // InterfaceKind::Export
|
||||||
0x01, // string of length 1
|
0x01, // string of length 1
|
||||||
0x61, // "a"
|
0x61, // "a"
|
||||||
0x02, // list of 2 items
|
0x02, // list of 2 items
|
||||||
|
@ -84,10 +84,7 @@
|
|||||||
//! # }
|
//! # }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
use crate::{
|
use crate::{ast::*, interpreter::Instruction};
|
||||||
ast::{Adapter, Export, Import, InterfaceType, Interfaces, Type},
|
|
||||||
interpreter::Instruction,
|
|
||||||
};
|
|
||||||
use std::string::ToString;
|
use std::string::ToString;
|
||||||
|
|
||||||
/// Encode an `InterfaceType` into a string.
|
/// Encode an `InterfaceType` into a string.
|
||||||
@ -198,18 +195,6 @@ fn output_types_to_result(output_types: &[InterfaceType]) -> String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Encode an `Export` into a string.
|
|
||||||
impl<'input> ToString for &Export<'input> {
|
|
||||||
fn to_string(&self) -> String {
|
|
||||||
format!(
|
|
||||||
r#"(@interface export "{name}"{inputs}{outputs})"#,
|
|
||||||
name = self.name,
|
|
||||||
inputs = input_types_to_param(&self.input_types),
|
|
||||||
outputs = output_types_to_result(&self.output_types),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Encode a `Type` into a string.
|
/// Encode a `Type` into a string.
|
||||||
impl<'input> ToString for &Type {
|
impl<'input> ToString for &Type {
|
||||||
fn to_string(&self) -> String {
|
fn to_string(&self) -> String {
|
||||||
@ -225,11 +210,10 @@ impl<'input> ToString for &Type {
|
|||||||
impl<'input> ToString for &Import<'input> {
|
impl<'input> ToString for &Import<'input> {
|
||||||
fn to_string(&self) -> String {
|
fn to_string(&self) -> String {
|
||||||
format!(
|
format!(
|
||||||
r#"(@interface func ${namespace}_{name} (import "{namespace}" "{name}"){inputs}{outputs})"#,
|
r#"(@interface import "{namespace}" "{name}" (func (type {type})))"#,
|
||||||
namespace = self.namespace,
|
namespace = self.namespace,
|
||||||
name = self.name,
|
name = self.name,
|
||||||
inputs = input_types_to_param(&self.input_types),
|
type = self.signature_type,
|
||||||
outputs = output_types_to_result(&self.output_types),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -237,49 +221,40 @@ impl<'input> ToString for &Import<'input> {
|
|||||||
/// Encode an `Adapter` into a string.
|
/// Encode an `Adapter` into a string.
|
||||||
impl<'input> ToString for &Adapter<'input> {
|
impl<'input> ToString for &Adapter<'input> {
|
||||||
fn to_string(&self) -> String {
|
fn to_string(&self) -> String {
|
||||||
match self {
|
format!(
|
||||||
Adapter::Import {
|
r#"(@interface func (type {function_type}){instructions})"#,
|
||||||
namespace,
|
function_type = self.function_type,
|
||||||
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 =
|
||||||
instructions
|
self.instructions
|
||||||
.iter()
|
.iter()
|
||||||
.fold(String::new(), |mut accumulator, instruction| {
|
.fold(String::new(), |mut accumulator, instruction| {
|
||||||
accumulator.push_str("\n ");
|
accumulator.push_str("\n ");
|
||||||
accumulator.push_str(&instruction.to_string());
|
accumulator.push_str(&instruction.to_string());
|
||||||
accumulator
|
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(&instruction.to_string());
|
|
||||||
accumulator
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -288,15 +263,6 @@ impl<'input> ToString for &Interfaces<'input> {
|
|||||||
fn to_string(&self) -> String {
|
fn to_string(&self) -> String {
|
||||||
let mut output = String::from(";; Interfaces");
|
let mut output = String::from(";; Interfaces");
|
||||||
|
|
||||||
let exports = self
|
|
||||||
.exports
|
|
||||||
.iter()
|
|
||||||
.fold(String::new(), |mut accumulator, export| {
|
|
||||||
accumulator.push_str(&format!("\n\n;; Interface, Export {}\n", export.name));
|
|
||||||
accumulator.push_str(&export.to_string());
|
|
||||||
accumulator
|
|
||||||
});
|
|
||||||
|
|
||||||
let types = self
|
let types = self
|
||||||
.types
|
.types
|
||||||
.iter()
|
.iter()
|
||||||
@ -309,10 +275,6 @@ impl<'input> ToString for &Interfaces<'input> {
|
|||||||
.imports
|
.imports
|
||||||
.iter()
|
.iter()
|
||||||
.fold(String::new(), |mut accumulator, import| {
|
.fold(String::new(), |mut accumulator, import| {
|
||||||
accumulator.push_str(&format!(
|
|
||||||
"\n\n;; Interface, Import {}.{}\n",
|
|
||||||
import.namespace, import.name
|
|
||||||
));
|
|
||||||
accumulator.push_str(&import.to_string());
|
accumulator.push_str(&import.to_string());
|
||||||
accumulator
|
accumulator
|
||||||
});
|
});
|
||||||
@ -321,26 +283,31 @@ impl<'input> ToString for &Interfaces<'input> {
|
|||||||
.adapters
|
.adapters
|
||||||
.iter()
|
.iter()
|
||||||
.fold(String::new(), |mut accumulator, adapter| {
|
.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))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
accumulator.push_str(&adapter.to_string());
|
accumulator.push_str(&adapter.to_string());
|
||||||
accumulator
|
accumulator
|
||||||
});
|
});
|
||||||
|
|
||||||
output.push_str(&exports);
|
let exports = self
|
||||||
|
.exports
|
||||||
|
.iter()
|
||||||
|
.fold(String::new(), |mut accumulator, export| {
|
||||||
|
accumulator.push_str(&export.to_string());
|
||||||
|
accumulator
|
||||||
|
});
|
||||||
|
|
||||||
|
let implementations =
|
||||||
|
self.implementations
|
||||||
|
.iter()
|
||||||
|
.fold(String::new(), |mut accumulator, implementation| {
|
||||||
|
accumulator.push_str(&implementation.to_string());
|
||||||
|
accumulator
|
||||||
|
});
|
||||||
|
|
||||||
output.push_str(&types);
|
output.push_str(&types);
|
||||||
output.push_str(&imports);
|
output.push_str(&imports);
|
||||||
output.push_str(&adapters);
|
output.push_str(&adapters);
|
||||||
|
output.push_str(&exports);
|
||||||
|
output.push_str(&implementations);
|
||||||
|
|
||||||
output
|
output
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,11 @@ macro_rules! consume {
|
|||||||
let (next_input, $parser_output) = $parser_expression;
|
let (next_input, $parser_output) = $parser_expression;
|
||||||
$input = next_input;
|
$input = next_input;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
(($input:ident, mut $parser_output:ident) = $parser_expression:expr) => {
|
||||||
|
let (next_input, mut $parser_output) = $parser_expression;
|
||||||
|
$input = next_input;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This macro creates an executable instruction for the interpreter.
|
/// This macro creates an executable instruction for the interpreter.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user