Skip to main content

luaur_vm/functions/
getfunc.rs

1//! Node: `cxx:Function:Luau.VM:VM/src/lbaselib.cpp:108:getfunc`
2//!
3//! `getfunc` — resolve the function argument for `getfenv`/`setfenv`: either the
4//! explicit function at slot 1, or the function at stack `level` (via
5//! `lua_getinfo`'s `f` option, which pushes it). Used by the env builtins.
6
7use crate::functions::lua_getinfo::lua_getinfo;
8use crate::functions::lua_l_checkinteger::lua_l_checkinteger;
9use crate::functions::lua_l_optinteger::lua_l_optinteger;
10use crate::functions::lua_pushvalue::lua_pushvalue;
11use crate::macros::lua_isfunction::lua_isfunction;
12use crate::macros::lua_isnil::lua_isnil;
13use crate::macros::lua_l_argcheck::luaL_argcheck;
14use crate::macros::lua_l_argerror::luaL_argerror;
15use crate::macros::lua_l_error::luaL_error;
16use crate::records::lua_debug::LuaDebug;
17use crate::type_aliases::lua_state::lua_State;
18use core::ffi::c_int;
19
20pub fn getfunc(L: *mut lua_State, opt: i32) {
21    unsafe {
22        if lua_isfunction!(L, 1) {
23            lua_pushvalue(L, 1);
24        } else {
25            let mut ar: LuaDebug = core::mem::zeroed();
26            let level: c_int = if opt != 0 {
27                lua_l_optinteger(L, 1, 1)
28            } else {
29                lua_l_checkinteger(L, 1)
30            };
31            luaL_argcheck!(L, level >= 0, 1, "level must be non-negative");
32            if lua_getinfo(L, level, c"f".as_ptr(), &mut ar) == 0 {
33                luaL_argerror!(L, 1, "invalid level");
34            }
35            if lua_isnil!(L, -1) {
36                luaL_error!(
37                    L,
38                    "no function environment for tail call at level {}",
39                    level
40                );
41            }
42        }
43    }
44}