(
&mut self,
ir_program: &mut IrProgram,
cond: &Expression,
body: &Block,
)
| 486 | lowered.value |
| 487 | } else { |
| 488 | self.context.error(format!( |
| 489 | "failed to lower while condition `{}` (see previous diagnostics for root cause)", |
| 490 | self.format_expression(cond) |
| 491 | )); |
| 492 | IrValue::Bool(false) |
| 493 | }; |
| 494 | |
| 495 | self.set_terminator(IrTerminator::Branch { |
| 496 | cond: cond_value, |
| 497 | then_label: body_label.clone(), |
| 498 | else_label: exit_label.clone(), |
| 499 | }); |
| 500 | |
| 501 | // Loop-carried locals stay in stack slots until COMPILER_QUALITY_PLAN.md. |
| 502 | self.start_new_block(body_label.0.clone()); |
| 503 | self.loop_labels |
| 504 | .push((cond_label.clone(), exit_label.clone())); |
| 505 | self.lower_block(ir_program, body); |
| 506 | self.loop_labels.pop(); |
| 507 | self.set_terminator(IrTerminator::Jump(cond_label.clone())); |
| 508 | |
| 509 | self.start_new_block(exit_label.0.clone()); |
| 510 | } |
| 511 | |
| 512 | // A `for` loop desugars to a `while` loop, reusing the existing `while` |
| 513 | // lowering (phi/break/continue) so no new IR forms are needed. |
| 514 | pub(super) fn lower_for( |
| 515 | &mut self, |
| 516 | ir_program: &mut IrProgram, |
| 517 | var: &str, |
| 518 | iter: &crate::ast::ForIter, |
| 519 | body: &Block, |
| 520 | ) { |
| 521 | match iter { |
| 522 | crate::ast::ForIter::Range { |
| 523 | start, |
| 524 | end, |
| 525 | inclusive, |
| 526 | } => self.lower_for_range(ir_program, var, start, end, *inclusive, body), |
| 527 | crate::ast::ForIter::Each(seq) => self.lower_for_each(ir_program, var, seq, body), |
| 528 | } |
| 529 | } |
| 530 | |
| 531 | // Desugars to a while loop: `end` is evaluated once into a temporary, the |
| 532 | // compare is `<` (`<=` when inclusive), and the step increments by one. |
| 533 | fn lower_for_range( |
| 534 | &mut self, |
| 535 | ir_program: &mut IrProgram, |
| 536 | var: &str, |
| 537 | start: &Expression, |
| 538 | end: &Expression, |
| 539 | inclusive: bool, |
| 540 | body: &Block, |
| 541 | ) { |
| 542 | let id = self.for_loop_id; |
| 543 | self.for_loop_id += 1; |
| 544 | let end_name = format!("__for_end_{id}"); |
| 545 |
no test coverage detected