Skip to main content

luaur_vm/functions/
lua_v_settable.rs

1//! Node: `cxx:Function:Luau.VM:VM/src/lvmutils.cpp:182:luaV_settable`
2//! Source: `VM/src/lvmutils.cpp:182-240` (hand-ported)
3
4use crate::functions::call_tm::call_tm;
5use crate::functions::lua_g_indexerror::luaG_indexerror;
6use crate::functions::lua_g_missingmembererror::luaG_missingmembererror;
7use crate::functions::lua_g_readonlyerror::luaG_readonlyerror;
8use crate::functions::lua_h_get::lua_h_get;
9use crate::functions::lua_t_gettmbyobj::lua_t_gettmbyobj;
10use crate::macros::fasttm::fasttm;
11use crate::macros::gval_2_slot::gval2slot;
12use crate::macros::hvalue::hvalue;
13use crate::macros::lua_c_barrier::luaC_barrier;
14use crate::macros::lua_c_barriert::luaC_barriert;
15use crate::macros::lua_g_runerror::lua_g_runerror;
16use crate::macros::lua_h_setslot::luaH_setslot;
17use crate::macros::lua_r_lookupmemberatoffset::luaR_lookupmemberatoffset;
18use crate::macros::maxtagloop::MAXTAGLOOP;
19use crate::macros::nvalue::nvalue;
20use crate::macros::objectvalue::objectvalue;
21use crate::macros::setobj::setobj;
22use crate::macros::setobj_2_class::setobj2class;
23use crate::macros::setobj_2_t::setobj2t;
24use crate::macros::ttisfunction::ttisfunction;
25use crate::macros::ttisnil::ttisnil;
26use crate::macros::ttisobject::ttisobject;
27use crate::macros::ttistable::ttistable;
28use crate::records::luau_object::LuauObject;
29use crate::type_aliases::lua_state::lua_State;
30use crate::type_aliases::stk_id::StkId;
31use crate::type_aliases::t_value::TValue;
32use crate::type_aliases::tms::TMS;
33use luaur_common::macros::luau_assert::LUAU_ASSERT;
34
35#[allow(non_snake_case)]
36pub unsafe fn lua_v_settable(
37    L: *mut lua_State,
38    mut t: *const TValue,
39    key: *mut TValue,
40    val: StkId,
41) {
42    let mut temp: TValue = core::mem::zeroed();
43    let mut loop_ = 0;
44    while loop_ < MAXTAGLOOP {
45        let mut tm: *const TValue = core::ptr::null();
46        if ttistable!(t) {
47            let h = hvalue!(t);
48
49            let oldval = lua_h_get(h, key as *const TValue);
50
51            if ttisnil!(oldval) {
52                tm = fasttm(L, (*h).metatable, TMS::TM_NEWINDEX as i32);
53            }
54
55            if !ttisnil!(oldval) || tm.is_null() {
56                if (*h).readonly != 0 {
57                    luaG_readonlyerror(L);
58                }
59
60                let newval = luaH_setslot!(L, h, oldval, key as *const TValue);
61
62                (*L).cachedslot = gval2slot!(h, newval as *const TValue);
63
64                setobj2t!(L, newval, val as *const TValue);
65                luaC_barriert!(L, h, val as *const TValue);
66                return;
67            }
68        } else if luaur_common::FFlag::DebugLuauUserDefinedClassesRuntime.get() && ttisobject!(t) {
69            let inst = &mut **objectvalue!(t) as *mut LuauObject;
70            let offset = lua_h_get((*(*inst).lclass).memberstooffset, key as *const TValue);
71            if ttisnil!(offset) {
72                luaG_missingmembererror(L, t, key as *const TValue);
73            }
74            let offsetnum = nvalue!(offset) as i32;
75            LUAU_ASSERT!(offsetnum >= 0 && offsetnum < (*(*inst).lclass).numberofallmembers);
76            if offsetnum >= (*(*inst).lclass).numberofinstancemembers {
77                luaG_indexerror(L, t, key as *const TValue);
78            }
79            setobj2class!(
80                L,
81                (*inst).members.add(offsetnum as usize),
82                val as *const TValue
83            );
84            luaC_barrier!(L, inst, val as *const TValue);
85            return;
86        } else {
87            tm = lua_t_gettmbyobj(L, t, TMS::TM_NEWINDEX);
88            if ttisnil!(tm) {
89                luaG_indexerror(L, t, key as *const TValue);
90            }
91        }
92
93        if ttisfunction!(tm) {
94            call_tm(L, tm, t, key as *const TValue, val as *const TValue);
95            return;
96        }
97        setobj!(L, &mut temp as *mut TValue, tm);
98        t = &temp as *const TValue;
99        loop_ += 1;
100    }
101    lua_g_runerror!(L, "'__newindex' chain too long; possible loop");
102}
103
104#[export_name = "luaV_settable"]
105pub unsafe extern "C" fn lua_v_settable_export(
106    L: *mut lua_State,
107    t: *const TValue,
108    key: *mut TValue,
109    val: StkId,
110) {
111    lua_v_settable(L, t, key, val);
112}
113
114#[allow(non_snake_case, unused_imports)]
115pub use lua_v_settable as luaV_settable;