Skip to main content

cl_ast/desugar/
while_else.rs

1//! Desugars `while {...} else` expressions
2//! into `loop if {...} else break` expressions
3
4use crate::{
5    ast::*,
6    fold::{Fold, Foldable, impl_default_fold},
7};
8
9/// Desugars while-else expressions
10/// into loop-if-else-break expressions
11pub struct WhileElseDesugar;
12
13impl<A: AstTypes> Fold<A, A> for WhileElseDesugar {
14    type Error = ();
15    impl_default_fold!(A, A);
16
17    fn fold_at_expr(&mut self, expr: At<Expr<A>, A>) -> Result<At<Expr<A>, A>, Self::Error> {
18        let expr = expr.children(self)?;
19        let At(Expr::Op(Op::While, mut parts), span) = expr else {
20            return Ok(expr);
21        };
22        assert_eq!(parts.len(), 3, "`while` must have exactly 3 branches");
23        let fail = parts.pop().unwrap();
24        let pass = parts.pop().unwrap();
25        let cond = parts.pop().unwrap();
26        let fail_span = fail.1;
27        let fail = Expr::Op(Op::Break, vec![fail]).at(fail_span);
28        let body = Expr::Op(Op::If, vec![cond, pass, fail]).at(span);
29        let expr = Expr::Op(Op::Loop, vec![body]).at(span);
30
31        Ok(expr)
32    }
33}