wit_text/ast/
instr.rs

1use wast::parser::{Parse, Parser, Result};
2use wast::Span;
3
4macro_rules! instructions {
5    ($(#[$a:meta])* pub enum Instruction<'a> {
6        $(
7            $name:ident $(($($arg:tt)*))? : $instr:tt,
8        )*
9    }) => (
10        $(#[$a])*
11        pub enum Instruction<'a> {
12            $(
13                $name $(( $($arg)* ))?,
14            )*
15        }
16
17        #[allow(non_snake_case)]
18        impl<'a> Parse<'a> for Instruction<'a> {
19            fn parse(parser: Parser<'a>) -> Result<Self> {
20                $(
21                    fn $name<'a>(_parser: Parser<'a>) -> Result<Instruction<'a>> {
22                        Ok(Instruction::$name $((
23                            _parser.parse::<$($arg)*>()?,
24                        ))?)
25                    }
26                )*
27                let parse_remainder = parser.step(|c| {
28                    let (kw, rest) = match c.keyword() {
29                        Some(pair) => pair,
30                        None => return Err(c.error("expected an instruction")),
31                    };
32                    match kw {
33                        $($instr => Ok(($name as fn(_) -> _, rest)),)*
34                        _ => return Err(c.error("unknown operator or unexpected token")),
35                    }
36                })?;
37                parse_remainder(parser)
38            }
39        }
40    );
41
42    (@first $first:ident $($t:tt)*) => ($first);
43}
44
45instructions! {
46    /// List of instructions in adapter functions.
47    #[allow(missing_docs)]
48    pub enum Instruction<'a> {
49        ArgGet(wast::Index<'a>) : "arg.get",
50        CallCore(wast::Index<'a>) : "call-core",
51        MemoryToString(MemoryToString<'a>) : "memory-to-string",
52        StringToMemory(StringToMemory<'a>) : "string-to-memory",
53        CallAdapter(wast::Index<'a>) : "call-adapter",
54        DeferCallCore(wast::Index<'a>) : "defer-call-core",
55
56        I32ToS8 : "i32-to-s8",
57        I32ToS8X : "i32-to-s8x",
58        I32ToU8 : "i32-to-u8",
59        I32ToS16 : "i32-to-s16",
60        I32ToS16X : "i32-to-s16x",
61        I32ToU16 : "i32-to-u16",
62        I32ToS32 : "i32-to-s32",
63        I32ToU32 : "i32-to-u32",
64        I32ToS64 : "i32-to-s64",
65        I32ToU64 : "i32-to-u64",
66
67        I64ToS8 : "i64-to-s8",
68        I64ToS8X : "i64-to-s8x",
69        I64ToU8 : "i64-to-u8",
70        I64ToS16 : "i64-to-s16",
71        I64ToS16X : "i64-to-s16x",
72        I64ToU16 : "i64-to-u16",
73        I64ToS32 : "i64-to-s32",
74        I64ToS32X : "i64-to-s32x",
75        I64ToU32 : "i64-to-u32",
76        I64ToS64 : "i64-to-s64",
77        I64ToU64 : "i64-to-u64",
78
79        S8ToI32 : "s8-to-i32",
80        U8ToI32 : "u8-to-i32",
81        S16ToI32 : "s16-to-i32",
82        U16ToI32 : "u16-to-i32",
83        S32ToI32 : "s32-to-i32",
84        U32ToI32 : "u32-to-i32",
85        S64ToI32 : "s64-to-i32",
86        S64ToI32X : "s64-to-i32x",
87        U64ToI32 : "u64-to-i32",
88        U64ToI32X : "u64-to-i32x",
89
90        S8ToI64 : "s8-to-i64",
91        U8ToI64 : "u8-to-i64",
92        S16ToI64 : "s16-to-i64",
93        U16ToI64 : "u16-to-i64",
94        S32ToI64 : "s32-to-i64",
95        U32ToI64 : "u32-to-i64",
96        S64ToI64 : "s64-to-i64",
97        U64ToI64 : "u64-to-i64",
98    }
99}
100
101/// Payload of the `memory-to-string` instruction
102pub struct MemoryToString<'a> {
103    /// Index of the memory that the string is coming from.
104    pub mem: wast::Index<'a>,
105}
106
107impl<'a> Parse<'a> for MemoryToString<'a> {
108    fn parse(parser: Parser<'a>) -> Result<Self> {
109        Ok(MemoryToString {
110            mem: parser
111                .parse::<Option<_>>()?
112                .unwrap_or(wast::Index::Num(0, Span::from_offset(0))),
113        })
114    }
115}
116
117/// Payload of the `string-to-memory` instruction
118pub struct StringToMemory<'a> {
119    /// Function which is used as a memory allocator to allocate memory to place
120    /// the string in `mem`.
121    pub malloc: wast::Index<'a>,
122    /// Index of the memory that the string is coming from.
123    pub mem: wast::Index<'a>,
124}
125
126impl<'a> Parse<'a> for StringToMemory<'a> {
127    fn parse(parser: Parser<'a>) -> Result<Self> {
128        Ok(StringToMemory {
129            malloc: parser.parse()?,
130            mem: parser
131                .parse::<Option<_>>()?
132                .unwrap_or(wast::Index::Num(0, Span::from_offset(0))),
133        })
134    }
135}