Fork of daniellemaywood.uk/gleam — Wasm codegen work
2

Configure Feed

Select the types of activity you want to include in your feed.

Perform expression flattening

author
Danielle Maywood
committer
nandi
date (Jul 26, 2026, 12:11 PM -0700) commit 34064946 parent 969373cc change-id pkvyskmn
+166 -130
+88 -9
compiler-core/src/cranelift/mir.rs
··· 39 39 Generic, 40 40 } 41 41 42 - #[derive(Debug, PartialEq, Eq)] 42 + #[derive(Debug, PartialEq, Eq, Clone)] 43 43 pub enum Expression { 44 44 Block(Vec<Expression>), 45 45 ··· 104 104 FunctionParameter { name, type_ } 105 105 })); 106 106 107 - let body = BodyTranslator::default().translate(&function.body); 107 + let body = Self::flatten_expression(BodyTranslator::default().translate(&function.body)); 108 108 109 109 Function { 110 110 name, ··· 142 142 type_::Type::Tuple { elements: _ } => todo!(), 143 143 } 144 144 } 145 + 146 + fn flatten_expression(expression: Expression) -> Expression { 147 + match expression { 148 + Expression::Block(expressions) => { 149 + let mut block = vec![]; 150 + 151 + for expression in expressions { 152 + let expression = Self::flatten_expression(expression); 153 + 154 + match expression { 155 + Expression::Block(mut expressions) => block.append(&mut expressions), 156 + Expression::Var { .. } 157 + | Expression::Int { .. } 158 + | Expression::Equals { .. } 159 + | Expression::IntAdd { .. } 160 + | Expression::Set { .. } 161 + | Expression::If { .. } => block.push(expression), 162 + }; 163 + } 164 + 165 + match block.as_slice() { 166 + [single] => single.clone(), 167 + _ => Expression::Block(block), 168 + } 169 + } 170 + Expression::Var { name: _ } => expression, 171 + Expression::Int { value: _ } => expression, 172 + Expression::Equals { lhs, rhs } => Expression::Equals { 173 + lhs: Box::new(Self::flatten_expression(*lhs)), 174 + rhs: Box::new(Self::flatten_expression(*rhs)), 175 + }, 176 + Expression::IntAdd { lhs, rhs } => Expression::IntAdd { 177 + lhs: Box::new(Self::flatten_expression(*lhs)), 178 + rhs: Box::new(Self::flatten_expression(*rhs)), 179 + }, 180 + Expression::Set { name, value } => Expression::Set { 181 + name, 182 + value: Box::new(Self::flatten_expression(*value)), 183 + }, 184 + Expression::If { cond, then, else_ } => Expression::If { 185 + cond: Box::new(Self::flatten_expression(*cond)), 186 + then: Box::new(Self::flatten_expression(*then)), 187 + else_: Box::new(Self::flatten_expression(*else_)), 188 + }, 189 + } 190 + } 145 191 } 146 192 147 193 #[derive(Debug, Default)] 148 194 pub struct BodyTranslator { 149 195 variables: HashSet<EcoString>, 150 196 variable_count: usize, 197 + } 198 + 199 + #[derive(Debug, Clone, Copy, PartialEq, Eq)] 200 + enum DecisionKind { 201 + Case, 202 + Let, 151 203 } 152 204 153 205 impl BodyTranslator { ··· 280 332 return name; 281 333 })); 282 334 283 - block.push(self.translate_decision(&subject_vars, clauses, &compiled_case.tree)); 335 + block.push(self.translate_decision( 336 + DecisionKind::Case, 337 + &subject_vars, 338 + clauses, 339 + &compiled_case.tree, 340 + )); 284 341 285 342 Expression::Block(block) 286 343 } ··· 356 413 } 357 414 } 358 415 359 - fn translate_assignment(&mut self, _assignment: &ast::TypedAssignment) -> Expression { 360 - todo!() 416 + fn translate_assignment(&mut self, assignment: &ast::TypedAssignment) -> Expression { 417 + let mut block = vec![]; 418 + 419 + let value_var = self.make_tmp_var(); 420 + let value = self.translate_expression(&assignment.value); 421 + 422 + block.push(Expression::Set { 423 + name: value_var.clone(), 424 + value: Box::new(value), 425 + }); 426 + 427 + block.push(self.translate_decision( 428 + DecisionKind::Let, 429 + &[value_var.clone()], 430 + &[], 431 + &assignment.compiled_case.tree, 432 + )); 433 + 434 + block.push(Expression::Var { name: value_var }); 435 + 436 + Expression::Block(block) 361 437 } 362 438 363 439 fn make_tmp_var(&mut self) -> EcoString { ··· 373 449 374 450 fn translate_decision( 375 451 &mut self, 452 + kind: DecisionKind, 376 453 subjects: &[EcoString], 377 454 clauses: &[ast::TypedClause], 378 455 decision: &exhaustiveness::Decision, ··· 385 462 block.push(self.translate_binding(subjects, binding.clone(), value)); 386 463 } 387 464 388 - block.push(self.translate_expression(&clauses[body.clause_index].then)); 465 + if kind == DecisionKind::Case { 466 + block.push(self.translate_expression(&clauses[body.clause_index].then)); 467 + } 389 468 390 469 Expression::Block(block) 391 470 } ··· 425 504 block 426 505 }; 427 506 428 - let if_false = self.translate_decision(subjects, clauses, if_false); 507 + let if_false = self.translate_decision(kind, subjects, clauses, if_false); 429 508 430 509 block.push(Expression::If { 431 510 cond: Box::new(cond), ··· 441 520 fallback, 442 521 fallback_check: _, 443 522 } => { 444 - let fallback = self.translate_decision(subjects, clauses, fallback); 523 + let fallback = self.translate_decision(kind, subjects, clauses, fallback); 445 524 446 525 DoubleEndedIterator::rfold(choices.iter(), fallback, |fallback, (check, then)| { 447 526 Expression::If { ··· 451 530 name: subjects[var.id].clone(), 452 531 }, 453 532 )), 454 - then: Box::new(self.translate_decision(subjects, clauses, then)), 533 + then: Box::new(self.translate_decision(kind, subjects, clauses, then)), 455 534 else_: Box::new(fallback), 456 535 } 457 536 })
+30 -46
compiler-core/src/cranelift/snapshots/gleam_core__cranelift__mir__tests__translates_samples-2.snap
··· 17 17 ], 18 18 body: Block( 19 19 [ 20 - Block( 21 - [ 22 - Set { 20 + Set { 21 + name: "_tmp0", 22 + value: Var { 23 + name: "n", 24 + }, 25 + }, 26 + If { 27 + cond: Equals { 28 + lhs: Var { 23 29 name: "_tmp0", 24 - value: Var { 25 - name: "n", 26 - }, 27 30 }, 28 - If { 29 - cond: Equals { 30 - lhs: Var { 31 - name: "_tmp0", 32 - }, 33 - rhs: Int { 34 - value: 0, 35 - }, 31 + rhs: Int { 32 + value: 0, 33 + }, 34 + }, 35 + then: Int { 36 + value: 2, 37 + }, 38 + else_: If { 39 + cond: Equals { 40 + lhs: Var { 41 + name: "_tmp0", 36 42 }, 37 - then: Block( 38 - [ 39 - Int { 40 - value: 2, 41 - }, 42 - ], 43 - ), 44 - else_: If { 45 - cond: Equals { 46 - lhs: Var { 47 - name: "_tmp0", 48 - }, 49 - rhs: Int { 50 - value: 1, 51 - }, 52 - }, 53 - then: Block( 54 - [ 55 - Int { 56 - value: 4, 57 - }, 58 - ], 59 - ), 60 - else_: Block( 61 - [ 62 - Int { 63 - value: 6, 64 - }, 65 - ], 66 - ), 43 + rhs: Int { 44 + value: 1, 67 45 }, 68 46 }, 69 - ], 70 - ), 47 + then: Int { 48 + value: 4, 49 + }, 50 + else_: Int { 51 + value: 6, 52 + }, 53 + }, 54 + }, 71 55 ], 72 56 ), 73 57 },
+39 -59
compiler-core/src/cranelift/snapshots/gleam_core__cranelift__mir__tests__translates_samples-3.snap
··· 17 17 ], 18 18 body: Block( 19 19 [ 20 - Block( 21 - [ 22 - Set { 23 - name: "_tmp0", 24 - value: Var { 25 - name: "n", 20 + Set { 21 + name: "_tmp0", 22 + value: Var { 23 + name: "n", 24 + }, 25 + }, 26 + Set { 27 + name: "y", 28 + value: Var { 29 + name: "_tmp0", 30 + }, 31 + }, 32 + If { 33 + cond: Equals { 34 + lhs: Var { 35 + name: "y", 36 + }, 37 + rhs: Int { 38 + value: 0, 39 + }, 40 + }, 41 + then: Int { 42 + value: 2, 43 + }, 44 + else_: If { 45 + cond: Equals { 46 + lhs: Var { 47 + name: "_tmp0", 48 + }, 49 + rhs: Int { 50 + value: 1, 26 51 }, 27 52 }, 28 - Block( 29 - [ 30 - Set { 31 - name: "y", 32 - value: Var { 33 - name: "_tmp0", 34 - }, 35 - }, 36 - If { 37 - cond: Equals { 38 - lhs: Var { 39 - name: "y", 40 - }, 41 - rhs: Int { 42 - value: 0, 43 - }, 44 - }, 45 - then: Block( 46 - [ 47 - Int { 48 - value: 2, 49 - }, 50 - ], 51 - ), 52 - else_: If { 53 - cond: Equals { 54 - lhs: Var { 55 - name: "_tmp0", 56 - }, 57 - rhs: Int { 58 - value: 1, 59 - }, 60 - }, 61 - then: Block( 62 - [ 63 - Int { 64 - value: 4, 65 - }, 66 - ], 67 - ), 68 - else_: Block( 69 - [ 70 - Int { 71 - value: 6, 72 - }, 73 - ], 74 - ), 75 - }, 76 - }, 77 - ], 78 - ), 79 - ], 80 - ), 53 + then: Int { 54 + value: 4, 55 + }, 56 + else_: Int { 57 + value: 6, 58 + }, 59 + }, 60 + }, 81 61 ], 82 62 ), 83 63 },
+8 -12
compiler-core/src/cranelift/snapshots/gleam_core__cranelift__mir__tests__translates_samples.snap
··· 21 21 ), 22 22 }, 23 23 ], 24 - body: Block( 25 - [ 26 - IntAdd { 27 - lhs: Var { 28 - name: "lhs", 29 - }, 30 - rhs: Var { 31 - name: "rhs", 32 - }, 33 - }, 34 - ], 35 - ), 24 + body: IntAdd { 25 + lhs: Var { 26 + name: "lhs", 27 + }, 28 + rhs: Var { 29 + name: "rhs", 30 + }, 31 + }, 36 32 }, 37 33 ], 38 34 }
+1 -4
test/project_cranelift/src/project_cranelift.gleam
··· 1 1 pub fn add(lhs: Int, rhs: Int) -> Int { 2 - case lhs { 3 - x if x == 0 -> 10 4 - _ -> rhs 5 - } 2 + let x = 10 6 3 }