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 #[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
101pub struct MemoryToString<'a> {
103 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
117pub struct StringToMemory<'a> {
119 pub malloc: wast::Index<'a>,
122 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}