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