feat(interface-types) Parse Adapter in the WAT decoders.

This commit is contained in:
Ivan Enderlin 2020-02-19 17:41:06 +01:00
parent d07542fbb4
commit e90365beb1

View File

@ -115,7 +115,7 @@ fn export<'input, E: ParseError<&'input str>>(
)(input)
}
/// Parse a `(import …)`.
/// Parse an `(import "ns" "foo")`.
fn import_qualifier<'input, E: ParseError<&'input str>>(
input: &'input str,
) -> IResult<&'input str, (&'input str, &'input str), E> {
@ -141,6 +141,26 @@ fn import_qualifier<'input, E: ParseError<&'input str>>(
)(input)
}
/// Parse an `(export "foo")`.
fn export_qualifier<'input, E: ParseError<&'input str>>(
input: &'input str,
) -> IResult<&'input str, &'input str, E> {
delimited(
char('('),
preceded(
opt(whitespace),
preceded(
tag("export"),
preceded(
whitespace,
preceded(char('"'), cut(terminated(string, char('"')))),
),
),
),
char(')'),
)(input)
}
/// Parse a `$…`.
fn index_variable<'input, E: ParseError<&'input str>>(
input: &'input str,
@ -187,6 +207,63 @@ fn import<'input, E: ParseError<&'input str>>(
)(input)
}
/// Parse an `Adapter`.
fn adapter<'input, E: ParseError<&'input str>>(
input: &'input str,
) -> IResult<&'input str, Adapter, E> {
fn adapter_import<'input, E: ParseError<&'input str>>(
input: &'input str,
) -> IResult<&'input str, Adapter, E> {
map(
tuple((
preceded(whitespace, import_qualifier),
opt(preceded(whitespace, param)),
opt(preceded(whitespace, result)),
)),
|((namespace, name), input_types, output_types)| Adapter::Import {
namespace,
name,
input_types: input_types.unwrap_or_else(|| vec![]),
output_types: output_types.unwrap_or_else(|| vec![]),
instructions: vec![],
},
)(input)
}
fn adapter_export<'input, E: ParseError<&'input str>>(
input: &'input str,
) -> IResult<&'input str, Adapter, E> {
map(
tuple((
preceded(whitespace, export_qualifier),
opt(preceded(whitespace, param)),
opt(preceded(whitespace, result)),
)),
|(name, input_types, output_types)| Adapter::Export {
name,
input_types: input_types.unwrap_or_else(|| vec![]),
output_types: output_types.unwrap_or_else(|| vec![]),
instructions: vec![],
},
)(input)
}
delimited(
char('('),
preceded(
opt(whitespace),
preceded(
tag("@interface"),
preceded(
whitespace,
preceded(tag("adapt"), alt((adapter_import, adapter_export))),
),
),
),
char(')'),
)(input)
}
#[cfg(test)]
mod tests {
use super::*;
@ -326,6 +403,14 @@ mod tests {
assert_eq!(import_qualifier::<()>(input), Ok(("", output)));
}
#[test]
fn test_export_qualifier() {
let input = r#"(export "name")"#;
let output = "name";
assert_eq!(export_qualifier::<()>(input), Ok(("", output)));
}
#[test]
fn test_import_with_no_param_no_result() {
let input = r#"(@interface func $ns_foo (import "ns" "foo"))"#;
@ -391,4 +476,31 @@ mod tests {
assert_eq!(import::<()>(input), Ok(("", output)));
}
#[test]
fn test_adapter_import() {
let input = r#"(@interface adapt (import "ns" "foo") (param i32 i32) (result i32))"#;
let output = Adapter::Import {
namespace: "ns",
name: "foo",
input_types: vec![InterfaceType::I32, InterfaceType::I32],
output_types: vec![InterfaceType::I32],
instructions: vec![],
};
assert_eq!(adapter::<()>(input), Ok(("", output)));
}
#[test]
fn test_adapter_export() {
let input = r#"(@interface adapt (export "foo") (param i32 i32) (result i32))"#;
let output = Adapter::Export {
name: "foo",
input_types: vec![InterfaceType::I32, InterfaceType::I32],
output_types: vec![InterfaceType::I32],
instructions: vec![],
};
assert_eq!(adapter::<()>(input), Ok(("", output)));
}
}