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
use crate::ast::{self, kw};
use wast::parser::{Parse, Parser, Result};

/// A means of implementing a core wasm imported function with an adapter
/// function.
pub struct Implement<'a> {
    /// Where this directive was defined
    pub span: wast::Span,
    /// What's being implemented
    pub implemented: Implemented<'a>,
    /// How it's being implemented
    pub implementation: Implementation<'a>,
}

/// Different ways to specify what's being implemented
pub enum Implemented<'a> {
    /// A specification of what's being impelmented by module/name
    #[allow(missing_docs)]
    ByName { module: &'a str, name: &'a str },

    /// A specification using an index
    ByIndex(wast::Index<'a>),
}

/// Different ways to specify an implementation
pub enum Implementation<'a> {
    /// A specification using an index
    ByIndex(wast::Index<'a>),

    /// An inline definition of what's being implemented
    Inline {
        /// The type that this function has
        ty: ast::TypeUse<'a>,
        /// Body of the implementation
        instrs: ast::Instructions<'a>,
    },
}

impl<'a> Parse<'a> for Implement<'a> {
    fn parse(parser: Parser<'a>) -> Result<Implement<'a>> {
        let span = parser.parse::<kw::implement>()?.0;

        let implemented = parser.parens(|parser| {
            if parser.peek::<kw::func>() {
                parser.parse::<kw::func>()?;
                Ok(Implemented::ByIndex(parser.parse()?))
            } else {
                parser.parse::<kw::import>()?;
                Ok(Implemented::ByName {
                    module: parser.parse()?,
                    name: parser.parse()?,
                })
            }
        })?;

        let implementation = if parser.peek2::<kw::func>() {
            parser.parens(|parser| {
                parser.parse::<kw::func>()?;
                Ok(Implementation::ByIndex(parser.parse()?))
            })?
        } else {
            Implementation::Inline {
                ty: parser.parse()?,
                instrs: parser.parse()?,
            }
        };

        Ok(Implement {
            span,
            implemented,
            implementation,
        })
    }
}