Skip to main content

luaur_compiler/methods/
compiler_compile_expr_index_name.rs

1use crate::functions::sref_compiler::sref_ast_name;
2use crate::records::compile_error::CompileError;
3use crate::records::compiler::Compiler;
4use crate::records::reg_scope::RegScope;
5use luaur_ast::records::ast_expr_global::AstExprGlobal;
6use luaur_ast::records::ast_expr_index_name::AstExprIndexName;
7use luaur_bytecode::methods::bytecode_builder_get_string_hash::bytecode_builder_get_string_hash;
8use luaur_common::enums::luau_bytecode_type::LuauBytecodeType;
9use luaur_common::enums::luau_opcode::LuauOpcode;
10
11impl Compiler {
12    pub fn compile_expr_index_name(
13        &mut self,
14        expr: *mut AstExprIndexName,
15        target: u8,
16        target_temp: bool,
17    ) {
18        unsafe {
19            let expr_ref = &*expr;
20            self.set_debug_line_ast_node(expr as *mut _);
21
22            let mut import_root: *mut AstExprGlobal = core::ptr::null_mut();
23            let mut import1: *mut AstExprIndexName = core::ptr::null_mut();
24            let mut import2: *mut AstExprIndexName = core::ptr::null_mut();
25
26            let index = luaur_ast::rtti::ast_node_as::<AstExprIndexName>(
27                expr_ref.expr as *mut luaur_ast::records::ast_node::AstNode,
28            );
29            if !index.is_null() {
30                import_root = luaur_ast::rtti::ast_node_as::<AstExprGlobal>(
31                    (*index).expr as *mut luaur_ast::records::ast_node::AstNode,
32                );
33                import1 = index;
34                import2 = expr;
35            } else {
36                import_root = luaur_ast::rtti::ast_node_as::<AstExprGlobal>(
37                    expr_ref.expr as *mut luaur_ast::records::ast_node::AstNode,
38                );
39                import1 = expr;
40            }
41
42            if !import_root.is_null() && self.can_import_chain(import_root) {
43                let id0 = (*self.bytecode).add_constant_string(sref_ast_name((*import_root).name));
44                let id1 = (*self.bytecode).add_constant_string(sref_ast_name((*import1).index));
45                let id2 = if !import2.is_null() {
46                    (*self.bytecode).add_constant_string(sref_ast_name((*import2).index))
47                } else {
48                    -1
49                };
50
51                if id0 >= 0 && id1 >= 0 && (import2.is_null() || id2 >= 0) {
52                    if id0 < 1024 && id1 < 1024 && (import2.is_null() || id2 < 1024) {
53                        let iid = if !import2.is_null() {
54                            get_import_id_3(id0, id1, id2)
55                        } else {
56                            get_import_id_2(id0, id1)
57                        };
58                        let cid = (*self.bytecode).add_import(iid);
59                        if cid >= 0 && cid < 32768 {
60                            (*self.bytecode).emit_ad(LuauOpcode::LOP_GETIMPORT, target, cid as i16);
61                            (*self.bytecode).emit_aux(iid as u32);
62                            return;
63                        }
64                    }
65                }
66            }
67
68            let mut rs = self.reg_scope_compiler();
69            let reg = if let local_reg = self.get_expr_local_reg(expr_ref.expr) {
70                if local_reg >= 0 {
71                    local_reg as u8
72                } else if target_temp {
73                    self.compile_expr_temp(expr_ref.expr, target);
74                    target
75                } else {
76                    self.compile_expr_auto(expr_ref.expr, &mut rs)
77                }
78            } else {
79                self.compile_expr_auto(expr_ref.expr, &mut rs)
80            };
81
82            self.set_debug_line_location(&expr_ref.index_location);
83            let iname = sref_ast_name(expr_ref.index);
84            let cid = (*self.bytecode).add_constant_string(iname);
85            if cid < 0 {
86                CompileError::raise(
87                    &expr_ref.base.base.location,
88                    format_args!("Exceeded constant limit; simplify the code to compile"),
89                );
90            }
91
92            (*self.bytecode).emit_abc(
93                LuauOpcode::LOP_GETTABLEKS,
94                target,
95                reg,
96                bytecode_builder_get_string_hash(iname) as u8,
97            );
98            (*self.bytecode).emit_aux(cid as u32);
99            self.hint_temporary_expr_reg_type(expr_ref.expr, reg as i32, LuauBytecodeType(4), 2);
100        }
101    }
102}
103
104fn get_import_id_2(id0: i32, id1: i32) -> u32 {
105    ((2u32) << 30) | ((id0 as u32) << 20) | ((id1 as u32) << 10)
106}
107
108fn get_import_id_3(id0: i32, id1: i32, id2: i32) -> u32 {
109    ((3u32) << 30) | ((id0 as u32) << 20) | ((id1 as u32) << 10) | id2 as u32
110}