mirror of
https://github.com/fluencelabs/wasmer
synced 2025-03-16 16:20:49 +00:00
feat(interface-types) Parse Import
in the WAT decoders.
This commit is contained in:
parent
c97122899d
commit
2e78cf1fc0
@ -7,11 +7,11 @@ use nom::{
|
||||
branch::alt,
|
||||
bytes::complete::{escaped, tag, take_while1},
|
||||
character::complete::{alphanumeric1, char, one_of},
|
||||
combinator::{cut, opt, value},
|
||||
combinator::{cut, map, opt, value},
|
||||
error::ParseError,
|
||||
multi::many0,
|
||||
sequence::{delimited, preceded, terminated, tuple},
|
||||
IResult,
|
||||
AsChar, IResult,
|
||||
};
|
||||
|
||||
/// Parse a whitespace.
|
||||
@ -82,24 +82,22 @@ fn result<'input, E: ParseError<&'input str>>(
|
||||
fn export<'input, E: ParseError<&'input str>>(
|
||||
input: &'input str,
|
||||
) -> IResult<&'input str, Export, E> {
|
||||
//(@interface export "name")
|
||||
let (remains, (export_name, input_types, output_types)): (
|
||||
&str,
|
||||
(&str, Option<Vec<InterfaceType>>, Option<Vec<InterfaceType>>),
|
||||
) = delimited(
|
||||
char('('),
|
||||
preceded(
|
||||
opt(whitespace),
|
||||
map(
|
||||
delimited(
|
||||
char('('),
|
||||
preceded(
|
||||
tag("@interface"),
|
||||
opt(whitespace),
|
||||
preceded(
|
||||
whitespace,
|
||||
tag("@interface"),
|
||||
preceded(
|
||||
tag("export"),
|
||||
whitespace,
|
||||
preceded(
|
||||
whitespace,
|
||||
tag("export"),
|
||||
tuple((
|
||||
preceded(char('"'), cut(terminated(string, char('"')))),
|
||||
preceded(
|
||||
whitespace,
|
||||
preceded(char('"'), cut(terminated(string, char('"')))),
|
||||
),
|
||||
opt(preceded(whitespace, param)),
|
||||
opt(preceded(whitespace, result)),
|
||||
)),
|
||||
@ -107,18 +105,86 @@ fn export<'input, E: ParseError<&'input str>>(
|
||||
),
|
||||
),
|
||||
),
|
||||
char(')'),
|
||||
),
|
||||
char(')'),
|
||||
)(input)?;
|
||||
|
||||
Ok((
|
||||
remains,
|
||||
Export {
|
||||
name: export_name,
|
||||
|(name, input_types, output_types)| Export {
|
||||
name,
|
||||
input_types: input_types.unwrap_or_else(|| vec![]),
|
||||
output_types: output_types.unwrap_or_else(|| vec![]),
|
||||
},
|
||||
))
|
||||
)(input)
|
||||
}
|
||||
|
||||
/// Parse a `(import …)`.
|
||||
fn import_qualifier<'input, E: ParseError<&'input str>>(
|
||||
input: &'input str,
|
||||
) -> IResult<&'input str, (&'input str, &'input str), E> {
|
||||
delimited(
|
||||
char('('),
|
||||
preceded(
|
||||
opt(whitespace),
|
||||
preceded(
|
||||
tag("import"),
|
||||
tuple((
|
||||
preceded(
|
||||
whitespace,
|
||||
preceded(char('"'), cut(terminated(string, char('"')))),
|
||||
),
|
||||
preceded(
|
||||
whitespace,
|
||||
preceded(char('"'), cut(terminated(string, char('"')))),
|
||||
),
|
||||
)),
|
||||
),
|
||||
),
|
||||
char(')'),
|
||||
)(input)
|
||||
}
|
||||
|
||||
/// Parse a `$…`.
|
||||
fn index_variable<'input, E: ParseError<&'input str>>(
|
||||
input: &'input str,
|
||||
) -> IResult<&'input str, &'input str, E> {
|
||||
preceded(
|
||||
char('$'),
|
||||
take_while1(move |c: char| c.is_alphanum() || c == '_'),
|
||||
)(input)
|
||||
}
|
||||
|
||||
/// Parse an `Import`.
|
||||
fn import<'input, E: ParseError<&'input str>>(
|
||||
input: &'input str,
|
||||
) -> IResult<&'input str, Import, E> {
|
||||
map(
|
||||
delimited(
|
||||
char('('),
|
||||
preceded(
|
||||
opt(whitespace),
|
||||
preceded(
|
||||
tag("@interface"),
|
||||
preceded(
|
||||
whitespace,
|
||||
preceded(
|
||||
tag("func"),
|
||||
tuple((
|
||||
opt(preceded(whitespace, index_variable)),
|
||||
preceded(whitespace, import_qualifier),
|
||||
opt(preceded(whitespace, param)),
|
||||
opt(preceded(whitespace, result)),
|
||||
)),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
char(')'),
|
||||
),
|
||||
|(_index, (namespace, name), input_types, output_types)| Import {
|
||||
namespace,
|
||||
name,
|
||||
input_types: input_types.unwrap_or_else(|| vec![]),
|
||||
output_types: output_types.unwrap_or_else(|| vec![]),
|
||||
},
|
||||
)(input)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -239,4 +305,90 @@ mod tests {
|
||||
|
||||
assert_eq!(export::<()>(input), Ok(("", output)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_export_escaped_name() {
|
||||
let input = r#"(@interface export "fo\"o")"#;
|
||||
let output = Export {
|
||||
name: r#"fo\"o"#,
|
||||
input_types: vec![],
|
||||
output_types: vec![],
|
||||
};
|
||||
|
||||
assert_eq!(export::<()>(input), Ok(("", output)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_import_qualifier() {
|
||||
let input = r#"(import "ns" "name")"#;
|
||||
let output = ("ns", "name");
|
||||
|
||||
assert_eq!(import_qualifier::<()>(input), Ok(("", output)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_import_with_no_param_no_result() {
|
||||
let input = r#"(@interface func $ns_foo (import "ns" "foo"))"#;
|
||||
let output = Import {
|
||||
namespace: "ns",
|
||||
name: "foo",
|
||||
input_types: vec![],
|
||||
output_types: vec![],
|
||||
};
|
||||
|
||||
assert_eq!(import::<()>(input), Ok(("", output)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_import_with_no_index_variable_no_param_no_result() {
|
||||
let input = r#"(@interface func (import "ns" "foo"))"#;
|
||||
let output = Import {
|
||||
namespace: "ns",
|
||||
name: "foo",
|
||||
input_types: vec![],
|
||||
output_types: vec![],
|
||||
};
|
||||
|
||||
assert_eq!(import::<()>(input), Ok(("", output)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_import_with_some_param_no_result() {
|
||||
let input = r#"(@interface func $ns_foo (import "ns" "foo") (param i32))"#;
|
||||
let output = Import {
|
||||
namespace: "ns",
|
||||
name: "foo",
|
||||
input_types: vec![InterfaceType::I32],
|
||||
output_types: vec![],
|
||||
};
|
||||
|
||||
assert_eq!(import::<()>(input), Ok(("", output)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_import_with_no_param_some_result() {
|
||||
let input = r#"(@interface func $ns_foo (import "ns" "foo") (result i32))"#;
|
||||
let output = Import {
|
||||
namespace: "ns",
|
||||
name: "foo",
|
||||
input_types: vec![],
|
||||
output_types: vec![InterfaceType::I32],
|
||||
};
|
||||
|
||||
assert_eq!(import::<()>(input), Ok(("", output)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_import_with_some_param_some_result() {
|
||||
let input =
|
||||
r#"(@interface func $ns_foo (import "ns" "foo") (param String) (result i32 i32))"#;
|
||||
let output = Import {
|
||||
namespace: "ns",
|
||||
name: "foo",
|
||||
input_types: vec![InterfaceType::String],
|
||||
output_types: vec![InterfaceType::I32, InterfaceType::I32],
|
||||
};
|
||||
|
||||
assert_eq!(import::<()>(input), Ok(("", output)));
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user