luaur-compiler 0.1.3

Luau source-to-bytecode compiler (Rust).
Documentation
use crate::enums::type_constant_folding::Type;
use crate::records::assignment::Assignment;
use crate::records::compiler::Compiler;
use crate::records::constant::Constant;
use crate::records::reg_scope::RegScope;
use luaur_ast::records::ast_expr_binary::AstExprBinaryOp;
use luaur_ast::records::ast_stat_compound_assign::AstStatCompoundAssign;
use luaur_common::enums::luau_bytecode_type::LuauBytecodeType;
use luaur_common::enums::luau_opcode::LuauOpcode;
use luaur_common::macros::luau_assert::LUAU_ASSERT;

impl Compiler {
    pub fn compile_stat_compound_assign(&mut self, stat: *mut AstStatCompoundAssign) {
        unsafe {
            let stat_ref = &*stat;
            let mut rs = self.reg_scope_compiler();
            let var = self.compile_l_value(stat_ref.var, &mut rs);
            let target = if var.kind == crate::enums::kind::Kind::Kind_Local {
                var.reg
            } else {
                self.alloc_reg(stat as *mut _, 1)
            };

            match stat_ref.op {
                AstExprBinaryOp::Add
                | AstExprBinaryOp::Sub
                | AstExprBinaryOp::Mul
                | AstExprBinaryOp::Div
                | AstExprBinaryOp::FloorDiv
                | AstExprBinaryOp::Mod
                | AstExprBinaryOp::Pow => {
                    if var.kind != crate::enums::kind::Kind::Kind_Local {
                        self.compile_l_value_use(&var, target, false, stat_ref.var);
                    }
                    let rc = self.get_constant_number(stat_ref.value);
                    if rc >= 0 && rc <= 255 {
                        (*self.bytecode).emit_abc(
                            self.get_binary_op_arith(stat_ref.op, true),
                            target,
                            target,
                            rc as u8,
                        );
                    } else {
                        let rr = self.compile_expr_auto(stat_ref.value, &mut rs);
                        (*self.bytecode).emit_abc(
                            self.get_binary_op_arith(stat_ref.op, false),
                            target,
                            target,
                            rr,
                        );
                        if var.kind != crate::enums::kind::Kind::Kind_Local {
                            self.hint_temporary_reg_type(
                                stat_ref.var,
                                target as i32,
                                LuauBytecodeType(2),
                                1,
                            );
                        }
                        self.hint_temporary_expr_reg_type(
                            stat_ref.value,
                            rr as i32,
                            LuauBytecodeType(2),
                            1,
                        );
                    }
                }
                AstExprBinaryOp::Concat => {
                    let mut args = vec![stat_ref.value];
                    self.unroll_concats(&mut args);
                    let regs = self.alloc_reg(stat as *mut _, (1 + args.len()) as u32);
                    self.compile_l_value_use(&var, regs, false, stat_ref.var);
                    for (i, &arg) in args.iter().enumerate() {
                        self.compile_expr_temp(arg, regs + 1 + i as u8);
                    }
                    (*self.bytecode).emit_abc(
                        LuauOpcode::LOP_CONCAT,
                        target,
                        regs,
                        regs + args.len() as u8,
                    );
                }
                _ => LUAU_ASSERT!(false),
            }

            if var.kind != crate::enums::kind::Kind::Kind_Local {
                self.compile_assign(&var, target, stat_ref.var);
            }
        }
    }
}