wit_text/ast/
module.rs

1use crate::ast::{self, annotation, kw};
2use wast::parser::{Parse, Parser, Result};
3
4/// A `*.wat` file in its entirety, including wasm interface types.
5///
6/// This is typically what you're parsing at the top-level.
7pub struct Wat<'a> {
8    /// The module that this `*.wat` file contained.
9    pub module: Module<'a>,
10}
11
12impl<'a> Parse<'a> for Wat<'a> {
13    fn parse(parser: Parser<'a>) -> Result<Self> {
14        let module = if !parser.peek2::<kw::module>() {
15            parse_text_module(parser.cur_span(), None, None, parser)?
16        } else {
17            parser.parens(|parser| parser.parse())?
18        };
19        Ok(Wat { module })
20    }
21}
22
23/// A WebAssembly interface types-enhanced module.
24pub struct Module<'a> {
25    /// The core WebAssembly module which doesn't use interface types.
26    pub core: wast::Module<'a>,
27    /// The various `@interface` adapter directives representing the wasm
28    /// interface types of this module.
29    pub adapters: Vec<Adapter<'a>>,
30}
31
32impl Module<'_> {
33    /// Encodes this `Module` into its binary form.
34    pub fn encode(&mut self) -> std::result::Result<Vec<u8>, wast::Error> {
35        let names = self.core.resolve()?;
36        let core = match &self.core.kind {
37            wast::ModuleKind::Text(list) => &list[..],
38            wast::ModuleKind::Binary(_) => &[],
39        };
40        crate::resolve::resolve(core, &mut self.adapters, &names)?;
41        let mut core = self.core.encode()?;
42        crate::binary::append(&self.adapters, &mut core);
43        Ok(core)
44    }
45}
46
47impl<'a> Parse<'a> for Module<'a> {
48    fn parse(parser: Parser<'a>) -> Result<Module<'a>> {
49        // Parse `(module binary ...)` here, noting that we don't parse the
50        // binary itself when looking for wasm adapters.
51        if parser.peek2::<kw::binary>() {
52            return Ok(Module {
53                core: parser.parse()?,
54                adapters: Vec::new(),
55            });
56        }
57
58        let span = parser.parse::<kw::module>()?.0;
59        let name = parser.parse()?;
60        let annotation = parser.parse()?;
61        parse_text_module(span, name, annotation, parser)
62    }
63}
64
65fn parse_text_module<'a>(
66    span: wast::Span,
67    id: Option<wast::Id<'a>>,
68    name: Option<wast::NameAnnotation<'a>>,
69    parser: Parser<'a>,
70) -> Result<Module<'a>> {
71    let _r = parser.register_annotation("custom");
72    let _r = parser.register_annotation("interface");
73
74    let mut fields = Vec::new();
75    let mut adapters = Vec::new();
76    while !parser.is_empty() {
77        parser.parens(|parser| {
78            if parser.peek::<annotation::interface>() {
79                adapters.push(parser.parse()?);
80            } else {
81                fields.push(parser.parse()?);
82            }
83            Ok(())
84        })?;
85    }
86    Ok(Module {
87        core: wast::Module {
88            span,
89            id,
90            name,
91            kind: wast::ModuleKind::Text(fields),
92        },
93        adapters,
94    })
95}
96
97/// List of possible `@interface` adapters that can be listed in a module.
98pub enum Adapter<'a> {
99    /// An interface type definition (function signature).
100    Type(ast::Type<'a>),
101    /// An import definition using interface types as a function signature.
102    Import(ast::Import<'a>),
103    /// An export using wasm interface types as a function signature.
104    Export(ast::Export<'a>),
105    /// An adapter function using wasm interface types.
106    Func(ast::Func<'a>),
107    /// A connection between a core wasm import and an inline defined function.
108    Implement(ast::Implement<'a>),
109}
110
111impl<'a> Parse<'a> for Adapter<'a> {
112    fn parse(parser: Parser<'a>) -> Result<Adapter<'a>> {
113        parser.parse::<annotation::interface>()?;
114        let mut l = parser.lookahead1();
115        if l.peek::<kw::r#type>() {
116            return Ok(Adapter::Type(parser.parse()?));
117        }
118        if l.peek::<kw::import>() {
119            return Ok(Adapter::Import(parser.parse()?));
120        }
121        if l.peek::<kw::export>() {
122            return Ok(Adapter::Export(parser.parse()?));
123        }
124        if l.peek::<kw::func>() {
125            return Ok(Adapter::Func(parser.parse()?));
126        }
127        if l.peek::<kw::implement>() {
128            return Ok(Adapter::Implement(parser.parse()?));
129        }
130        Err(l.error())
131    }
132}