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