1use wast::parser::{Parse, Parser, Result};
2
3use crate::{
4 Atom, Expr, Index, Indexes, Integer, SExpr, SymbolicIndex, ValueType,
5};
6
7pub fn fold(i: Instruction) -> Expression {
8 Expression::Folded(i)
9}
10
11pub fn global_get<S: AsRef<str>>(s: S) -> Instruction {
12 Instruction::GlobalGet(GlobalGet {
13 idx: Index::Symbolic(SymbolicIndex::new(s.as_ref().to_owned())),
14 exprs: vec![],
15 })
16}
17
18pub fn i32_const<S: AsRef<str>>(s: S) -> Instruction {
19 Instruction::I32Const(I32Const {
20 integer: Integer::new(s.as_ref().to_owned()),
21 exprs: vec![],
22 })
23}
24
25pub fn i64_const<S: AsRef<str>>(s: S) -> Instruction {
26 Instruction::I64Const(I64Const {
27 integer: Integer::new(s.as_ref().to_owned()),
28 exprs: vec![],
29 })
30}
31
32pub fn local_get<S: AsRef<str>>(s: S) -> Instruction {
33 Instruction::LocalGet(LocalGet {
34 idx: Index::Symbolic(SymbolicIndex::new(s.as_ref().to_owned())),
35 exprs: vec![],
36 })
37}
38
39enum Paren {
40 None,
41 Left,
42 Right,
43}
44
45#[derive(Debug, Clone, PartialEq, Eq)]
46struct Level {
47 expr: Expression,
48 subexprs: Vec<Expression>,
49}
50
51#[derive(Debug, Clone, PartialEq, Eq)]
52pub enum Expression {
53 Unfolded(Instruction),
54 Folded(Instruction),
55}
56
57impl Expression {
58 pub(crate) fn expr(&self) -> Expr {
59 match self {
60 Self::Unfolded(i) => Expr::Atom(i.as_atom()),
61 Self::Folded(i) => Expr::SExpr(Box::new(i.clone())),
62 }
63 }
64
65 fn subexprs(&mut self) -> &mut Vec<Expression> {
66 match self {
67 Self::Unfolded(i) => i.subexprs(),
68 Self::Folded(i) => i.subexprs(),
69 }
70 }
71}
72
73#[derive(Default)]
74pub(crate) struct ExpressionParser {
75 exprs: Vec<Expression>,
76 stack: Vec<Level>,
77}
78
79impl ExpressionParser {
80 pub fn parse(mut self, parser: Parser) -> Result<Vec<Expression>> {
81 while !parser.is_empty() || !self.stack.is_empty() {
82 match self.paren(parser)? {
83 Paren::Left => {
84 let instr = parser.parse::<Instruction>()?;
85 self.stack.push(Level {
86 expr: Expression::Folded(instr),
87 subexprs: Vec::new(),
88 });
89 },
90 Paren::None => {
91 let instr = parser.parse::<Instruction>()?;
92 let expr = Expression::Unfolded(instr);
93
94 match self.stack.last_mut() {
95 Some(level) => level.subexprs.push(expr),
96 None => self.exprs.push(expr),
97 }
98 },
99 Paren::Right => match self.stack.pop() {
100 Some(mut level) => {
101 level.expr.subexprs().append(&mut level.subexprs);
102
103 if let Some(top) = self.stack.last_mut() {
104 top.subexprs.push(level.expr);
105 } else {
106 self.exprs.push(level.expr);
107 }
108 },
109 None => {},
110 },
111 }
112 }
113
114 Ok(self.exprs.clone())
115 }
116
117 fn paren(&self, parser: Parser) -> Result<Paren> {
119 parser.step(|cursor| {
120 Ok(match cursor.lparen() {
121 Some(rest) => (Paren::Left, rest),
122 None if self.stack.is_empty() => (Paren::None, cursor),
123 None => match cursor.rparen() {
124 Some(rest) => (Paren::Right, rest),
125 None => (Paren::None, cursor),
126 },
127 })
128 })
129 }
130}
131
132#[macro_export]
133macro_rules! instructions {
134 (pub enum Instruction {
135 $(
136 $name:ident : $keyword:tt : $instr:tt {
137 $($field_name:ident: $field_type:ty),*
138 },
139 )*
140 }) => {
141 mod kw {
142 $(
143 wast::custom_keyword!($keyword = $instr);
144 )*
145 }
146
147 #[derive(Debug, Clone, PartialEq, Eq)]
148 pub enum Instruction {
149 $(
150 $name($name),
151 )*
152 }
153
154
155 impl Instruction {
156 pub fn subexprs(&mut self) -> &mut Vec<Expression> {
157 match self {
158 $(
159 Self::$name(i) => &mut i.exprs,
160 )*
161 }
162 }
163 }
164
165 impl Instruction {
166 pub fn as_atom(&self) -> Atom {
167 match self {
168 $(
169 Self::$name(i) => i.as_atom(),
170 )*
171 }
172 }
173 }
174
175 impl Parse<'_> for Instruction {
176 fn parse(parser: Parser<'_>) -> Result<Self> {
177 let mut l = parser.lookahead1();
178
179 $(
180 if l.peek::<kw::$keyword>() {
181 return Ok(Self::$name(parser.parse()?));
182 }
183 )*
184
185 Err(l.error())
186 }
187 }
188
189 impl SExpr for Instruction {
190 fn car(&self) -> std::string::String {
191 match self {
192 $(
193 Self::$name(i) => i.car(),
194 )*
195 }
196 }
197
198 fn cdr(&self) -> Vec<Expr> {
199 match self {
200 $(
201 Self::$name(i) => i.cdr(),
202 )*
203 }
204 }
205 }
206
207 $(
208 #[derive(Debug, Clone, PartialEq, Eq)]
209 pub struct $name {
210 $(
211 pub $field_name: $field_type,
212 )*
213 pub exprs: Vec<Expression>,
214 }
215
216 impl $name {
217 pub fn as_atom(&self) -> Atom {
218 #[allow(unused_mut)]
219 let mut s = std::string::String::new();
220
221 $(
222 s.push(' ');
223 s.push_str(
224 &self
225 .$field_name
226 .as_atoms()
227 .iter()
228 .map(ToString::to_string)
229 .collect::<Vec<std::string::String>>()
230 .join(" ")
231 );
232 )*
233
234 Atom::new(s)
235 }
236 }
237
238 impl SExpr for $name {
239 fn car(&self) -> std::string::String {
240 format!("{}", $instr)
241 }
242
243 fn cdr(&self) -> Vec<Expr> {
244 let mut v = Vec::new();
245
246 $(
247 v.append(
248 &mut self
249 .clone()
250 .$field_name
251 .as_atoms()
252 .iter()
253 .map(|a| Expr::Atom(a.clone()))
254 .collect()
255 );
256 )*
257
258 v.append(
259 &mut self
260 .exprs
261 .iter()
262 .map(|e| e.expr())
263 .collect()
264 );
265
266 v
267 }
268 }
269
270 impl Parse<'_> for $name {
271 fn parse(parser: Parser<'_>) -> Result<Self> {
272 parser.parse::<kw::$keyword>()?;
273
274 $(
275 let $field_name = parser.parse::<$field_type>()?;
276 )*
277
278 Ok(Self {
279 $(
280 $field_name,
281 )*
282 exprs: Vec::new(),
283 })
284 }
285 }
286 )*
287 };
288}
289
290instructions!(
291 pub enum Instruction {
292 Block : block : "block" { idx: Option<Index> },
293 Br : br : "br" { idx: Index },
294 BrIf : br_if : "br_if" { idx: Index },
295 BrTable : br_table : "br_table" { idxs: Indexes },
296 Call : call : "call" { idx: Index },
297 Drop : drop : "drop" {},
298 Else : r#else : "else" {},
299 GlobalGet : global_get : "global.get" { idx: Index },
300 GlobalSet : global_set : "global.set" { idx: Index },
301 I32Add : i32_add : "i32.add" {},
302 I32Const : i32_const : "i32.const" { integer: Integer },
303 I32Eq : i32_eq : "i32.eq" {},
304 I32Eqz : i32_eqz : "i32.eqz" {},
305 I32GtU : i32_gt_u : "i32.gt_u" {},
306 I32Load : i32_load : "i32.load" {},
307 I32LtS : i32_lt_s : "i32.lt_s" {},
308 I32LtU : i32_lt_u : "i32.lt_u" {},
309 I32Mul : i32_mul : "i32.mul" {},
310 I32Ne : i32_ne : "i32.ne" {},
311 I32RemU : i32_rem_u : "i32.rem_u" {},
312 I32ShrU : i32_shr_u : "i32.shr_u" {},
313 I32Sub : i32_sub : "i32.sub" {},
314 I64Const : i64_const : "i64.const" { integer: Integer },
315 If : r#if : "if" {},
316 Local : local : "local" { idx: Index, value_type: ValueType },
317 LocalGet : local_get : "local.get" { idx: Index },
318 LocalSet : local_set : "local.set" { idx: Index },
319 LocalTee : local_tee : "local.tee" { idx: Index },
320 Loop : r#loop : "loop" { idx: Option<Index> },
321 MemoryGrow : memory_grow : "memory.grow" {},
322 Return : r#return : "return" {},
323 Then : then : "then" {},
324 }
325);
326
327pub trait AsAtoms {
328 fn as_atoms(&self) -> Vec<Atom>;
329}
330
331impl AsAtoms for String {
332 fn as_atoms(&self) -> Vec<Atom> {
333 vec![Atom::new(format!(r#""{}""#, self))]
334 }
335}
336
337impl<T: AsAtoms + Clone> AsAtoms for Option<T> {
338 fn as_atoms(&self) -> Vec<Atom> {
339 self.clone().map_or(Vec::new(), |x| x.as_atoms())
340 }
341}