Skip to main content

luaur_analysis/functions/
set_write_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_write_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.setwriteproperty: 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.setwriteproperty: 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.setwriteproperty: 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.setwriteproperty: 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.setwriteproperty: 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        if let Some(existing) = (*tftt).props.get(&key_name) {
79            if existing.is_write_only() {
80                (*tftt).props.remove(&key_name);
81            } else if let Some(prop) = (*tftt).props.get_mut(&key_name) {
82                prop.write_ty = None;
83            }
84        }
85
86        return 0;
87    }
88
89    let value = get_type_user_data(l, 3);
90    if let Some(prop) = (*tftt).props.get_mut(&key_name) {
91        prop.write_ty = Some(value);
92    } else {
93        (*tftt)
94            .props
95            .insert(key_name, TypeFunctionProperty::writeonly(value));
96    }
97
98    0
99}