luaur_compiler/methods/
compiler_compile_expr_function.rs1use 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}