1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
use crate::ast::{self, annotation, kw};
use wast::parser::{Parse, Parser, Result};

/// A `*.wat` file in its entirety, including wasm interface types.
///
/// This is typically what you're parsing at the top-level.
pub struct Wat<'a> {
    /// The module that this `*.wat` file contained.
    pub module: Module<'a>,
}

impl<'a> Parse<'a> for Wat<'a> {
    fn parse(parser: Parser<'a>) -> Result<Self> {
        let module = if !parser.peek2::<kw::module>() {
            parse_text_module(parser.cur_span(), None, None, parser)?
        } else {
            parser.parens(|parser| parser.parse())?
        };
        Ok(Wat { module })
    }
}

/// A WebAssembly interface types-enhanced module.
pub struct Module<'a> {
    /// The core WebAssembly module which doesn't use interface types.
    pub core: wast::Module<'a>,
    /// The various `@interface` adapter directives representing the wasm
    /// interface types of this module.
    pub adapters: Vec<Adapter<'a>>,
}

impl Module<'_> {
    /// Encodes this `Module` into its binary form.
    pub fn encode(&mut self) -> std::result::Result<Vec<u8>, wast::Error> {
        let names = self.core.resolve()?;
        let core = match &self.core.kind {
            wast::ModuleKind::Text(list) => &list[..],
            wast::ModuleKind::Binary(_) => &[],
        };
        crate::resolve::resolve(core, &mut self.adapters, &names)?;
        let mut core = self.core.encode()?;
        crate::binary::append(&self.adapters, &mut core);
        Ok(core)
    }
}

impl<'a> Parse<'a> for Module<'a> {
    fn parse(parser: Parser<'a>) -> Result<Module<'a>> {
        // Parse `(module binary ...)` here, noting that we don't parse the
        // binary itself when looking for wasm adapters.
        if parser.peek2::<kw::binary>() {
            return Ok(Module {
                core: parser.parse()?,
                adapters: Vec::new(),
            });
        }

        let span = parser.parse::<kw::module>()?.0;
        let name = parser.parse()?;
        let annotation = parser.parse()?;
        parse_text_module(span, name, annotation, parser)
    }
}

fn parse_text_module<'a>(
    span: wast::Span,
    id: Option<wast::Id<'a>>,
    name: Option<wast::NameAnnotation<'a>>,
    parser: Parser<'a>,
) -> Result<Module<'a>> {
    let _r = parser.register_annotation("custom");
    let _r = parser.register_annotation("interface");

    let mut fields = Vec::new();
    let mut adapters = Vec::new();
    while !parser.is_empty() {
        parser.parens(|parser| {
            if parser.peek::<annotation::interface>() {
                adapters.push(parser.parse()?);
            } else {
                fields.push(parser.parse()?);
            }
            Ok(())
        })?;
    }
    Ok(Module {
        core: wast::Module {
            span,
            id,
            name,
            kind: wast::ModuleKind::Text(fields),
        },
        adapters,
    })
}

/// List of possible `@interface` adapters that can be listed in a module.
pub enum Adapter<'a> {
    /// An interface type definition (function signature).
    Type(ast::Type<'a>),
    /// An import definition using interface types as a function signature.
    Import(ast::Import<'a>),
    /// An export using wasm interface types as a function signature.
    Export(ast::Export<'a>),
    /// An adapter function using wasm interface types.
    Func(ast::Func<'a>),
    /// A connection between a core wasm import and an inline defined function.
    Implement(ast::Implement<'a>),
}

impl<'a> Parse<'a> for Adapter<'a> {
    fn parse(parser: Parser<'a>) -> Result<Adapter<'a>> {
        parser.parse::<annotation::interface>()?;
        let mut l = parser.lookahead1();
        if l.peek::<kw::r#type>() {
            return Ok(Adapter::Type(parser.parse()?));
        }
        if l.peek::<kw::import>() {
            return Ok(Adapter::Import(parser.parse()?));
        }
        if l.peek::<kw::export>() {
            return Ok(Adapter::Export(parser.parse()?));
        }
        if l.peek::<kw::func>() {
            return Ok(Adapter::Func(parser.parse()?));
        }
        if l.peek::<kw::implement>() {
            return Ok(Adapter::Implement(parser.parse()?));
        }
        Err(l.error())
    }
}