Skip to main content

luaur_compiler/methods/
compiler_compile_stat_assign.rs

1use crate::records::assignment::Assignment;
2use crate::records::compiler::Compiler;
3use crate::records::reg_scope::RegScope;
4use luaur_ast::records::ast_expr::AstExpr;
5use luaur_ast::records::ast_stat_assign::AstStatAssign;
6use luaur_common::enums::luau_opcode::LuauOpcode;
7use luaur_common::macros::luau_assert::LUAU_ASSERT;
8
9impl Compiler {
10    pub fn compile_stat_assign(&mut self, stat: *mut AstStatAssign) {
11        unsafe {
12            let stat_ref = &*stat;
13            let mut rs = self.reg_scope_compiler();
14
15            if stat_ref.vars.size == 1 && stat_ref.values.size == 1 {
16                let var = self.compile_l_value(*stat_ref.vars.data, &mut rs);
17                if var.kind == crate::enums::kind::Kind::Kind_Local {
18                    self.compile_expr(*stat_ref.values.data, var.reg, false);
19                } else {
20                    let reg = self.compile_expr_auto(*stat_ref.values.data, &mut rs);
21                    self.set_debug_line_ast_node(
22                        *stat_ref.vars.data as *mut luaur_ast::records::ast_node::AstNode,
23                    );
24                    self.compile_assign(&var, reg, *stat_ref.vars.data);
25                }
26                return;
27            }
28
29            let mut vars = Vec::with_capacity(stat_ref.vars.size);
30            for i in 0..stat_ref.vars.size {
31                vars.push(Assignment {
32                    lvalue: self.compile_l_value(*stat_ref.vars.data.add(i), &mut rs),
33                    conflict_reg: Assignment::kInvalidReg,
34                    value_reg: Assignment::kInvalidReg,
35                });
36            }
37
38            self.resolve_assign_conflicts(stat as *mut _, &mut vars, &stat_ref.values);
39
40            for i in 0..stat_ref.vars.size.min(stat_ref.values.size) {
41                let value = *stat_ref.values.data.add(i);
42                if i + 1 == stat_ref.values.size && stat_ref.vars.size > stat_ref.values.size {
43                    let rest = (stat_ref.vars.size - stat_ref.values.size + 1) as u32;
44                    let temp = self.alloc_reg(stat as *mut _, rest);
45                    self.compile_expr_temp_n(value, temp, rest as u8, true);
46                    for j in i..stat_ref.vars.size {
47                        vars[j].value_reg = temp + (j - i) as u8;
48                    }
49                } else {
50                    let var = &mut vars[i];
51                    if var.lvalue.kind == crate::enums::kind::Kind::Kind_Local {
52                        var.value_reg = if var.conflict_reg == Assignment::kInvalidReg {
53                            var.lvalue.reg
54                        } else {
55                            var.conflict_reg
56                        };
57                        self.compile_expr(value, var.value_reg, false);
58                    } else {
59                        var.value_reg = self.compile_expr_auto(value, &mut rs);
60                    }
61                }
62            }
63
64            for i in stat_ref.vars.size..stat_ref.values.size {
65                self.compile_expr_side(*stat_ref.values.data.add(i));
66            }
67
68            for (i, var) in vars.iter().enumerate() {
69                LUAU_ASSERT!(var.value_reg != Assignment::kInvalidReg);
70                if var.lvalue.kind != crate::enums::kind::Kind::Kind_Local {
71                    self.set_debug_line_location(&var.lvalue.location);
72                    let target_expr = if i < stat_ref.vars.size {
73                        *stat_ref.vars.data.add(i)
74                    } else {
75                        core::ptr::null_mut()
76                    };
77                    self.compile_assign(&var.lvalue, var.value_reg, target_expr);
78                }
79            }
80
81            for var in vars {
82                if var.lvalue.kind == crate::enums::kind::Kind::Kind_Local
83                    && var.value_reg != var.lvalue.reg
84                {
85                    (*self.bytecode).emit_abc(
86                        LuauOpcode::LOP_MOVE,
87                        var.lvalue.reg,
88                        var.value_reg,
89                        0,
90                    );
91                }
92            }
93        }
94    }
95}