From bae5cfbbe345d92315028ff1adb032d0eaf62574 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 21 Feb 2020 12:23:20 +0100 Subject: [PATCH] feat(interface-types) Add the `parse` public API. Also rename `kw` to `keyword`. --- src/decoders/wat.rs | 257 +++++++++++++++++++++++++++++--------------- 1 file changed, 173 insertions(+), 84 deletions(-) diff --git a/src/decoders/wat.rs b/src/decoders/wat.rs index b000259..7ef1d54 100644 --- a/src/decoders/wat.rs +++ b/src/decoders/wat.rs @@ -1,12 +1,13 @@ -//! Parse the WIT textual representation into an AST. +//! Parse the WIT textual representation into an [AST](crate::ast). use crate::{ast::*, interpreter::Instruction}; +pub use wast::parser::ParseBuffer as Buffer; use wast::{ - parser::{Cursor, Parse, Parser, Peek, Result}, + parser::{self, Cursor, Parse, Parser, Peek, Result}, Id, LParen, }; -mod kw { +mod keyword { pub use wast::{ custom_keyword, kw::{anyref, export, f32, f64, func, i32, i64, import, param, result}, @@ -51,44 +52,44 @@ impl Parse<'_> for InterfaceType { fn parse(parser: Parser<'_>) -> Result { let mut lookahead = parser.lookahead1(); - if lookahead.peek::() { - parser.parse::()?; + if lookahead.peek::() { + parser.parse::()?; Ok(InterfaceType::Int) - } else if lookahead.peek::() { - parser.parse::()?; + } else if lookahead.peek::() { + parser.parse::()?; Ok(InterfaceType::Float) - } else if lookahead.peek::() { - parser.parse::()?; + } else if lookahead.peek::() { + parser.parse::()?; Ok(InterfaceType::Any) - } else if lookahead.peek::() { - parser.parse::()?; + } else if lookahead.peek::() { + parser.parse::()?; Ok(InterfaceType::String) - } else if lookahead.peek::() { - parser.parse::()?; + } else if lookahead.peek::() { + parser.parse::()?; Ok(InterfaceType::Seq) - } else if lookahead.peek::() { - parser.parse::()?; + } else if lookahead.peek::() { + parser.parse::()?; Ok(InterfaceType::I32) - } else if lookahead.peek::() { - parser.parse::()?; + } else if lookahead.peek::() { + parser.parse::()?; Ok(InterfaceType::I64) - } else if lookahead.peek::() { - parser.parse::()?; + } else if lookahead.peek::() { + parser.parse::()?; Ok(InterfaceType::F32) - } else if lookahead.peek::() { - parser.parse::()?; + } else if lookahead.peek::() { + parser.parse::()?; Ok(InterfaceType::F64) - } else if lookahead.peek::() { - parser.parse::()?; + } else if lookahead.peek::() { + parser.parse::()?; Ok(InterfaceType::AnyRef) } else { @@ -101,92 +102,92 @@ impl<'a> Parse<'a> for Instruction<'a> { fn parse(parser: Parser<'a>) -> Result { let mut lookahead = parser.lookahead1(); - if lookahead.peek::() { - parser.parse::()?; + if lookahead.peek::() { + parser.parse::()?; Ok(Instruction::ArgumentGet { index: parser.parse()?, }) - } else if lookahead.peek::() { - parser.parse::()?; + } else if lookahead.peek::() { + parser.parse::()?; Ok(Instruction::Call { function_index: parser.parse::()? as usize, }) - } else if lookahead.peek::() { - parser.parse::()?; + } else if lookahead.peek::() { + parser.parse::()?; Ok(Instruction::CallExport { export_name: parser.parse()?, }) - } else if lookahead.peek::() { - parser.parse::()?; + } else if lookahead.peek::() { + parser.parse::()?; Ok(Instruction::ReadUtf8) - } else if lookahead.peek::() { - parser.parse::()?; + } else if lookahead.peek::() { + parser.parse::()?; Ok(Instruction::WriteUtf8 { allocator_name: parser.parse()?, }) - } else if lookahead.peek::() { - parser.parse::()?; + } else if lookahead.peek::() { + parser.parse::()?; Ok(Instruction::AsWasm(parser.parse()?)) - } else if lookahead.peek::() { - parser.parse::()?; + } else if lookahead.peek::() { + parser.parse::()?; Ok(Instruction::AsInterface(parser.parse()?)) - } else if lookahead.peek::() { - parser.parse::()?; + } else if lookahead.peek::() { + parser.parse::()?; Ok(Instruction::TableRefAdd) - } else if lookahead.peek::() { - parser.parse::()?; + } else if lookahead.peek::() { + parser.parse::()?; Ok(Instruction::TableRefGet) - } else if lookahead.peek::() { - parser.parse::()?; + } else if lookahead.peek::() { + parser.parse::()?; Ok(Instruction::CallMethod(parser.parse()?)) - } else if lookahead.peek::() { - parser.parse::()?; + } else if lookahead.peek::() { + parser.parse::()?; Ok(Instruction::MakeRecord(parser.parse()?)) - } else if lookahead.peek::() { - parser.parse::()?; + } else if lookahead.peek::() { + parser.parse::()?; Ok(Instruction::GetField(parser.parse()?, parser.parse()?)) - } else if lookahead.peek::() { - parser.parse::()?; + } else if lookahead.peek::() { + parser.parse::()?; Ok(Instruction::Const(parser.parse()?, parser.parse()?)) - } else if lookahead.peek::() { - parser.parse::()?; + } else if lookahead.peek::() { + parser.parse::()?; Ok(Instruction::FoldSeq(parser.parse()?)) - } else if lookahead.peek::() { - parser.parse::()?; + } else if lookahead.peek::() { + parser.parse::()?; Ok(Instruction::Add(parser.parse()?)) - } else if lookahead.peek::() { - parser.parse::()?; + } else if lookahead.peek::() { + parser.parse::()?; Ok(Instruction::MemToSeq(parser.parse()?, parser.parse()?)) - } else if lookahead.peek::() { - parser.parse::()?; + } else if lookahead.peek::() { + parser.parse::()?; Ok(Instruction::Load(parser.parse()?, parser.parse()?)) - } else if lookahead.peek::() { - parser.parse::()?; + } else if lookahead.peek::() { + parser.parse::()?; Ok(Instruction::SeqNew(parser.parse()?)) - } else if lookahead.peek::() { - parser.parse::()?; + } else if lookahead.peek::() { + parser.parse::()?; Ok(Instruction::ListPush) - } else if lookahead.peek::() { - parser.parse::()?; + } else if lookahead.peek::() { + parser.parse::()?; Ok(Instruction::RepeatUntil(parser.parse()?, parser.parse()?)) } else { @@ -230,8 +231,8 @@ impl Parse<'_> for FunctionType { parser.parens(|parser| { let mut lookahead = parser.lookahead1(); - if lookahead.peek::() { - parser.parse::()?; + if lookahead.peek::() { + parser.parse::()?; let mut inputs = vec![]; @@ -240,8 +241,8 @@ impl Parse<'_> for FunctionType { } Ok(FunctionType::Input(inputs)) - } else if lookahead.peek::() { - parser.parse::()?; + } else if lookahead.peek::() { + parser.parse::()?; let mut outputs = vec![]; @@ -277,13 +278,13 @@ impl<'a> Parse<'a> for Interface<'a> { let mut lookahead = parser.lookahead1(); - if lookahead.peek::() { + if lookahead.peek::() { Ok(Interface::Export(parser.parse()?)) - } else if lookahead.peek::() { + } else if lookahead.peek::() { Ok(Interface::Import(parser.parse()?)) - } else if lookahead.peek::() { + } else if lookahead.peek::() { Ok(Interface::Adapter(parser.parse()?)) - } else if lookahead.peek::() { + } else if lookahead.peek::() { Ok(Interface::Forward(parser.parse()?)) } else { Err(lookahead.error()) @@ -297,7 +298,7 @@ impl<'a> Parse<'a> for Interface<'a> { impl<'a> Parse<'a> for Export<'a> { fn parse(parser: Parser<'a>) -> Result { - parser.parse::()?; + parser.parse::()?; let name = parser.parse()?; let mut input_types = vec![]; @@ -322,11 +323,11 @@ impl<'a> Parse<'a> for Export<'a> { 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::()?; + parser.parse::()?; Ok((parser.parse()?, parser.parse()?)) })?; @@ -353,17 +354,17 @@ impl<'a> Parse<'a> for Import<'a> { 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(); - if lookahead.peek::() { - parser.parse::()?; + if lookahead.peek::() { + parser.parse::()?; Ok((AdapterKind::Import, parser.parse()?, parser.parse()?)) - } else if lookahead.peek::() { - parser.parse::()?; + } else if lookahead.peek::() { + parser.parse::()?; Ok((AdapterKind::Export, "", parser.parse()?)) } else { @@ -410,10 +411,10 @@ impl<'a> Parse<'a> for Adapter<'a> { impl<'a> Parse<'a> for Forward<'a> { fn parse(parser: Parser<'a>) -> Result { - parser.parse::()?; + parser.parse::()?; let name = parser.parens(|parser| { - parser.parse::()?; + parser.parse::()?; Ok(parser.parse()?) })?; @@ -442,13 +443,101 @@ impl<'a> Parse<'a> for Interfaces<'a> { } } +/// Parse a WIT definition in its textual format, and produces an +/// [AST](crate::ast) with the [`Interfaces`](crate::ast::Interfaces) +/// structure upon succesful. +/// +/// # Examples +/// +/// ```rust +/// use wasmer_interface_types::{ +/// ast::*, +/// decoders::wat::{parse, Buffer}, +/// interpreter::Instruction, +/// }; +/// +/// # fn main() { +/// let input = Buffer::new( +/// r#"(@interface export "foo" +/// (param i32)) +/// +/// (@interface export "bar") +/// +/// (@interface func $ns_foo (import "ns" "foo") +/// (result i32)) +/// +/// (@interface func $ns_bar (import "ns" "bar")) +/// +/// (@interface adapt (import "ns" "foo") +/// (param i32) +/// arg.get 42) +/// +/// (@interface adapt (export "bar") +/// arg.get 42) +/// +/// (@interface forward (export "main"))"#, +/// ) +/// .unwrap(); +/// let output = Interfaces { +/// exports: vec![ +/// Export { +/// name: "foo", +/// input_types: vec![InterfaceType::I32], +/// output_types: vec![], +/// }, +/// Export { +/// name: "bar", +/// input_types: vec![], +/// output_types: vec![], +/// }, +/// ], +/// types: vec![], +/// imports: vec![ +/// Import { +/// namespace: "ns", +/// name: "foo", +/// input_types: vec![], +/// output_types: vec![InterfaceType::I32], +/// }, +/// Import { +/// namespace: "ns", +/// name: "bar", +/// input_types: vec![], +/// output_types: vec![], +/// }, +/// ], +/// adapters: vec![ +/// Adapter::Import { +/// namespace: "ns", +/// name: "foo", +/// input_types: vec![InterfaceType::I32], +/// output_types: vec![], +/// instructions: vec![Instruction::ArgumentGet { index: 42 }], +/// }, +/// Adapter::Export { +/// name: "bar", +/// input_types: vec![], +/// output_types: vec![], +/// instructions: vec![Instruction::ArgumentGet { index: 42 }], +/// }, +/// ], +/// forwards: vec![Forward { name: "main" }], +/// }; +/// +/// assert_eq!(parse(&input).unwrap(), output); +/// # } +/// ``` +pub fn parse<'input>(input: &'input Buffer) -> Result> { + parser::parse::(&input) +} + #[cfg(test)] mod tests { use super::*; - use wast::parser::{self, ParseBuffer}; + use wast::parser; - fn buffer(input: &str) -> ParseBuffer { - ParseBuffer::new(input).expect("Failed to build the parser buffer.") + fn buffer(input: &str) -> Buffer { + Buffer::new(input).expect("Failed to build the parser buffer.") } #[test]