Skip to main content

luaur_code_gen/functions/
forg_loop_non_table_fallback.rs

1use crate::macros::vm_reg::VM_REG;
2use luaur_vm::functions::lua_d_performcally::lua_d_performcally;
3use luaur_vm::macros::setobj_2_s::setobj_2_s as setobj2s;
4use luaur_vm::macros::ttisnil::ttisnil;
5
6use crate::type_aliases::lua_state::LuaState;
7use luaur_vm::type_aliases::t_value::TValue;
8
9pub unsafe fn forg_loop_non_table_fallback(
10    L: *mut luaur_vm::records::lua_state::lua_State,
11    insn_a: i32,
12    aux: i32,
13) -> i32 {
14    let l_ptr = L;
15    let base: *mut TValue = (*l_ptr).base;
16    let mut ra: *mut TValue = VM_REG!(insn_a, l_ptr, base);
17
18    // note: it's safe to push arguments past top for complicated reasons (see lvmexecute.cpp)
19    setobj2s!(l_ptr, ra.add(3 + 2), ra.add(2));
20    setobj2s!(l_ptr, ra.add(3 + 1), ra.add(1));
21    setobj2s!(l_ptr, ra.add(3), ra);
22
23    (*l_ptr).top = ra.add(3 + 3); // func + 2 args (state and index)
24    luaur_common::LUAU_ASSERT!((*l_ptr).top <= (*l_ptr).stack_last);
25
26    if lua_d_performcally(l_ptr, ra.add(3), aux as u8 as i32) {
27        return -1; // yield/break, caller must exit native execution
28    }
29
30    (*l_ptr).top = (*(*l_ptr).ci).top;
31
32    // recompute ra since stack might have been reallocated
33    let base = (*l_ptr).base;
34    ra = VM_REG!(insn_a, l_ptr, base);
35
36    // copy first variable back into the iteration index
37    setobj2s!(l_ptr, ra.add(2), ra.add(3));
38
39    if ttisnil!(ra.add(3)) {
40        0
41    } else {
42        1
43    }
44}
45
46#[no_mangle]
47pub unsafe extern "C" fn forgLoopNonTableFallback(
48    L: *mut luaur_vm::records::lua_state::LuaState,
49    insn_a: i32,
50    aux: i32,
51) -> i32 {
52    forg_loop_non_table_fallback(L, insn_a, aux)
53}