luaur_compiler/methods/
compiler_compile_stat_assign.rs1use 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}