wit_text/ast/
func.rs

1use crate::ast::{self, kw};
2use wast::parser::{Parse, Parser, Result};
3
4/// A definition of an adapter function
5pub struct Func<'a> {
6    /// Where this function was defined
7    pub span: wast::Span,
8    /// An optional name used to refer to this function
9    pub name: Option<wast::Id<'a>>,
10    /// An optional name that this function is being exported under
11    pub export: Option<&'a str>,
12    /// The type that this function has
13    pub ty: ast::TypeUse<'a>,
14    /// How this function is defined
15    pub kind: FuncKind<'a>,
16}
17
18/// Different flavors of functions that can be defined.
19pub enum FuncKind<'a> {
20    /// An sugared `import` declaration.
21    Import {
22        /// Where we're importing from
23        module: &'a str,
24        /// What we're importing
25        name: &'a str,
26    },
27
28    /// An inline function definition which contains actual instructions
29    #[allow(missing_docs)]
30    Inline { instrs: ast::Instructions<'a> },
31}
32
33impl<'a> Parse<'a> for Func<'a> {
34    fn parse(parser: Parser<'a>) -> Result<Func<'a>> {
35        let span = parser.parse::<kw::func>()?.0;
36        let name = parser.parse()?;
37        let export = if parser.peek2::<kw::export>() {
38            Some(parser.parens(|p| {
39                p.parse::<kw::export>()?;
40                p.parse()
41            })?)
42        } else {
43            None
44        };
45
46        let (ty, kind) = if parser.peek2::<kw::import>() {
47            let (module, name) = parser.parens(|p| {
48                p.parse::<kw::import>()?;
49                Ok((p.parse()?, p.parse()?))
50            })?;
51            (parser.parse()?, FuncKind::Import { module, name })
52        } else {
53            let ty = parser.parse()?;
54            let instrs = parser.parse()?;
55            (ty, FuncKind::Inline { instrs })
56        };
57
58        Ok(Func {
59            span,
60            name,
61            export,
62            ty,
63            kind,
64        })
65    }
66}
67
68/// A list of instructions, possibly in s-expression form
69#[allow(missing_docs)]
70pub struct Instructions<'a> {
71    pub instrs: Vec<ast::Instruction<'a>>,
72}
73
74impl<'a> Parse<'a> for Instructions<'a> {
75    fn parse(parser: Parser<'a>) -> Result<Instructions<'a>> {
76        let mut instrs = Vec::new();
77        while !parser.is_empty() {
78            instrs.push(parser.parse()?);
79        }
80        Ok(Instructions { instrs })
81    }
82}