Skip to main content

luaur_compiler/methods/
compiler_compile_expr_function.rs

1use crate::records::compiler::Compiler;
2use luaur_ast::records::ast_expr_function::AstExprFunction;
3use luaur_common::enums::luau_capture_type::LuauCaptureType;
4use luaur_common::enums::luau_opcode::LuauOpcode;
5use luaur_common::macros::luau_assert::LUAU_ASSERT;
6
7impl Compiler {
8    pub fn compile_expr_function(&mut self, expr: *mut AstExprFunction, target: u8) {
9        let f = self.functions.find(&expr).unwrap();
10        let fid = f.id;
11        let upvals = f.upvals.clone();
12        let pid = unsafe { (*self.bytecode).add_child_function(fid) };
13        if pid < 0 {
14            unsafe {
15                crate::records::compile_error::CompileError::raise(
16                    &(*expr).base.base.location,
17                    format_args!("Exceeded closure limit"),
18                );
19            }
20        }
21        self.captures.clear();
22        for uv in upvals {
23            let reg = self.get_local_reg(uv);
24            if reg >= 0 {
25                let ul = self.variables.find(&uv);
26                let immutable = ul.map_or(true, |ul| !ul.written);
27                self.captures.push(crate::records::capture::Capture {
28                    r#type: if immutable {
29                        LuauCaptureType::LCT_VAL
30                    } else {
31                        LuauCaptureType::LCT_REF
32                    },
33                    data: reg as u8,
34                });
35            } else if let Some(uc) = self.locstants.find(&uv).copied() {
36                let reg = self.alloc_reg(expr as *mut _, 1);
37                self.compile_expr_constant(expr as *mut _, &uc, reg);
38                self.captures.push(crate::records::capture::Capture {
39                    r#type: LuauCaptureType::LCT_VAL,
40                    data: reg,
41                });
42            } else {
43                let uid = self.get_upval(uv);
44                self.captures.push(crate::records::capture::Capture {
45                    r#type: LuauCaptureType::LCT_UPVAL,
46                    data: uid,
47                });
48            }
49        }
50        let mut shared = -1i16;
51        if self.options.optimization_level >= 1
52            && self.should_share_closure(expr)
53            && !self.setfenv_used
54        {
55            let cid = unsafe { (*self.bytecode).add_constant_closure(fid) };
56            if cid >= 0 && cid < 32768 {
57                shared = cid as i16;
58            }
59        }
60        unsafe {
61            if shared >= 0 {
62                (*self.bytecode).emit_ad(LuauOpcode::LOP_DUPCLOSURE, target, shared);
63            } else {
64                (*self.bytecode).emit_ad(LuauOpcode::LOP_NEWCLOSURE, target, pid);
65            }
66            for c in &self.captures {
67                (*self.bytecode).emit_abc(LuauOpcode::LOP_CAPTURE, c.r#type as u8, c.data, 0);
68            }
69        }
70    }
71}