rue_compiler/compile/expr/
if_expr.rs

1use log::debug;
2use rue_ast::{AstIfExpr, AstNode};
3use rue_hir::{Hir, Value};
4use rue_types::{Type, TypeId, Union};
5
6use crate::{Compiler, compile_expr};
7
8pub fn compile_if_expr(
9    ctx: &mut Compiler,
10    expr: &AstIfExpr,
11    expected_type: Option<TypeId>,
12) -> Value {
13    let condition = if let Some(condition) = expr.condition() {
14        let value = compile_expr(ctx, &condition, None);
15        ctx.check_condition(condition.syntax(), value.ty);
16        value
17    } else {
18        debug!("Unresolved if condition");
19        ctx.builtins().unresolved.clone()
20    };
21
22    let then_expr = if let Some(then_expr) = expr.then_expr() {
23        if expr.inline().is_some() {
24            // We can't type guard if the branches are eagerly evaluated
25            compile_expr(ctx, &then_expr, expected_type)
26        } else {
27            let range = then_expr.syntax().text_range();
28            let index = ctx.push_mappings(condition.then_map.clone(), range.start());
29            let value = compile_expr(ctx, &then_expr, expected_type);
30            ctx.revert_mappings(index, range.end());
31            value
32        }
33    } else {
34        debug!("Unresolved if then expr");
35        ctx.builtins().unresolved.clone()
36    };
37
38    let else_expr = if let Some(else_expr) = expr.else_expr() {
39        if expr.inline().is_some() {
40            // We can't type guard if the branches are eagerly evaluated
41            compile_expr(ctx, &else_expr, expected_type)
42        } else {
43            let range = else_expr.syntax().text_range();
44            let index = ctx.push_mappings(condition.else_map.clone(), range.start());
45            let value = compile_expr(ctx, &else_expr, expected_type);
46            ctx.revert_mappings(index, range.end());
47            value
48        }
49    } else {
50        debug!("Unresolved if else expr");
51        ctx.builtins().unresolved.clone()
52    };
53
54    let ty = ctx.alloc_type(Type::Union(Union::new(vec![then_expr.ty, else_expr.ty])));
55    let hir = ctx.alloc_hir(Hir::If(
56        condition.hir,
57        then_expr.hir,
58        else_expr.hir,
59        expr.inline().is_some(),
60    ));
61
62    Value::new(hir, ty)
63}