Skip to main content

luaur_compiler/methods/
compiler_compile_expr_and_or.rs

1use crate::enums::type_constant_folding::Type;
2use crate::records::compiler::Compiler;
3use crate::records::constant::Constant;
4use crate::records::reg_scope::RegScope;
5use luaur_ast::records::ast_expr_binary::AstExprBinary;
6use luaur_common::enums::luau_opcode::LuauOpcode;
7
8impl Compiler {
9    pub fn compile_expr_and_or(&mut self, expr: *mut AstExprBinary, target: u8, target_temp: bool) {
10        unsafe {
11            let expr_ref = &*expr;
12            let and_ = expr_ref.op == luaur_ast::records::ast_expr_binary::AstExprBinaryOp::And;
13            let mut rs = self.reg_scope_compiler();
14
15            if let Some(cl) = self.constants.find(&expr_ref.left) {
16                if cl.r#type != Type::Type_Unknown {
17                    self.compile_expr(
18                        if and_ == cl.is_truthful() {
19                            expr_ref.right
20                        } else {
21                            expr_ref.left
22                        },
23                        target,
24                        target_temp,
25                    );
26                    return;
27                }
28            }
29
30            if !self.is_condition_fast(expr_ref.left) {
31                if let reg = self.get_expr_local_reg(expr_ref.right) {
32                    if reg >= 0 {
33                        let lr = self.compile_expr_auto(expr_ref.left, &mut rs);
34                        (*self.bytecode).emit_abc(
35                            if and_ {
36                                LuauOpcode::LOP_AND
37                            } else {
38                                LuauOpcode::LOP_OR
39                            },
40                            target,
41                            lr,
42                            reg as u8,
43                        );
44                        return;
45                    }
46                }
47
48                let cid = self.get_constant_index(expr_ref.right);
49                if cid >= 0 && cid <= 255 {
50                    let lr = self.compile_expr_auto(expr_ref.left, &mut rs);
51                    (*self.bytecode).emit_abc(
52                        if and_ {
53                            LuauOpcode::LOP_ANDK
54                        } else {
55                            LuauOpcode::LOP_ORK
56                        },
57                        target,
58                        lr,
59                        cid as u8,
60                    );
61                    return;
62                }
63            }
64
65            let reg = if target_temp {
66                target
67            } else {
68                self.alloc_reg(expr as *mut _, 1)
69            };
70            let mut skip_jump = Vec::new();
71            self.compile_condition_value(expr_ref.left, &reg, &mut skip_jump, !and_);
72            self.compile_expr_temp(expr_ref.right, reg);
73            let move_label = (*self.bytecode).emit_label();
74            self.patch_jumps(expr as *mut _, &mut skip_jump, move_label);
75
76            if target != reg {
77                (*self.bytecode).emit_abc(LuauOpcode::LOP_MOVE, target, reg, 0);
78            }
79        }
80    }
81}