luaur_vm/functions/
lua_v_settable.rs1use 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;