Skip to main content

luaur_compiler/methods/
compiler_compile_stat_local.rs

1use crate::functions::sref_compiler::sref_ast_name;
2use crate::records::compile_error::CompileError;
3use crate::records::compiler::Compiler;
4use luaur_ast::records::ast_expr::AstExpr;
5use luaur_ast::records::ast_node::AstNode;
6use luaur_ast::records::ast_stat_local::AstStatLocal;
7use luaur_bytecode::methods::bytecode_builder_get_string_hash::bytecode_builder_get_string_hash;
8use luaur_common::enums::luau_opcode::LuauOpcode;
9
10impl Compiler {
11    pub fn compile_stat_local(&mut self, stat: *mut AstStatLocal) {
12        unsafe {
13            if self.options.optimization_level >= 1
14                && self.options.debug_level <= 1
15                && self.are_locals_redundant(stat)
16            {
17                return;
18            }
19
20            let stat_ref = &*stat;
21
22            if self.options.optimization_level >= 1
23                && stat_ref.vars.size == 1
24                && stat_ref.values.size == 1
25            {
26                let value = *stat_ref.values.data;
27                let re = self.get_expr_local(value);
28
29                if !re.is_null() {
30                    let local = *stat_ref.vars.data;
31                    let lv_written = self.variables.find(&local).map_or(false, |lv| lv.written);
32                    let rv_local = (*re).local;
33                    let rv_written = self
34                        .variables
35                        .find(&rv_local)
36                        .map_or(false, |rv| rv.written);
37                    let reg = self.get_expr_local_reg(value);
38
39                    if reg >= 0
40                        && !lv_written
41                        && !rv_written
42                        && !(*local).is_exported
43                        && !(*rv_local).is_exported
44                    {
45                        let allocpc = (*self.bytecode).get_debug_pc();
46                        self.push_local(local, reg as u8, allocpc);
47                        return;
48                    }
49                }
50            }
51
52            let vars = self.alloc_reg(stat as *mut AstNode, stat_ref.vars.size as u32);
53            let allocpc = (*self.bytecode).get_debug_pc();
54
55            self.compile_expr_list_temp(&stat_ref.values, vars, stat_ref.vars.size as u8, true);
56
57            for i in 0..stat_ref.vars.size {
58                let local = *stat_ref.vars.data.add(i);
59
60                if luaur_common::FFlag::LuauExportValueSyntax.get() && (*local).is_exported {
61                    self.ensure_export_table(stat as *mut AstNode);
62
63                    let name_ref = sref_ast_name((*local).name);
64                    let cid = (*self.bytecode).add_constant_string(name_ref);
65                    if cid < 0 {
66                        CompileError::raise(
67                            &(*local).location,
68                            format_args!("Exceeded constant limit; simplify the code to compile"),
69                        );
70                    }
71
72                    let table_reg = self.get_export_table_reg(stat as *mut AstNode);
73                    (*self.bytecode).emit_abc(
74                        LuauOpcode::LOP_SETTABLEKS,
75                        vars + i as u8,
76                        table_reg,
77                        bytecode_builder_get_string_hash(name_ref) as u8,
78                    );
79                    (*self.bytecode).emit_aux(cid as u32);
80                } else {
81                    self.push_local(local, vars + i as u8, allocpc);
82                }
83            }
84        }
85    }
86}