wat_ast/
types.rs

1use std::fmt;
2
3use wast::parser::{self, Cursor, Parse, Parser, Peek};
4
5use crate::{AsAtoms, Atom, Expr, Integer, Param, Result, SExpr};
6
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub enum ValueType {
9    I32,
10    I64,
11    F32,
12    F64,
13}
14
15impl ValueType {
16    pub fn as_expr(&self) -> Expr {
17        Expr::Atom(Atom::new(self.to_string()))
18    }
19}
20
21impl AsAtoms for ValueType {
22    fn as_atoms(&self) -> Vec<Atom> {
23        vec![Atom::new(self.to_string())]
24    }
25}
26
27impl fmt::Display for ValueType {
28    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29        match self {
30            Self::I32 => write!(f, "i32"),
31            Self::I64 => write!(f, "i64"),
32            Self::F32 => write!(f, "f32"),
33            Self::F64 => write!(f, "f64"),
34        }
35    }
36}
37
38impl Parse<'_> for ValueType {
39    fn parse(parser: Parser<'_>) -> parser::Result<Self> {
40        let mut l = parser.lookahead1();
41
42        if l.peek::<wast::kw::i32>() {
43            parser.parse::<wast::kw::i32>()?;
44            Ok(Self::I32)
45        } else if l.peek::<wast::kw::i64>() {
46            parser.parse::<wast::kw::i64>()?;
47            Ok(Self::I64)
48        } else if l.peek::<wast::kw::f32>() {
49            parser.parse::<wast::kw::f32>()?;
50            Ok(Self::F32)
51        } else if l.peek::<wast::kw::f64>() {
52            parser.parse::<wast::kw::f64>()?;
53            Ok(Self::F64)
54        } else {
55            Err(l.error())
56        }
57    }
58}
59
60impl Peek for ValueType {
61    fn peek(cursor: Cursor<'_>) -> bool {
62        wast::kw::i32::peek(cursor)
63            || wast::kw::i64::peek(cursor)
64            || wast::kw::f32::peek(cursor)
65            || wast::kw::f64::peek(cursor)
66    }
67
68    fn display() -> &'static str {
69        "a value type"
70    }
71}
72
73/// https://webassembly.github.io/spec/core/text/types.html#function-types
74#[derive(Debug, Clone, PartialEq, Eq)]
75pub struct FuncType {
76    params:  Vec<Param>,
77    results: Vec<Result>,
78}
79
80impl FuncType {
81    pub fn new(params: Vec<Param>, results: Vec<Result>) -> Self {
82        Self { params, results }
83    }
84}
85
86impl SExpr for FuncType {
87    fn car(&self) -> String {
88        "func".to_owned()
89    }
90
91    fn cdr(&self) -> Vec<Expr> {
92        let mut v: Vec<_> = self
93            .params
94            .iter()
95            .map(|p| Expr::SExpr(Box::new(p.clone())))
96            .collect();
97        let mut results: Vec<_> = self
98            .results
99            .iter()
100            .map(|r| Expr::SExpr(Box::new(r.clone())))
101            .collect();
102
103        v.append(&mut results);
104
105        v
106    }
107}
108
109impl Parse<'_> for FuncType {
110    fn parse(parser: Parser<'_>) -> parser::Result<Self> {
111        parser.parse::<wast::kw::func>()?;
112
113        let mut params = Vec::new();
114        let mut results = Vec::new();
115
116        while !parser.is_empty() {
117            if parser.peek2::<wast::kw::param>() {
118                params.push(parser.parens(Param::parse)?)
119            } else {
120                break;
121            }
122        }
123
124        while !parser.is_empty() {
125            if parser.peek2::<wast::kw::result>() {
126                results.push(parser.parens(Result::parse)?)
127            } else {
128                break;
129            }
130        }
131
132        Ok(Self { params, results })
133    }
134}
135
136#[derive(Debug, Clone, PartialEq, Eq)]
137pub struct Limits {
138    min: Integer,
139    max: Option<Integer>,
140}
141
142impl Limits {
143    pub fn new(min: Integer, max: Option<Integer>) -> Self {
144        Self { min, max }
145    }
146
147    pub(crate) fn exprs(&self) -> Vec<Expr> {
148        let mut v = vec![Expr::Atom(Atom::new(self.min.to_string()))];
149
150        if let Some(ref max) = self.max {
151            v.push(Expr::Atom(Atom::new(max.to_string())));
152        }
153
154        v
155    }
156}
157
158impl Parse<'_> for Limits {
159    fn parse(parser: Parser<'_>) -> parser::Result<Self> {
160        let min = parser.parse::<Integer>()?;
161        let max = parser.parse::<Option<Integer>>()?;
162
163        Ok(Self { min, max })
164    }
165}
166
167#[derive(Debug, Clone, PartialEq, Eq)]
168pub struct MemType {
169    lim: Limits,
170}
171
172impl MemType {
173    pub fn new(lim: Limits) -> Self {
174        Self { lim }
175    }
176
177    pub(crate) fn exprs(&self) -> Vec<Expr> {
178        self.lim.exprs()
179    }
180}
181
182impl Parse<'_> for MemType {
183    fn parse(parser: Parser<'_>) -> parser::Result<Self> {
184        let lim = parser.parse::<Limits>()?;
185
186        Ok(Self { lim })
187    }
188}
189
190#[derive(Debug, Clone, PartialEq, Eq)]
191pub enum GlobalType {
192    Mut(GlobalTypeMut),
193    NonMut(ValueType),
194}
195
196impl GlobalType {
197    pub(crate) fn expr(&self) -> Expr {
198        match self {
199            Self::Mut(m) => Expr::SExpr(Box::new(m.clone())),
200            Self::NonMut(v) => Expr::Atom(Atom::new(v.to_string())),
201        }
202    }
203}
204
205impl Parse<'_> for GlobalType {
206    fn parse(parser: Parser<'_>) -> parser::Result<Self> {
207        if parser.peek::<wast::LParen>() {
208            Ok(Self::Mut(parser.parens(GlobalTypeMut::parse)?))
209        } else {
210            let val_type = parser.parse::<ValueType>()?;
211
212            Ok(Self::NonMut(val_type))
213        }
214    }
215}
216
217#[derive(Debug, Clone, PartialEq, Eq)]
218pub struct GlobalTypeMut {
219    val_type: ValueType,
220}
221
222impl GlobalTypeMut {
223    pub fn new(val_type: ValueType) -> Self {
224        Self { val_type }
225    }
226}
227
228impl Parse<'_> for GlobalTypeMut {
229    fn parse(parser: Parser<'_>) -> parser::Result<Self> {
230        parser.parse::<wast::kw::r#mut>()?;
231
232        let val_type = parser.parse::<ValueType>()?;
233
234        Ok(Self { val_type })
235    }
236}
237
238impl SExpr for GlobalTypeMut {
239    fn car(&self) -> String {
240        "mut".to_owned()
241    }
242
243    fn cdr(&self) -> Vec<Expr> {
244        vec![Expr::Atom(Atom::new(self.val_type.to_string()))]
245    }
246}