diff options
-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 | ||