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:
Ivan Enderlin 2020-02-24 18:12:01 +01:00
parent c64febdad6
commit 0c5d46eec9
6 changed files with 383 additions and 399 deletions

View File

@ -50,16 +50,6 @@ pub enum InterfaceType {
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.
#[derive(PartialEq, Debug)]
pub struct Type {
@ -70,20 +60,7 @@ pub struct Type {
pub outputs: Vec<InterfaceType>,
}
/// Represents an exported function signature.
#[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.
/// Represents an imported function.
#[derive(PartialEq, Debug)]
pub struct Import<'input> {
/// The function namespace.
@ -92,48 +69,57 @@ pub struct Import<'input> {
/// The function name.
pub name: &'input str,
/// The function input types.
pub input_types: Vec<InterfaceType>,
/// The type signature.
pub signature_type: u32,
}
/// The function output types.
pub output_types: Vec<InterfaceType>,
/// Represents an exported function signature.
#[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.
#[derive(PartialEq, Debug)]
pub enum Adapter<'input> {
/// An adapter for an imported function.
Import {
/// The function namespace.
namespace: &'input str,
pub struct Adapter<'input> {
/// The adapter function type.
pub function_type: u32,
/// The function name.
name: &'input str,
/// The instructions.
pub instructions: Vec<Instruction<'input>>,
}
/// The function input types.
input_types: Vec<InterfaceType>,
/// Represents the kind of interface.
#[derive(PartialEq, Debug)]
pub(crate) enum InterfaceKind {
/// A type.
Type,
/// The function output types.
output_types: Vec<InterfaceType>,
/// An imported function.
Import,
/// The instructions of the adapter.
instructions: Vec<Instruction<'input>>,
},
/// An adapter.
Adapter,
/// An adapter for an exported function.
Export {
/// The function name.
name: &'input str,
/// An exported function.
Export,
/// The function input types.
input_types: Vec<InterfaceType>,
/// The function output types.
output_types: Vec<InterfaceType>,
/// The instructions of the adapter.
instructions: Vec<Instruction<'input>>,
},
/// An implementation.
Implementation,
}
/// Represents a set of interfaces, i.e. it entirely describes a WIT
@ -143,12 +129,15 @@ pub struct Interfaces<'input> {
/// All the types.
pub types: Vec<Type>,
/// All the exported functions.
pub exports: Vec<Export<'input>>,
/// All the imported functions.
pub imports: Vec<Import<'input>>,
/// All the adapters.
pub adapters: Vec<Adapter<'input>>,
/// All the exported functions.
pub exports: Vec<Export<'input>>,
/// All the implementations.
pub implementations: Vec<Implementation>,
}

View File

