luaur_compiler/methods/
compiler_compile_expr.rs1use crate::enums::type_constant_folding::Type;
2use crate::functions::sref_compiler::sref_ast_name;
3use crate::functions::sref_compiler_alt_c::sref_ast_array_c_char;
4use crate::records::compile_error::CompileError;
5use crate::records::compiler::Compiler;
6use luaur_ast::records::ast_expr::AstExpr;
7use luaur_ast::records::ast_expr_binary::AstExprBinary;
8use luaur_ast::records::ast_expr_call::AstExprCall;
9use luaur_ast::records::ast_expr_constant_bool::AstExprConstantBool;
10use luaur_ast::records::ast_expr_constant_integer::AstExprConstantInteger;
11use luaur_ast::records::ast_expr_constant_nil::AstExprConstantNil;
12use luaur_ast::records::ast_expr_constant_number::AstExprConstantNumber;
13use luaur_ast::records::ast_expr_constant_string::AstExprConstantString;
14use luaur_ast::records::ast_expr_function::AstExprFunction;
15use luaur_ast::records::ast_expr_global::AstExprGlobal;
16use luaur_ast::records::ast_expr_group::AstExprGroup;
17use luaur_ast::records::ast_expr_if_else::AstExprIfElse;
18use luaur_ast::records::ast_expr_index_expr::AstExprIndexExpr;
19use luaur_ast::records::ast_expr_index_name::AstExprIndexName;
20use luaur_ast::records::ast_expr_instantiate::AstExprInstantiate;
21use luaur_ast::records::ast_expr_interp_string::AstExprInterpString;
22use luaur_ast::records::ast_expr_local::AstExprLocal;
23use luaur_ast::records::ast_expr_table::AstExprTable;
24use luaur_ast::records::ast_expr_type_assertion::AstExprTypeAssertion;
25use luaur_ast::records::ast_expr_unary::AstExprUnary;
26use luaur_ast::records::ast_expr_varargs::AstExprVarargs;
27use luaur_ast::records::ast_node::AstNode;
28use luaur_bytecode::methods::bytecode_builder_get_string_hash::bytecode_builder_get_string_hash;
29use luaur_common::enums::luau_opcode::LuauOpcode;
30use luaur_common::macros::luau_assert::LUAU_ASSERT;
31
32impl Compiler {
33 pub fn compile_expr(&mut self, node: *mut AstExpr, target: u8, target_temp: bool) {
34 self.set_debug_line_ast_node(node as *mut AstNode);
35
36 unsafe {
37 if self.options.coverage_level >= 2 && self.needs_coverage(node as *mut AstNode) {
38 (*self.bytecode).emit_abc(LuauOpcode::LOP_COVERAGE, 0, 0, 0);
39 }
40
41 if let Some(cv) = self.constants.find(&node) {
42 if cv.r#type != Type::Type_Unknown {
43 let cv = *cv;
44 self.compile_expr_constant(node, &cv, target);
45 return;
46 }
47 }
48
49 let expr_group = luaur_ast::rtti::ast_node_as::<AstExprGroup>(node as *mut AstNode);
50 if !expr_group.is_null() {
51 self.compile_expr((*expr_group).expr, target, target_temp);
52 return;
53 }
54
55 if luaur_ast::rtti::ast_node_is::<AstExprConstantNil>(&*(node as *mut AstNode)) {
56 (*self.bytecode).emit_abc(LuauOpcode::LOP_LOADNIL, target, 0, 0);
57 return;
58 }
59
60 let expr_bool =
61 luaur_ast::rtti::ast_node_as::<AstExprConstantBool>(node as *mut AstNode);
62 if !expr_bool.is_null() {
63 (*self.bytecode).emit_abc(
64 LuauOpcode::LOP_LOADB,
65 target,
66 (*expr_bool).value as u8,
67 0,
68 );
69 return;
70 }
71
72 let expr_number =
73 luaur_ast::rtti::ast_node_as::<AstExprConstantNumber>(node as *mut AstNode);
74 if !expr_number.is_null() {
75 let cid = (*self.bytecode).add_constant_number((*expr_number).value);
76 if cid < 0 {
77 CompileError::raise(
78 &(*expr_number).base.base.location,
79 format_args!("Exceeded constant limit; simplify the code to compile"),
80 );
81 }
82 self.emit_load_k(target, cid);
83 return;
84 }
85
86 let expr_integer =
87 luaur_ast::rtti::ast_node_as::<AstExprConstantInteger>(node as *mut AstNode);
88 if !expr_integer.is_null() {
89 let cid = (*self.bytecode).add_constant_integer((*expr_integer).value);
90 if cid < 0 {
91 CompileError::raise(
92 &(*expr_integer).base.base.location,
93 format_args!("Exceeded constant limit; simplify the code to compile"),
94 );
95 }
96 self.emit_load_k(target, cid);
97 return;
98 }
99
100 let expr_string =
101 luaur_ast::rtti::ast_node_as::<AstExprConstantString>(node as *mut AstNode);
102 if !expr_string.is_null() {
103 let cid = (*self.bytecode)
104 .add_constant_string(sref_ast_array_c_char((*expr_string).value));
105 if cid < 0 {
106 CompileError::raise(
107 &(*expr_string).base.base.location,
108 format_args!("Exceeded constant limit; simplify the code to compile"),
109 );
110 }
111 self.emit_load_k(target, cid);
112 return;
113 }
114
115 let expr_local = luaur_ast::rtti::ast_node_as::<AstExprLocal>(node as *mut AstNode);
116 if !expr_local.is_null() {
117 if luaur_common::FFlag::LuauExportValueSyntax.get()
118 && (*(*expr_local).local).is_exported
119 {
120 let table_reg = self.get_export_table_reg(node as *mut AstNode);
121 let name = sref_ast_name((*(*expr_local).local).name);
122 let cid = (*self.bytecode).add_constant_string(name);
123 if cid < 0 {
124 CompileError::raise(
125 &(*expr_local).base.base.location,
126 format_args!("Exceeded constant limit; simplify the code to compile"),
127 );
128 }
129 (*self.bytecode).emit_abc(
130 LuauOpcode::LOP_GETTABLEKS,
131 target,
132 table_reg,
133 bytecode_builder_get_string_hash(name) as u8,
134 );
135 (*self.bytecode).emit_aux(cid as u32);
136 } else {
137 let reg = self.get_expr_local_reg(node);
138 if reg >= 0 {
139 if self.options.optimization_level == 0 || target != reg as u8 {
140 (*self.bytecode).emit_abc(LuauOpcode::LOP_MOVE, target, reg as u8, 0);
141 }
142 } else {
143 LUAU_ASSERT!((*expr_local).upvalue);
144 let uid = self.get_upval((*expr_local).local);
145 (*self.bytecode).emit_abc(LuauOpcode::LOP_GETUPVAL, target, uid, 0);
146 }
147 }
148 return;
149 }
150
151 let expr_global = luaur_ast::rtti::ast_node_as::<AstExprGlobal>(node as *mut AstNode);
152 if !expr_global.is_null() {
153 self.compile_expr_global(expr_global, target);
154 return;
155 }
156
157 let expr_varargs = luaur_ast::rtti::ast_node_as::<AstExprVarargs>(node as *mut AstNode);
158 if !expr_varargs.is_null() {
159 self.compile_expr_varargs(expr_varargs, target, 1, false);
160 return;
161 }
162
163 let expr_call = luaur_ast::rtti::ast_node_as::<AstExprCall>(node as *mut AstNode);
164 if !expr_call.is_null() {
165 if target_temp && self.reg_top != 0 && u32::from(target) == self.reg_top - 1 {
166 self.compile_expr_call(expr_call, target, 1, true, false);
167 } else {
168 self.compile_expr_call(expr_call, target, 1, false, false);
169 }
170 return;
171 }
172
173 let expr_index_name =
174 luaur_ast::rtti::ast_node_as::<AstExprIndexName>(node as *mut AstNode);
175 if !expr_index_name.is_null() {
176 self.compile_expr_index_name(expr_index_name, target, target_temp);
177 return;
178 }
179
180 let expr_index_expr =
181 luaur_ast::rtti::ast_node_as::<AstExprIndexExpr>(node as *mut AstNode);
182 if !expr_index_expr.is_null() {
183 self.compile_expr_index_expr(expr_index_expr, target);
184 return;
185 }
186
187 let expr_function =
188 luaur_ast::rtti::ast_node_as::<AstExprFunction>(node as *mut AstNode);
189 if !expr_function.is_null() {
190 self.compile_expr_function(expr_function, target);
191 return;
192 }
193
194 let expr_table = luaur_ast::rtti::ast_node_as::<AstExprTable>(node as *mut AstNode);
195 if !expr_table.is_null() {
196 self.compile_expr_table(expr_table, target, target_temp);
197 return;
198 }
199
200 let expr_unary = luaur_ast::rtti::ast_node_as::<AstExprUnary>(node as *mut AstNode);
201 if !expr_unary.is_null() {
202 self.compile_expr_unary(expr_unary, target);
203 return;
204 }
205
206 let expr_binary = luaur_ast::rtti::ast_node_as::<AstExprBinary>(node as *mut AstNode);
207 if !expr_binary.is_null() {
208 self.compile_expr_binary(expr_binary, target, target_temp);
209 return;
210 }
211
212 let expr_assertion =
213 luaur_ast::rtti::ast_node_as::<AstExprTypeAssertion>(node as *mut AstNode);
214 if !expr_assertion.is_null() {
215 self.compile_expr((*expr_assertion).expr, target, target_temp);
216 return;
217 }
218
219 let expr_if_else = luaur_ast::rtti::ast_node_as::<AstExprIfElse>(node as *mut AstNode);
220 if !expr_if_else.is_null() {
221 self.compile_expr_if_else(expr_if_else, target, target_temp);
222 return;
223 }
224
225 let interp_string =
226 luaur_ast::rtti::ast_node_as::<AstExprInterpString>(node as *mut AstNode);
227 if !interp_string.is_null() {
228 self.compile_expr_interp_string(interp_string, target, target_temp);
229 return;
230 }
231
232 let expr_instantiate =
233 luaur_ast::rtti::ast_node_as::<AstExprInstantiate>(node as *mut AstNode);
234 if !expr_instantiate.is_null() {
235 self.compile_expr((*expr_instantiate).expr, target, target_temp);
236 return;
237 }
238 }
239
240 LUAU_ASSERT!(false);
241 }
242}