aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenoit Germain <benoit.germain@ubisoft.com>2024-06-07 11:46:25 +0200
committerBenoit Germain <benoit.germain@ubisoft.com>2024-06-07 11:46:25 +0200
commitee32d4281a5e59ce81d7f38f86a49fa8ff64d2c3 (patch)
tree68c0d74ac40c6ee098abf606e3d660a862acf04f
parent35d7a6bb691d7e0564cda324b3d724caf4901545 (diff)
downloadlanes-ee32d4281a5e59ce81d7f38f86a49fa8ff64d2c3.tar.gz
lanes-ee32d4281a5e59ce81d7f38f86a49fa8ff64d2c3.tar.bz2
lanes-ee32d4281a5e59ce81d7f38f86a49fa8ff64d2c3.zip
Boyscouting some luaG_ functions
-rw-r--r--src/cancel.cpp2
-rw-r--r--src/compat.h43
-rw-r--r--src/deep.cpp14
-rw-r--r--src/intercopycontext.cpp45
-rw-r--r--src/keeper.cpp6
-rw-r--r--src/lane.cpp22
-rw-r--r--src/lanes.cpp30
-rw-r--r--src/linda.cpp10
-rw-r--r--src/lindafactory.cpp10
-rw-r--r--src/macros_and_utils.h27
-rw-r--r--src/nameof.cpp2
-rw-r--r--src/state.cpp10
-rw-r--r--src/tools.cpp16
-rw-r--r--src/tracker.cpp2
-rw-r--r--src/uniquekey.h2
-rw-r--r--src/universe.cpp10
-rw-r--r--src/universe.h2
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
307template <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
305inline void luaG_registerlibfuncs(lua_State* L_, luaL_Reg const funcs_[]) 315inline 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
330template <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
339template <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
347template<typename ...EXTRA> 380template<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
118KeyUD* KeyUD::GetPtr(KeeperState const K_, int idx_) 118KeyUD* 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)
80static LUAG_FUNC(set_debug_threadname) 80static 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
194LUAG_FUNC(require) 194LUAG_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)
216LUAG_FUNC(register) 216LUAG_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_)
252LUAG_FUNC(linda_cancel) 252LUAG_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
35template <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
42template <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
53template <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
61using lua_Duration = std::chrono::template duration<lua_Number>; 34using 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
317LUAG_FUNC(universe_gc) 317LUAG_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