1use crate::core::{HeapType, V128Const};
2use crate::kw;
3use crate::parser::{Cursor, Parse, Parser, Peek, Result};
4use crate::token::{Index, F32, F64};
5
6#[derive(Debug)]
9#[allow(missing_docs)]
10pub enum WastArgCore<'a> {
11 I32(i32),
12 I64(i64),
13 F32(F32),
14 F64(F64),
15 V128(V128Const),
16 RefNull(HeapType<'a>),
17 RefExtern(u32),
18 RefHost(u32),
19}
20
21static ARGS: &[(&str, fn(Parser<'_>) -> Result<WastArgCore<'_>>)] = {
22 use WastArgCore::*;
23 &[
24 ("i32.const", |p| Ok(I32(p.parse()?))),
25 ("i64.const", |p| Ok(I64(p.parse()?))),
26 ("f32.const", |p| Ok(F32(p.parse()?))),
27 ("f64.const", |p| Ok(F64(p.parse()?))),
28 ("v128.const", |p| Ok(V128(p.parse()?))),
29 ("ref.null", |p| Ok(RefNull(p.parse()?))),
30 ("ref.extern", |p| Ok(RefExtern(p.parse()?))),
31 ("ref.host", |p| Ok(RefHost(p.parse()?))),
32 ]
33};
34
35impl<'a> Parse<'a> for WastArgCore<'a> {
36 fn parse(parser: Parser<'a>) -> Result<Self> {
37 let parse = parser.step(|c| {
38 if let Some((kw, rest)) = c.keyword()? {
39 if let Some(i) = ARGS.iter().position(|(name, _)| *name == kw) {
40 return Ok((ARGS[i].1, rest));
41 }
42 }
43 Err(c.error("expected a [type].const expression"))
44 })?;
45 parse(parser)
46 }
47}
48
49impl Peek for WastArgCore<'_> {
50 fn peek(cursor: Cursor<'_>) -> Result<bool> {
51 let kw = match cursor.keyword()? {
52 Some((kw, _)) => kw,
53 None => return Ok(false),
54 };
55 Ok(ARGS.iter().find(|(name, _)| *name == kw).is_some())
56 }
57
58 fn display() -> &'static str {
59 "core wasm argument"
60 }
61}
62
63#[derive(Debug)]
66#[allow(missing_docs)]
67pub enum WastRetCore<'a> {
68 I32(i32),
69 I64(i64),
70 F32(NanPattern<F32>),
71 F64(NanPattern<F64>),
72 V128(V128Pattern),
73
74 RefNull(Option<HeapType<'a>>),
76 RefExtern(Option<u32>),
79 RefHost(u32),
81 RefFunc(Option<Index<'a>>),
83 RefAny,
85 RefEq,
87 RefArray,
89 RefStruct,
91 RefI31,
93 RefI31Shared,
95
96 Either(Vec<WastRetCore<'a>>),
97}
98
99static RETS: &[(&str, fn(Parser<'_>) -> Result<WastRetCore<'_>>)] = {
100 use WastRetCore::*;
101 &[
102 ("i32.const", |p| Ok(I32(p.parse()?))),
103 ("i64.const", |p| Ok(I64(p.parse()?))),
104 ("f32.const", |p| Ok(F32(p.parse()?))),
105 ("f64.const", |p| Ok(F64(p.parse()?))),
106 ("v128.const", |p| Ok(V128(p.parse()?))),
107 ("ref.null", |p| Ok(RefNull(p.parse()?))),
108 ("ref.extern", |p| Ok(RefExtern(p.parse()?))),
109 ("ref.host", |p| Ok(RefHost(p.parse()?))),
110 ("ref.func", |p| Ok(RefFunc(p.parse()?))),
111 ("ref.any", |_| Ok(RefAny)),
112 ("ref.eq", |_| Ok(RefEq)),
113 ("ref.array", |_| Ok(RefArray)),
114 ("ref.struct", |_| Ok(RefStruct)),
115 ("ref.i31", |_| Ok(RefI31)),
116 ("ref.i31_shared", |_| Ok(RefI31Shared)),
117 ("either", |p| {
118 p.depth_check()?;
119 let mut cases = Vec::new();
120 while !p.is_empty() {
121 cases.push(p.parens(|p| p.parse())?);
122 }
123 Ok(Either(cases))
124 }),
125 ]
126};
127
128impl<'a> Parse<'a> for WastRetCore<'a> {
129 fn parse(parser: Parser<'a>) -> Result<Self> {
130 let parse = parser.step(|c| {
131 if let Some((kw, rest)) = c.keyword()? {
132 if let Some(i) = RETS.iter().position(|(name, _)| *name == kw) {
133 return Ok((RETS[i].1, rest));
134 }
135 }
136 Err(c.error("expected a [type].const expression"))
137 })?;
138 parse(parser)
139 }
140}
141
142impl Peek for WastRetCore<'_> {
143 fn peek(cursor: Cursor<'_>) -> Result<bool> {
144 let kw = match cursor.keyword()? {
145 Some((kw, _)) => kw,
146 None => return Ok(false),
147 };
148 Ok(RETS.iter().find(|(name, _)| *name == kw).is_some())
149 }
150
151 fn display() -> &'static str {
152 "core wasm return value"
153 }
154}
155
156#[derive(Copy, Clone, Debug, PartialEq)]
158#[allow(missing_docs)]
159pub enum NanPattern<T> {
160 CanonicalNan,
161 ArithmeticNan,
162 Value(T),
163}
164
165impl<'a, T> Parse<'a> for NanPattern<T>
166where
167 T: Parse<'a>,
168{
169 fn parse(parser: Parser<'a>) -> Result<Self> {
170 if parser.peek::<kw::nan_canonical>()? {
171 parser.parse::<kw::nan_canonical>()?;
172 Ok(NanPattern::CanonicalNan)
173 } else if parser.peek::<kw::nan_arithmetic>()? {
174 parser.parse::<kw::nan_arithmetic>()?;
175 Ok(NanPattern::ArithmeticNan)
176 } else {
177 let val = parser.parse()?;
178 Ok(NanPattern::Value(val))
179 }
180 }
181}
182
183#[derive(Clone, Debug)]
188#[allow(missing_docs)]
189pub enum V128Pattern {
190 I8x16([i8; 16]),
191 I16x8([i16; 8]),
192 I32x4([i32; 4]),
193 I64x2([i64; 2]),
194 F32x4([NanPattern<F32>; 4]),
195 F64x2([NanPattern<F64>; 2]),
196}
197
198impl<'a> Parse<'a> for V128Pattern {
199 fn parse(parser: Parser<'a>) -> Result<Self> {
200 let mut l = parser.lookahead1();
201 if l.peek::<kw::i8x16>()? {
202 parser.parse::<kw::i8x16>()?;
203 Ok(V128Pattern::I8x16([
204 parser.parse()?,
205 parser.parse()?,
206 parser.parse()?,
207 parser.parse()?,
208 parser.parse()?,
209 parser.parse()?,
210 parser.parse()?,
211 parser.parse()?,
212 parser.parse()?,
213 parser.parse()?,
214 parser.parse()?,
215 parser.parse()?,
216 parser.parse()?,
217 parser.parse()?,
218 parser.parse()?,
219 parser.parse()?,
220 ]))
221 } else if l.peek::<kw::i16x8>()? {
222 parser.parse::<kw::i16x8>()?;
223 Ok(V128Pattern::I16x8([
224 parser.parse()?,
225 parser.parse()?,
226 parser.parse()?,
227 parser.parse()?,
228 parser.parse()?,
229 parser.parse()?,
230 parser.parse()?,
231 parser.parse()?,
232 ]))
233 } else if l.peek::<kw::i32x4>()? {
234 parser.parse::<kw::i32x4>()?;
235 Ok(V128Pattern::I32x4([
236 parser.parse()?,
237 parser.parse()?,
238 parser.parse()?,
239 parser.parse()?,
240 ]))
241 } else if l.peek::<kw::i64x2>()? {
242 parser.parse::<kw::i64x2>()?;
243 Ok(V128Pattern::I64x2([parser.parse()?, parser.parse()?]))
244 } else if l.peek::<kw::f32x4>()? {
245 parser.parse::<kw::f32x4>()?;
246 Ok(V128Pattern::F32x4([
247 parser.parse()?,
248 parser.parse()?,
249 parser.parse()?,
250 parser.parse()?,
251 ]))
252 } else if l.peek::<kw::f64x2>()? {
253 parser.parse::<kw::f64x2>()?;
254 Ok(V128Pattern::F64x2([parser.parse()?, parser.parse()?]))
255 } else {
256 Err(l.error())
257 }
258 }
259}