Skip to main content

luaur_compiler/methods/
compiler_compile_unrolled_for.rs

1use 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}