diff options
| author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-06-07 11:46:25 +0200 |
|---|---|---|
| committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-06-07 11:46:25 +0200 |
| commit | ee32d4281a5e59ce81d7f38f86a49fa8ff64d2c3 (patch) | |
| tree | 68c0d74ac40c6ee098abf606e3d660a862acf04f /src | |
| parent | 35d7a6bb691d7e0564cda324b3d724caf4901545 (diff) | |
| download | lanes-ee32d4281a5e59ce81d7f38f86a49fa8ff64d2c3.tar.gz lanes-ee32d4281a5e59ce81d7f38f86a49fa8ff64d2c3.tar.bz2 lanes-ee32d4281a5e59ce81d7f38f86a49fa8ff64d2c3.zip | |
Boyscouting some luaG_ functions
Diffstat (limited to 'src')
| -rw-r--r-- | src/cancel.cpp | 2 | ||||
| -rw-r--r-- | src/compat.h | 43 | ||||
| -rw-r--r-- | src/deep.cpp | 14 | ||||
| -rw-r--r-- | src/intercopycontext.cpp | 45 | ||||
| -rw-r--r-- | src/keeper.cpp | 6 | ||||
| -rw-r--r-- | src/lane.cpp | 22 | ||||
| -rw-r--r-- | src/lanes.cpp | 30 | ||||
| -rw-r--r-- | src/linda.cpp | 10 | ||||
| -rw-r--r-- | src/lindafactory.cpp | 10 | ||||
| -rw-r--r-- | src/macros_and_utils.h | 27 | ||||
| -rw-r--r-- | src/nameof.cpp | 2 | ||||
| -rw-r--r-- | src/state.cpp | 10 | ||||
| -rw-r--r-- | src/tools.cpp | 16 | ||||
| -rw-r--r-- | src/tracker.cpp | 2 | ||||
| -rw-r--r-- | src/uniquekey.h | 2 | ||||
| -rw-r--r-- | src/universe.cpp | 10 | ||||
| -rw-r--r-- | src/universe.h | 2 |
17 files changed, 129 insertions, 124 deletions
diff --git a/src/cancel.cpp b/src/cancel.cpp index 8845e9d..4205d1f 100644 --- a/src/cancel.cpp +++ b/src/cancel.cpp | |||
| @@ -186,7 +186,7 @@ CancelOp which_cancel_op(std::string_view const& opString_) | |||
| 186 | [[nodiscard]] static CancelOp which_cancel_op(lua_State* L_, int idx_) | 186 | [[nodiscard]] static CancelOp which_cancel_op(lua_State* L_, int idx_) |
| 187 | { | 187 | { |
| 188 | if (luaG_type(L_, idx_) == LuaType::STRING) { | 188 | if (luaG_type(L_, idx_) == LuaType::STRING) { |
| 189 | std::string_view const _str{ luaG_tostringview(L_, idx_) }; | 189 | std::string_view const _str{ luaG_tostring(L_, idx_) }; |
| 190 | CancelOp _op{ which_cancel_op(_str) }; | 190 | CancelOp _op{ which_cancel_op(_str) }; |
| 191 | lua_remove(L_, idx_); // argument is processed, remove it | 191 | lua_remove(L_, idx_); // argument is processed, remove it |
| 192 | if (_op == CancelOp::Invalid) { | 192 | if (_op == CancelOp::Invalid) { |
diff --git a/src/compat.h b/src/compat.h index 24a105f..8963ef7 100644 --- a/src/compat.h +++ b/src/compat.h | |||
| @@ -11,6 +11,8 @@ extern "C" | |||
| 11 | } | 11 | } |
| 12 | #endif // __cplusplus | 12 | #endif // __cplusplus |
| 13 | 13 | ||
| 14 | #include "debug.h" | ||
| 15 | |||
| 14 | // try to detect if we are building against LuaJIT or MoonJIT | 16 | // try to detect if we are building against LuaJIT or MoonJIT |
| 15 | #if defined(LUA_JITLIBNAME) | 17 | #if defined(LUA_JITLIBNAME) |
| 16 | #include "luajit.h" | 18 | #include "luajit.h" |
| @@ -302,6 +304,14 @@ inline void luaG_newlib(lua_State* const L_, luaL_Reg const (&funcs_)[N]) | |||
| 302 | 304 | ||
| 303 | // ------------------------------------------------------------------------------------------------- | 305 | // ------------------------------------------------------------------------------------------------- |
| 304 | 306 | ||
| 307 | template <typename T> | ||
| 308 | [[nodiscard]] T* luaG_newuserdatauv(lua_State* L_, int nuvalue_) | ||
| 309 | { | ||
| 310 | return static_cast<T*>(lua_newuserdatauv(L_, sizeof(T), nuvalue_)); | ||
| 311 | } | ||
| 312 | |||
| 313 | // ------------------------------------------------------------------------------------------------- | ||
| 314 | |||
| 305 | inline void luaG_registerlibfuncs(lua_State* L_, luaL_Reg const funcs_[]) | 315 | inline void luaG_registerlibfuncs(lua_State* L_, luaL_Reg const funcs_[]) |
| 306 | { | 316 | { |
| 307 | Wrap<LUA_VERSION_NUM>::luaL_setfuncs(L_, funcs_, 0); | 317 | Wrap<LUA_VERSION_NUM>::luaL_setfuncs(L_, funcs_, 0); |
| @@ -314,27 +324,50 @@ inline void luaG_setmetatable(lua_State* const L_, std::string_view const& tname | |||
| 314 | return Wrap<LUA_VERSION_NUM>::luaL_setmetatable(L_, tname_); | 324 | return Wrap<LUA_VERSION_NUM>::luaL_setmetatable(L_, tname_); |
| 315 | } | 325 | } |
| 316 | 326 | ||
| 327 | // ------------------------------------------------------------------------------------------------- | ||
| 328 | |||
| 329 | // a small helper to extract a full userdata pointer from the stack in a safe way | ||
| 330 | template <typename T> | ||
| 331 | [[nodiscard]] T* luaG_tofulluserdata(lua_State* L_, int index_) | ||
| 332 | { | ||
| 333 | LUA_ASSERT(L_, lua_isnil(L_, index_) || lua_type(L_, index_) == LUA_TUSERDATA); | ||
| 334 | return static_cast<T*>(lua_touserdata(L_, index_)); | ||
| 335 | } | ||
| 336 | |||
| 337 | // ------------------------------------------------------------------------------------------------- | ||
| 338 | |||
| 339 | template <typename T> | ||
| 340 | [[nodiscard]] auto luaG_tolightuserdata(lua_State* L_, int index_) | ||
| 341 | { | ||
| 342 | LUA_ASSERT(L_, lua_isnil(L_, index_) || lua_islightuserdata(L_, index_)); | ||
| 343 | if constexpr (std::is_pointer_v<T>) { | ||
| 344 | return static_cast<T>(lua_touserdata(L_, index_)); | ||
| 345 | } else { | ||
| 346 | return static_cast<T*>(lua_touserdata(L_, index_)); | ||
| 347 | } | ||
| 348 | } | ||
| 349 | |||
| 317 | // ################################################################################################# | 350 | // ################################################################################################# |
| 318 | 351 | ||
| 319 | // must keep as a macro as long as we do constant string concatenations | 352 | // must keep as a macro as long as we do constant string concatenations |
| 320 | #define STRINGVIEW_FMT "%.*s" | 353 | #define STRINGVIEW_FMT "%.*s" |
| 321 | 354 | ||
| 322 | // a replacement of lua_tolstring | 355 | // a replacement of lua_tolstring |
| 323 | [[nodiscard]] inline std::string_view luaG_tostringview(lua_State* const L_, int const idx_) | 356 | [[nodiscard]] inline std::string_view luaG_tostring(lua_State* const L_, int const idx_) |
| 324 | { | 357 | { |
| 325 | size_t _len{ 0 }; | 358 | size_t _len{ 0 }; |
| 326 | char const* _str{ lua_tolstring(L_, idx_, &_len) }; | 359 | char const* _str{ lua_tolstring(L_, idx_, &_len) }; |
| 327 | return std::string_view{ _str, _len }; | 360 | return std::string_view{ _str, _len }; |
| 328 | } | 361 | } |
| 329 | 362 | ||
| 330 | [[nodiscard]] inline std::string_view luaG_checkstringview(lua_State* const L_, int const idx_) | 363 | [[nodiscard]] inline std::string_view luaG_checkstring(lua_State* const L_, int const idx_) |
| 331 | { | 364 | { |
| 332 | size_t _len{ 0 }; | 365 | size_t _len{ 0 }; |
| 333 | char const* _str{ luaL_checklstring(L_, idx_, &_len) }; | 366 | char const* _str{ luaL_checklstring(L_, idx_, &_len) }; |
| 334 | return std::string_view{ _str, _len }; | 367 | return std::string_view{ _str, _len }; |
| 335 | } | 368 | } |
| 336 | 369 | ||
| 337 | [[nodiscard]] inline std::string_view luaG_optstringview(lua_State* const L_, int const idx_, std::string_view const& default_) | 370 | [[nodiscard]] inline std::string_view luaG_optstring(lua_State* const L_, int const idx_, std::string_view const& default_) |
| 338 | { | 371 | { |
| 339 | if (lua_isnoneornil(L_, idx_)) { | 372 | if (lua_isnoneornil(L_, idx_)) { |
| 340 | return default_; | 373 | return default_; |
| @@ -345,13 +378,13 @@ inline void luaG_setmetatable(lua_State* const L_, std::string_view const& tname | |||
| 345 | } | 378 | } |
| 346 | 379 | ||
| 347 | template<typename ...EXTRA> | 380 | template<typename ...EXTRA> |
| 348 | [[nodiscard]] inline std::string_view luaG_pushstringview(lua_State* const L_, std::string_view const& str_, EXTRA&&... extra_) | 381 | [[nodiscard]] inline std::string_view luaG_pushstring(lua_State* const L_, std::string_view const& str_, EXTRA&&... extra_) |
| 349 | { | 382 | { |
| 350 | if constexpr (sizeof...(EXTRA) == 0) { | 383 | if constexpr (sizeof...(EXTRA) == 0) { |
| 351 | if constexpr (LUA_VERSION_NUM == 501) { | 384 | if constexpr (LUA_VERSION_NUM == 501) { |
| 352 | // lua_pushlstring doesn't return a value in Lua 5.1 | 385 | // lua_pushlstring doesn't return a value in Lua 5.1 |
| 353 | lua_pushlstring(L_, str_.data(), str_.size()); | 386 | lua_pushlstring(L_, str_.data(), str_.size()); |
| 354 | return luaG_tostringview(L_, -1); | 387 | return luaG_tostring(L_, -1); |
| 355 | } else { | 388 | } else { |
| 356 | return std::string_view{ lua_pushlstring(L_, str_.data(), str_.size()), str_.size() }; | 389 | return std::string_view{ lua_pushlstring(L_, str_.data(), str_.size()), str_.size() }; |
| 357 | } | 390 | } |
diff --git a/src/deep.cpp b/src/deep.cpp index 0fdcb31..b6a9a22 100644 --- a/src/deep.cpp +++ b/src/deep.cpp | |||
| @@ -70,7 +70,7 @@ namespace { | |||
| 70 | */ | 70 | */ |
| 71 | [[nodiscard]] static int DeepGC(lua_State* const L_) | 71 | [[nodiscard]] static int DeepGC(lua_State* const L_) |
| 72 | { | 72 | { |
| 73 | DeepPrelude* const* const _proxy{ lua_tofulluserdata<DeepPrelude*>(L_, 1) }; | 73 | DeepPrelude* const* const _proxy{ luaG_tofulluserdata<DeepPrelude*>(L_, 1) }; |
| 74 | DeepPrelude* const _p{ *_proxy }; | 74 | DeepPrelude* const _p{ *_proxy }; |
| 75 | 75 | ||
| 76 | // can work without a universe if creating a deep userdata from some external C module when Lanes isn't loaded | 76 | // can work without a universe if creating a deep userdata from some external C module when Lanes isn't loaded |
| @@ -135,7 +135,7 @@ void DeepFactory::DeleteDeepObject(lua_State* const L_, DeepPrelude* const o_) | |||
| 135 | { | 135 | { |
| 136 | // when looking inside a keeper, we are 100% sure the object is a deep userdata | 136 | // when looking inside a keeper, we are 100% sure the object is a deep userdata |
| 137 | if (mode_ == LookupMode::FromKeeper) { | 137 | if (mode_ == LookupMode::FromKeeper) { |
| 138 | DeepPrelude* const _proxy{ *lua_tofulluserdata<DeepPrelude*>(L_, index_) }; | 138 | DeepPrelude* const _proxy{ *luaG_tofulluserdata<DeepPrelude*>(L_, index_) }; |
| 139 | // we can (and must) cast and fetch the internally stored factory | 139 | // we can (and must) cast and fetch the internally stored factory |
| 140 | return &_proxy->factory; | 140 | return &_proxy->factory; |
| 141 | } else { | 141 | } else { |
| @@ -152,7 +152,7 @@ void DeepFactory::DeleteDeepObject(lua_State* const L_, DeepPrelude* const o_) | |||
| 152 | // replace metatable with the factory pointer, if it is actually a deep userdata | 152 | // replace metatable with the factory pointer, if it is actually a deep userdata |
| 153 | LookupDeep(L_); // L_: deep ... factory|nil | 153 | LookupDeep(L_); // L_: deep ... factory|nil |
| 154 | 154 | ||
| 155 | DeepFactory* const _ret{ lua_tolightuserdata<DeepFactory>(L_, -1) }; // nullptr if not a userdata | 155 | DeepFactory* const _ret{ luaG_tolightuserdata<DeepFactory>(L_, -1) }; // nullptr if not a userdata |
| 156 | lua_pop(L_, 1); | 156 | lua_pop(L_, 1); |
| 157 | STACK_CHECK(L_, 0); | 157 | STACK_CHECK(L_, 0); |
| 158 | return _ret; | 158 | return _ret; |
| @@ -188,7 +188,7 @@ void DeepFactory::PushDeepProxy(DestState const L_, DeepPrelude* const prelude_, | |||
| 188 | STACK_GROW(L_, 7); | 188 | STACK_GROW(L_, 7); |
| 189 | 189 | ||
| 190 | // a new full userdata, fitted with the specified number of uservalue slots (always 1 for Lua < 5.4) | 190 | // a new full userdata, fitted with the specified number of uservalue slots (always 1 for Lua < 5.4) |
| 191 | DeepPrelude** const _proxy{ lua_newuserdatauv<DeepPrelude*>(L_, nuv_) }; // L_: DPC proxy | 191 | DeepPrelude** const _proxy{ luaG_newuserdatauv<DeepPrelude*>(L_, nuv_) }; // L_: DPC proxy |
| 192 | LUA_ASSERT(L_, _proxy); | 192 | LUA_ASSERT(L_, _proxy); |
| 193 | *_proxy = prelude_; | 193 | *_proxy = prelude_; |
| 194 | prelude_->refcount.fetch_add(1, std::memory_order_relaxed); // one more proxy pointing to this deep data | 194 | prelude_->refcount.fetch_add(1, std::memory_order_relaxed); // one more proxy pointing to this deep data |
| @@ -237,7 +237,7 @@ void DeepFactory::PushDeepProxy(DestState const L_, DeepPrelude* const prelude_, | |||
| 237 | raise_luaL_error(errL_, "lanes receiving deep userdata should register the 'package' library"); | 237 | raise_luaL_error(errL_, "lanes receiving deep userdata should register the 'package' library"); |
| 238 | } | 238 | } |
| 239 | 239 | ||
| 240 | std::ignore = luaG_pushstringview(L_, _modname); // L_: DPC proxy metatable require() "module" | 240 | std::ignore = luaG_pushstring(L_, _modname); // L_: DPC proxy metatable require() "module" |
| 241 | if (luaG_getfield(L_, LUA_REGISTRYINDEX, LUA_LOADED_TABLE) != LuaType::TABLE) { // L_: DPC proxy metatable require() "module" _R._LOADED | 241 | if (luaG_getfield(L_, LUA_REGISTRYINDEX, LUA_LOADED_TABLE) != LuaType::TABLE) { // L_: DPC proxy metatable require() "module" _R._LOADED |
| 242 | // no L.registry._LOADED; can this ever happen? | 242 | // no L.registry._LOADED; can this ever happen? |
| 243 | lua_pop(L_, 6); // L_: | 243 | lua_pop(L_, 6); // L_: |
| @@ -256,7 +256,7 @@ void DeepFactory::PushDeepProxy(DestState const L_, DeepPrelude* const prelude_, | |||
| 256 | LuaError const _require_result{ lua_pcall(L_, 1, 0, 0) }; // L_: DPC proxy metatable error? | 256 | LuaError const _require_result{ lua_pcall(L_, 1, 0, 0) }; // L_: DPC proxy metatable error? |
| 257 | if (_require_result != LuaError::OK) { | 257 | if (_require_result != LuaError::OK) { |
| 258 | // failed, raise the error in the proper state | 258 | // failed, raise the error in the proper state |
| 259 | raise_luaL_error(errL_, luaG_tostringview(L_, -1)); | 259 | raise_luaL_error(errL_, luaG_tostring(L_, -1)); |
| 260 | } | 260 | } |
| 261 | } | 261 | } |
| 262 | } else { // already loaded, we are happy | 262 | } else { // already loaded, we are happy |
| @@ -368,7 +368,7 @@ DeepPrelude* DeepFactory::toDeep(lua_State* const L_, int const index_) const | |||
| 368 | } | 368 | } |
| 369 | STACK_CHECK(L_, 0); | 369 | STACK_CHECK(L_, 0); |
| 370 | 370 | ||
| 371 | DeepPrelude** const _proxy{ lua_tofulluserdata<DeepPrelude*>(L_, index_) }; | 371 | DeepPrelude** const _proxy{ luaG_tofulluserdata<DeepPrelude*>(L_, index_) }; |
| 372 | return *_proxy; | 372 | return *_proxy; |
| 373 | } | 373 | } |
| 374 | 374 | ||
diff --git a/src/intercopycontext.cpp b/src/intercopycontext.cpp index f00b268..8142b6a 100644 --- a/src/intercopycontext.cpp +++ b/src/intercopycontext.cpp | |||
| @@ -100,7 +100,7 @@ THE SOFTWARE. | |||
| 100 | lua_pushvalue(L1, L1_i); // L1: ... v ... {} v | 100 | lua_pushvalue(L1, L1_i); // L1: ... v ... {} v |
| 101 | lua_rawget(L1, -2); // L1: ... v ... {} "f.q.n" | 101 | lua_rawget(L1, -2); // L1: ... v ... {} "f.q.n" |
| 102 | } | 102 | } |
| 103 | std::string_view _fqn{ luaG_tostringview(L1, -1) }; | 103 | std::string_view _fqn{ luaG_tostring(L1, -1) }; |
| 104 | DEBUGSPEW_CODE(DebugSpew(Universe::Get(L1)) << "function [C] " << _fqn << std::endl); | 104 | DEBUGSPEW_CODE(DebugSpew(Universe::Get(L1)) << "function [C] " << _fqn << std::endl); |
| 105 | // popping doesn't invalidate the pointer since this is an interned string gotten from the lookup database | 105 | // popping doesn't invalidate the pointer since this is an interned string gotten from the lookup database |
| 106 | lua_pop(L1, (mode == LookupMode::FromKeeper) ? 1 : 2); // L1: ... v ... | 106 | lua_pop(L1, (mode == LookupMode::FromKeeper) ? 1 : 2); // L1: ... v ... |
| @@ -224,7 +224,7 @@ void InterCopyContext::copy_func() const | |||
| 224 | } | 224 | } |
| 225 | 225 | ||
| 226 | { | 226 | { |
| 227 | std::string_view const _bytecode{ luaG_tostringview(L1, -1) }; // L1: ... b | 227 | std::string_view const _bytecode{ luaG_tostring(L1, -1) }; // L1: ... b |
| 228 | LUA_ASSERT(L1, !_bytecode.empty()); | 228 | LUA_ASSERT(L1, !_bytecode.empty()); |
| 229 | STACK_GROW(L2, 2); | 229 | STACK_GROW(L2, 2); |
| 230 | // Note: Line numbers seem to be taken precisely from the | 230 | // Note: Line numbers seem to be taken precisely from the |
| @@ -313,7 +313,7 @@ void InterCopyContext::lookup_native_func() const | |||
| 313 | 313 | ||
| 314 | case LookupMode::ToKeeper: | 314 | case LookupMode::ToKeeper: |
| 315 | // push a sentinel closure that holds the lookup name as upvalue | 315 | // push a sentinel closure that holds the lookup name as upvalue |
| 316 | std::ignore = luaG_pushstringview(L2, _fqn); // L1: ... f ... L2: "f.q.n" | 316 | std::ignore = luaG_pushstring(L2, _fqn); // L1: ... f ... L2: "f.q.n" |
| 317 | lua_pushcclosure(L2, func_lookup_sentinel, 1); // L1: ... f ... L2: f | 317 | lua_pushcclosure(L2, func_lookup_sentinel, 1); // L1: ... f ... L2: f |
| 318 | break; | 318 | break; |
| 319 | 319 | ||
| @@ -322,7 +322,7 @@ void InterCopyContext::lookup_native_func() const | |||
| 322 | kLookupRegKey.pushValue(L2); // L1: ... f ... L2: {} | 322 | kLookupRegKey.pushValue(L2); // L1: ... f ... L2: {} |
| 323 | STACK_CHECK(L2, 1); | 323 | STACK_CHECK(L2, 1); |
| 324 | LUA_ASSERT(L1, lua_istable(L2, -1)); | 324 | LUA_ASSERT(L1, lua_istable(L2, -1)); |
| 325 | std::ignore = luaG_pushstringview(L2, _fqn); // L1: ... f ... L2: {} "f.q.n" | 325 | std::ignore = luaG_pushstring(L2, _fqn); // L1: ... f ... L2: {} "f.q.n" |
| 326 | lua_rawget(L2, -2); // L1: ... f ... L2: {} f | 326 | lua_rawget(L2, -2); // L1: ... f ... L2: {} f |
| 327 | // nil means we don't know how to transfer stuff: user should do something | 327 | // nil means we don't know how to transfer stuff: user should do something |
| 328 | // anything other than function or table should not happen! | 328 | // anything other than function or table should not happen! |
| @@ -388,7 +388,7 @@ void InterCopyContext::copy_cached_func() const | |||
| 388 | // push a light userdata uniquely representing the function | 388 | // push a light userdata uniquely representing the function |
| 389 | lua_pushlightuserdata(L2, _aspointer); // L2: ... {cache} ... p | 389 | lua_pushlightuserdata(L2, _aspointer); // L2: ... {cache} ... p |
| 390 | 390 | ||
| 391 | //DEBUGSPEW_CODE(DebugSpew(U) << "<< ID: " << luaG_tostringview(L2, -1) << " >>" << std::endl); | 391 | //DEBUGSPEW_CODE(DebugSpew(U) << "<< ID: " << luaG_tostring(L2, -1) << " >>" << std::endl); |
| 392 | 392 | ||
| 393 | lua_pushvalue(L2, -1); // L2: ... {cache} ... p p | 393 | lua_pushvalue(L2, -1); // L2: ... {cache} ... p p |
| 394 | lua_rawget(L2, L2_cache_i); // L2: ... {cache} ... p function|nil|true | 394 | lua_rawget(L2, L2_cache_i); // L2: ... {cache} ... p function|nil|true |
| @@ -433,7 +433,7 @@ void InterCopyContext::copy_cached_func() const | |||
| 433 | 433 | ||
| 434 | case LookupMode::ToKeeper: | 434 | case LookupMode::ToKeeper: |
| 435 | // push a sentinel closure that holds the lookup name as upvalue | 435 | // push a sentinel closure that holds the lookup name as upvalue |
| 436 | std::ignore = luaG_pushstringview(L2, _fqn); // L1: ... t ... L2: "f.q.n" | 436 | std::ignore = luaG_pushstring(L2, _fqn); // L1: ... t ... L2: "f.q.n" |
| 437 | lua_pushcclosure(L2, table_lookup_sentinel, 1); // L1: ... t ... L2: f | 437 | lua_pushcclosure(L2, table_lookup_sentinel, 1); // L1: ... t ... L2: f |
| 438 | break; | 438 | break; |
| 439 | 439 | ||
| @@ -442,7 +442,7 @@ void InterCopyContext::copy_cached_func() const | |||
| 442 | kLookupRegKey.pushValue(L2); // L1: ... t ... L2: {} | 442 | kLookupRegKey.pushValue(L2); // L1: ... t ... L2: {} |
| 443 | STACK_CHECK(L2, 1); | 443 | STACK_CHECK(L2, 1); |
| 444 | LUA_ASSERT(L1, lua_istable(L2, -1)); | 444 | LUA_ASSERT(L1, lua_istable(L2, -1)); |
| 445 | std::ignore = luaG_pushstringview(L2, _fqn); // L2: {} "f.q.n" | 445 | std::ignore = luaG_pushstring(L2, _fqn); // L2: {} "f.q.n" |
| 446 | lua_rawget(L2, -2); // L2: {} t | 446 | lua_rawget(L2, -2); // L2: {} t |
| 447 | // we accept destination lookup failures in the case of transfering the Lanes body function (this will result in the source table being cloned instead) | 447 | // we accept destination lookup failures in the case of transfering the Lanes body function (this will result in the source table being cloned instead) |
| 448 | // but not when we extract something out of a keeper, as there is nothing to clone! | 448 | // but not when we extract something out of a keeper, as there is nothing to clone! |
| @@ -492,7 +492,7 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
| 492 | if (U->verboseErrors) { | 492 | if (U->verboseErrors) { |
| 493 | // for debug purposes, let's try to build a useful name | 493 | // for debug purposes, let's try to build a useful name |
| 494 | if (luaG_type(L1, _key_i) == LuaType::STRING) { | 494 | if (luaG_type(L1, _key_i) == LuaType::STRING) { |
| 495 | std::string_view const _key{ luaG_tostringview(L1, _key_i) }; | 495 | std::string_view const _key{ luaG_tostring(L1, _key_i) }; |
| 496 | size_t const _bufLen{ strlen(name) + _key.size() + 2 }; // +2 for separator dot and terminating 0 | 496 | size_t const _bufLen{ strlen(name) + _key.size() + 2 }; // +2 for separator dot and terminating 0 |
| 497 | _valPath = static_cast<char*>(alloca(_bufLen)); | 497 | _valPath = static_cast<char*>(alloca(_bufLen)); |
| 498 | sprintf(_valPath, "%s." STRINGVIEW_FMT, name, (int) _key.size(), _key.data()); | 498 | sprintf(_valPath, "%s." STRINGVIEW_FMT, name, (int) _key.size(), _key.data()); |
| @@ -597,7 +597,7 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
| 597 | // push a light userdata uniquely representing the table | 597 | // push a light userdata uniquely representing the table |
| 598 | lua_pushlightuserdata(L2, const_cast<void*>(_p)); // L1: ... t ... L2: ... p | 598 | lua_pushlightuserdata(L2, const_cast<void*>(_p)); // L1: ... t ... L2: ... p |
| 599 | 599 | ||
| 600 | //DEBUGSPEW_CODE(DebugSpew(U) << "<< ID: " << luaG_tostringview(L2, -1) << " >>" << std::endl); | 600 | //DEBUGSPEW_CODE(DebugSpew(U) << "<< ID: " << luaG_tostring(L2, -1) << " >>" << std::endl); |
| 601 | 601 | ||
| 602 | lua_rawget(L2, L2_cache_i); // L1: ... t ... L2: ... {cached|nil} | 602 | lua_rawget(L2, L2_cache_i); // L1: ... t ... L2: ... {cached|nil} |
| 603 | bool const _not_found_in_cache{ lua_isnil(L2, -1) }; | 603 | bool const _not_found_in_cache{ lua_isnil(L2, -1) }; |
| @@ -723,7 +723,7 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
| 723 | // Returns false if not a deep userdata, else true (unless an error occured) | 723 | // Returns false if not a deep userdata, else true (unless an error occured) |
| 724 | [[nodiscard]] bool InterCopyContext::tryCopyDeep() const | 724 | [[nodiscard]] bool InterCopyContext::tryCopyDeep() const |
| 725 | { | 725 | { |
| 726 | DeepFactory* const _factory{ DeepFactory::LookupFactory(L1, L1_i, mode) }; | 726 | DeepFactory* const _factory{ DeepFactory::LookupFactory(L1, L1_i, mode) }; // L1: ... deep ... |
| 727 | if (_factory == nullptr) { | 727 | if (_factory == nullptr) { |
| 728 | return false; // not a deep userdata | 728 | return false; // not a deep userdata |
| 729 | } | 729 | } |
| @@ -733,30 +733,31 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
| 733 | 733 | ||
| 734 | // extract all uservalues of the source. unfortunately, the only way to know their count is to iterate until we fail | 734 | // extract all uservalues of the source. unfortunately, the only way to know their count is to iterate until we fail |
| 735 | int _nuv{ 0 }; | 735 | int _nuv{ 0 }; |
| 736 | while (lua_getiuservalue(L1, L1_i, _nuv + 1) != LUA_TNONE) { // L1: ... u [uv]* nil | 736 | while (lua_getiuservalue(L1, L1_i, _nuv + 1) != LUA_TNONE) { // L1: ... deep ... [uv]* nil |
| 737 | ++_nuv; | 737 | ++_nuv; |
| 738 | } | 738 | } |
| 739 | // last call returned TNONE and pushed nil, that we don't need | 739 | // last call returned TNONE and pushed nil, that we don't need |
| 740 | lua_pop(L1, 1); // L1: ... u [uv]* | 740 | lua_pop(L1, 1); // L1: ... deep ... [uv]* |
| 741 | STACK_CHECK(L1, _nuv); | 741 | STACK_CHECK(L1, _nuv); |
| 742 | 742 | ||
| 743 | DeepPrelude* const _u{ *lua_tofulluserdata<DeepPrelude*>(L1, L1_i) }; | 743 | DeepPrelude* const _deep{ *luaG_tofulluserdata<DeepPrelude*>(L1, L1_i) }; |
| 744 | DeepFactory::PushDeepProxy(L2, _u, _nuv, mode, getErrL()); // L1: ... u [uv]* L2: u | 744 | DeepFactory::PushDeepProxy(L2, _deep, _nuv, mode, getErrL()); // L1: ... deep ... [uv]* L2: deep |
| 745 | 745 | ||
| 746 | // transfer all uservalues of the source in the destination | 746 | // transfer all uservalues of the source in the destination |
| 747 | { | 747 | { |
| 748 | InterCopyContext _c{ U, L2, L1, L2_cache_i, {}, VT::NORMAL, mode, name }; | 748 | InterCopyContext _c{ U, L2, L1, L2_cache_i, {}, VT::NORMAL, mode, name }; |
| 749 | int const _clone_i{ lua_gettop(L2) }; | 749 | int const _clone_i{ lua_gettop(L2) }; |
| 750 | // TODO: STACK_GROW(L2, _nuv), and same for L1 above and everywhere we use lua_getiuservalue | ||
| 750 | while (_nuv) { | 751 | while (_nuv) { |
| 751 | _c.L1_i = SourceIndex{ luaG_absindex(L1, -1) }; | 752 | _c.L1_i = SourceIndex{ luaG_absindex(L1, -1) }; |
| 752 | if (!_c.inter_copy_one()) { // L1: ... u [uv]* L2: u uv | 753 | if (!_c.inter_copy_one()) { // L1: ... deep ... [uv]* L2: deep uv |
| 753 | raise_luaL_error(getErrL(), "Cannot copy upvalue type '%s'", luaL_typename(L1, -1)); | 754 | raise_luaL_error(getErrL(), "Cannot copy upvalue type '%s'", luaL_typename(L1, -1)); |
| 754 | } | 755 | } |
| 755 | lua_pop(L1, 1); // L1: ... u [uv]* | 756 | lua_pop(L1, 1); // L1: ... deep ... [uv]* |
| 756 | // this pops the value from the stack | 757 | // this pops the value from the stack |
| 757 | lua_setiuservalue(L2, _clone_i, _nuv); // L2: u | 758 | lua_setiuservalue(L2, _clone_i, _nuv); // L2: deep |
| 758 | --_nuv; | 759 | --_nuv; |
| 759 | } | 760 | } // loop done: no uv remains on L1 stack // L1: ... deep ... |
| 760 | } | 761 | } |
| 761 | 762 | ||
| 762 | STACK_CHECK(L2, 1); | 763 | STACK_CHECK(L2, 1); |
| @@ -940,9 +941,9 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
| 940 | 941 | ||
| 941 | [[nodiscard]] bool InterCopyContext::inter_copy_string() const | 942 | [[nodiscard]] bool InterCopyContext::inter_copy_string() const |
| 942 | { | 943 | { |
| 943 | std::string_view const _s{ luaG_tostringview(L1, L1_i) }; | 944 | std::string_view const _s{ luaG_tostring(L1, L1_i) }; |
| 944 | DEBUGSPEW_CODE(DebugSpew(nullptr) << "'" << _s << "'" << std::endl); | 945 | DEBUGSPEW_CODE(DebugSpew(nullptr) << "'" << _s << "'" << std::endl); |
| 945 | std::ignore = luaG_pushstringview(L2, _s); | 946 | std::ignore = luaG_pushstring(L2, _s); |
| 946 | return true; | 947 | return true; |
| 947 | } | 948 | } |
| 948 | 949 | ||
| @@ -1188,7 +1189,7 @@ namespace { | |||
| 1188 | 1189 | ||
| 1189 | STACK_CHECK_START_REL(L1, 0); | 1190 | STACK_CHECK_START_REL(L1, 0); |
| 1190 | if (luaG_type(L1, L1_i) != LuaType::TABLE) { | 1191 | if (luaG_type(L1, L1_i) != LuaType::TABLE) { |
| 1191 | std::string_view const _msg{ luaG_pushstringview(L1, "expected package as table, got a %s", luaL_typename(L1, L1_i)) }; | 1192 | std::string_view const _msg{ luaG_pushstring(L1, "expected package as table, got a %s", luaL_typename(L1, L1_i)) }; |
| 1192 | STACK_CHECK(L1, 1); | 1193 | STACK_CHECK(L1, 1); |
| 1193 | // raise the error when copying from lane to lane, else just leave it on the stack to be raised later | 1194 | // raise the error when copying from lane to lane, else just leave it on the stack to be raised later |
| 1194 | if (mode == LookupMode::LaneBody) { | 1195 | if (mode == LookupMode::LaneBody) { |
| @@ -1224,7 +1225,7 @@ namespace { | |||
| 1224 | if (_result == InterCopyResult::Success) { | 1225 | if (_result == InterCopyResult::Success) { |
| 1225 | lua_setfield(L2, -2, _entry.data()); // set package[entry] | 1226 | lua_setfield(L2, -2, _entry.data()); // set package[entry] |
| 1226 | } else { | 1227 | } else { |
| 1227 | std::string_view const _msg{ luaG_pushstringview(L1, "failed to copy package.%s", _entry.data()) }; | 1228 | std::string_view const _msg{ luaG_pushstring(L1, "failed to copy package.%s", _entry.data()) }; |
| 1228 | // raise the error when copying from lane to lane, else just leave it on the stack to be raised later | 1229 | // raise the error when copying from lane to lane, else just leave it on the stack to be raised later |
| 1229 | if (mode == LookupMode::LaneBody) { | 1230 | if (mode == LookupMode::LaneBody) { |
| 1230 | raise_luaL_error(getErrL(), _msg); | 1231 | raise_luaL_error(getErrL(), _msg); |
diff --git a/src/keeper.cpp b/src/keeper.cpp index 87f5505..22bd67e 100644 --- a/src/keeper.cpp +++ b/src/keeper.cpp | |||
| @@ -69,7 +69,7 @@ class KeyUD | |||
| 69 | int limit{ -1 }; | 69 | int limit{ -1 }; |
| 70 | 70 | ||
| 71 | // a fifo full userdata has one uservalue, the table that holds the actual fifo contents | 71 | // a fifo full userdata has one uservalue, the table that holds the actual fifo contents |
| 72 | [[nodiscard]] static void* operator new([[maybe_unused]] size_t size_, KeeperState L_) noexcept { return lua_newuserdatauv<KeyUD>(L_, 1); } | 72 | [[nodiscard]] static void* operator new([[maybe_unused]] size_t size_, KeeperState L_) noexcept { return luaG_newuserdatauv<KeyUD>(L_, 1); } |
| 73 | // always embedded somewhere else or "in-place constructed" as a full userdata | 73 | // always embedded somewhere else or "in-place constructed" as a full userdata |
| 74 | // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception | 74 | // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception |
| 75 | static void operator delete([[maybe_unused]] void* p_, [[maybe_unused]] KeeperState L_) { LUA_ASSERT(L_, !"should never be called"); } | 75 | static void operator delete([[maybe_unused]] void* p_, [[maybe_unused]] KeeperState L_) { LUA_ASSERT(L_, !"should never be called"); } |
| @@ -117,7 +117,7 @@ KeyUD* KeyUD::Create(KeeperState const K_) | |||
| 117 | 117 | ||
| 118 | KeyUD* KeyUD::GetPtr(KeeperState const K_, int idx_) | 118 | KeyUD* KeyUD::GetPtr(KeeperState const K_, int idx_) |
| 119 | { | 119 | { |
| 120 | return lua_tofulluserdata<KeyUD>(K_, idx_); | 120 | return luaG_tofulluserdata<KeyUD>(K_, idx_); |
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | // ################################################################################################# | 123 | // ################################################################################################# |
| @@ -824,7 +824,7 @@ void Keepers::initialize(Universe& U_, lua_State* L_, int const nbKeepers_, int | |||
| 824 | keeper_.K = _K; | 824 | keeper_.K = _K; |
| 825 | 825 | ||
| 826 | // Give a name to the state | 826 | // Give a name to the state |
| 827 | std::ignore = luaG_pushstringview(_K, "Keeper #%d", i_ + 1); // L_: settings _K: "Keeper #n" | 827 | std::ignore = luaG_pushstring(_K, "Keeper #%d", i_ + 1); // L_: settings _K: "Keeper #n" |
| 828 | if constexpr (HAVE_DECODA_SUPPORT()) { | 828 | if constexpr (HAVE_DECODA_SUPPORT()) { |
| 829 | lua_pushvalue(_K, -1); // _K: "Keeper #n" Keeper #n" | 829 | lua_pushvalue(_K, -1); // _K: "Keeper #n" Keeper #n" |
| 830 | lua_setglobal(_K, "decoda_name"); // L_: settings _K: "Keeper #n" | 830 | lua_setglobal(_K, "decoda_name"); // L_: settings _K: "Keeper #n" |
diff --git a/src/lane.cpp b/src/lane.cpp index ea3edb0..de513c2 100644 --- a/src/lane.cpp +++ b/src/lane.cpp | |||
| @@ -46,7 +46,7 @@ static LUAG_FUNC(get_debug_threadname) | |||
| 46 | { | 46 | { |
| 47 | Lane* const _lane{ ToLane(L_, 1) }; | 47 | Lane* const _lane{ ToLane(L_, 1) }; |
| 48 | luaL_argcheck(L_, lua_gettop(L_) == 1, 2, "too many arguments"); | 48 | luaL_argcheck(L_, lua_gettop(L_) == 1, 2, "too many arguments"); |
| 49 | std::ignore = luaG_pushstringview(L_, _lane->debugName); | 49 | std::ignore = luaG_pushstring(L_, _lane->debugName); |
| 50 | return 1; | 50 | return 1; |
| 51 | } | 51 | } |
| 52 | 52 | ||
| @@ -80,7 +80,7 @@ static LUAG_FUNC(set_finalizer) | |||
| 80 | static LUAG_FUNC(set_debug_threadname) | 80 | static LUAG_FUNC(set_debug_threadname) |
| 81 | { | 81 | { |
| 82 | // C s_lane structure is a light userdata upvalue | 82 | // C s_lane structure is a light userdata upvalue |
| 83 | Lane* const _lane{ lua_tolightuserdata<Lane>(L_, lua_upvalueindex(1)) }; | 83 | Lane* const _lane{ luaG_tolightuserdata<Lane>(L_, lua_upvalueindex(1)) }; |
| 84 | LUA_ASSERT(L_, L_ == _lane->L); // this function is exported in a lane's state, therefore it is callable only from inside the Lane's state | 84 | LUA_ASSERT(L_, L_ == _lane->L); // this function is exported in a lane's state, therefore it is callable only from inside the Lane's state |
| 85 | lua_settop(L_, 1); | 85 | lua_settop(L_, 1); |
| 86 | STACK_CHECK_START_REL(L_, 0); | 86 | STACK_CHECK_START_REL(L_, 0); |
| @@ -300,7 +300,7 @@ static int thread_index_string(lua_State* L_) | |||
| 300 | Lane* const _lane{ ToLane(L_, kSelf) }; | 300 | Lane* const _lane{ ToLane(L_, kSelf) }; |
| 301 | LUA_ASSERT(L_, lua_gettop(L_) == 2); // L_: lane "key" | 301 | LUA_ASSERT(L_, lua_gettop(L_) == 2); // L_: lane "key" |
| 302 | 302 | ||
| 303 | std::string_view const _keystr{ luaG_tostringview(L_, kKey) }; | 303 | std::string_view const _keystr{ luaG_tostring(L_, kKey) }; |
| 304 | lua_settop(L_, 2); // keep only our original arguments on the stack | 304 | lua_settop(L_, 2); // keep only our original arguments on the stack |
| 305 | if (_keystr == "status") { | 305 | if (_keystr == "status") { |
| 306 | std::ignore = _lane->pushThreadStatus(L_); // L_: lane "key" "<status>" | 306 | std::ignore = _lane->pushThreadStatus(L_); // L_: lane "key" "<status>" |
| @@ -462,9 +462,9 @@ static constexpr RegistryUniqueKey kStackTraceRegKey{ 0x3F327747CACAA904ull }; | |||
| 462 | lua_pushstring(L_, _ar.what); // L_: some_error {} {} what | 462 | lua_pushstring(L_, _ar.what); // L_: some_error {} {} what |
| 463 | lua_setfield(L_, -2, "what"); // L_: some_error {} {} | 463 | lua_setfield(L_, -2, "what"); // L_: some_error {} {} |
| 464 | } else if (_ar.currentline > 0) { | 464 | } else if (_ar.currentline > 0) { |
| 465 | std::ignore = luaG_pushstringview(L_, "%s:%d", _ar.short_src, _ar.currentline); // L_: some_error {} "blah:blah" | 465 | std::ignore = luaG_pushstring(L_, "%s:%d", _ar.short_src, _ar.currentline); // L_: some_error {} "blah:blah" |
| 466 | } else { | 466 | } else { |
| 467 | std::ignore = luaG_pushstringview(L_, "%s:?", _ar.short_src); // L_: some_error {} "blah" | 467 | std::ignore = luaG_pushstring(L_, "%s:?", _ar.short_src); // L_: some_error {} "blah" |
| 468 | } | 468 | } |
| 469 | lua_rawseti(L_, -2, static_cast<lua_Integer>(_n)); // L_: some_error {} | 469 | lua_rawseti(L_, -2, static_cast<lua_Integer>(_n)); // L_: some_error {} |
| 470 | } | 470 | } |
| @@ -551,7 +551,7 @@ static void push_stack_trace(lua_State* L_, Lane::ErrorTraceLevel errorTraceLeve | |||
| 551 | LUA_ASSERT(L_, lua_isfunction(L_, -1)); | 551 | LUA_ASSERT(L_, lua_isfunction(L_, -1)); |
| 552 | if (lua_rc_ != LuaError::OK) { // we have an error message and an optional stack trace at the bottom of the stack | 552 | if (lua_rc_ != LuaError::OK) { // we have an error message and an optional stack trace at the bottom of the stack |
| 553 | LUA_ASSERT(L_, _finalizers_index == 2 || _finalizers_index == 3); | 553 | LUA_ASSERT(L_, _finalizers_index == 2 || _finalizers_index == 3); |
| 554 | //std::string_view const _err_msg{ luaG_tostringview(L_, 1) }; | 554 | //std::string_view const _err_msg{ luaG_tostring(L_, 1) }; |
| 555 | lua_pushvalue(L_, 1); // L_: ... finalizers lane_error finalizer err_msg | 555 | lua_pushvalue(L_, 1); // L_: ... finalizers lane_error finalizer err_msg |
| 556 | // note we don't always have a stack trace for example when kCancelError, or when we got an error that doesn't call our handler, such as LUA_ERRMEM | 556 | // note we don't always have a stack trace for example when kCancelError, or when we got an error that doesn't call our handler, such as LUA_ERRMEM |
| 557 | if (_finalizers_index == 3) { | 557 | if (_finalizers_index == 3) { |
| @@ -745,7 +745,7 @@ static void lane_main(Lane* lane_) | |||
| 745 | lua_rawget(L_, -2); // L_: ud uservalue gc_cb|nil | 745 | lua_rawget(L_, -2); // L_: ud uservalue gc_cb|nil |
| 746 | if (!lua_isnil(L_, -1)) { | 746 | if (!lua_isnil(L_, -1)) { |
| 747 | lua_remove(L_, -2); // L_: ud gc_cb|nil | 747 | lua_remove(L_, -2); // L_: ud gc_cb|nil |
| 748 | std::ignore = luaG_pushstringview(L_, _lane->debugName); // L_: ud gc_cb name | 748 | std::ignore = luaG_pushstring(L_, _lane->debugName); // L_: ud gc_cb name |
| 749 | _have_gc_cb = true; | 749 | _have_gc_cb = true; |
| 750 | } else { | 750 | } else { |
| 751 | lua_pop(L_, 2); // L_: ud | 751 | lua_pop(L_, 2); // L_: ud |
| @@ -810,7 +810,7 @@ void Lane::changeDebugName(int const nameIdx_) | |||
| 810 | // store a hidden reference in the registry to make sure the string is kept around even if a lane decides to manually change the "decoda_name" global... | 810 | // store a hidden reference in the registry to make sure the string is kept around even if a lane decides to manually change the "decoda_name" global... |
| 811 | kLaneNameRegKey.setValue(L, [idx = _nameIdx](lua_State* L_) { lua_pushvalue(L_, idx); }); // L: ... "name" ... | 811 | kLaneNameRegKey.setValue(L, [idx = _nameIdx](lua_State* L_) { lua_pushvalue(L_, idx); }); // L: ... "name" ... |
| 812 | // keep a direct pointer on the string | 812 | // keep a direct pointer on the string |
| 813 | debugName = luaG_tostringview(L, _nameIdx); | 813 | debugName = luaG_tostring(L, _nameIdx); |
| 814 | if constexpr (HAVE_DECODA_SUPPORT()) { | 814 | if constexpr (HAVE_DECODA_SUPPORT()) { |
| 815 | // to see VM name in Decoda debugger Virtual Machine window | 815 | // to see VM name in Decoda debugger Virtual Machine window |
| 816 | lua_pushvalue(L, _nameIdx); // L: ... "name" ... "name" | 816 | lua_pushvalue(L, _nameIdx); // L: ... "name" ... "name" |
| @@ -897,7 +897,7 @@ void Lane::PushMetatable(lua_State* L_) | |||
| 897 | std::string_view const _str{ threadStatusString() }; | 897 | std::string_view const _str{ threadStatusString() }; |
| 898 | LUA_ASSERT(L_, !_str.empty()); | 898 | LUA_ASSERT(L_, !_str.empty()); |
| 899 | 899 | ||
| 900 | return luaG_pushstringview(L_, _str); | 900 | return luaG_pushstring(L_, _str); |
| 901 | } | 901 | } |
| 902 | 902 | ||
| 903 | // ################################################################################################# | 903 | // ################################################################################################# |
| @@ -907,7 +907,7 @@ void Lane::PushMetatable(lua_State* L_) | |||
| 907 | std::string_view const _str{ errorTraceLevelString() }; | 907 | std::string_view const _str{ errorTraceLevelString() }; |
| 908 | LUA_ASSERT(L_, !_str.empty()); | 908 | LUA_ASSERT(L_, !_str.empty()); |
| 909 | 909 | ||
| 910 | return luaG_pushstringview(L_, _str); | 910 | return luaG_pushstring(L_, _str); |
| 911 | } | 911 | } |
| 912 | 912 | ||
| 913 | // ################################################################################################# | 913 | // ################################################################################################# |
| @@ -922,7 +922,7 @@ void Lane::securizeDebugName(lua_State* L_) | |||
| 922 | LUA_ASSERT(L_, lua_istable(L_, -1)); | 922 | LUA_ASSERT(L_, lua_istable(L_, -1)); |
| 923 | // we don't care about the actual key, so long as it's unique and can't collide with anything. | 923 | // we don't care about the actual key, so long as it's unique and can't collide with anything. |
| 924 | lua_newtable(L_); // L_: lane ... {uv} {} | 924 | lua_newtable(L_); // L_: lane ... {uv} {} |
| 925 | debugName = luaG_pushstringview(L_, debugName); // L_: lane ... {uv} {} name | 925 | debugName = luaG_pushstring(L_, debugName); // L_: lane ... {uv} {} name |
| 926 | lua_rawset(L_, -3); // L_: lane ... {uv} | 926 | lua_rawset(L_, -3); // L_: lane ... {uv} |
| 927 | lua_pop(L_, 1); // L_: lane | 927 | lua_pop(L_, 1); // L_: lane |
| 928 | STACK_CHECK(L_, 0); | 928 | STACK_CHECK(L_, 0); |
diff --git a/src/lanes.cpp b/src/lanes.cpp index 96d4ecd..a7631bb 100644 --- a/src/lanes.cpp +++ b/src/lanes.cpp | |||
| @@ -169,7 +169,7 @@ LUAG_FUNC(sleep) | |||
| 169 | lua_pushcfunction(L_, LG_linda_receive); // L_: duration|nil receive() | 169 | lua_pushcfunction(L_, LG_linda_receive); // L_: duration|nil receive() |
| 170 | STACK_CHECK_START_REL(L_, 0); // we pushed the function we intend to call, now prepare the arguments | 170 | STACK_CHECK_START_REL(L_, 0); // we pushed the function we intend to call, now prepare the arguments |
| 171 | _U->timerLinda->push(L_); // L_: duration|nil receive() timerLinda | 171 | _U->timerLinda->push(L_); // L_: duration|nil receive() timerLinda |
| 172 | if (luaG_tostringview(L_, 1) == "indefinitely") { | 172 | if (luaG_tostring(L_, 1) == "indefinitely") { |
| 173 | lua_pushnil(L_); // L_: duration? receive() timerLinda nil | 173 | lua_pushnil(L_); // L_: duration? receive() timerLinda nil |
| 174 | } else if (lua_isnoneornil(L_, 1)) { | 174 | } else if (lua_isnoneornil(L_, 1)) { |
| 175 | lua_pushnumber(L_, 0); // L_: duration? receive() timerLinda 0 | 175 | lua_pushnumber(L_, 0); // L_: duration? receive() timerLinda 0 |
| @@ -179,7 +179,7 @@ LUAG_FUNC(sleep) | |||
| 179 | else { | 179 | else { |
| 180 | lua_pushnumber(L_, lua_tonumber(L_, 1)); // L_: duration? receive() timerLinda duration | 180 | lua_pushnumber(L_, lua_tonumber(L_, 1)); // L_: duration? receive() timerLinda duration |
| 181 | } | 181 | } |
| 182 | std::ignore = luaG_pushstringview(L_, "ac100de1-a696-4619-b2f0-a26de9d58ab8"); // L_: duration? receive() timerLinda duration key | 182 | std::ignore = luaG_pushstring(L_, "ac100de1-a696-4619-b2f0-a26de9d58ab8"); // L_: duration? receive() timerLinda duration key |
| 183 | STACK_CHECK(L_, 3); // 3 arguments ready | 183 | STACK_CHECK(L_, 3); // 3 arguments ready |
| 184 | lua_call(L_, 3, LUA_MULTRET); // timerLinda:receive(duration,key) // L_: duration? result... | 184 | lua_call(L_, 3, LUA_MULTRET); // timerLinda:receive(duration,key) // L_: duration? result... |
| 185 | return lua_gettop(L_) - 1; | 185 | return lua_gettop(L_) - 1; |
| @@ -193,7 +193,7 @@ LUAG_FUNC(sleep) | |||
| 193 | // upvalue[1]: _G.require | 193 | // upvalue[1]: _G.require |
| 194 | LUAG_FUNC(require) | 194 | LUAG_FUNC(require) |
| 195 | { | 195 | { |
| 196 | std::string_view const _name{ luaG_tostringview(L_, 1) }; // L_: "name" ... | 196 | std::string_view const _name{ luaG_tostring(L_, 1) }; // L_: "name" ... |
| 197 | int const _nargs{ lua_gettop(L_) }; | 197 | int const _nargs{ lua_gettop(L_) }; |
| 198 | DEBUGSPEW_CODE(Universe * _U{ Universe::Get(L_) }); | 198 | DEBUGSPEW_CODE(Universe * _U{ Universe::Get(L_) }); |
| 199 | STACK_CHECK_START_REL(L_, 0); | 199 | STACK_CHECK_START_REL(L_, 0); |
| @@ -215,7 +215,7 @@ LUAG_FUNC(require) | |||
| 215 | // lanes.register( "modname", module) | 215 | // lanes.register( "modname", module) |
| 216 | LUAG_FUNC(register) | 216 | LUAG_FUNC(register) |
| 217 | { | 217 | { |
| 218 | std::string_view const _name{ luaG_checkstringview(L_, 1) }; | 218 | std::string_view const _name{ luaG_checkstring(L_, 1) }; |
| 219 | LuaType const _mod_type{ luaG_type(L_, 2) }; | 219 | LuaType const _mod_type{ luaG_type(L_, 2) }; |
| 220 | // ignore extra parameters, just in case | 220 | // ignore extra parameters, just in case |
| 221 | lua_settop(L_, 2); | 221 | lua_settop(L_, 2); |
| @@ -265,7 +265,7 @@ LUAG_FUNC(lane_new) | |||
| 265 | Universe* const _U{ Universe::Get(L_) }; | 265 | Universe* const _U{ Universe::Get(L_) }; |
| 266 | DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: setup" << std::endl); | 266 | DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: setup" << std::endl); |
| 267 | 267 | ||
| 268 | std::optional<std::string_view> _libs_str{ lua_isnil(L_, kLibsIdx) ? std::nullopt : std::make_optional(luaG_tostringview(L_, kLibsIdx)) }; | 268 | std::optional<std::string_view> _libs_str{ lua_isnil(L_, kLibsIdx) ? std::nullopt : std::make_optional(luaG_tostring(L_, kLibsIdx)) }; |
| 269 | lua_State* const _L2{ state::NewLaneState(_U, SourceState{ L_ }, _libs_str) }; // L_: [fixed] ... L2: | 269 | lua_State* const _L2{ state::NewLaneState(_U, SourceState{ L_ }, _libs_str) }; // L_: [fixed] ... L2: |
| 270 | STACK_CHECK_START_REL(_L2, 0); | 270 | STACK_CHECK_START_REL(_L2, 0); |
| 271 | 271 | ||
| @@ -318,7 +318,7 @@ LUAG_FUNC(lane_new) | |||
| 318 | DEBUGSPEW_CODE(DebugSpew(lane->U) << "lane_new: preparing lane userdata" << std::endl); | 318 | DEBUGSPEW_CODE(DebugSpew(lane->U) << "lane_new: preparing lane userdata" << std::endl); |
| 319 | STACK_CHECK_START_REL(L, 0); | 319 | STACK_CHECK_START_REL(L, 0); |
| 320 | // a Lane full userdata needs a single uservalue | 320 | // a Lane full userdata needs a single uservalue |
| 321 | Lane** const _ud{ lua_newuserdatauv<Lane*>(L, 1) }; // L: ... lane | 321 | Lane** const _ud{ luaG_newuserdatauv<Lane*>(L, 1) }; // L: ... lane |
| 322 | *_ud = lane; // don't forget to store the pointer in the userdata! | 322 | *_ud = lane; // don't forget to store the pointer in the userdata! |
| 323 | 323 | ||
| 324 | // Set metatable for the userdata | 324 | // Set metatable for the userdata |
| @@ -344,18 +344,16 @@ LUAG_FUNC(lane_new) | |||
| 344 | lua_State* _L2{ lane->L }; | 344 | lua_State* _L2{ lane->L }; |
| 345 | STACK_CHECK_START_REL(_L2, 0); | 345 | STACK_CHECK_START_REL(_L2, 0); |
| 346 | int const _name_idx{ lua_isnoneornil(L, kNameIdx) ? 0 : kNameIdx }; | 346 | int const _name_idx{ lua_isnoneornil(L, kNameIdx) ? 0 : kNameIdx }; |
| 347 | std::string_view const _debugName{ (_name_idx > 0) ? luaG_tostringview(L, _name_idx) : std::string_view{} }; | 347 | std::string_view const _debugName{ (_name_idx > 0) ? luaG_tostring(L, _name_idx) : std::string_view{} }; |
| 348 | if (!_debugName.empty()) | 348 | if (!_debugName.empty()) |
| 349 | { | 349 | { |
| 350 | if (_debugName != "auto") { | 350 | if (_debugName != "auto") { |
| 351 | std::ignore = luaG_pushstringview(_L2, _debugName); // L: ... lane L2: "<name>" | 351 | std::ignore = luaG_pushstring(_L2, _debugName); // L: ... lane L2: "<name>" |
| 352 | } else { | 352 | } else { |
| 353 | lua_Debug _ar; | 353 | lua_Debug _ar; |
| 354 | lua_pushvalue(L, 1); // L: ... lane func | 354 | lua_pushvalue(L, 1); // L: ... lane func |
| 355 | lua_getinfo(L, ">S", &_ar); // L: ... lane | 355 | lua_getinfo(L, ">S", &_ar); // L: ... lane |
| 356 | std::ignore = luaG_pushstringview( | 356 | std::ignore = luaG_pushstring(_L2, "%s:%d", _ar.short_src, _ar.linedefined); // L: ... lane L2: "<name>" |
| 357 | _L2, "%s:%d", _ar.short_src, _ar.linedefined | ||
| 358 | ); // L: ... lane L2: "<name>" | ||
| 359 | } | 357 | } |
| 360 | lane->changeDebugName(-1); | 358 | lane->changeDebugName(-1); |
| 361 | lua_pop(_L2, 1); // L: ... lane L2: | 359 | lua_pop(_L2, 1); // L: ... lane L2: |
| @@ -424,7 +422,7 @@ LUAG_FUNC(lane_new) | |||
| 424 | raise_luaL_error(L_, "required module list should be a list of strings"); | 422 | raise_luaL_error(L_, "required module list should be a list of strings"); |
| 425 | } else { | 423 | } else { |
| 426 | // require the module in the target state, and populate the lookup table there too | 424 | // require the module in the target state, and populate the lookup table there too |
| 427 | std::string_view const _name{ luaG_tostringview(L_, -1) }; | 425 | std::string_view const _name{ luaG_tostring(L_, -1) }; |
| 428 | DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: require '" << _name << "'" << std::endl); | 426 | DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: require '" << _name << "'" << std::endl); |
| 429 | 427 | ||
| 430 | // require the module in the target lane | 428 | // require the module in the target lane |
| @@ -433,7 +431,7 @@ LUAG_FUNC(lane_new) | |||
| 433 | lua_pop(_L2, 1); // L_: [fixed] args... n "modname" L2: | 431 | lua_pop(_L2, 1); // L_: [fixed] args... n "modname" L2: |
| 434 | raise_luaL_error(L_, "cannot pre-require modules without loading 'package' library first"); | 432 | raise_luaL_error(L_, "cannot pre-require modules without loading 'package' library first"); |
| 435 | } else { | 433 | } else { |
| 436 | std::ignore = luaG_pushstringview(_L2, _name); // L_: [fixed] args... n "modname" L2: require() name | 434 | std::ignore = luaG_pushstring(_L2, _name); // L_: [fixed] args... n "modname" L2: require() name |
| 437 | LuaError const _rc{ lua_pcall(_L2, 1, 1, 0) }; // L_: [fixed] args... n "modname" L2: ret/errcode | 435 | LuaError const _rc{ lua_pcall(_L2, 1, 1, 0) }; // L_: [fixed] args... n "modname" L2: ret/errcode |
| 438 | if (_rc != LuaError::OK) { | 436 | if (_rc != LuaError::OK) { |
| 439 | // propagate error to main state if any | 437 | // propagate error to main state if any |
| @@ -656,7 +654,7 @@ LUAG_FUNC(configure) | |||
| 656 | 654 | ||
| 657 | Universe* _U{ Universe::Get(L_) }; | 655 | Universe* _U{ Universe::Get(L_) }; |
| 658 | bool const _from_master_state{ _U == nullptr }; | 656 | bool const _from_master_state{ _U == nullptr }; |
| 659 | std::string_view const _name{ luaG_checkstringview(L_, lua_upvalueindex(1)) }; | 657 | std::string_view const _name{ luaG_checkstring(L_, lua_upvalueindex(1)) }; |
| 660 | LUA_ASSERT(L_, luaG_type(L_, 1) == LuaType::TABLE); | 658 | LUA_ASSERT(L_, luaG_type(L_, 1) == LuaType::TABLE); |
| 661 | 659 | ||
| 662 | STACK_GROW(L_, 4); | 660 | STACK_GROW(L_, 4); |
| @@ -667,7 +665,7 @@ LUAG_FUNC(configure) | |||
| 667 | 665 | ||
| 668 | if (_U == nullptr) { | 666 | if (_U == nullptr) { |
| 669 | // store a hidden reference in the registry to make sure the string is kept around even if a lane decides to manually change the "decoda_name" global... | 667 | // store a hidden reference in the registry to make sure the string is kept around even if a lane decides to manually change the "decoda_name" global... |
| 670 | kLaneNameRegKey.setValue(L_, [](lua_State* L_) { std::ignore = luaG_pushstringview(L_, "main"); }); | 668 | kLaneNameRegKey.setValue(L_, [](lua_State* L_) { std::ignore = luaG_pushstring(L_, "main"); }); |
| 671 | 669 | ||
| 672 | // create the universe | 670 | // create the universe |
| 673 | _U = Universe::Create(L_); // L_: settings universe | 671 | _U = Universe::Create(L_); // L_: settings universe |
| @@ -707,7 +705,7 @@ LUAG_FUNC(configure) | |||
| 707 | lua_pushcclosure(L_, LG_require, 1); // L_: settings M lanes.require | 705 | lua_pushcclosure(L_, LG_require, 1); // L_: settings M lanes.require |
| 708 | lua_setfield(L_, -2, "require"); // L_: settings M | 706 | lua_setfield(L_, -2, "require"); // L_: settings M |
| 709 | 707 | ||
| 710 | std::ignore = luaG_pushstringview( | 708 | std::ignore = luaG_pushstring( |
| 711 | L_, | 709 | L_, |
| 712 | "%d.%d.%d", | 710 | "%d.%d.%d", |
| 713 | LANES_VERSION_MAJOR, | 711 | LANES_VERSION_MAJOR, |
diff --git a/src/linda.cpp b/src/linda.cpp index 031eea0..e4ae3f4 100644 --- a/src/linda.cpp +++ b/src/linda.cpp | |||
| @@ -81,13 +81,13 @@ template <bool OPT> | |||
| 81 | { | 81 | { |
| 82 | Linda* const _linda{ ToLinda<OPT>(L_, idx_) }; | 82 | Linda* const _linda{ ToLinda<OPT>(L_, idx_) }; |
| 83 | if (_linda != nullptr) { | 83 | if (_linda != nullptr) { |
| 84 | std::ignore = luaG_pushstringview(L_, "Linda: "); | 84 | std::ignore = luaG_pushstring(L_, "Linda: "); |
| 85 | std::string_view const _lindaName{ _linda->getName() }; | 85 | std::string_view const _lindaName{ _linda->getName() }; |
| 86 | if (!_lindaName.empty()) { | 86 | if (!_lindaName.empty()) { |
| 87 | std::ignore = luaG_pushstringview(L_, _lindaName); | 87 | std::ignore = luaG_pushstring(L_, _lindaName); |
| 88 | } else { | 88 | } else { |
| 89 | // obfuscate the pointer so that we can't read the value with our eyes out of a script | 89 | // obfuscate the pointer so that we can't read the value with our eyes out of a script |
| 90 | std::ignore = luaG_pushstringview(L_, "%p", std::bit_cast<uintptr_t>(_linda) ^ kConfigRegKey.storage); | 90 | std::ignore = luaG_pushstring(L_, "%p", std::bit_cast<uintptr_t>(_linda) ^ kConfigRegKey.storage); |
| 91 | } | 91 | } |
| 92 | lua_concat(L_, 2); | 92 | lua_concat(L_, 2); |
| 93 | return 1; | 93 | return 1; |
| @@ -252,7 +252,7 @@ void Linda::setName(std::string_view const& name_) | |||
| 252 | LUAG_FUNC(linda_cancel) | 252 | LUAG_FUNC(linda_cancel) |
| 253 | { | 253 | { |
| 254 | Linda* const _linda{ ToLinda<false>(L_, 1) }; | 254 | Linda* const _linda{ ToLinda<false>(L_, 1) }; |
| 255 | std::string_view const _who{ luaG_optstringview(L_, 2, "both") }; | 255 | std::string_view const _who{ luaG_optstring(L_, 2, "both") }; |
| 256 | // make sure we got 2 arguments: the linda and the cancellation mode | 256 | // make sure we got 2 arguments: the linda and the cancellation mode |
| 257 | luaL_argcheck(L_, lua_gettop(L_) <= 2, 2, "wrong number of arguments"); | 257 | luaL_argcheck(L_, lua_gettop(L_) <= 2, 2, "wrong number of arguments"); |
| 258 | 258 | ||
| @@ -564,7 +564,7 @@ LUAG_FUNC(linda_receive) | |||
| 564 | if (_nbPushed == 0) { | 564 | if (_nbPushed == 0) { |
| 565 | // not enough data in the linda slot to fulfill the request, return nil, "timeout" | 565 | // not enough data in the linda slot to fulfill the request, return nil, "timeout" |
| 566 | lua_pushnil(L_); | 566 | lua_pushnil(L_); |
| 567 | std::ignore = luaG_pushstringview(L_, "timeout"); | 567 | std::ignore = luaG_pushstring(L_, "timeout"); |
| 568 | return 2; | 568 | return 2; |
| 569 | } | 569 | } |
| 570 | return _nbPushed; | 570 | return _nbPushed; |
diff --git a/src/lindafactory.cpp b/src/lindafactory.cpp index 68cb471..8622c12 100644 --- a/src/lindafactory.cpp +++ b/src/lindafactory.cpp | |||
| @@ -114,14 +114,14 @@ DeepPrelude* LindaFactory::newDeepObjectInternal(lua_State* const L_) const | |||
| 114 | 114 | ||
| 115 | case 1: // 1 parameter, either a name or a group | 115 | case 1: // 1 parameter, either a name or a group |
| 116 | if (luaG_type(L_, -1) == LuaType::STRING) { | 116 | if (luaG_type(L_, -1) == LuaType::STRING) { |
| 117 | _linda_name = luaG_tostringview(L_, -1); | 117 | _linda_name = luaG_tostring(L_, -1); |
| 118 | } else { | 118 | } else { |
| 119 | _linda_group = LindaGroup{ static_cast<int>(lua_tointeger(L_, -1)) }; | 119 | _linda_group = LindaGroup{ static_cast<int>(lua_tointeger(L_, -1)) }; |
| 120 | } | 120 | } |
| 121 | break; | 121 | break; |
| 122 | 122 | ||
| 123 | case 2: // 2 parameters, a name and group, in that order | 123 | case 2: // 2 parameters, a name and group, in that order |
| 124 | _linda_name = luaG_tostringview(L_, -2); | 124 | _linda_name = luaG_tostring(L_, -2); |
| 125 | _linda_group = LindaGroup{ static_cast<int>(lua_tointeger(L_, -1)) }; | 125 | _linda_group = LindaGroup{ static_cast<int>(lua_tointeger(L_, -1)) }; |
| 126 | break; | 126 | break; |
| 127 | } | 127 | } |
| @@ -131,12 +131,12 @@ DeepPrelude* LindaFactory::newDeepObjectInternal(lua_State* const L_) const | |||
| 131 | lua_Debug _ar; | 131 | lua_Debug _ar; |
| 132 | if (lua_getstack(L_, 1, &_ar) == 1) { // 1 because we want the name of the function that called lanes.linda (where we currently are) | 132 | if (lua_getstack(L_, 1, &_ar) == 1) { // 1 because we want the name of the function that called lanes.linda (where we currently are) |
| 133 | lua_getinfo(L_, "Sln", &_ar); | 133 | lua_getinfo(L_, "Sln", &_ar); |
| 134 | _linda_name = luaG_pushstringview(L_, "%s:%d", _ar.short_src, _ar.currentline); | 134 | _linda_name = luaG_pushstring(L_, "%s:%d", _ar.short_src, _ar.currentline); |
| 135 | } else { | 135 | } else { |
| 136 | _linda_name = luaG_pushstringview(L_, "<unresolved>"); | 136 | _linda_name = luaG_pushstring(L_, "<unresolved>"); |
| 137 | } | 137 | } |
| 138 | // since the name is not empty, it is at slot 1, and we can replace "auto" with the result, just in case | 138 | // since the name is not empty, it is at slot 1, and we can replace "auto" with the result, just in case |
| 139 | LUA_ASSERT(L_, luaG_tostringview(L_, 1) == "auto"); | 139 | LUA_ASSERT(L_, luaG_tostring(L_, 1) == "auto"); |
| 140 | lua_replace(L_, 1); | 140 | lua_replace(L_, 1); |
| 141 | } | 141 | } |
| 142 | 142 | ||
diff --git a/src/macros_and_utils.h b/src/macros_and_utils.h index 338e389..3e0b425 100644 --- a/src/macros_and_utils.h +++ b/src/macros_and_utils.h | |||
| @@ -31,33 +31,6 @@ inline void STACK_GROW(lua_State* L_, int n_) | |||
| 31 | 31 | ||
| 32 | // ################################################################################################# | 32 | // ################################################################################################# |
| 33 | 33 | ||
| 34 | // a small helper to extract a full userdata pointer from the stack in a safe way | ||
| 35 | template <typename T> | ||
| 36 | [[nodiscard]] T* lua_tofulluserdata(lua_State* L_, int index_) | ||
| 37 | { | ||
| 38 | LUA_ASSERT(L_, lua_isnil(L_, index_) || lua_type(L_, index_) == LUA_TUSERDATA); | ||
| 39 | return static_cast<T*>(lua_touserdata(L_, index_)); | ||
| 40 | } | ||
| 41 | |||
| 42 | template <typename T> | ||
| 43 | [[nodiscard]] auto lua_tolightuserdata(lua_State* L_, int index_) | ||
| 44 | { | ||
| 45 | LUA_ASSERT(L_, lua_isnil(L_, index_) || lua_islightuserdata(L_, index_)); | ||
| 46 | if constexpr (std::is_pointer_v<T>) { | ||
| 47 | return static_cast<T>(lua_touserdata(L_, index_)); | ||
| 48 | } else { | ||
| 49 | return static_cast<T*>(lua_touserdata(L_, index_)); | ||
| 50 | } | ||
| 51 | } | ||
| 52 | |||
| 53 | template <typename T> | ||
| 54 | [[nodiscard]] T* lua_newuserdatauv(lua_State* L_, int nuvalue_) | ||
| 55 | { | ||
| 56 | return static_cast<T*>(lua_newuserdatauv(L_, sizeof(T), nuvalue_)); | ||
| 57 | } | ||
| 58 | |||
| 59 | // ################################################################################################# | ||
| 60 | |||
| 61 | using lua_Duration = std::chrono::template duration<lua_Number>; | 34 | using lua_Duration = std::chrono::template duration<lua_Number>; |
| 62 | 35 | ||
| 63 | // ################################################################################################# | 36 | // ################################################################################################# |
diff --git a/src/nameof.cpp b/src/nameof.cpp index 8e79fda..6c968d5 100644 --- a/src/nameof.cpp +++ b/src/nameof.cpp | |||
| @@ -60,7 +60,7 @@ THE SOFTWARE. | |||
| 60 | // scan table contents | 60 | // scan table contents |
| 61 | lua_pushnil(L_); // L_: o "r" {c} {fqn} ... {?} nil | 61 | lua_pushnil(L_); // L_: o "r" {c} {fqn} ... {?} nil |
| 62 | while (lua_next(L_, -2)) { // L_: o "r" {c} {fqn} ... {?} k v | 62 | while (lua_next(L_, -2)) { // L_: o "r" {c} {fqn} ... {?} k v |
| 63 | // std::string_view const _strKey{ (luaG_type(L_, -2) == LuaType::STRING) ? luaG_tostringview(L_, -2) : "" }; // only for debugging | 63 | // std::string_view const _strKey{ (luaG_type(L_, -2) == LuaType::STRING) ? luaG_tostring(L_, -2) : "" }; // only for debugging |
| 64 | // lua_Number const numKey = (luaG_type(L_, -2) == LuaType::NUMBER) ? lua_tonumber(L_, -2) : -6666; // only for debugging | 64 | // lua_Number const numKey = (luaG_type(L_, -2) == LuaType::NUMBER) ? lua_tonumber(L_, -2) : -6666; // only for debugging |
| 65 | STACK_CHECK(L_, 2); | 65 | STACK_CHECK(L_, 2); |
| 66 | // append key name to fqn stack | 66 | // append key name to fqn stack |
diff --git a/src/state.cpp b/src/state.cpp index 47e31c3..cafabf1 100644 --- a/src/state.cpp +++ b/src/state.cpp | |||
| @@ -183,7 +183,7 @@ namespace state { | |||
| 183 | STACK_CHECK(L_, 1); | 183 | STACK_CHECK(L_, 1); |
| 184 | // capture error and raise it in caller state | 184 | // capture error and raise it in caller state |
| 185 | std::string_view const _stateType{ mode_ == LookupMode::LaneBody ? "lane" : "keeper" }; | 185 | std::string_view const _stateType{ mode_ == LookupMode::LaneBody ? "lane" : "keeper" }; |
| 186 | std::ignore = luaG_pushstringview(L_, _stateType); // L_: on_state_create() "<type>" | 186 | std::ignore = luaG_pushstring(L_, _stateType); // L_: on_state_create() "<type>" |
| 187 | if (lua_pcall(L_, 1, 0, 0) != LUA_OK) { | 187 | if (lua_pcall(L_, 1, 0, 0) != LUA_OK) { |
| 188 | raise_luaL_error(from_, "%s failed: \"%s\"", kOnStateCreate, lua_isstring(L_, -1) ? lua_tostring(L_, -1) : luaG_typename(L_, luaG_type(L_, -1))); | 188 | raise_luaL_error(from_, "%s failed: \"%s\"", kOnStateCreate, lua_isstring(L_, -1) ? lua_tostring(L_, -1) : luaG_typename(L_, luaG_type(L_, -1))); |
| 189 | } | 189 | } |
| @@ -204,7 +204,7 @@ namespace state { | |||
| 204 | if (U->provideAllocator != nullptr) { // we have a function we can call to obtain an allocator | 204 | if (U->provideAllocator != nullptr) { // we have a function we can call to obtain an allocator |
| 205 | lua_pushcclosure(from, U->provideAllocator, 0); | 205 | lua_pushcclosure(from, U->provideAllocator, 0); |
| 206 | lua_call(from, 0, 1); | 206 | lua_call(from, 0, 1); |
| 207 | AllocatorDefinition* const _def{ lua_tofulluserdata<AllocatorDefinition>(from, -1) }; | 207 | AllocatorDefinition* const _def{ luaG_tofulluserdata<AllocatorDefinition>(from, -1) }; |
| 208 | lua_State* const _L{ lua_newstate(_def->allocF, _def->allocUD) }; | 208 | lua_State* const _L{ lua_newstate(_def->allocF, _def->allocUD) }; |
| 209 | lua_pop(from, 1); | 209 | lua_pop(from, 1); |
| 210 | return _L; | 210 | return _L; |
| @@ -364,19 +364,19 @@ namespace state { | |||
| 364 | kLookupRegKey.pushValue(_L); // L: {} | 364 | kLookupRegKey.pushValue(_L); // L: {} |
| 365 | lua_pushnil(_L); // L: {} nil | 365 | lua_pushnil(_L); // L: {} nil |
| 366 | while (lua_next(_L, -2)) { // L: {} k v | 366 | while (lua_next(_L, -2)) { // L: {} k v |
| 367 | std::ignore = luaG_pushstringview(_L, "["); // L: {} k v "[" | 367 | std::ignore = luaG_pushstring(_L, "["); // L: {} k v "[" |
| 368 | 368 | ||
| 369 | lua_getglobal(_L, "tostring"); // L: {} k v "[" tostring | 369 | lua_getglobal(_L, "tostring"); // L: {} k v "[" tostring |
| 370 | lua_pushvalue(_L, -4); // L: {} k v "[" tostring k | 370 | lua_pushvalue(_L, -4); // L: {} k v "[" tostring k |
| 371 | lua_call(_L, 1, 1); // L: {} k v "[" 'k' | 371 | lua_call(_L, 1, 1); // L: {} k v "[" 'k' |
| 372 | 372 | ||
| 373 | std::ignore = luaG_pushstringview(_L, "] = "); // L: {} k v "[" 'k' "] = " | 373 | std::ignore = luaG_pushstring(_L, "] = "); // L: {} k v "[" 'k' "] = " |
| 374 | 374 | ||
| 375 | lua_getglobal(_L, "tostring"); // L: {} k v "[" 'k' "] = " tostring | 375 | lua_getglobal(_L, "tostring"); // L: {} k v "[" 'k' "] = " tostring |
| 376 | lua_pushvalue(_L, -5); // L: {} k v "[" 'k' "] = " tostring v | 376 | lua_pushvalue(_L, -5); // L: {} k v "[" 'k' "] = " tostring v |
| 377 | lua_call(_L, 1, 1); // L: {} k v "[" 'k' "] = " 'v' | 377 | lua_call(_L, 1, 1); // L: {} k v "[" 'k' "] = " 'v' |
| 378 | lua_concat(_L, 4); // L: {} k v "[k] = v" | 378 | lua_concat(_L, 4); // L: {} k v "[k] = v" |
| 379 | DEBUGSPEW_CODE(DebugSpew(U_) << luaG_tostringview(_L, -1) << std::endl); | 379 | DEBUGSPEW_CODE(DebugSpew(U_) << luaG_tostring(_L, -1) << std::endl); |
| 380 | lua_pop(_L, 2); // L: {} k | 380 | lua_pop(_L, 2); // L: {} k |
| 381 | } // lua_next() // L: {} | 381 | } // lua_next() // L: {} |
| 382 | lua_pop(_L, 1); // L: | 382 | lua_pop(_L, 1); // L: |
diff --git a/src/tools.cpp b/src/tools.cpp index 1afc2b8..efded98 100644 --- a/src/tools.cpp +++ b/src/tools.cpp | |||
| @@ -112,7 +112,7 @@ namespace tools { | |||
| 112 | // &b is popped at that point (-> replaced by the result) | 112 | // &b is popped at that point (-> replaced by the result) |
| 113 | luaL_pushresult(&_b); // L_: ... {} ... "<result>" | 113 | luaL_pushresult(&_b); // L_: ... {} ... "<result>" |
| 114 | STACK_CHECK(L_, 1); | 114 | STACK_CHECK(L_, 1); |
| 115 | return luaG_tostringview(L_, -1); | 115 | return luaG_tostring(L_, -1); |
| 116 | } | 116 | } |
| 117 | 117 | ||
| 118 | } // namespace tools | 118 | } // namespace tools |
| @@ -142,7 +142,7 @@ static void update_lookup_entry(lua_State* L_, int ctxBase_, int depth_) | |||
| 142 | // first, raise an error if the function is already known | 142 | // first, raise an error if the function is already known |
| 143 | lua_pushvalue(L_, -1); // L_: ... {bfc} k o o | 143 | lua_pushvalue(L_, -1); // L_: ... {bfc} k o o |
| 144 | lua_rawget(L_, _dest); // L_: ... {bfc} k o name? | 144 | lua_rawget(L_, _dest); // L_: ... {bfc} k o name? |
| 145 | std::string_view const _prevName{ luaG_tostringview(L_, -1) }; // nullptr if we got nil (first encounter of this object) | 145 | std::string_view const _prevName{ luaG_tostring(L_, -1) }; // nullptr if we got nil (first encounter of this object) |
| 146 | // push name in fqn stack (note that concatenation will crash if name is a not string or a number) | 146 | // push name in fqn stack (note that concatenation will crash if name is a not string or a number) |
| 147 | lua_pushvalue(L_, -3); // L_: ... {bfc} k o name? k | 147 | lua_pushvalue(L_, -3); // L_: ... {bfc} k o name? k |
| 148 | LUA_ASSERT(L_, luaG_type(L_, -1) == LuaType::NUMBER || luaG_type(L_, -1) == LuaType::STRING); | 148 | LUA_ASSERT(L_, luaG_type(L_, -1) == LuaType::NUMBER || luaG_type(L_, -1) == LuaType::STRING); |
| @@ -237,7 +237,7 @@ static void populate_func_lookup_table_recur(lua_State* L_, int dbIdx_, int i_, | |||
| 237 | lua_pushnil(L_); // L_: ... {i_} {bfc} nil | 237 | lua_pushnil(L_); // L_: ... {i_} {bfc} nil |
| 238 | while (lua_next(L_, i_) != 0) { // L_: ... {i_} {bfc} k v | 238 | while (lua_next(L_, i_) != 0) { // L_: ... {i_} {bfc} k v |
| 239 | // just for debug, not actually needed | 239 | // just for debug, not actually needed |
| 240 | // std::string_view const _key{ (luaG_type(L_, -2) == LuaType::STRING) ? luaG_tostringview(L_, -2) : "not a string" }; | 240 | // std::string_view const _key{ (luaG_type(L_, -2) == LuaType::STRING) ? luaG_tostring(L_, -2) : "not a string" }; |
| 241 | // subtable: process it recursively | 241 | // subtable: process it recursively |
| 242 | if (lua_istable(L_, -1)) { // L_: ... {i_} {bfc} k {} | 242 | if (lua_istable(L_, -1)) { // L_: ... {i_} {bfc} k {} |
| 243 | // increment visit count to make sure we will actually scan it at this recursive level | 243 | // increment visit count to make sure we will actually scan it at this recursive level |
| @@ -267,7 +267,7 @@ static void populate_func_lookup_table_recur(lua_State* L_, int dbIdx_, int i_, | |||
| 267 | ++depth_; | 267 | ++depth_; |
| 268 | lua_pushnil(L_); // L_: ... {i_} {bfc} nil | 268 | lua_pushnil(L_); // L_: ... {i_} {bfc} nil |
| 269 | while (lua_next(L_, breadthFirstCache) != 0) { // L_: ... {i_} {bfc} k {} | 269 | while (lua_next(L_, breadthFirstCache) != 0) { // L_: ... {i_} {bfc} k {} |
| 270 | DEBUGSPEW_CODE(std::string_view const _key{ (luaG_type(L_, -2) == LuaType::STRING) ? luaG_tostringview(L_, -2) : std::string_view{ "<not a string>" } }); | 270 | DEBUGSPEW_CODE(std::string_view const _key{ (luaG_type(L_, -2) == LuaType::STRING) ? luaG_tostring(L_, -2) : std::string_view{ "<not a string>" } }); |
| 271 | DEBUGSPEW_CODE(DebugSpew(_U) << "table '"<< _key <<"'" << std::endl); | 271 | DEBUGSPEW_CODE(DebugSpew(_U) << "table '"<< _key <<"'" << std::endl); |
| 272 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope2{ _U }); | 272 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope2{ _U }); |
| 273 | // un-visit this table in case we do need to process it | 273 | // un-visit this table in case we do need to process it |
| @@ -323,9 +323,9 @@ namespace tools { | |||
| 323 | _name = "nullptr"; | 323 | _name = "nullptr"; |
| 324 | } | 324 | } |
| 325 | lua_pushvalue(L_, _in_base); // L_: {} f | 325 | lua_pushvalue(L_, _in_base); // L_: {} f |
| 326 | std::ignore = luaG_pushstringview(L_, _name); // L_: {} f name_ | 326 | std::ignore = luaG_pushstring(L_, _name); // L_: {} f name_ |
| 327 | lua_rawset(L_, -3); // L_: {} | 327 | lua_rawset(L_, -3); // L_: {} |
| 328 | std::ignore = luaG_pushstringview(L_, _name); // L_: {} name_ | 328 | std::ignore = luaG_pushstring(L_, _name); // L_: {} name_ |
| 329 | lua_pushvalue(L_, _in_base); // L_: {} name_ f | 329 | lua_pushvalue(L_, _in_base); // L_: {} name_ f |
| 330 | lua_rawset(L_, -3); // L_: {} | 330 | lua_rawset(L_, -3); // L_: {} |
| 331 | lua_pop(L_, 1); // L_: | 331 | lua_pop(L_, 1); // L_: |
| @@ -334,7 +334,7 @@ namespace tools { | |||
| 334 | int _startDepth{ 0 }; | 334 | int _startDepth{ 0 }; |
| 335 | if (!_name.empty()) { | 335 | if (!_name.empty()) { |
| 336 | STACK_CHECK(L_, 2); | 336 | STACK_CHECK(L_, 2); |
| 337 | std::ignore = luaG_pushstringview(L_, _name); // L_: {} {fqn} "name" | 337 | std::ignore = luaG_pushstring(L_, _name); // L_: {} {fqn} "name" |
| 338 | // generate a name, and if we already had one name, keep whichever is the shorter | 338 | // generate a name, and if we already had one name, keep whichever is the shorter |
| 339 | lua_pushvalue(L_, _in_base); // L_: {} {fqn} "name" t | 339 | lua_pushvalue(L_, _in_base); // L_: {} {fqn} "name" t |
| 340 | update_lookup_entry(L_, _dbIdx, _startDepth); // L_: {} {fqn} "name" | 340 | update_lookup_entry(L_, _dbIdx, _startDepth); // L_: {} {fqn} "name" |
| @@ -367,7 +367,7 @@ namespace tools { | |||
| 367 | +[](lua_State* L_) | 367 | +[](lua_State* L_) |
| 368 | { | 368 | { |
| 369 | int const _args{ lua_gettop(L_) }; // L_: args... | 369 | int const _args{ lua_gettop(L_) }; // L_: args... |
| 370 | //[[maybe_unused]] std::string_view const _modname{ luaG_checkstringview(L_, 1) }; | 370 | //[[maybe_unused]] std::string_view const _modname{ luaG_checkstring(L_, 1) }; |
| 371 | 371 | ||
| 372 | STACK_GROW(L_, 1); | 372 | STACK_GROW(L_, 1); |
| 373 | 373 | ||
diff --git a/src/tracker.cpp b/src/tracker.cpp index 24e8d01..ae4d116 100644 --- a/src/tracker.cpp +++ b/src/tracker.cpp | |||
| @@ -94,7 +94,7 @@ void LaneTracker::tracking_add(Lane* lane_) | |||
| 94 | while (_lane != TRACKING_END) { | 94 | while (_lane != TRACKING_END) { |
| 95 | // insert a { name='<name>', status='<status>' } tuple, so that several lanes with the same name can't clobber each other | 95 | // insert a { name='<name>', status='<status>' } tuple, so that several lanes with the same name can't clobber each other |
| 96 | lua_createtable(L_, 0, 2); // L_: {} {} | 96 | lua_createtable(L_, 0, 2); // L_: {} {} |
| 97 | std::ignore = luaG_pushstringview(L_, _lane->debugName); // L_: {} {} "name" | 97 | std::ignore = luaG_pushstring(L_, _lane->debugName); // L_: {} {} "name" |
| 98 | lua_setfield(L_, -2, "name"); // L_: {} {} | 98 | lua_setfield(L_, -2, "name"); // L_: {} {} |
| 99 | std::ignore = _lane->pushThreadStatus(L_); // L_: {} {} "status" | 99 | std::ignore = _lane->pushThreadStatus(L_); // L_: {} {} "status" |
| 100 | lua_setfield(L_, -2, "status"); // L_: {} {} | 100 | lua_setfield(L_, -2, "status"); // L_: {} {} |
diff --git a/src/uniquekey.h b/src/uniquekey.h index 114d22e..94c09c7 100644 --- a/src/uniquekey.h +++ b/src/uniquekey.h | |||
| @@ -70,7 +70,7 @@ class RegistryUniqueKey | |||
| 70 | STACK_GROW(L_, 1); | 70 | STACK_GROW(L_, 1); |
| 71 | STACK_CHECK_START_REL(L_, 0); | 71 | STACK_CHECK_START_REL(L_, 0); |
| 72 | pushValue(L_); | 72 | pushValue(L_); |
| 73 | T* const value{ lua_tolightuserdata<T>(L_, -1) }; // lightuserdata/nil | 73 | T* const value{ luaG_tolightuserdata<T>(L_, -1) }; // lightuserdata/nil |
| 74 | lua_pop(L_, 1); | 74 | lua_pop(L_, 1); |
| 75 | STACK_CHECK(L_, 0); | 75 | STACK_CHECK(L_, 0); |
| 76 | return value; | 76 | return value; |
diff --git a/src/universe.cpp b/src/universe.cpp index 116c8e3..9ab6019 100644 --- a/src/universe.cpp +++ b/src/universe.cpp | |||
| @@ -135,13 +135,13 @@ Universe::Universe() | |||
| 135 | 135 | ||
| 136 | // Initialize 'timerLinda'; a common Linda object shared by all states | 136 | // Initialize 'timerLinda'; a common Linda object shared by all states |
| 137 | lua_pushcfunction(L_, LG_linda); // L_: settings lanes.linda | 137 | lua_pushcfunction(L_, LG_linda); // L_: settings lanes.linda |
| 138 | std::ignore = luaG_pushstringview(L_, "lanes-timer"); // L_: settings lanes.linda "lanes-timer" | 138 | std::ignore = luaG_pushstring(L_, "lanes-timer"); // L_: settings lanes.linda "lanes-timer" |
| 139 | lua_pushinteger(L_, 0); // L_: settings lanes.linda "lanes-timer" 0 | 139 | lua_pushinteger(L_, 0); // L_: settings lanes.linda "lanes-timer" 0 |
| 140 | lua_call(L_, 2, 1); // L_: settings linda | 140 | lua_call(L_, 2, 1); // L_: settings linda |
| 141 | STACK_CHECK(L_, 1); | 141 | STACK_CHECK(L_, 1); |
| 142 | 142 | ||
| 143 | // Proxy userdata contents is only a 'DeepPrelude*' pointer | 143 | // Proxy userdata contents is only a 'DeepPrelude*' pointer |
| 144 | _U->timerLinda = *lua_tofulluserdata<DeepPrelude*>(L_, -1); | 144 | _U->timerLinda = *luaG_tofulluserdata<DeepPrelude*>(L_, -1); |
| 145 | // increment refcount so that this linda remains alive as long as the universe exists. | 145 | // increment refcount so that this linda remains alive as long as the universe exists. |
| 146 | _U->timerLinda->refcount.fetch_add(1, std::memory_order_relaxed); | 146 | _U->timerLinda->refcount.fetch_add(1, std::memory_order_relaxed); |
| 147 | lua_pop(L_, 1); // L_: settings | 147 | lua_pop(L_, 1); // L_: settings |
| @@ -210,7 +210,7 @@ void Universe::initializeAllocatorFunction(lua_State* const L_) | |||
| 210 | STACK_CHECK(L_, 1); | 210 | STACK_CHECK(L_, 1); |
| 211 | 211 | ||
| 212 | std::ignore = luaG_getfield(L_, -1, "internal_allocator"); // L_: settings "libc"|"allocator" | 212 | std::ignore = luaG_getfield(L_, -1, "internal_allocator"); // L_: settings "libc"|"allocator" |
| 213 | std::string_view const _allocator{ luaG_tostringview(L_, -1) }; | 213 | std::string_view const _allocator{ luaG_tostring(L_, -1) }; |
| 214 | if (_allocator == "libc") { | 214 | if (_allocator == "libc") { |
| 215 | internalAllocator = AllocatorDefinition{ libc_lua_Alloc, nullptr }; | 215 | internalAllocator = AllocatorDefinition{ libc_lua_Alloc, nullptr }; |
| 216 | } else if (provideAllocator == luaG_provide_protected_allocator) { | 216 | } else if (provideAllocator == luaG_provide_protected_allocator) { |
| @@ -317,9 +317,9 @@ void Universe::terminateFreeRunningLanes(lua_State* const L_, lua_Duration const | |||
| 317 | LUAG_FUNC(universe_gc) | 317 | LUAG_FUNC(universe_gc) |
| 318 | { | 318 | { |
| 319 | lua_Duration const _shutdown_timeout{ lua_tonumber(L_, lua_upvalueindex(1)) }; | 319 | lua_Duration const _shutdown_timeout{ lua_tonumber(L_, lua_upvalueindex(1)) }; |
| 320 | std::string_view const _op_string{ luaG_tostringview(L_, lua_upvalueindex(2)) }; | 320 | std::string_view const _op_string{ luaG_tostring(L_, lua_upvalueindex(2)) }; |
| 321 | STACK_CHECK_START_ABS(L_, 1); | 321 | STACK_CHECK_START_ABS(L_, 1); |
| 322 | Universe* const _U{ lua_tofulluserdata<Universe>(L_, 1) }; // L_: U | 322 | Universe* const _U{ luaG_tofulluserdata<Universe>(L_, 1) }; // L_: U |
| 323 | _U->terminateFreeRunningLanes(L_, _shutdown_timeout, which_cancel_op(_op_string)); | 323 | _U->terminateFreeRunningLanes(L_, _shutdown_timeout, which_cancel_op(_op_string)); |
| 324 | 324 | ||
| 325 | // invoke the function installed by lanes.finally() | 325 | // invoke the function installed by lanes.finally() |
diff --git a/src/universe.h b/src/universe.h index 6f03ed3..2b8cdf2 100644 --- a/src/universe.h +++ b/src/universe.h | |||
| @@ -171,7 +171,7 @@ class Universe | |||
| 171 | std::atomic<int> selfdestructingCount{ 0 }; | 171 | std::atomic<int> selfdestructingCount{ 0 }; |
| 172 | 172 | ||
| 173 | public: | 173 | public: |
| 174 | [[nodiscard]] static void* operator new([[maybe_unused]] size_t size_, lua_State* L_) noexcept { return lua_newuserdatauv<Universe>(L_, 0); }; | 174 | [[nodiscard]] static void* operator new([[maybe_unused]] size_t size_, lua_State* L_) noexcept { return luaG_newuserdatauv<Universe>(L_, 0); }; |
| 175 | // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception | 175 | // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception |
| 176 | static void operator delete([[maybe_unused]] void* p_, [[maybe_unused]] lua_State* L_) {} // nothing to do, as nothing is allocated independently | 176 | static void operator delete([[maybe_unused]] void* p_, [[maybe_unused]] lua_State* L_) {} // nothing to do, as nothing is allocated independently |
| 177 | 177 | ||
