diff --git a/src/ast.rs b/src/ast.rs index 5d587b6..49a33d5 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -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, } -/// 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, - - /// The function output types. - pub output_types: Vec, -} - -/// 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, + /// The type signature. + pub signature_type: u32, +} - /// The function output types. - pub output_types: Vec, +/// 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>, +} - /// The function input types. - input_types: Vec, +/// Represents the kind of interface. +#[derive(PartialEq, Debug)] +pub(crate) enum InterfaceKind { + /// A type. + Type, - /// The function output types. - output_types: Vec, + /// An imported function. + Import, - /// The instructions of the adapter. - instructions: Vec>, - }, + /// 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, - - /// The function output types. - output_types: Vec, - - /// The instructions of the adapter. - instructions: Vec>, - }, + /// 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, - /// All the exported functions. - pub exports: Vec>, - /// All the imported functions. pub imports: Vec>, /// All the adapters. pub adapters: Vec>, + + /// All the exported functions. + pub exports: Vec>, + + /// All the implementations. + pub implementations: Vec, } diff --git a/src/decoders/binary.rs b/src/decoders/binary.rs index 68474d7..3372153 100644 --- a/src/decoders/binary.rs +++ b/src/decoders/binary.rs @@ -32,15 +32,18 @@ impl TryFrom for InterfaceType { } } -/// Parse an adapter kind. -impl TryFrom for AdapterKind { +/// Parse an interface kind. +impl TryFrom for InterfaceKind { type Error = &'static str; fn try_from(code: u8) -> Result { 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, 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, 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, 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 }], - }], + }*/], }, )); diff --git a/src/decoders/wat.rs b/src/decoders/wat.rs index 1d7804f..2f96ca4 100644 --- a/src/decoders/wat.rs +++ b/src/decoders/wat.rs @@ -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::() { - Ok(Interface::Export(parser.parse()?)) - } else if lookahead.peek::() { - Ok(Interface::Import(parser.parse()?)) - } else if lookahead.peek::() { - Ok(Interface::Adapter(parser.parse()?)) - } else if lookahead.peek::() { + if lookahead.peek::() { Ok(Interface::Type(parser.parse()?)) + } else if lookahead.peek::() { + Ok(Interface::Import(parser.parse()?)) + } else if lookahead.peek::() { + Ok(Interface::Adapter(parser.parse()?)) + } else if lookahead.peek::() { + Ok(Interface::Export(parser.parse()?)) + } else if lookahead.peek::() { + 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 { - parser.parse::()?; - let name = parser.parse()?; - - let mut input_types = vec![]; - let mut output_types = vec![]; - - while !parser.is_empty() { - let function_type = parser.parse::()?; - - 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 { - parser.parse::()?; - parser.parse::()?; + parser.parse::()?; - let (namespace, name) = parser.parens(|parser| { - parser.parse::()?; + let namespace = parser.parse()?; + let name = parser.parse()?; - Ok((parser.parse()?, parser.parse()?)) + let signature_type = parser.parens(|parser| { + parser.parse::()?; + + parser.parens(|parser| { + parser.parse::()?; + + parser.parse() + }) })?; - let mut input_types = vec![]; - let mut output_types = vec![]; - - while !parser.is_empty() { - let function_type = parser.parse::()?; - - 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 { + parser.parse::()?; + + let name = parser.parse()?; + + let function_type = parser.parens(|parser| { + parser.parse::()?; + + parser.parse() + })?; + + Ok(Export { + name, + function_type, + }) + } +} + +impl<'a> Parse<'a> for Implementation { + fn parse(parser: Parser<'a>) -> Result { + parser.parse::()?; + + let core_function_type = parser.parens(|parser| { + parser.parse::()?; + + parser.parse() + })?; + + let adapter_function_type = parser.parens(|parser| { + parser.parse::()?; + + parser.parse() + })?; + + Ok(Implementation { + core_function_type, + adapter_function_type, }) } } impl<'a> Parse<'a> for Adapter<'a> { fn parse(parser: Parser<'a>) -> Result { - parser.parse::()?; + parser.parse::()?; - let (kind, namespace, name) = parser.parens(|parser| { - let mut lookahead = parser.lookahead1(); + let function_type = parser.parens(|parser| { + parser.parse::()?; - if lookahead.peek::() { - parser.parse::()?; - - Ok((AdapterKind::Import, parser.parse()?, parser.parse()?)) - } else if lookahead.peek::() { - parser.parse::()?; - - 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::() { - let function_type = parser.parse::()?; - - 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::()?; 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) + } } } diff --git a/src/encoders/binary.rs b/src/encoders/binary.rs index 40c8a96..e15f7d6 100644 --- a/src/encoders/binary.rs +++ b/src/encoders/binary.rs @@ -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 ToBytes for AdapterKind +/// Encode an `InterfaceKind` into bytes. +impl ToBytes 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 ToBytes 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 ToBytes 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 ToBytes 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 ToBytes 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 diff --git a/src/encoders/wat.rs b/src/encoders/wat.rs index a6b8767..44c3287 100644 --- a/src/encoders/wat.rs +++ b/src/encoders/wat.rs @@ -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 } diff --git a/src/macros.rs b/src/macros.rs index 735cecd..7ddfb69 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -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.