Skip to main content

luaur_compiler/methods/
compiler_compile_expr_if_else.rs

1use crate::records::compiler::Compiler;
2use luaur_ast::records::ast_expr::AstExpr;
3use luaur_ast::records::ast_expr_if_else::AstExprIfElse;
4use luaur_ast::records::ast_node::AstNode;
5use luaur_common::enums::luau_opcode::LuauOpcode;
6
7impl Compiler {
8    pub fn compile_expr_if_else(
9        &mut self,
10        expr: *mut AstExprIfElse,
11        target: u8,
12        target_temp: bool,
13    ) {
14        let expr_ref = unsafe { &*expr };
15
16        if self.is_constant(expr_ref.condition) {
17            if self.is_constant_true(expr_ref.condition) {
18                self.compile_expr(expr_ref.true_expr, target, target_temp);
19            } else {
20                self.compile_expr(expr_ref.false_expr, target, target_temp);
21            }
22        } else {
23            let creg = self.get_expr_local_reg(expr_ref.condition);
24            if creg >= 0 {
25                let true_reg = self.get_expr_local_reg(expr_ref.true_expr);
26                let false_reg = self.get_expr_local_reg(expr_ref.false_expr);
27
28                if creg == true_reg && (false_reg >= 0 || self.is_constant(expr_ref.false_expr)) {
29                    return self.compile_expr_if_else_and_or(
30                        false,
31                        creg as u8,
32                        expr_ref.false_expr,
33                        target,
34                    );
35                } else if creg == false_reg
36                    && (true_reg >= 0 || self.is_constant(expr_ref.true_expr))
37                {
38                    return self.compile_expr_if_else_and_or(
39                        true,
40                        creg as u8,
41                        expr_ref.true_expr,
42                        target,
43                    );
44                }
45            }
46
47            let mut else_jump = Vec::new();
48            self.compile_condition_value(
49                expr_ref.condition,
50                core::ptr::null(),
51                &mut else_jump,
52                false,
53            );
54            self.compile_expr(expr_ref.true_expr, target, target_temp);
55
56            let bytecode = unsafe { &mut *self.bytecode };
57            let then_label = bytecode.emit_label();
58            bytecode.emit_ad(LuauOpcode::LOP_JUMP, 0, 0);
59
60            let else_label = bytecode.emit_label();
61            self.compile_expr(expr_ref.false_expr, target, target_temp);
62            let end_label = bytecode.emit_label();
63
64            self.patch_jumps(expr as *mut AstNode, &mut else_jump, else_label);
65            self.patch_jump(expr as *mut AstNode, then_label, end_label);
66        }
67    }
68}