Fork of daniellemaywood.uk/gleam — Wasm codegen work
9.7 kB
350 lines
1use ecow::EcoString;
2use num_bigint::BigInt;
3
4#[derive(Debug, Clone, PartialEq, Eq)]
5pub enum IncompleteType {
6 Int,
7 Float,
8 Bool,
9 String,
10 Func {
11 arguments: Vec<IncompleteType>,
12 returns: Box<IncompleteType>,
13 },
14 Tuple {
15 elements: Vec<IncompleteType>,
16 },
17 Struct {
18 elements: Vec<IncompleteType>,
19 },
20 List(Box<IncompleteType>),
21 Generic {
22 id: u64,
23 },
24}
25
26#[derive(Debug, Clone, PartialEq, Eq, Hash)]
27pub enum CompleteType {
28 Int,
29 Float,
30 Bool,
31 String,
32 Func {
33 arguments: Vec<CompleteType>,
34 returns: Box<CompleteType>,
35 },
36 Tuple {
37 elements: Vec<CompleteType>,
38 },
39 Struct {
40 elements: Vec<CompleteType>,
41 },
42 List(Box<CompleteType>),
43}
44
45#[derive(Debug, PartialEq, Eq, Default)]
46pub struct Module<T> {
47 pub name: EcoString,
48 pub functions: Vec<Function<T>>,
49}
50
51#[derive(Debug, PartialEq, Eq, Clone)]
52pub struct Function<T> {
53 pub name: EcoString,
54 pub return_type: T,
55 pub parameters: Vec<FunctionParameter<T>>,
56 /// `None` for `@external(wasm, …)` imports (no Gleam body).
57 pub body: Option<Expression<T>>,
58 /// When set, this function is a Wasm import rather than a defined function.
59 pub external_wasm: Option<(EcoString, EcoString)>,
60}
61
62#[derive(Debug, PartialEq, Eq, Clone)]
63pub struct FunctionParameter<T> {
64 pub type_: T,
65 pub name: Option<EcoString>,
66}
67
68#[derive(Debug, PartialEq, Eq, Clone)]
69pub struct Var<T> {
70 pub name: EcoString,
71 pub type_: T,
72}
73
74#[derive(Debug, PartialEq, Eq, Clone)]
75pub enum Expression<T> {
76 Block(Vec<Expression<T>>),
77
78 FunctionRef {
79 module: EcoString,
80 name: EcoString,
81 arity: usize,
82 type_: T,
83 },
84
85 Var(Var<T>),
86
87 Int {
88 value: BigInt,
89 },
90
91 Float {
92 value: EcoString,
93 },
94
95 Bool {
96 value: bool,
97 },
98
99 String {
100 value: EcoString,
101 },
102
103 Equals {
104 lhs: Box<Expression<T>>,
105 rhs: Box<Expression<T>>,
106 },
107
108 NotEquals {
109 lhs: Box<Expression<T>>,
110 rhs: Box<Expression<T>>,
111 },
112
113 IntGt {
114 lhs: Box<Expression<T>>,
115 rhs: Box<Expression<T>>,
116 },
117
118 IntGtEq {
119 lhs: Box<Expression<T>>,
120 rhs: Box<Expression<T>>,
121 },
122
123 IntLt {
124 lhs: Box<Expression<T>>,
125 rhs: Box<Expression<T>>,
126 },
127
128 IntLtEq {
129 lhs: Box<Expression<T>>,
130 rhs: Box<Expression<T>>,
131 },
132
133 IntAdd {
134 lhs: Box<Expression<T>>,
135 rhs: Box<Expression<T>>,
136 },
137
138 IntSub {
139 lhs: Box<Expression<T>>,
140 rhs: Box<Expression<T>>,
141 },
142
143 IntMul {
144 lhs: Box<Expression<T>>,
145 rhs: Box<Expression<T>>,
146 },
147
148 IntDiv {
149 lhs: Box<Expression<T>>,
150 rhs: Box<Expression<T>>,
151 },
152
153 IntRem {
154 lhs: Box<Expression<T>>,
155 rhs: Box<Expression<T>>,
156 },
157
158 FloatGt {
159 lhs: Box<Expression<T>>,
160 rhs: Box<Expression<T>>,
161 },
162
163 FloatGtEq {
164 lhs: Box<Expression<T>>,
165 rhs: Box<Expression<T>>,
166 },
167
168 FloatLt {
169 lhs: Box<Expression<T>>,
170 rhs: Box<Expression<T>>,
171 },
172
173 FloatLtEq {
174 lhs: Box<Expression<T>>,
175 rhs: Box<Expression<T>>,
176 },
177
178 FloatAdd {
179 lhs: Box<Expression<T>>,
180 rhs: Box<Expression<T>>,
181 },
182
183 FloatSub {
184 lhs: Box<Expression<T>>,
185 rhs: Box<Expression<T>>,
186 },
187
188 FloatMul {
189 lhs: Box<Expression<T>>,
190 rhs: Box<Expression<T>>,
191 },
192
193 FloatDiv {
194 lhs: Box<Expression<T>>,
195 rhs: Box<Expression<T>>,
196 },
197
198 StringConcat {
199 lhs: Box<Expression<T>>,
200 rhs: Box<Expression<T>>,
201 },
202
203 List {
204 items: Vec<Expression<T>>,
205 tail: Option<Box<Expression<T>>>,
206 type_: T,
207 },
208
209 Tuple {
210 items: Vec<Expression<T>>,
211 type_: T,
212 },
213
214 TupleAccess {
215 value: Box<Expression<T>>,
216 index: u64,
217 type_: T,
218 },
219
220 Struct {
221 tag: u32,
222 items: Vec<Expression<T>>,
223 type_: T,
224 },
225
226 StructTag {
227 value: Box<Expression<T>>,
228 },
229
230 StructAccess {
231 value: Box<Expression<T>>,
232 index: u64,
233 type_: T,
234 },
235
236 Set {
237 name: Var<T>,
238 value: Box<Expression<T>>,
239 },
240
241 If {
242 cond: Box<Expression<T>>,
243 then: Box<Expression<T>>,
244 else_: Box<Expression<T>>,
245 },
246
247 Call {
248 target: Box<Expression<T>>,
249 args: Vec<Expression<T>>,
250 type_: T,
251 },
252
253 Panic {
254 type_: T,
255 },
256}
257
258impl Expression<IncompleteType> {
259 pub fn type_(&self) -> IncompleteType {
260 match self {
261 Expression::Block(expressions) => expressions
262 .last()
263 .expect("a block should not be empty")
264 .type_(),
265 Expression::FunctionRef { type_, .. } => type_.clone(),
266 Expression::Var(var) => var.type_.clone(),
267 Expression::Int { .. } => IncompleteType::Int,
268 Expression::Float { .. } => IncompleteType::Float,
269 Expression::Bool { .. } => IncompleteType::Bool,
270 Expression::String { .. } => IncompleteType::String,
271 Expression::Equals { .. } => IncompleteType::Bool,
272 Expression::NotEquals { .. } => IncompleteType::Bool,
273 Expression::IntGt { .. } => IncompleteType::Bool,
274 Expression::IntGtEq { .. } => IncompleteType::Bool,
275 Expression::IntLt { .. } => IncompleteType::Bool,
276 Expression::IntLtEq { .. } => IncompleteType::Bool,
277 Expression::IntAdd { .. } => IncompleteType::Int,
278 Expression::IntSub { .. } => IncompleteType::Int,
279 Expression::IntMul { .. } => IncompleteType::Int,
280 Expression::IntDiv { .. } => IncompleteType::Int,
281 Expression::IntRem { .. } => IncompleteType::Int,
282 Expression::FloatGt { .. } => IncompleteType::Bool,
283 Expression::FloatGtEq { .. } => IncompleteType::Bool,
284 Expression::FloatLt { .. } => IncompleteType::Bool,
285 Expression::FloatLtEq { .. } => IncompleteType::Bool,
286 Expression::FloatAdd { .. } => IncompleteType::Float,
287 Expression::FloatSub { .. } => IncompleteType::Float,
288 Expression::FloatMul { .. } => IncompleteType::Float,
289 Expression::FloatDiv { .. } => IncompleteType::Float,
290 Expression::StringConcat { .. } => IncompleteType::String,
291 Expression::List { type_, .. } => type_.clone(),
292 Expression::Tuple { type_, .. } => type_.clone(),
293 Expression::TupleAccess { type_, .. } => type_.clone(),
294 Expression::Struct { type_, .. } => type_.clone(),
295 Expression::StructTag { .. } => IncompleteType::Int,
296 Expression::StructAccess { type_, .. } => type_.clone(),
297 Expression::Set { value, .. } => value.type_(),
298 Expression::If { then, .. } => then.type_(),
299 Expression::Call { type_, .. } => type_.clone(),
300 Expression::Panic { type_ } => type_.clone(),
301 }
302 }
303}
304
305impl Expression<CompleteType> {
306 pub fn type_(&self) -> CompleteType {
307 match self {
308 Expression::Block(expressions) => expressions
309 .last()
310 .expect("a block should not be empty")
311 .type_(),
312 Expression::FunctionRef { type_, .. } => type_.clone(),
313 Expression::Var(var) => var.type_.clone(),
314 Expression::Int { .. } => CompleteType::Int,
315 Expression::Float { .. } => CompleteType::Float,
316 Expression::Bool { .. } => CompleteType::Bool,
317 Expression::String { .. } => CompleteType::String,
318 Expression::Equals { .. } => CompleteType::Bool,
319 Expression::NotEquals { .. } => CompleteType::Bool,
320 Expression::IntGt { .. } => CompleteType::Bool,
321 Expression::IntGtEq { .. } => CompleteType::Bool,
322 Expression::IntLt { .. } => CompleteType::Bool,
323 Expression::IntLtEq { .. } => CompleteType::Bool,
324 Expression::IntAdd { .. } => CompleteType::Int,
325 Expression::IntSub { .. } => CompleteType::Int,
326 Expression::IntMul { .. } => CompleteType::Int,
327 Expression::IntDiv { .. } => CompleteType::Int,
328 Expression::IntRem { .. } => CompleteType::Int,
329 Expression::FloatGt { .. } => CompleteType::Bool,
330 Expression::FloatGtEq { .. } => CompleteType::Bool,
331 Expression::FloatLt { .. } => CompleteType::Bool,
332 Expression::FloatLtEq { .. } => CompleteType::Bool,
333 Expression::FloatAdd { .. } => CompleteType::Float,
334 Expression::FloatSub { .. } => CompleteType::Float,
335 Expression::FloatMul { .. } => CompleteType::Float,
336 Expression::FloatDiv { .. } => CompleteType::Float,
337 Expression::StringConcat { .. } => CompleteType::String,
338 Expression::List { type_, .. } => type_.clone(),
339 Expression::Tuple { type_, .. } => type_.clone(),
340 Expression::TupleAccess { type_, .. } => type_.clone(),
341 Expression::Struct { type_, .. } => type_.clone(),
342 Expression::StructTag { .. } => CompleteType::Int,
343 Expression::StructAccess { type_, .. } => type_.clone(),
344 Expression::Set { value, .. } => value.type_(),
345 Expression::If { then, .. } => then.type_(),
346 Expression::Call { type_, .. } => type_.clone(),
347 Expression::Panic { type_ } => type_.clone(),
348 }
349 }
350}