// Expects: Function, followed by narg arguments, on top of the stack. // Calls pcall with traceback error handler, removes error handler. // Error is left on top of the stack. // Returns the error code, and the stack index at which the return values start. inline std::tuple<int, int> pcall_helper(lua_State * L, int narg, int nret) noexcept { PRIMER_ASSERT(lua_gettop(L) >= (1 + narg), "Not enough arguments on stack for pcall!"); PRIMER_ASSERT(lua_isfunction(L, -1 - narg), "Missing function for pcall!"); primer::get_error_handler(L); lua_insert(L, -2 - narg); const int error_handler_index = lua_absindex(L, -2 - narg); const int result_code = lua_pcall(L, narg, nret, error_handler_index); lua_remove(L, error_handler_index); return std::tuple<int, int>{result_code, error_handler_index}; }
T unsigned_to_signed(typename std::make_unsigned<T>::type x) { using U = decltype(x); constexpr T max = std::numeric_limits<T>::max(); constexpr T min = std::numeric_limits<T>::min(); if (x <= static_cast<U>(max)) { return static_cast<T>(x); } if (x >= static_cast<U>(min)) { return static_cast<T>(x - min) + min; } PRIMER_ASSERT(false, "Bad unsigned -> signed integer conversion! x = " << x); return 0; }
void fcn_call(expected<T> & result, lua_State * L, int narg) { int err_code; int results_idx; std::tie(err_code, results_idx) = detail::pcall_helper(L, narg, return_helper<T>::nrets); if (err_code != LUA_OK) { result = primer::pop_error(L, err_code); } else { return_helper<T>::pop(L, results_idx, result); } PRIMER_ASSERT(lua_gettop(L) == (results_idx - 1), "hmm stack discipline error"); }
// Expects: Function, followed by narg arguments, on top of the stack. // Calls lua_resume. If an error occurs, calls the traceback error handler, // removes error handler. Error is left on top of the stack. // Returns the error code, and the stack index at which the return values start. inline std::tuple<int, int> resume_helper(lua_State * L, int narg) noexcept { PRIMER_ASSERT(lua_gettop(L) >= (narg), "Not enough arguments on stack for resume!"); const int result_index = lua_absindex(L, -1 - narg); const int result_code = lua_resume(L, nullptr, narg); if ((result_code != LUA_OK) && (result_code != LUA_YIELD)) { primer::get_error_handler(L); lua_insert(L, -2); lua_call(L, 1, 1); } return std::tuple<int, int>{result_code, result_index}; }