Skip to main content

luaur_compiler/methods/
compiler_compile_expr_constant.rs

1use crate::enums::type_constant_folding::Type;
2use crate::functions::sref_compiler_alt_c::sref_ast_array_c_char;
3use crate::records::compile_error::CompileError;
4use crate::records::compiler::Compiler;
5use crate::records::constant::Constant;
6use luaur_ast::records::ast_expr::AstExpr;
7use luaur_common::enums::luau_opcode::LuauOpcode;
8
9use core::ffi::c_char;
10
11impl Compiler {
12    pub fn compile_expr_constant(&mut self, node: *mut AstExpr, cv: &Constant, target: u8) {
13        match cv.r#type {
14            Type::Type_Nil => unsafe {
15                (*self.bytecode).emit_abc(LuauOpcode::LOP_LOADNIL, target, 0, 0);
16            },
17            Type::Type_Boolean => {
18                let b = unsafe { cv.data.value_boolean };
19                unsafe {
20                    (*self.bytecode).emit_abc(LuauOpcode::LOP_LOADB, target, b as u8, 0);
21                }
22            }
23            Type::Type_Number => {
24                let d = unsafe { cv.data.value_number };
25
26                let fits_i16 = d >= (i16::MIN as f64)
27                    && d <= (i16::MAX as f64)
28                    && (d as i16 as f64) == d
29                    && !(d == 0.0 && d.is_sign_negative());
30
31                if fits_i16 {
32                    unsafe {
33                        (*self.bytecode).emit_ad(LuauOpcode::LOP_LOADN, target, d as i16);
34                    }
35                } else {
36                    let cid = unsafe { (*self.bytecode).add_constant_number(d) };
37                    if cid < 0 {
38                        let location = unsafe { (*node).base.location };
39                        CompileError::raise(
40                            &location,
41                            format_args!("Exceeded constant limit; simplify the code to compile"),
42                        );
43                    }
44                    self.emit_load_k(target, cid);
45                }
46            }
47            Type::Type_Integer => {
48                let l = unsafe { cv.data.value_integer64 };
49                let cid = unsafe { (*self.bytecode).add_constant_integer(l) };
50                if cid < 0 {
51                    let location = unsafe { (*node).base.location };
52                    CompileError::raise(
53                        &location,
54                        format_args!("Exceeded constant limit; simplify the code to compile"),
55                    );
56                }
57                self.emit_load_k(target, cid);
58            }
59            Type::Type_Vector => {
60                let x = unsafe { cv.data.value_vector[0] };
61                let y = unsafe { cv.data.value_vector[1] };
62                let z = unsafe { cv.data.value_vector[2] };
63                let w = unsafe { cv.data.value_vector[3] };
64
65                let cid = unsafe { (*self.bytecode).add_constant_vector(x, y, z, w) };
66                if cid < 0 {
67                    let location = unsafe { (*node).base.location };
68                    CompileError::raise(
69                        &location,
70                        format_args!("Exceeded constant limit; simplify the code to compile"),
71                    );
72                }
73                self.emit_load_k(target, cid);
74            }
75            Type::Type_String => {
76                let s = cv.get_string();
77                let cid = unsafe { (*self.bytecode).add_constant_string(sref_ast_array_c_char(s)) };
78                if cid < 0 {
79                    let location = unsafe { (*node).base.location };
80                    CompileError::raise(
81                        &location,
82                        format_args!("Exceeded constant limit; simplify the code to compile"),
83                    );
84                }
85                self.emit_load_k(target, cid);
86            }
87            _ => {
88                luaur_common::macros::luau_assert::LUAU_ASSERT!(false);
89            }
90        }
91    }
92}