@ -32,15 +32,18 @@ impl TryFrom<u8> for InterfaceType {
}
}
/// Parse an adapter kind.
impl TryFrom<u8> for AdapterKind {
/// Parse an interface kind.
impl TryFrom<u8> for InterfaceKind {
type Error = &'static str;
fn try_from(code: u8) -> Result<Self, Self::Error> {
Ok(match code {
0x0 => Self::Import,
0x1 => Self::Export,
_ => return Err("Unknown adapter kind code."),
0x00 => Self::Type,
0x01 => Self::Import,
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.
fn types<'input, E: ParseError<&'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);
for _ in 0..number_of_imports {
consume!((input, import_namespace) = string(input)?);
consume!((input, import_name) = string(input)?);
consume!((input, import_input_types) = list(input, ty)?);
consume!((input, import_output_types) = list(input, ty)?);
consume!((input, namespace) = string(input)?);
consume!((input, name) = string(input)?);
consume!((input, signature_type) = uleb(input)?);
imports.push(Import {
namespace: import_namespace,
name: import_name,
input_types: import_input_types,
output_types: import_output_types,
namespace,
name,
signature_type: signature_type as u32,
});
}
@ -338,64 +316,112 @@ fn adapters<'input, E: ParseError<&'input [u8]>>(
let mut adapters = Vec::with_capacity(number_of_adapters as usize);
for _ in 0..number_of_adapters {
consume!((input, adapter_kind) = byte(input)?);
let adapter_kind = AdapterKind::try_from(adapter_kind)
.map_err(|_| Err::Error(make_error(input, ErrorKind::ParseTo)))?;
consume!((input, function_type) = uleb(input)?);
consume!((input, instructions) = list(input, instruction)?);
match adapter_kind {
AdapterKind::Import => {
consume!((input, adapter_namespace) = string(input)?);
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,
});
}
}
adapters.push(Adapter {
function_type: function_type as u32,
instructions,
});
}
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.
fn interfaces<'input, E: ParseError<&'input [u8]>>(
bytes: &'input [u8],
) -> IResult<&'input [u8], Interfaces, E> {
let mut input = bytes;
consume!((input, exports) = exports(input)?);
consume!((input, types) = types(input)?);
consume!((input, imports) = imports(input)?);
consume!((input, adapters) = adapters(input)?);
consume!((input, interface_kind) = byte(input)?);
let interface_kind = InterfaceKind::try_from(interface_kind)
.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((
input,
Interfaces {
exports,
types,
imports,
adapters,
types: all_types,
imports: all_imports,
adapters: all_adapters,
exports: all_exports,
implementations: all_implementations,
},
))
}
@ -792,6 +818,7 @@ mod tests {
assert_eq!(imports::<()>(input), output);
}
/*
#[test]
fn test_adapters() {
let input = &[
@ -838,6 +865,7 @@ mod tests {
assert_eq!(adapters::<()>(input), output);
}
*/
#[test]
fn test_parse() {
@ -863,18 +891,20 @@ mod tests {
0x0c, // I32
0x01, // list of 1 item
0x0d, // I64
0x01, // 1 adapter
0x00, // adapter kind: import
0x01, // string of 1 byte
0x61, // "a"
0x01, // string of 1 byte
0x62, // "b"
0x01, // list of 1 item
0x0c, // I32
0x01, // list of 1 item
0x0c, // I32
0x01, // list of 1 item
0x00, 0x01, // ArgumentGet { index: 1 }
/*
0x01, // 1 adapter
0x00, // adapter kind: import
0x01, // string of 1 byte
0x61, // "a"
0x01, // string of 1 byte
0x62, // "b"
0x01, // list of 1 item
0x0c, // I32
0x01, // list of 1 item
0x0c, // I32
0x01, // list of 1 item
0x00, 0x01, // ArgumentGet { index: 1 }
*/
];
let output = Ok((
&[] as &[u8],
@ -894,13 +924,13 @@ mod tests {
input_types: vec![InterfaceType::I32],
output_types: vec![InterfaceType::I64],
}],
adapters: vec![Adapter::Import {
adapters: vec![/*Adapter::Import {
namespace: "a",
name: "b",
input_types: vec![InterfaceType::I32],
output_types: vec![InterfaceType::I32],
instructions: vec![Instruction::ArgumentGet { index: 1 }],
}],
}*/],
},
));

View File

@ -2,10 +2,7 @@
use crate::{ast::*, interpreter::Instruction};
pub use wast::parser::ParseBuffer as Buffer;
use wast::{
parser::{self, Cursor, Parse, Parser, Peek, Result},
Id, LParen,
};
use wast::parser::{self, Cursor, Parse, Parser, Peek, Result};
mod keyword {
pub use wast::{
@ -14,7 +11,7 @@ mod keyword {
};
// New keywords.
custom_keyword!(adapt);
custom_keyword!(implement);
custom_keyword!(r#type = "type");
// New types.
@ -283,10 +280,11 @@ impl Parse<'_> for FunctionType {
#[derive(PartialEq, Debug)]
enum Interface<'a> {
Export(Export<'a>),
Type(Type),
Import(Import<'a>),
Adapter(Adapter<'a>),
Export(Export<'a>),
Implementation(Implementation),
}
impl<'a> Parse<'a> for Interface<'a> {
@ -299,14 +297,16 @@ impl<'a> Parse<'a> for Interface<'a> {
let mut lookahead = parser.lookahead1();
if lookahead.peek::<keyword::export>() {
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>() {
if lookahead.peek::<keyword::r#type>() {
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 {
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> {
fn parse(parser: Parser<'a>) -> Result<Self> {
parser.parse::<keyword::func>()?;
parser.parse::<Id>()?;
parser.parse::<keyword::import>()?;
let (namespace, name) = parser.parens(|parser| {
parser.parse::<keyword::import>()?;
let namespace = parser.parse()?;
let name = parser.parse()?;
Ok((parser.parse()?, 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 {
namespace,
name,
input_types,
output_types,
signature_type,
})
}
}
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> {
fn parse(parser: Parser<'a>) -> Result<Self> {
parser.parse::<keyword::adapt>()?;
parser.parse::<keyword::func>()?;
let (kind, namespace, name) = parser.parens(|parser| {
let mut lookahead = parser.lookahead1();
let function_type = parser.parens(|parser| {
parser.parse::<keyword::r#type>()?;
if lookahead.peek::<keyword::import>() {
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())
}
parser.parse()
})?;
let mut input_types = vec![];
let mut output_types = vec![];
let mut instructions = vec![];
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 {
AdapterKind::Import => Adapter::Import {
namespace,
name,
input_types,
output_types,
instructions,
},
AdapterKind::Export => Adapter::Export {
name,
input_types,
output_types,
instructions,
},
Ok(Adapter {
function_type,
instructions,
})
}
}
@ -462,10 +441,13 @@ impl<'a> Parse<'a> for Interfaces<'a> {
let interface = parser.parse::<Interface>()?;
match interface {
Interface::Export(export) => interfaces.exports.push(export),
Interface::Type(ty) => interfaces.types.push(ty),
Interface::Import(import) => interfaces.imports.push(import),
Interface::Adapter(adapter) => interfaces.adapters.push(adapter),
Interface::Export(export) => interfaces.exports.push(export),
Interface::Implementation(implementation) => {
interfaces.implementations.push(implementation)
}
}
}

View File

@ -1,9 +1,6 @@
//! Writes the AST into bytes representing WIT with its binary format.
use crate::{
ast::{Adapter, AdapterKind, Export, Import, InterfaceType, Interfaces, Type},
interpreter::Instruction,
};
use crate::{ast::*, interpreter::Instruction};
use std::io::{self, Write};
/// A trait for converting a value to bytes.
@ -115,35 +112,22 @@ where
}
}
/// Encode an `AdapterKind` into bytes.
impl<W> ToBytes<W> for AdapterKind
/// Encode an `InterfaceKind` into bytes.
impl<W> ToBytes<W> for InterfaceKind
where
W: Write,
{
fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
match self {
AdapterKind::Import => 0x00_u8.to_bytes(writer),
AdapterKind::Export => 0x01_u8.to_bytes(writer),
Self::Type => 0x00_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.
///
/// Decoder is in `decoders::binary::types`.
@ -169,8 +153,7 @@ where
fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
self.namespace.to_bytes(writer)?;
self.name.to_bytes(writer)?;
self.input_types.to_bytes(writer)?;
self.output_types.to_bytes(writer)?;
(self.signature_type as u64).to_bytes(writer)?;
Ok(())
}
@ -178,41 +161,44 @@ where
/// Encode an `Adapter` into bytes.
///
/// Decoder is in `decoders::binary::imports`.
/// Decoder is in `decoders::binary::adapters`.
impl<W> ToBytes<W> for Adapter<'_>
where
W: Write,
{
fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
match self {
Adapter::Import {
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)?;
}
(self.function_type as u64).to_bytes(writer)?;
self.instructions.to_bytes(writer)?;
Adapter::Export {
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)?;
}
}
Ok(())
}
}
/// 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(())
}
@ -226,10 +212,32 @@ where
W: Write,
{
fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
self.exports.to_bytes(writer)?;
self.types.to_bytes(writer)?;
self.imports.to_bytes(writer)?;
self.adapters.to_bytes(writer)?;
if !self.types.is_empty() {
InterfaceKind::Type.to_bytes(writer)?;
self.types.to_bytes(writer)?;
}
if !self.imports.is_empty() {
InterfaceKind::Import.to_bytes(writer)?;
self.imports.to_bytes(writer)?;
}
if !self.adapters.is_empty() {
InterfaceKind::Adapter.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(())
}
@ -437,9 +445,12 @@ mod tests {
}
#[test]
fn test_adapter_kind() {
assert_to_bytes!(AdapterKind::Import, &[0x00]);
assert_to_bytes!(AdapterKind::Export, &[0x01]);
fn test_interface_kind() {
assert_to_bytes!(InterfaceKind::Type, &[0x00]);
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]
@ -515,7 +526,7 @@ mod tests {
instructions: vec![Instruction::ArgumentGet { index: 1 }],
},
&[
0x00, // AdapterKind::Import
0x01, // InterfaceKind::Import
0x01, // string of length 1
0x61, // "a"
0x01, // string of length 1
@ -541,7 +552,7 @@ mod tests {
instructions: vec![Instruction::ArgumentGet { index: 1 }],
},
&[
0x01, // AdapterKind::Export
0x03, // InterfaceKind::Export
0x01, // string of length 1
0x61, // "a"
0x02, // list of 2 items

View File

@ -84,10 +84,7 @@
//! # }
//! ```
use crate::{
ast::{Adapter, Export, Import, InterfaceType, Interfaces, Type},
interpreter::Instruction,
};
use crate::{ast::*, interpreter::Instruction};
use std::string::ToString;
/// 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.
impl<'input> ToString for &Type {
fn to_string(&self) -> String {
@ -225,11 +210,10 @@ impl<'input> ToString for &Type {
impl<'input> ToString for &Import<'input> {
fn to_string(&self) -> String {
format!(
r#"(@interface func ${namespace}_{name} (import "{namespace}" "{name}"){inputs}{outputs})"#,
r#"(@interface import "{namespace}" "{name}" (func (type {type})))"#,
namespace = self.namespace,
name = self.name,
inputs = input_types_to_param(&self.input_types),
outputs = output_types_to_result(&self.output_types),
type = self.signature_type,
)
}
}
@ -237,49 +221,40 @@ impl<'input> ToString for &Import<'input> {
/// Encode an `Adapter` into a string.
impl<'input> ToString for &Adapter<'input> {
fn to_string(&self) -> String {
match self {
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(&instruction.to_string());
accumulator
}),
),
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
}),
)
}
}
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 {
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
.types
.iter()
@ -309,10 +275,6 @@ impl<'input> ToString for &Interfaces<'input> {
.imports
.iter()
.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
});
@ -321,26 +283,31 @@ impl<'input> ToString for &Interfaces<'input> {
.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))
}
}
accumulator.push_str(&adapter.to_string());
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(&imports);
output.push_str(&adapters);
output.push_str(&exports);
output.push_str(&implementations);
output
}

View File

@ -5,6 +5,11 @@ macro_rules! consume {
let (next_input, $parser_output) = $parser_expression;
$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.