Skip to main content

luaur_analysis/functions/
set_table_prop.rs

1use crate::functions::get_mutable_type_function_runtime_alt_g::get_mutable_type_function_type_id;
2use crate::functions::get_tag::get_tag;
3use crate::functions::get_type_function_runtime_alt_o::get_type_function_type_id;
4use crate::functions::get_type_user_data::get_type_user_data;
5use crate::records::type_function_property::TypeFunctionProperty;
6use crate::records::type_function_singleton_type::TypeFunctionSingletonType;
7use crate::records::type_function_table_type::TypeFunctionTableType;
8use crate::type_aliases::lua_state::lua_State;
9use luaur_vm::functions::lua_gettop::lua_gettop;
10use luaur_vm::functions::lua_l_error_l::lua_l_error_l;
11use luaur_vm::macros::lua_isnil::lua_isnil;
12
13pub unsafe fn set_table_prop(l: *mut lua_State) -> i32 {
14    let vm_l = l as *mut luaur_vm::records::lua_state::lua_State;
15    let argument_count = lua_gettop(vm_l);
16    if argument_count < 2 || argument_count > 3 {
17        lua_l_error_l(
18            vm_l,
19            c"%s".as_ptr(),
20            core::format_args!(
21                "type.setproperty: expected 2-3 arguments, but got {}",
22                argument_count
23            ),
24        );
25    }
26
27    let self_ty = get_type_user_data(l, 1);
28    let tftt = get_mutable_type_function_type_id::<TypeFunctionTableType>(self_ty);
29    if tftt.is_null() {
30        lua_l_error_l(
31            vm_l,
32            c"%s".as_ptr(),
33            core::format_args!(
34                "type.setproperty: expected self to be a table, but got {} instead",
35                get_tag(l, self_ty)
36            ),
37        );
38    }
39
40    if luaur_common::FFlag::LuauTypeFunctionSupportsFrozen.get() && (*self_ty).frozen {
41        lua_l_error_l(
42            vm_l,
43            c"%s".as_ptr(),
44            core::format_args!(
45                "type.setproperty: cannot be called to mutate a frozen type, use `types.copy` to make a copy"
46            ),
47        );
48    }
49
50    let key = get_type_user_data(l, 2);
51    let tfst = get_type_function_type_id::<TypeFunctionSingletonType>(key);
52    if tfst.is_null() {
53        lua_l_error_l(
54            vm_l,
55            c"%s".as_ptr(),
56            core::format_args!(
57                "type.setproperty: expected to be given a singleton type, but got {} instead",
58                get_tag(l, key)
59            ),
60        );
61    }
62
63    let tfsst = (*tfst).variant.get_if_1();
64    if tfsst.is_none() {
65        lua_l_error_l(
66            vm_l,
67            c"%s".as_ptr(),
68            core::format_args!(
69                "type.setproperty: expected to be given a string singleton type, but got {} instead",
70                get_tag(l, key)
71            ),
72        );
73    }
74
75    let key_name = tfsst.unwrap().value.clone();
76
77    if argument_count == 2 || lua_isnil!(vm_l, 3) {
78        (*tftt).props.remove(&key_name);
79        return 0;
80    }
81
82    let value = get_type_user_data(l, 3);
83    (*tftt).props.insert(
84        key_name,
85        TypeFunctionProperty {
86            read_ty: Some(value),
87            write_ty: Some(value),
88        },
89    );
90
91    0
92}