Skip to main content

luaur_compiler/methods/
compiler_compile_stat_compound_assign.rs

1use crate::enums::type_constant_folding::Type;
2use crate::records::assignment::Assignment;
3use crate::records::compiler::Compiler;
4use crate::records::constant::Constant;
5use crate::records::reg_scope::RegScope;
6use luaur_ast::records::ast_expr_binary::AstExprBinaryOp;
7use luaur_ast::records::ast_stat_compound_assign::AstStatCompoundAssign;
8use luaur_common::enums::luau_bytecode_type::LuauBytecodeType;
9use luaur_common::enums::luau_opcode::LuauOpcode;
10use luaur_common::macros::luau_assert::LUAU_ASSERT;
11
12impl Compiler {
13    pub fn compile_stat_compound_assign(&mut self, stat: *mut AstStatCompoundAssign) {
14        unsafe {
15            let stat_ref = &*stat;
16            let mut rs = self.reg_scope_compiler();
17            let var = self.compile_l_value(stat_ref.var, &mut rs);
18            let target = if var.kind == crate::enums::kind::Kind::Kind_Local {
19                var.reg
20            } else {
21                self.alloc_reg(stat as *mut _, 1)
22            };
23
24            match stat_ref.op {
25                AstExprBinaryOp::Add
26                | AstExprBinaryOp::Sub
27                | AstExprBinaryOp::Mul
28                | AstExprBinaryOp::Div
29                | AstExprBinaryOp::FloorDiv
30                | AstExprBinaryOp::Mod
31                | AstExprBinaryOp::Pow => {
32                    if var.kind != crate::enums::kind::Kind::Kind_Local {
33                        self.compile_l_value_use(&var, target, false, stat_ref.var);
34                    }
35                    let rc = self.get_constant_number(stat_ref.value);
36                    if rc >= 0 && rc <= 255 {
37                        (*self.bytecode).emit_abc(
38                            self.get_binary_op_arith(stat_ref.op, true),
39                            target,
40                            target,
41                            rc as u8,
42                        );
43                    } else {
44                        let rr = self.compile_expr_auto(stat_ref.value, &mut rs);
45                        (*self.bytecode).emit_abc(
46                            self.get_binary_op_arith(stat_ref.op, false),
47                            target,
48                            target,
49                            rr,
50                        );
51                        if var.kind != crate::enums::kind::Kind::Kind_Local {
52                            self.hint_temporary_reg_type(
53                                stat_ref.var,
54                                target as i32,
55                                LuauBytecodeType(2),
56                                1,
57                            );
58                        }
59                        self.hint_temporary_expr_reg_type(
60                            stat_ref.value,
61                            rr as i32,
62                            LuauBytecodeType(2),
63                            1,
64                        );
65                    }
66                }
67                AstExprBinaryOp::Concat => {
68                    let mut args = vec![stat_ref.value];
69                    self.unroll_concats(&mut args);
70                    let regs = self.alloc_reg(stat as *mut _, (1 + args.len()) as u32);
71                    self.compile_l_value_use(&var, regs, false, stat_ref.var);
72                    for (i, &arg) in args.iter().enumerate() {
73                        self.compile_expr_temp(arg, regs + 1 + i as u8);
74                    }
75                    (*self.bytecode).emit_abc(
76                        LuauOpcode::LOP_CONCAT,
77                        target,
78                        regs,
79                        regs + args.len() as u8,
80                    );
81                }
82                _ => LUAU_ASSERT!(false),
83            }
84
85            if var.kind != crate::enums::kind::Kind::Kind_Local {
86                self.compile_assign(&var, target, stat_ref.var);
87            }
88        }
89    }
90}