1use crate::kw;
2use crate::parser::{Cursor, Parse, Parser, Peek, Result};
3use crate::token::{F32, F64};
4
5#[derive(Debug)]
8#[allow(missing_docs)]
9pub enum WastVal<'a> {
10 Bool(bool),
11 U8(u8),
12 S8(i8),
13 U16(u16),
14 S16(i16),
15 U32(u32),
16 S32(i32),
17 U64(u64),
18 S64(i64),
19 F32(F32),
20 F64(F64),
21 Char(char),
22 String(&'a str),
23 List(Vec<WastVal<'a>>),
24 Record(Vec<(&'a str, WastVal<'a>)>),
25 Tuple(Vec<WastVal<'a>>),
26 Variant(&'a str, Option<Box<WastVal<'a>>>),
27 Enum(&'a str),
28 Option(Option<Box<WastVal<'a>>>),
29 Result(Result<Option<Box<WastVal<'a>>>, Option<Box<WastVal<'a>>>>),
30 Flags(Vec<&'a str>),
31}
32
33static CASES: &[(&str, fn(Parser<'_>) -> Result<WastVal<'_>>)] = {
34 use WastVal::*;
35 &[
36 ("bool.const", |p| {
37 let mut l = p.lookahead1();
38 if l.peek::<kw::true_>()? {
39 p.parse::<kw::true_>()?;
40 Ok(Bool(true))
41 } else if l.peek::<kw::false_>()? {
42 p.parse::<kw::false_>()?;
43 Ok(Bool(false))
44 } else {
45 Err(l.error())
46 }
47 }),
48 ("u8.const", |p| Ok(U8(p.parse()?))),
49 ("s8.const", |p| Ok(S8(p.parse()?))),
50 ("u16.const", |p| Ok(U16(p.parse()?))),
51 ("s16.const", |p| Ok(S16(p.parse()?))),
52 ("u32.const", |p| Ok(U32(p.parse()?))),
53 ("s32.const", |p| Ok(S32(p.parse()?))),
54 ("u64.const", |p| Ok(U64(p.parse()?))),
55 ("s64.const", |p| Ok(S64(p.parse()?))),
56 ("f32.const", |p| Ok(F32(p.parse()?))),
57 ("f64.const", |p| Ok(F64(p.parse()?))),
58 ("char.const", |p| {
59 let s = p.parse::<&str>()?;
60 let mut ch = s.chars();
61 let ret = match ch.next() {
62 Some(c) => c,
63 None => return Err(p.error("empty string")),
64 };
65 if ch.next().is_some() {
66 return Err(p.error("more than one character"));
67 }
68 Ok(Char(ret))
69 }),
70 ("str.const", |p| Ok(String(p.parse()?))),
71 ("list.const", |p| {
72 let mut ret = Vec::new();
73 while !p.is_empty() {
74 ret.push(p.parens(|p| p.parse())?);
75 }
76 Ok(List(ret))
77 }),
78 ("record.const", |p| {
79 let mut ret = Vec::new();
80 while !p.is_empty() {
81 ret.push(p.parens(|p| {
82 p.parse::<kw::field>()?;
83 Ok((p.parse()?, p.parse()?))
84 })?);
85 }
86 Ok(Record(ret))
87 }),
88 ("tuple.const", |p| {
89 let mut ret = Vec::new();
90 while !p.is_empty() {
91 ret.push(p.parens(|p| p.parse())?);
92 }
93 Ok(Tuple(ret))
94 }),
95 ("variant.const", |p| {
96 let name = p.parse()?;
97 let payload = if p.is_empty() {
98 None
99 } else {
100 Some(Box::new(p.parens(|p| p.parse())?))
101 };
102 Ok(Variant(name, payload))
103 }),
104 ("enum.const", |p| Ok(Enum(p.parse()?))),
105 ("option.none", |_| Ok(Option(None))),
106 ("option.some", |p| {
107 Ok(Option(Some(Box::new(p.parens(|p| p.parse())?))))
108 }),
109 ("result.ok", |p| {
110 Ok(Result(Ok(if p.is_empty() {
111 None
112 } else {
113 Some(Box::new(p.parens(|p| p.parse())?))
114 })))
115 }),
116 ("result.err", |p| {
117 Ok(Result(Err(if p.is_empty() {
118 None
119 } else {
120 Some(Box::new(p.parens(|p| p.parse())?))
121 })))
122 }),
123 ("flags.const", |p| {
124 let mut ret = Vec::new();
125 while !p.is_empty() {
126 ret.push(p.parse()?);
127 }
128 Ok(Flags(ret))
129 }),
130 ]
131};
132
133impl<'a> Parse<'a> for WastVal<'a> {
134 fn parse(parser: Parser<'a>) -> Result<Self> {
135 parser.depth_check()?;
136 let parse = parser.step(|c| {
137 if let Some((kw, rest)) = c.keyword()? {
138 if let Some(i) = CASES.iter().position(|(name, _)| *name == kw) {
139 return Ok((CASES[i].1, rest));
140 }
141 }
142 Err(c.error("expected a [type].const expression"))
143 })?;
144 parse(parser)
145 }
146}
147
148impl Peek for WastVal<'_> {
149 fn peek(cursor: Cursor<'_>) -> Result<bool> {
150 let kw = match cursor.keyword()? {
151 Some((kw, _)) => kw,
152 None => return Ok(false),
153 };
154 Ok(CASES.iter().any(|(name, _)| *name == kw))
155 }
156
157 fn display() -> &'static str {
158 "core wasm argument"
159 }
160}