luaur_compiler/methods/
compiler_compile_unrolled_for.rs1use crate::enums::type_compiler::Type as LoopJumpType;
2use crate::enums::type_constant_folding::Type;
3use crate::functions::fold_constants::fold_constants;
4use crate::functions::undo_changes_constant_folding::undo_changes_dense_hash_map_ast_expr_constant_expr_constant_change_log;
5use crate::functions::undo_changes_constant_folding_alt_b::undo_changes_dense_hash_map_ast_local_constant_local_constant_change_log;
6use crate::records::compiler::Compiler;
7use crate::records::constant::{Constant, ConstantData};
8use crate::records::loop_jump::LoopJump;
9use luaur_ast::records::ast_node::AstNode;
10use luaur_ast::records::ast_stat::AstStat;
11use luaur_ast::records::ast_stat_for::AstStatFor;
12
13impl Compiler {
14 pub fn compile_unrolled_for(
15 &mut self,
16 stat: *mut AstStatFor,
17 trip_count: i32,
18 from: f64,
19 step: f64,
20 ) {
21 unsafe {
22 let stat_ref = &*stat;
23 let old_locals = self.local_stack.len();
24 let old_jumps = self.loop_jumps.len();
25
26 self.loops.push(crate::records::r#loop::Loop {
27 local_offset: old_locals,
28 local_offset_continue: old_locals,
29 continue_used: core::ptr::null_mut(),
30 });
31
32 let record_changes = luaur_common::FFlag::LuauCompilePropagateTableProps2.get()
33 && luaur_common::FFlag::LuauCompileFoldOptimize.get();
34
35 if record_changes {
36 self.expr_changes.clear();
37 self.local_changes.clear();
38 }
39
40 for iv in 0..trip_count {
41 *self.locstants.get_or_insert(stat_ref.var) = Constant {
42 r#type: Type::Type_Number,
43 string_length: 0,
44 data: ConstantData {
45 value_number: from + f64::from(iv) * step,
46 },
47 };
48
49 fold_constants(
50 &mut self.constants,
51 &mut self.variables,
52 &mut self.locstants,
53 self.builtins_fold,
54 self.builtins_fold_library_k,
55 self.options.library_member_constant_cb,
56 stat_ref.body as *mut AstNode,
57 &mut *self.names,
58 &self.table_constants,
59 if record_changes && iv == 0 {
60 &mut self.expr_changes as *mut _
61 } else {
62 core::ptr::null_mut()
63 },
64 if record_changes && iv == 0 {
65 &mut self.local_changes as *mut _
66 } else {
67 core::ptr::null_mut()
68 },
69 );
70
71 let iter_jumps = self.loop_jumps.len();
72 self.compile_stat(stat_ref.body as *mut AstStat);
73
74 let cont_label = (*self.bytecode).emit_label();
75
76 for i in iter_jumps..self.loop_jumps.len() {
77 if self.loop_jumps[i].r#type == LoopJumpType::Continue {
78 self.patch_jump(stat as *mut AstNode, self.loop_jumps[i].label, cont_label);
79 }
80 }
81 }
82
83 let end_label = (*self.bytecode).emit_label();
84
85 for i in old_jumps..self.loop_jumps.len() {
86 if self.loop_jumps[i].r#type == LoopJumpType::Break {
87 self.patch_jump(stat as *mut AstNode, self.loop_jumps[i].label, end_label);
88 }
89 }
90
91 self.loop_jumps.resize(
92 old_jumps,
93 LoopJump {
94 r#type: LoopJumpType::Break,
95 label: 0,
96 },
97 );
98
99 self.loops.pop();
100
101 self.locstants.get_or_insert(stat_ref.var).r#type = Type::Type_Unknown;
102
103 if record_changes {
104 undo_changes_dense_hash_map_ast_expr_constant_expr_constant_change_log(
105 &mut self.constants,
106 &self.expr_changes,
107 );
108 undo_changes_dense_hash_map_ast_local_constant_local_constant_change_log(
109 &mut self.locstants,
110 &self.local_changes,
111 );
112 } else {
113 fold_constants(
114 &mut self.constants,
115 &mut self.variables,
116 &mut self.locstants,
117 self.builtins_fold,
118 self.builtins_fold_library_k,
119 self.options.library_member_constant_cb,
120 stat_ref.body as *mut AstNode,
121 &mut *self.names,
122 &self.table_constants,
123 core::ptr::null_mut(),
124 core::ptr::null_mut(),
125 );
126 }
127 }
128 }
129}