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