luaur_compiler/methods/
compiler_compile_stat.rs1use crate::records::compiler::Compiler;
2use luaur_ast::records::ast_node::AstNode;
3use luaur_ast::records::ast_stat::AstStat;
4use luaur_ast::records::ast_stat_assign::AstStatAssign;
5use luaur_ast::records::ast_stat_block::AstStatBlock;
6use luaur_ast::records::ast_stat_break::AstStatBreak;
7use luaur_ast::records::ast_stat_class::AstStatClass;
8use luaur_ast::records::ast_stat_compound_assign::AstStatCompoundAssign;
9use luaur_ast::records::ast_stat_continue::AstStatContinue;
10use luaur_ast::records::ast_stat_for::AstStatFor;
11use luaur_ast::records::ast_stat_for_in::AstStatForIn;
12use luaur_ast::records::ast_stat_function::AstStatFunction;
13use luaur_ast::records::ast_stat_if::AstStatIf;
14use luaur_ast::records::ast_stat_local::AstStatLocal;
15use luaur_ast::records::ast_stat_local_function::AstStatLocalFunction;
16use luaur_ast::records::ast_stat_repeat::AstStatRepeat;
17use luaur_ast::records::ast_stat_return::AstStatReturn;
18use luaur_ast::records::ast_stat_while::AstStatWhile;
19use luaur_ast::rtti;
20use luaur_common::enums::luau_opcode::LuauOpcode;
21use luaur_common::macros::luau_assert::LUAU_ASSERT;
22
23impl Compiler {
24 pub fn compile_stat(&mut self, node: *mut AstStat) {
25 unsafe {
26 self.set_debug_line_ast_node(node as *mut AstNode);
27 if self.options.coverage_level >= 1 && self.needs_coverage(node as *mut AstNode) {
28 (*self.bytecode).emit_abc(LuauOpcode::LOP_COVERAGE, 0, 0, 0);
29 }
30
31 let stat = rtti::ast_node_as::<AstStatBlock>(node as *mut AstNode);
32 if !stat.is_null() {
33 let _rs = self.reg_scope_compiler();
34 let old_locals = self.local_stack.len();
35 if luaur_common::FFlag::LuauExportValueSyntax.get() {
36 self.block_depth += 1;
37 }
38 for i in 0..(*stat).body.size {
39 let body_stat = *(*stat).body.data.add(i);
40 self.compile_stat(body_stat);
41 if self.always_terminates(body_stat) {
42 break;
43 }
44 }
45 if luaur_common::FFlag::LuauExportValueSyntax.get() {
46 self.block_depth -= 1;
47 }
48 self.close_locals(old_locals);
49 self.pop_locals(old_locals);
50 return;
51 }
52
53 let stat = rtti::ast_node_as::<AstStatIf>(node as *mut AstNode);
54 if !stat.is_null() {
55 self.compile_stat_if(stat);
56 return;
57 }
58
59 let stat = rtti::ast_node_as::<AstStatWhile>(node as *mut AstNode);
60 if !stat.is_null() {
61 self.compile_stat_while(stat);
62 return;
63 }
64
65 let stat = rtti::ast_node_as::<AstStatRepeat>(node as *mut AstNode);
66 if !stat.is_null() {
67 self.compile_stat_repeat(stat);
68 return;
69 }
70
71 if rtti::ast_node_is::<AstStatBreak>(&*(node as *mut AstNode)) {
72 LUAU_ASSERT!(!self.loops.is_empty());
73 self.close_locals(self.loops.last().unwrap().local_offset);
74 let label = (*self.bytecode).emit_label();
75 (*self.bytecode).emit_ad(LuauOpcode::LOP_JUMP, 0, 0);
76 self.loop_jumps.push(crate::records::loop_jump::LoopJump {
77 r#type: crate::enums::type_compiler::Type::Break,
78 label,
79 });
80 return;
81 }
82
83 let stat = rtti::ast_node_as::<AstStatContinue>(node as *mut AstNode);
84 if !stat.is_null() {
85 LUAU_ASSERT!(!self.loops.is_empty());
86 if self.loops.last().unwrap().continue_used.is_null() {
87 self.loops.last_mut().unwrap().continue_used = stat as *mut _;
88 }
89 self.close_locals(self.loops.last().unwrap().local_offset_continue);
90 let label = (*self.bytecode).emit_label();
91 (*self.bytecode).emit_ad(LuauOpcode::LOP_JUMP, 0, 0);
92 self.loop_jumps.push(crate::records::loop_jump::LoopJump {
93 r#type: crate::enums::type_compiler::Type::Continue,
94 label,
95 });
96 return;
97 }
98
99 let stat = rtti::ast_node_as::<AstStatReturn>(node as *mut AstNode);
100 if !stat.is_null() {
101 if self.options.optimization_level >= 2 && !self.inline_frames.is_empty() {
102 self.compile_inline_return(stat, false);
103 } else {
104 self.compile_stat_return(stat);
105 }
106 return;
107 }
108
109 let stat = rtti::ast_node_as::<luaur_ast::records::ast_stat_expr::AstStatExpr>(
110 node as *mut AstNode,
111 );
112 if !stat.is_null() {
113 let expr = rtti::ast_node_as::<luaur_ast::records::ast_expr_call::AstExprCall>(
114 (*stat).expr as *mut AstNode,
115 );
116 if !expr.is_null() {
117 self.compile_expr_call(expr, self.reg_top as u8, 0, false, false);
118 } else {
119 self.compile_expr_side((*stat).expr);
120 }
121 return;
122 }
123
124 let stat = rtti::ast_node_as::<AstStatLocal>(node as *mut AstNode);
125 if !stat.is_null() {
126 if luaur_common::FFlag::LuauExportValueSyntax.get() {
127 for i in 0..(*stat).vars.size {
128 self.check_exported_local(
129 *(*stat).vars.data.add(i),
130 &(*stat).base.base.location,
131 );
132 }
133 }
134 self.compile_stat_local(stat);
135 return;
136 }
137
138 let stat = rtti::ast_node_as::<AstStatFor>(node as *mut AstNode);
139 if !stat.is_null() {
140 self.compile_stat_for(stat);
141 return;
142 }
143
144 let stat = rtti::ast_node_as::<AstStatForIn>(node as *mut AstNode);
145 if !stat.is_null() {
146 self.compile_stat_for_in(stat);
147 return;
148 }
149
150 let stat = rtti::ast_node_as::<AstStatAssign>(node as *mut AstNode);
151 if !stat.is_null() {
152 self.compile_stat_assign(stat);
153 return;
154 }
155
156 let stat = rtti::ast_node_as::<AstStatCompoundAssign>(node as *mut AstNode);
157 if !stat.is_null() {
158 self.compile_stat_compound_assign(stat);
159 return;
160 }
161
162 let stat = rtti::ast_node_as::<AstStatFunction>(node as *mut AstNode);
163 if !stat.is_null() {
164 self.compile_stat_function(stat);
165 return;
166 }
167
168 let stat = rtti::ast_node_as::<AstStatLocalFunction>(node as *mut AstNode);
169 if !stat.is_null() {
170 if luaur_common::FFlag::LuauExportValueSyntax.get() && (*(*stat).name).is_exported {
171 self.check_exported_local((*stat).name, &(*stat).base.base.location);
172
173 self.ensure_export_table(stat as *mut AstNode);
174
175 let _rs = self.reg_scope_compiler();
176 let var = self.alloc_reg(stat as *mut AstNode, 1);
177 self.compile_expr_function((*stat).func, var);
178
179 let name_ref =
180 crate::functions::sref_compiler::sref_ast_name((*(*stat).name).name);
181 let cid = (*self.bytecode).add_constant_string(name_ref);
182 if cid < 0 {
183 crate::records::compile_error::CompileError::raise(
184 &(*(*stat).name).location,
185 format_args!("Exceeded constant limit; simplify the code to compile"),
186 );
187 }
188
189 let table_reg = self.get_export_table_reg(stat as *mut AstNode);
190 (*self.bytecode).emit_abc(
191 LuauOpcode::LOP_SETTABLEKS,
192 var,
193 table_reg,
194 luaur_bytecode::methods::bytecode_builder_get_string_hash::bytecode_builder_get_string_hash(name_ref) as u8,
195 );
196 (*self.bytecode).emit_aux(cid as u32);
197 } else {
198 let var = self.alloc_reg(stat as *mut AstNode, 1);
200
201 self.push_local((*stat).name, var, !0u32);
202 if luaur_common::FFlag::LuauExportValueSyntax.get() {
203 self.check_exported_local((*stat).name, &(*stat).base.base.location);
204 }
205 self.compile_expr_function((*stat).func, var);
206
207 let debugpc = (*self.bytecode).get_debug_pc();
211 self.locals.get_or_insert((*stat).name).debugpc = debugpc;
212 }
213 return;
214 }
215
216 if luaur_common::FFlag::DebugLuauUserDefinedClasses.get() {
217 let stat = rtti::ast_node_as::<AstStatClass>(node as *mut AstNode);
218 if !stat.is_null() {
219 self.compile_class_declaration(stat);
220 }
221 }
222 }
223 }
224}