diff options
author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-10-08 18:42:39 +0200 |
---|---|---|
committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-10-08 18:42:39 +0200 |
commit | 16b5070c0cd56e10c5074eb9903dbc3ae4e15a61 (patch) | |
tree | f6d5cdb74b505e13aa3261f7ab6192da0133b7b9 | |
parent | e939e5e6a894a042d3301e47faa05264445f27f6 (diff) | |
download | lanes-16b5070c0cd56e10c5074eb9903dbc3ae4e15a61.tar.gz lanes-16b5070c0cd56e10c5074eb9903dbc3ae4e15a61.tar.bz2 lanes-16b5070c0cd56e10c5074eb9903dbc3ae4e15a61.zip |
Sprinkling StackIndex all over the place
-rw-r--r-- | deep_test/deep_test.cpp | 20 | ||||
-rw-r--r-- | src/cancel.cpp | 10 | ||||
-rw-r--r-- | src/compat.cpp | 20 | ||||
-rw-r--r-- | src/compat.h | 48 | ||||
-rw-r--r-- | src/debug.h | 4 | ||||
-rw-r--r-- | src/deep.cpp | 24 | ||||
-rw-r--r-- | src/deep.h | 6 | ||||
-rw-r--r-- | src/intercopycontext.cpp | 82 | ||||
-rw-r--r-- | src/intercopycontext.h | 4 | ||||
-rw-r--r-- | src/keeper.cpp | 88 | ||||
-rw-r--r-- | src/keeper.h | 10 | ||||
-rw-r--r-- | src/lane.cpp | 140 | ||||
-rw-r--r-- | src/lane.h | 6 | ||||
-rw-r--r-- | src/lanes.cpp | 68 | ||||
-rw-r--r-- | src/linda.cpp | 52 | ||||
-rw-r--r-- | src/linda.h | 2 | ||||
-rw-r--r-- | src/lindafactory.cpp | 6 | ||||
-rw-r--r-- | src/luaerrors.h | 6 | ||||
-rw-r--r-- | src/macros_and_utils.h | 5 | ||||
-rw-r--r-- | src/nameof.cpp | 18 | ||||
-rw-r--r-- | src/state.cpp | 6 | ||||
-rw-r--r-- | src/tools.cpp | 50 | ||||
-rw-r--r-- | src/tools.h | 6 | ||||
-rw-r--r-- | src/unique.hpp | 22 | ||||
-rw-r--r-- | src/uniquekey.h | 24 | ||||
-rw-r--r-- | src/universe.cpp | 47 |
26 files changed, 394 insertions, 380 deletions
diff --git a/deep_test/deep_test.cpp b/deep_test/deep_test.cpp index c071dc6..39352f3 100644 --- a/deep_test/deep_test.cpp +++ b/deep_test/deep_test.cpp | |||
@@ -47,7 +47,7 @@ void MyDeepFactory::deleteDeepObjectInternal(lua_State* const L_, DeepPrelude* c | |||
47 | 47 | ||
48 | [[nodiscard]] static int deep_gc(lua_State* L) | 48 | [[nodiscard]] static int deep_gc(lua_State* L) |
49 | { | 49 | { |
50 | MyDeepUserdata* const _self{ static_cast<MyDeepUserdata*>(MyDeepFactory::Instance.toDeep(L, 1)) }; | 50 | MyDeepUserdata* const _self{ static_cast<MyDeepUserdata*>(MyDeepFactory::Instance.toDeep(L, StackIndex{ 1 })) }; |
51 | luaL_argcheck(L, 1, !_self->inUse.load(), "being collected while in use!"); | 51 | luaL_argcheck(L, 1, !_self->inUse.load(), "being collected while in use!"); |
52 | return 0; | 52 | return 0; |
53 | } | 53 | } |
@@ -56,7 +56,7 @@ void MyDeepFactory::deleteDeepObjectInternal(lua_State* const L_, DeepPrelude* c | |||
56 | 56 | ||
57 | [[nodiscard]] static int deep_tostring(lua_State* L) | 57 | [[nodiscard]] static int deep_tostring(lua_State* L) |
58 | { | 58 | { |
59 | MyDeepUserdata* const _self{ static_cast<MyDeepUserdata*>(MyDeepFactory::Instance.toDeep(L, 1)) }; | 59 | MyDeepUserdata* const _self{ static_cast<MyDeepUserdata*>(MyDeepFactory::Instance.toDeep(L, StackIndex{ 1 })) }; |
60 | _self->inUse.fetch_add(1, std::memory_order_seq_cst); | 60 | _self->inUse.fetch_add(1, std::memory_order_seq_cst); |
61 | luaG_pushstring(L, "%p:deep(%d)", _self, _self->val); | 61 | luaG_pushstring(L, "%p:deep(%d)", _self, _self->val); |
62 | _self->inUse.fetch_sub(1, std::memory_order_seq_cst); | 62 | _self->inUse.fetch_sub(1, std::memory_order_seq_cst); |
@@ -68,10 +68,10 @@ void MyDeepFactory::deleteDeepObjectInternal(lua_State* const L_, DeepPrelude* c | |||
68 | // won't actually do anything as deep userdata don't have uservalue slots | 68 | // won't actually do anything as deep userdata don't have uservalue slots |
69 | [[nodiscard]] static int deep_getuv(lua_State* L) | 69 | [[nodiscard]] static int deep_getuv(lua_State* L) |
70 | { | 70 | { |
71 | MyDeepUserdata* const _self{ static_cast<MyDeepUserdata*>(MyDeepFactory::Instance.toDeep(L, 1)) }; | 71 | MyDeepUserdata* const _self{ static_cast<MyDeepUserdata*>(MyDeepFactory::Instance.toDeep(L, StackIndex{ 1 })) }; |
72 | _self->inUse.fetch_add(1, std::memory_order_seq_cst); | 72 | _self->inUse.fetch_add(1, std::memory_order_seq_cst); |
73 | int _uv = (int) luaL_optinteger(L, 2, 1); | 73 | int _uv = (int) luaL_optinteger(L, 2, 1); |
74 | lua_getiuservalue(L, 1, _uv); | 74 | lua_getiuservalue(L, StackIndex{ 1 }, _uv); |
75 | _self->inUse.fetch_sub(1, std::memory_order_seq_cst); | 75 | _self->inUse.fetch_sub(1, std::memory_order_seq_cst); |
76 | return 1; | 76 | return 1; |
77 | } | 77 | } |
@@ -80,7 +80,7 @@ void MyDeepFactory::deleteDeepObjectInternal(lua_State* const L_, DeepPrelude* c | |||
80 | 80 | ||
81 | [[nodiscard]] static int deep_invoke(lua_State* L) | 81 | [[nodiscard]] static int deep_invoke(lua_State* L) |
82 | { | 82 | { |
83 | MyDeepUserdata* const _self{ static_cast<MyDeepUserdata*>(MyDeepFactory::Instance.toDeep(L, 1)) }; | 83 | MyDeepUserdata* const _self{ static_cast<MyDeepUserdata*>(MyDeepFactory::Instance.toDeep(L, StackIndex{ 1 })) }; |
84 | luaL_argcheck(L, 2, lua_gettop(L) >= 2, "need something to call"); | 84 | luaL_argcheck(L, 2, lua_gettop(L) >= 2, "need something to call"); |
85 | _self->inUse.fetch_add(1, std::memory_order_seq_cst); | 85 | _self->inUse.fetch_add(1, std::memory_order_seq_cst); |
86 | lua_call(L, lua_gettop(L) - 2, LUA_MULTRET); | 86 | lua_call(L, lua_gettop(L) - 2, LUA_MULTRET); |
@@ -92,7 +92,7 @@ void MyDeepFactory::deleteDeepObjectInternal(lua_State* const L_, DeepPrelude* c | |||
92 | 92 | ||
93 | [[nodiscard]] static int deep_set(lua_State* const L_) | 93 | [[nodiscard]] static int deep_set(lua_State* const L_) |
94 | { | 94 | { |
95 | MyDeepUserdata* const _self{ static_cast<MyDeepUserdata*>(MyDeepFactory::Instance.toDeep(L_, 1)) }; | 95 | MyDeepUserdata* const _self{ static_cast<MyDeepUserdata*>(MyDeepFactory::Instance.toDeep(L_, StackIndex{ 1 })) }; |
96 | _self->inUse.fetch_add(1, std::memory_order_seq_cst); | 96 | _self->inUse.fetch_add(1, std::memory_order_seq_cst); |
97 | lua_Integer _i = lua_tointeger(L_, 2); | 97 | lua_Integer _i = lua_tointeger(L_, 2); |
98 | _self->val = _i; | 98 | _self->val = _i; |
@@ -104,11 +104,11 @@ void MyDeepFactory::deleteDeepObjectInternal(lua_State* const L_, DeepPrelude* c | |||
104 | 104 | ||
105 | [[nodiscard]] static int deep_setuv(lua_State* L) | 105 | [[nodiscard]] static int deep_setuv(lua_State* L) |
106 | { | 106 | { |
107 | MyDeepUserdata* const _self{ static_cast<MyDeepUserdata*>(MyDeepFactory::Instance.toDeep(L, 1)) }; | 107 | MyDeepUserdata* const _self{ static_cast<MyDeepUserdata*>(MyDeepFactory::Instance.toDeep(L, StackIndex{ 1 })) }; |
108 | _self->inUse.fetch_add(1, std::memory_order_seq_cst); | 108 | _self->inUse.fetch_add(1, std::memory_order_seq_cst); |
109 | int _uv = (int) luaL_optinteger(L, 2, 1); | 109 | int _uv = (int) luaL_optinteger(L, 2, 1); |
110 | lua_settop(L, 3); | 110 | lua_settop(L, 3); |
111 | lua_pushboolean(L, lua_setiuservalue(L, 1, _uv) != 0); | 111 | lua_pushboolean(L, lua_setiuservalue(L, StackIndex{ 1 }, _uv) != 0); |
112 | _self->inUse.fetch_sub(1, std::memory_order_seq_cst); | 112 | _self->inUse.fetch_sub(1, std::memory_order_seq_cst); |
113 | return 1; | 113 | return 1; |
114 | } | 114 | } |
@@ -160,7 +160,7 @@ struct MyClonableUserdata | |||
160 | MyClonableUserdata* self = static_cast<MyClonableUserdata*>(lua_touserdata(L, 1)); | 160 | MyClonableUserdata* self = static_cast<MyClonableUserdata*>(lua_touserdata(L, 1)); |
161 | int uv = (int) luaL_optinteger(L, 2, 1); | 161 | int uv = (int) luaL_optinteger(L, 2, 1); |
162 | lua_settop(L, 3); | 162 | lua_settop(L, 3); |
163 | lua_pushboolean(L, lua_setiuservalue(L, 1, uv) != 0); | 163 | lua_pushboolean(L, lua_setiuservalue(L, StackIndex{ 1 }, uv) != 0); |
164 | return 1; | 164 | return 1; |
165 | } | 165 | } |
166 | 166 | ||
@@ -170,7 +170,7 @@ struct MyClonableUserdata | |||
170 | { | 170 | { |
171 | MyClonableUserdata* self = static_cast<MyClonableUserdata*>(lua_touserdata(L, 1)); | 171 | MyClonableUserdata* self = static_cast<MyClonableUserdata*>(lua_touserdata(L, 1)); |
172 | int uv = (int) luaL_optinteger(L, 2, 1); | 172 | int uv = (int) luaL_optinteger(L, 2, 1); |
173 | lua_getiuservalue(L, 1, uv); | 173 | lua_getiuservalue(L, StackIndex{ 1 }, uv); |
174 | return 1; | 174 | return 1; |
175 | } | 175 | } |
176 | 176 | ||
diff --git a/src/cancel.cpp b/src/cancel.cpp index 15a2c83..2cd3c53 100644 --- a/src/cancel.cpp +++ b/src/cancel.cpp | |||
@@ -103,7 +103,7 @@ CancelOp WhichCancelOp(std::string_view const& opString_) | |||
103 | 103 | ||
104 | // ################################################################################################# | 104 | // ################################################################################################# |
105 | 105 | ||
106 | [[nodiscard]] static CancelOp WhichCancelOp(lua_State* const L_, int const idx_) | 106 | [[nodiscard]] static CancelOp WhichCancelOp(lua_State* const L_, StackIndex const idx_) |
107 | { | 107 | { |
108 | if (luaG_type(L_, idx_) == LuaType::STRING) { | 108 | if (luaG_type(L_, idx_) == LuaType::STRING) { |
109 | std::string_view const _str{ luaG_tostring(L_, idx_) }; | 109 | std::string_view const _str{ luaG_tostring(L_, idx_) }; |
@@ -141,8 +141,8 @@ LUAG_FUNC(cancel_test) | |||
141 | // bool[,reason] = lane_h:cancel( [mode, hookcount] [, timeout] [, wake_lane]) | 141 | // bool[,reason] = lane_h:cancel( [mode, hookcount] [, timeout] [, wake_lane]) |
142 | LUAG_FUNC(thread_cancel) | 142 | LUAG_FUNC(thread_cancel) |
143 | { | 143 | { |
144 | Lane* const _lane{ ToLane(L_, 1) }; | 144 | Lane* const _lane{ ToLane(L_, StackIndex{ 1 }) }; |
145 | CancelOp const _op{ WhichCancelOp(L_, 2) }; // this removes the op string from the stack | 145 | CancelOp const _op{ WhichCancelOp(L_, StackIndex{ 2 }) }; // this removes the op string from the stack |
146 | 146 | ||
147 | int _hook_count{ 0 }; | 147 | int _hook_count{ 0 }; |
148 | if (static_cast<int>(_op) > static_cast<int>(CancelOp::Soft)) { // hook is requested | 148 | if (static_cast<int>(_op) > static_cast<int>(CancelOp::Soft)) { // hook is requested |
@@ -154,12 +154,12 @@ LUAG_FUNC(thread_cancel) | |||
154 | } | 154 | } |
155 | 155 | ||
156 | std::chrono::time_point<std::chrono::steady_clock> _until{ std::chrono::time_point<std::chrono::steady_clock>::max() }; | 156 | std::chrono::time_point<std::chrono::steady_clock> _until{ std::chrono::time_point<std::chrono::steady_clock>::max() }; |
157 | if (luaG_type(L_, 2) == LuaType::NUMBER) { // we don't want to use lua_isnumber() because of autocoercion | 157 | if (luaG_type(L_, StackIndex{ 2 }) == LuaType::NUMBER) { // we don't want to use lua_isnumber() because of autocoercion |
158 | lua_Duration const duration{ lua_tonumber(L_, 2) }; | 158 | lua_Duration const duration{ lua_tonumber(L_, 2) }; |
159 | if (duration.count() >= 0.0) { | 159 | if (duration.count() >= 0.0) { |
160 | _until = std::chrono::steady_clock::now() + std::chrono::duration_cast<std::chrono::steady_clock::duration>(duration); | 160 | _until = std::chrono::steady_clock::now() + std::chrono::duration_cast<std::chrono::steady_clock::duration>(duration); |
161 | } else { | 161 | } else { |
162 | raise_luaL_argerror(L_, 2, "duration cannot be < 0"); | 162 | raise_luaL_argerror(L_, StackIndex{ 2 }, "duration cannot be < 0"); |
163 | } | 163 | } |
164 | lua_remove(L_, 2); // argument is processed, remove it | 164 | lua_remove(L_, 2); // argument is processed, remove it |
165 | } else if (lua_isnil(L_, 2)) { // alternate explicit "infinite timeout" by passing nil before the key | 165 | } else if (lua_isnil(L_, 2)) { // alternate explicit "infinite timeout" by passing nil before the key |
diff --git a/src/compat.cpp b/src/compat.cpp index 4076aa6..1f8eaf9 100644 --- a/src/compat.cpp +++ b/src/compat.cpp | |||
@@ -5,10 +5,10 @@ | |||
5 | 5 | ||
6 | // ################################################################################################# | 6 | // ################################################################################################# |
7 | 7 | ||
8 | int luaG_getalluservalues(lua_State* const L_, int const idx_) | 8 | int luaG_getalluservalues(lua_State* const L_, StackIndex const idx_) |
9 | { | 9 | { |
10 | STACK_CHECK_START_REL(L_, 0); | 10 | STACK_CHECK_START_REL(L_, 0); |
11 | int const _idx{ luaG_absindex(L_, idx_) }; | 11 | StackIndex const _idx{ luaG_absindex(L_, idx_) }; |
12 | int _nuv{ 0 }; | 12 | int _nuv{ 0 }; |
13 | do { | 13 | do { |
14 | // we don't know how many uservalues we are going to extract, there might be a lot... | 14 | // we don't know how many uservalues we are going to extract, there might be a lot... |
@@ -27,12 +27,12 @@ int luaG_getalluservalues(lua_State* const L_, int const idx_) | |||
27 | LuaType luaG_getmodule(lua_State* const L_, std::string_view const& name_) | 27 | LuaType luaG_getmodule(lua_State* const L_, std::string_view const& name_) |
28 | { | 28 | { |
29 | STACK_CHECK_START_REL(L_, 0); | 29 | STACK_CHECK_START_REL(L_, 0); |
30 | LuaType _type{ luaG_getfield(L_, LUA_REGISTRYINDEX, LUA_LOADED_TABLE) }; // L_: _R._LOADED|nil | 30 | LuaType _type{ luaG_getfield(L_, kIdxRegistry, LUA_LOADED_TABLE) }; // L_: _R._LOADED|nil |
31 | if (_type != LuaType::TABLE) { // L_: _R._LOADED|nil | 31 | if (_type != LuaType::TABLE) { // L_: _R._LOADED|nil |
32 | STACK_CHECK(L_, 1); | 32 | STACK_CHECK(L_, 1); |
33 | return _type; | 33 | return _type; |
34 | } | 34 | } |
35 | _type = luaG_getfield(L_, -1, name_); // L_: _R._LOADED {module}|nil | 35 | _type = luaG_getfield(L_, kIdxTop, name_); // L_: _R._LOADED {module}|nil |
36 | lua_remove(L_, -2); // L_: {module}|nil | 36 | lua_remove(L_, -2); // L_: {module}|nil |
37 | STACK_CHECK(L_, 1); | 37 | STACK_CHECK(L_, 1); |
38 | return _type; | 38 | return _type; |
@@ -45,17 +45,17 @@ LuaType luaG_getmodule(lua_State* const L_, std::string_view const& name_) | |||
45 | // ################################################################################################# | 45 | // ################################################################################################# |
46 | 46 | ||
47 | // Copied from Lua 5.2 loadlib.c | 47 | // Copied from Lua 5.2 loadlib.c |
48 | int luaL_getsubtable(lua_State* L_, int idx_, const char* fname_) | 48 | int luaL_getsubtable(lua_State* const L_, StackIndex const idx_, char const* fname_) |
49 | { | 49 | { |
50 | lua_getfield(L_, idx_, fname_); | 50 | lua_getfield(L_, idx_, fname_); |
51 | if (lua_istable(L_, -1)) | 51 | if (lua_istable(L_, -1)) |
52 | return 1; /* table already there */ | 52 | return 1; /* table already there */ |
53 | else { | 53 | else { |
54 | lua_pop(L_, 1); /* remove previous result */ | 54 | lua_pop(L_, 1); /* remove previous result */ |
55 | idx_ = luaG_absindex(L_, idx_); | 55 | StackIndex const _absidx{ luaG_absindex(L_, idx_) }; |
56 | lua_newtable(L_); | 56 | lua_newtable(L_); |
57 | lua_pushvalue(L_, -1); /* copy to be left at top */ | 57 | lua_pushvalue(L_, -1); /* copy to be left at top */ |
58 | lua_setfield(L_, idx_, fname_); /* assign new table to field */ | 58 | lua_setfield(L_, _absidx, fname_); /* assign new table to field */ |
59 | return 0; /* false, because did not find table there */ | 59 | return 0; /* false, because did not find table there */ |
60 | } | 60 | } |
61 | } | 61 | } |
@@ -66,7 +66,7 @@ void luaL_requiref(lua_State* L_, const char* modname_, lua_CFunction openf_, in | |||
66 | lua_pushcfunction(L_, openf_); | 66 | lua_pushcfunction(L_, openf_); |
67 | lua_pushstring(L_, modname_); /* argument to open function */ | 67 | lua_pushstring(L_, modname_); /* argument to open function */ |
68 | lua_call(L_, 1, 1); /* open module */ | 68 | lua_call(L_, 1, 1); /* open module */ |
69 | luaL_getsubtable(L_, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); | 69 | luaL_getsubtable(L_, kIdxRegistry, LUA_LOADED_TABLE); |
70 | lua_pushvalue(L_, -2); /* make copy of module (call result) */ | 70 | lua_pushvalue(L_, -2); /* make copy of module (call result) */ |
71 | lua_setfield(L_, -2, modname_); /* _LOADED[modname] = module */ | 71 | lua_setfield(L_, -2, modname_); /* _LOADED[modname] = module */ |
72 | lua_pop(L_, 1); /* remove _LOADED table */ | 72 | lua_pop(L_, 1); /* remove _LOADED table */ |
@@ -92,7 +92,7 @@ void* lua_newuserdatauv(lua_State* L_, size_t sz_, [[maybe_unused]] int nuvalue_ | |||
92 | // ################################################################################################# | 92 | // ################################################################################################# |
93 | 93 | ||
94 | // push on stack uservalue #n of full userdata at idx | 94 | // push on stack uservalue #n of full userdata at idx |
95 | int lua_getiuservalue(lua_State* const L_, int const idx_, int const n_) | 95 | int lua_getiuservalue(lua_State* const L_, StackIndex const idx_, int const n_) |
96 | { | 96 | { |
97 | STACK_CHECK_START_REL(L_, 0); | 97 | STACK_CHECK_START_REL(L_, 0); |
98 | // full userdata can have only 1 uservalue before 5.4 | 98 | // full userdata can have only 1 uservalue before 5.4 |
@@ -129,7 +129,7 @@ int lua_getiuservalue(lua_State* const L_, int const idx_, int const n_) | |||
129 | 129 | ||
130 | // Pops a value from the stack and sets it as the new n-th user value associated to the full userdata at the given index. | 130 | // Pops a value from the stack and sets it as the new n-th user value associated to the full userdata at the given index. |
131 | // Returns 0 if the userdata does not have that value. | 131 | // Returns 0 if the userdata does not have that value. |
132 | int lua_setiuservalue(lua_State* L_, int idx_, int n_) | 132 | int lua_setiuservalue(lua_State* const L_, StackIndex const idx_, int const n_) |
133 | { | 133 | { |
134 | if (n_ > 1 | 134 | if (n_ > 1 |
135 | #if LUA_VERSION_NUM == 501 | 135 | #if LUA_VERSION_NUM == 501 |
diff --git a/src/compat.h b/src/compat.h index 8b3eb98..90e72a3 100644 --- a/src/compat.h +++ b/src/compat.h | |||
@@ -32,6 +32,10 @@ | |||
32 | 32 | ||
33 | // ################################################################################################# | 33 | // ################################################################################################# |
34 | 34 | ||
35 | static constexpr StackIndex kIdxRegistry{ LUA_REGISTRYINDEX }; | ||
36 | |||
37 | // ################################################################################################# | ||
38 | |||
35 | // a strong-typed wrapper over lua types to see them easier in a debugger | 39 | // a strong-typed wrapper over lua types to see them easier in a debugger |
36 | enum class LuaType | 40 | enum class LuaType |
37 | { | 41 | { |
@@ -53,13 +57,13 @@ enum class LuaType | |||
53 | // add some Lua 5.3-style API when building for Lua 5.1 | 57 | // add some Lua 5.3-style API when building for Lua 5.1 |
54 | #if LUA_VERSION_NUM == 501 | 58 | #if LUA_VERSION_NUM == 501 |
55 | 59 | ||
56 | inline size_t lua_rawlen(lua_State* L_, int idx_) | 60 | inline size_t lua_rawlen(lua_State* L_, StackIndex idx_) |
57 | { | 61 | { |
58 | return lua_objlen(L_, idx_); | 62 | return lua_objlen(L_, idx_); |
59 | } | 63 | } |
60 | void luaL_requiref(lua_State* L_, const char* modname_, lua_CFunction openf_, int glb_); // implementation copied from Lua 5.2 sources | 64 | void luaL_requiref(lua_State* L_, const char* modname_, lua_CFunction openf_, int glb_); // implementation copied from Lua 5.2 sources |
61 | 65 | ||
62 | int luaL_getsubtable(lua_State* L_, int idx_, const char* fname_); | 66 | int luaL_getsubtable(lua_State* L_, StackIndex idx_, const char* fname_); |
63 | 67 | ||
64 | #endif // LUA_VERSION_NUM == 501 | 68 | #endif // LUA_VERSION_NUM == 501 |
65 | 69 | ||
@@ -80,8 +84,8 @@ inline int luaL_optint(lua_State* L_, int n_, lua_Integer d_) | |||
80 | #if LUA_VERSION_NUM < 504 | 84 | #if LUA_VERSION_NUM < 504 |
81 | 85 | ||
82 | void* lua_newuserdatauv(lua_State* L_, size_t sz_, int nuvalue_); | 86 | void* lua_newuserdatauv(lua_State* L_, size_t sz_, int nuvalue_); |
83 | int lua_getiuservalue(lua_State* L_, int idx_, int n_); | 87 | int lua_getiuservalue(lua_State* L_, StackIndex idx_, int n_); |
84 | int lua_setiuservalue(lua_State* L_, int idx_, int n_); | 88 | int lua_setiuservalue(lua_State* L_, StackIndex idx_, int n_); |
85 | 89 | ||
86 | #define LUA_GNAME "_G" | 90 | #define LUA_GNAME "_G" |
87 | 91 | ||
@@ -92,7 +96,7 @@ int lua_setiuservalue(lua_State* L_, int idx_, int n_); | |||
92 | // wrap Lua 5.4 calls under Lua 5.1 API when it is simpler that way | 96 | // wrap Lua 5.4 calls under Lua 5.1 API when it is simpler that way |
93 | #if LUA_VERSION_NUM == 504 | 97 | #if LUA_VERSION_NUM == 504 |
94 | 98 | ||
95 | inline int luaL_optint(lua_State* L_, int n_, lua_Integer d_) | 99 | inline int luaL_optint(lua_State* L_, StackIndex n_, lua_Integer d_) |
96 | { | 100 | { |
97 | return static_cast<int>(luaL_optinteger(L_, n_, d_)); | 101 | return static_cast<int>(luaL_optinteger(L_, n_, d_)); |
98 | } | 102 | } |
@@ -123,7 +127,7 @@ inline constexpr LuaError ToLuaError(int const rc_) | |||
123 | // ################################################################################################# | 127 | // ################################################################################################# |
124 | 128 | ||
125 | // break lexical order for that one because it's needed below | 129 | // break lexical order for that one because it's needed below |
126 | inline LuaType luaG_type(lua_State* const L_, int const idx_) | 130 | inline LuaType luaG_type(lua_State* const L_, StackIndex const idx_) |
127 | { | 131 | { |
128 | return static_cast<LuaType>(lua_type(L_, idx_)); | 132 | return static_cast<LuaType>(lua_type(L_, idx_)); |
129 | } | 133 | } |
@@ -135,9 +139,9 @@ inline LuaType luaG_type(lua_State* const L_, int const idx_) | |||
135 | // ################################################################################################# | 139 | // ################################################################################################# |
136 | 140 | ||
137 | // use this in place of lua_absindex to save a function call | 141 | // use this in place of lua_absindex to save a function call |
138 | inline int luaG_absindex(lua_State* L_, int idx_) | 142 | inline StackIndex luaG_absindex(lua_State* const L_, StackIndex const idx_) |
139 | { | 143 | { |
140 | return (((idx_) >= 0 || (idx_) <= LUA_REGISTRYINDEX) ? (idx_) : lua_gettop(L_) + (idx_) + 1); | 144 | return StackIndex{ (idx_ >= 0 || idx_ <= kIdxRegistry) ? idx_ : lua_gettop(L_) + idx_ + 1 }; |
141 | } | 145 | } |
142 | 146 | ||
143 | // ################################################################################################# | 147 | // ################################################################################################# |
@@ -171,7 +175,7 @@ static inline int luaG_dump(lua_State* const L_, lua_Writer const writer_, void* | |||
171 | 175 | ||
172 | // ################################################################################################# | 176 | // ################################################################################################# |
173 | 177 | ||
174 | int luaG_getalluservalues(lua_State* L_, int idx_); | 178 | int luaG_getalluservalues(lua_State* L_, StackIndex idx_); |
175 | 179 | ||
176 | // ################################################################################################# | 180 | // ################################################################################################# |
177 | 181 | ||
@@ -184,7 +188,7 @@ concept RequiresOldLuaGetfield = requires(LUA_GETFIELD f_) | |||
184 | }; | 188 | }; |
185 | 189 | ||
186 | template <RequiresOldLuaGetfield LUA_GETFIELD> | 190 | template <RequiresOldLuaGetfield LUA_GETFIELD> |
187 | static inline int WrapLuaGetField(LUA_GETFIELD f_, lua_State* const L_, int const idx_, std::string_view const& name_) | 191 | static inline int WrapLuaGetField(LUA_GETFIELD f_, lua_State* const L_, StackIndex const idx_, std::string_view const& name_) |
188 | { | 192 | { |
189 | f_(L_, idx_, name_.data()); | 193 | f_(L_, idx_, name_.data()); |
190 | return lua_type(L_, -1); | 194 | return lua_type(L_, -1); |
@@ -201,14 +205,14 @@ concept RequiresNewLuaGetfield = requires(LUA_GETFIELD f_) | |||
201 | }; | 205 | }; |
202 | 206 | ||
203 | template <RequiresNewLuaGetfield LUA_GETFIELD> | 207 | template <RequiresNewLuaGetfield LUA_GETFIELD> |
204 | static inline int WrapLuaGetField(LUA_GETFIELD f_, lua_State* const L_, int const idx_, std::string_view const& name_) | 208 | static inline int WrapLuaGetField(LUA_GETFIELD f_, lua_State* const L_, StackIndex const idx_, std::string_view const& name_) |
205 | { | 209 | { |
206 | return f_(L_, idx_, name_.data()); | 210 | return f_(L_, idx_, name_.data()); |
207 | } | 211 | } |
208 | 212 | ||
209 | // ------------------------------------------------------------------------------------------------- | 213 | // ------------------------------------------------------------------------------------------------- |
210 | 214 | ||
211 | static inline LuaType luaG_getfield(lua_State* const L_, int const idx_, std::string_view const& name_) | 215 | static inline LuaType luaG_getfield(lua_State* const L_, StackIndex const idx_, std::string_view const& name_) |
212 | { | 216 | { |
213 | return static_cast<LuaType>(WrapLuaGetField(lua_getfield, L_, idx_, name_)); | 217 | return static_cast<LuaType>(WrapLuaGetField(lua_getfield, L_, idx_, name_)); |
214 | } | 218 | } |
@@ -306,14 +310,14 @@ inline void luaG_pushglobaltable(lua_State* const L_) | |||
306 | #ifdef LUA_GLOBALSINDEX // All flavors of Lua 5.1 | 310 | #ifdef LUA_GLOBALSINDEX // All flavors of Lua 5.1 |
307 | ::lua_pushvalue(L_, LUA_GLOBALSINDEX); | 311 | ::lua_pushvalue(L_, LUA_GLOBALSINDEX); |
308 | #else // LUA_GLOBALSINDEX | 312 | #else // LUA_GLOBALSINDEX |
309 | ::lua_rawgeti(L_, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS); | 313 | ::lua_rawgeti(L_, kIdxRegistry, LUA_RIDX_GLOBALS); |
310 | #endif // LUA_GLOBALSINDEX | 314 | #endif // LUA_GLOBALSINDEX |
311 | } | 315 | } |
312 | 316 | ||
313 | // ################################################################################################# | 317 | // ################################################################################################# |
314 | 318 | ||
315 | inline void luaG_setfield(lua_State* const L_, int const idx_, char const* k_) = delete; | 319 | inline void luaG_setfield(lua_State* const L_, StackIndex const idx_, char const* k_) = delete; |
316 | inline void luaG_setfield(lua_State* const L_, int const idx_, std::string_view const& k_) | 320 | inline void luaG_setfield(lua_State* const L_, StackIndex const idx_, std::string_view const& k_) |
317 | { | 321 | { |
318 | lua_setfield(L_, idx_, k_.data()); | 322 | lua_setfield(L_, idx_, k_.data()); |
319 | } | 323 | } |
@@ -336,7 +340,7 @@ inline void luaG_setmetatable(lua_State* const L_, std::string_view const& tname | |||
336 | 340 | ||
337 | // a small helper to extract a full userdata pointer from the stack in a safe way | 341 | // a small helper to extract a full userdata pointer from the stack in a safe way |
338 | template <typename T> | 342 | template <typename T> |
339 | [[nodiscard]] T* luaG_tofulluserdata(lua_State* const L_, int const index_) | 343 | [[nodiscard]] T* luaG_tofulluserdata(lua_State* const L_, StackIndex const index_) |
340 | { | 344 | { |
341 | LUA_ASSERT(L_, lua_isnil(L_, index_) || lua_type(L_, index_) == LUA_TUSERDATA); | 345 | LUA_ASSERT(L_, lua_isnil(L_, index_) || lua_type(L_, index_) == LUA_TUSERDATA); |
342 | return static_cast<T*>(lua_touserdata(L_, index_)); | 346 | return static_cast<T*>(lua_touserdata(L_, index_)); |
@@ -345,7 +349,7 @@ template <typename T> | |||
345 | // ------------------------------------------------------------------------------------------------- | 349 | // ------------------------------------------------------------------------------------------------- |
346 | 350 | ||
347 | template <typename T> | 351 | template <typename T> |
348 | [[nodiscard]] auto luaG_tolightuserdata(lua_State* const L_, int const index_) | 352 | [[nodiscard]] auto luaG_tolightuserdata(lua_State* const L_, StackIndex const index_) |
349 | { | 353 | { |
350 | LUA_ASSERT(L_, lua_isnil(L_, index_) || lua_islightuserdata(L_, index_)); | 354 | LUA_ASSERT(L_, lua_isnil(L_, index_) || lua_islightuserdata(L_, index_)); |
351 | if constexpr (std::is_pointer_v<T>) { | 355 | if constexpr (std::is_pointer_v<T>) { |
@@ -364,7 +368,7 @@ template <typename T> | |||
364 | 368 | ||
365 | // ------------------------------------------------------------------------------------------------- | 369 | // ------------------------------------------------------------------------------------------------- |
366 | 370 | ||
367 | [[nodiscard]] inline std::string_view luaG_typename(lua_State* const L_, int const idx_) | 371 | [[nodiscard]] inline std::string_view luaG_typename(lua_State* const L_, StackIndex const idx_) |
368 | { | 372 | { |
369 | return luaG_typename(L_, luaG_type(L_, idx_)); | 373 | return luaG_typename(L_, luaG_type(L_, idx_)); |
370 | } | 374 | } |
@@ -375,21 +379,21 @@ template <typename T> | |||
375 | #define STRINGVIEW_FMT "%.*s" | 379 | #define STRINGVIEW_FMT "%.*s" |
376 | 380 | ||
377 | // a replacement of lua_tolstring | 381 | // a replacement of lua_tolstring |
378 | [[nodiscard]] inline std::string_view luaG_tostring(lua_State* const L_, int const idx_) | 382 | [[nodiscard]] inline std::string_view luaG_tostring(lua_State* const L_, StackIndex const idx_) |
379 | { | 383 | { |
380 | size_t _len{ 0 }; | 384 | size_t _len{ 0 }; |
381 | char const* _str{ lua_tolstring(L_, idx_, &_len) }; | 385 | char const* _str{ lua_tolstring(L_, idx_, &_len) }; |
382 | return _str ? std::string_view{ _str, _len } : ""; | 386 | return _str ? std::string_view{ _str, _len } : ""; |
383 | } | 387 | } |
384 | 388 | ||
385 | [[nodiscard]] inline std::string_view luaG_checkstring(lua_State* const L_, int const idx_) | 389 | [[nodiscard]] inline std::string_view luaG_checkstring(lua_State* const L_, StackIndex const idx_) |
386 | { | 390 | { |
387 | size_t _len{ 0 }; | 391 | size_t _len{ 0 }; |
388 | char const* _str{ luaL_checklstring(L_, idx_, &_len) }; | 392 | char const* _str{ luaL_checklstring(L_, idx_, &_len) }; |
389 | return std::string_view{ _str, _len }; | 393 | return std::string_view{ _str, _len }; |
390 | } | 394 | } |
391 | 395 | ||
392 | [[nodiscard]] inline std::string_view luaG_optstring(lua_State* const L_, int const idx_, std::string_view const& default_) | 396 | [[nodiscard]] inline std::string_view luaG_optstring(lua_State* const L_, StackIndex const idx_, std::string_view const& default_) |
393 | { | 397 | { |
394 | if (lua_isnoneornil(L_, idx_)) { | 398 | if (lua_isnoneornil(L_, idx_)) { |
395 | return default_; | 399 | return default_; |
@@ -406,7 +410,7 @@ inline std::string_view luaG_pushstring(lua_State* const L_, std::string_view co | |||
406 | if constexpr (LUA_VERSION_NUM == 501) { | 410 | if constexpr (LUA_VERSION_NUM == 501) { |
407 | // lua_pushlstring doesn't return a value in Lua 5.1 | 411 | // lua_pushlstring doesn't return a value in Lua 5.1 |
408 | lua_pushlstring(L_, str_.data(), str_.size()); | 412 | lua_pushlstring(L_, str_.data(), str_.size()); |
409 | return luaG_tostring(L_, -1); | 413 | return luaG_tostring(L_, kIdxTop); |
410 | } else { | 414 | } else { |
411 | return std::string_view{ lua_pushlstring(L_, str_.data(), str_.size()), str_.size() }; | 415 | return std::string_view{ lua_pushlstring(L_, str_.data(), str_.size()), str_.size() }; |
412 | } | 416 | } |
diff --git a/src/debug.h b/src/debug.h index 0f5c6bc..b9a82f1 100644 --- a/src/debug.h +++ b/src/debug.h | |||
@@ -36,8 +36,8 @@ class StackChecker | |||
36 | int oldtop; | 36 | int oldtop; |
37 | 37 | ||
38 | public: | 38 | public: |
39 | using Relative = Unique<int>; | 39 | DECLARE_UNIQUE_TYPE(Relative, int); |
40 | using Absolute = Unique<int>; | 40 | DECLARE_UNIQUE_TYPE(Absolute, int); |
41 | 41 | ||
42 | StackChecker(lua_State* const L_, Relative const offset_, SourceLocation const& where_ = Where()) | 42 | StackChecker(lua_State* const L_, Relative const offset_, SourceLocation const& where_ = Where()) |
43 | : L{ L_ } | 43 | : L{ L_ } |
diff --git a/src/deep.cpp b/src/deep.cpp index bac011f..a244f8b 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{ luaG_tofulluserdata<DeepPrelude*>(L_, 1) }; | 73 | DeepPrelude* const* const _proxy{ luaG_tofulluserdata<DeepPrelude*>(L_, StackIndex{ 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 |
@@ -130,7 +130,7 @@ void DeepFactory::DeleteDeepObject(lua_State* const L_, DeepPrelude* const o_) | |||
130 | 130 | ||
131 | // ################################################################################################# | 131 | // ################################################################################################# |
132 | 132 | ||
133 | bool DeepFactory::IsDeepUserdata(lua_State* const L_, int const idx_) | 133 | bool DeepFactory::IsDeepUserdata(lua_State* const L_, StackIndex const idx_) |
134 | { | 134 | { |
135 | return LookupFactory(L_, idx_, LookupMode::LaneBody) != nullptr; | 135 | return LookupFactory(L_, idx_, LookupMode::LaneBody) != nullptr; |
136 | } | 136 | } |
@@ -138,7 +138,7 @@ bool DeepFactory::IsDeepUserdata(lua_State* const L_, int const idx_) | |||
138 | // ################################################################################################# | 138 | // ################################################################################################# |
139 | 139 | ||
140 | // Return the registered factory for 'index' (deep userdata proxy), or nullptr if 'index' is not a deep userdata proxy. | 140 | // Return the registered factory for 'index' (deep userdata proxy), or nullptr if 'index' is not a deep userdata proxy. |
141 | DeepFactory* DeepFactory::LookupFactory(lua_State* const L_, int const index_, LookupMode const mode_) | 141 | DeepFactory* DeepFactory::LookupFactory(lua_State* const L_, StackIndex const index_, LookupMode const mode_) |
142 | { | 142 | { |
143 | // when looking inside a keeper, we are 100% sure the object is a deep userdata | 143 | // when looking inside a keeper, we are 100% sure the object is a deep userdata |
144 | if (mode_ == LookupMode::FromKeeper) { | 144 | if (mode_ == LookupMode::FromKeeper) { |
@@ -159,7 +159,7 @@ DeepFactory* DeepFactory::LookupFactory(lua_State* const L_, int const index_, L | |||
159 | // replace metatable with the factory pointer, if it is actually a deep userdata | 159 | // replace metatable with the factory pointer, if it is actually a deep userdata |
160 | LookupDeep(L_); // L_: deep ... factory|nil | 160 | LookupDeep(L_); // L_: deep ... factory|nil |
161 | 161 | ||
162 | DeepFactory* const _ret{ luaG_tolightuserdata<DeepFactory>(L_, -1) }; // nullptr if not a userdata | 162 | DeepFactory* const _ret{ luaG_tolightuserdata<DeepFactory>(L_, kIdxTop) }; // nullptr if not a userdata |
163 | lua_pop(L_, 1); | 163 | lua_pop(L_, 1); |
164 | STACK_CHECK(L_, 0); | 164 | STACK_CHECK(L_, 0); |
165 | return _ret; | 165 | return _ret; |
@@ -207,7 +207,7 @@ void DeepFactory::PushDeepProxy(DestState const L_, DeepPrelude* const prelude_, | |||
207 | 207 | ||
208 | if (lua_isnil(L_, -1)) { // No metatable yet. | 208 | if (lua_isnil(L_, -1)) { // No metatable yet. |
209 | lua_pop(L_, 1); // L_: DPC proxy | 209 | lua_pop(L_, 1); // L_: DPC proxy |
210 | int const _oldtop{ lua_gettop(L_) }; | 210 | StackIndex const _oldtop{ lua_gettop(L_) }; |
211 | // 1 - make one and register it | 211 | // 1 - make one and register it |
212 | if (mode_ != LookupMode::ToKeeper) { | 212 | if (mode_ != LookupMode::ToKeeper) { |
213 | _factory.createMetatable(L_); // L_: DPC proxy metatable | 213 | _factory.createMetatable(L_); // L_: DPC proxy metatable |
@@ -216,7 +216,7 @@ void DeepFactory::PushDeepProxy(DestState const L_, DeepPrelude* const prelude_, | |||
216 | raise_luaL_error(errL_, "Bad DeepFactory::createMetatable overload: unexpected pushed value"); | 216 | raise_luaL_error(errL_, "Bad DeepFactory::createMetatable overload: unexpected pushed value"); |
217 | } | 217 | } |
218 | // if the metatable contains a __gc, we will call it from our own | 218 | // if the metatable contains a __gc, we will call it from our own |
219 | std::ignore = luaG_getfield(L_, -1, "__gc"); // L_: DPC proxy metatable __gc | 219 | std::ignore = luaG_getfield(L_, kIdxTop, "__gc"); // L_: DPC proxy metatable __gc |
220 | } else { | 220 | } else { |
221 | // keepers need a minimal metatable that only contains our own __gc | 221 | // keepers need a minimal metatable that only contains our own __gc |
222 | lua_createtable(L_, 0, 1); // L_: DPC proxy metatable | 222 | lua_createtable(L_, 0, 1); // L_: DPC proxy metatable |
@@ -245,7 +245,7 @@ void DeepFactory::PushDeepProxy(DestState const L_, DeepPrelude* const prelude_, | |||
245 | } | 245 | } |
246 | 246 | ||
247 | luaG_pushstring(L_, _modname); // L_: DPC proxy metatable require() "module" | 247 | luaG_pushstring(L_, _modname); // L_: DPC proxy metatable require() "module" |
248 | if (luaG_getfield(L_, LUA_REGISTRYINDEX, LUA_LOADED_TABLE) != LuaType::TABLE) { // L_: DPC proxy metatable require() "module" _R._LOADED | 248 | if (luaG_getfield(L_, kIdxRegistry, LUA_LOADED_TABLE) != LuaType::TABLE) { // L_: DPC proxy metatable require() "module" _R._LOADED |
249 | // no L.registry._LOADED; can this ever happen? | 249 | // no L.registry._LOADED; can this ever happen? |
250 | lua_pop(L_, 6); // L_: | 250 | lua_pop(L_, 6); // L_: |
251 | raise_luaL_error(errL_, "unexpected error while requiring a module identified by DeepFactory::moduleName"); | 251 | raise_luaL_error(errL_, "unexpected error while requiring a module identified by DeepFactory::moduleName"); |
@@ -263,7 +263,7 @@ void DeepFactory::PushDeepProxy(DestState const L_, DeepPrelude* const prelude_, | |||
263 | LuaError const _require_result{ lua_pcall(L_, 1, 0, 0) }; // L_: DPC proxy metatable error? | 263 | LuaError const _require_result{ lua_pcall(L_, 1, 0, 0) }; // L_: DPC proxy metatable error? |
264 | if (_require_result != LuaError::OK) { | 264 | if (_require_result != LuaError::OK) { |
265 | // failed, raise the error in the proper state | 265 | // failed, raise the error in the proper state |
266 | raise_luaL_error(errL_, luaG_tostring(L_, -1)); | 266 | raise_luaL_error(errL_, luaG_tostring(L_, kIdxTop)); |
267 | } | 267 | } |
268 | } | 268 | } |
269 | } else { // already loaded, we are happy | 269 | } else { // already loaded, we are happy |
@@ -272,7 +272,7 @@ void DeepFactory::PushDeepProxy(DestState const L_, DeepPrelude* const prelude_, | |||
272 | } | 272 | } |
273 | } | 273 | } |
274 | STACK_CHECK(L_, 3); // L_: DPC proxy metatable | 274 | STACK_CHECK(L_, 3); // L_: DPC proxy metatable |
275 | LUA_ASSERT(L_, luaG_type(L_, -2) == LuaType::USERDATA); | 275 | LUA_ASSERT(L_, luaG_type(L_, StackIndex{ -2 }) == LuaType::USERDATA); |
276 | LUA_ASSERT(L_, lua_istable(L_, -1)); | 276 | LUA_ASSERT(L_, lua_istable(L_, -1)); |
277 | lua_setmetatable(L_, -2); // L_: DPC proxy | 277 | lua_setmetatable(L_, -2); // L_: DPC proxy |
278 | 278 | ||
@@ -281,7 +281,7 @@ void DeepFactory::PushDeepProxy(DestState const L_, DeepPrelude* const prelude_, | |||
281 | lua_pushvalue(L_, -2); // L_: DPC proxy deep proxy | 281 | lua_pushvalue(L_, -2); // L_: DPC proxy deep proxy |
282 | lua_rawset(L_, -4); // L_: DPC proxy | 282 | lua_rawset(L_, -4); // L_: DPC proxy |
283 | lua_remove(L_, -2); // L_: proxy | 283 | lua_remove(L_, -2); // L_: proxy |
284 | LUA_ASSERT(L_, luaG_type(L_, -1) == LuaType::USERDATA); | 284 | LUA_ASSERT(L_, luaG_type(L_, kIdxTop) == LuaType::USERDATA); |
285 | STACK_CHECK(L_, 1); | 285 | STACK_CHECK(L_, 1); |
286 | } | 286 | } |
287 | 287 | ||
@@ -306,7 +306,7 @@ void DeepFactory::pushDeepUserdata(DestState const L_, int const nuv_) const | |||
306 | { | 306 | { |
307 | STACK_GROW(L_, 1); | 307 | STACK_GROW(L_, 1); |
308 | STACK_CHECK_START_REL(L_, 0); | 308 | STACK_CHECK_START_REL(L_, 0); |
309 | int const _oldtop{ lua_gettop(L_) }; | 309 | StackIndex const _oldtop{ lua_gettop(L_) }; |
310 | DeepPrelude* const _prelude{ newDeepObjectInternal(L_) }; | 310 | DeepPrelude* const _prelude{ newDeepObjectInternal(L_) }; |
311 | if (_prelude == nullptr) { | 311 | if (_prelude == nullptr) { |
312 | raise_luaL_error(L_, "DeepFactory::newDeepObjectInternal failed to create deep userdata (out of memory)"); | 312 | raise_luaL_error(L_, "DeepFactory::newDeepObjectInternal failed to create deep userdata (out of memory)"); |
@@ -365,7 +365,7 @@ void DeepFactory::storeDeepLookup(lua_State* const L_) const | |||
365 | * Reference count is not changed, and access to the deep userdata is not | 365 | * Reference count is not changed, and access to the deep userdata is not |
366 | * serialized. It is the module's responsibility to prevent conflicting usage. | 366 | * serialized. It is the module's responsibility to prevent conflicting usage. |
367 | */ | 367 | */ |
368 | DeepPrelude* DeepFactory::toDeep(lua_State* const L_, int const index_) const | 368 | DeepPrelude* DeepFactory::toDeep(lua_State* const L_, StackIndex const index_) const |
369 | { | 369 | { |
370 | STACK_CHECK_START_REL(L_, 0); | 370 | STACK_CHECK_START_REL(L_, 0); |
371 | // ensure it is actually a deep userdata we created | 371 | // ensure it is actually a deep userdata we created |
@@ -66,11 +66,11 @@ class DeepFactory | |||
66 | public: | 66 | public: |
67 | // NVI: public interface | 67 | // NVI: public interface |
68 | static void DeleteDeepObject(lua_State* L_, DeepPrelude* o_); | 68 | static void DeleteDeepObject(lua_State* L_, DeepPrelude* o_); |
69 | [[nodiscard]] static bool IsDeepUserdata(lua_State* const L_, int const idx_); | 69 | [[nodiscard]] static bool IsDeepUserdata(lua_State* const L_, StackIndex const idx_); |
70 | [[nodiscard]] static DeepFactory* LookupFactory(lua_State* L_, int index_, LookupMode mode_); | 70 | [[nodiscard]] static DeepFactory* LookupFactory(lua_State* L_, StackIndex index_, LookupMode mode_); |
71 | static void PushDeepProxy(DestState L_, DeepPrelude* o_, int nuv_, LookupMode mode_, lua_State* errL_); | 71 | static void PushDeepProxy(DestState L_, DeepPrelude* o_, int nuv_, LookupMode mode_, lua_State* errL_); |
72 | void pushDeepUserdata(DestState L_, int nuv_) const; | 72 | void pushDeepUserdata(DestState L_, int nuv_) const; |
73 | [[nodiscard]] DeepPrelude* toDeep(lua_State* L_, int index_) const; | 73 | [[nodiscard]] DeepPrelude* toDeep(lua_State* L_, StackIndex index_) const; |
74 | }; | 74 | }; |
75 | 75 | ||
76 | // ################################################################################################# | 76 | // ################################################################################################# |
diff --git a/src/intercopycontext.cpp b/src/intercopycontext.cpp index e29132d..d21995c 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_tostring(L1, -1) }; | 103 | std::string_view _fqn{ luaG_tostring(L1, kIdxTop) }; |
104 | DEBUGSPEW_CODE(DebugSpew(U) << "function [C] " << _fqn << std::endl); | 104 | DEBUGSPEW_CODE(DebugSpew(U) << "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 ... |
@@ -108,11 +108,12 @@ THE SOFTWARE. | |||
108 | if (_fqn.empty() && !lua_istable(L1, L1_i)) { // raise an error if we try to send an unknown function (but not for tables) | 108 | if (_fqn.empty() && !lua_istable(L1, L1_i)) { // raise an error if we try to send an unknown function (but not for tables) |
109 | // try to discover the name of the function we want to send | 109 | // try to discover the name of the function we want to send |
110 | kLaneNameRegKey.pushValue(L1); // L1: ... v ... lane_name | 110 | kLaneNameRegKey.pushValue(L1); // L1: ... v ... lane_name |
111 | std::string_view const _from{ luaG_tostring(L1, -1) }; | 111 | std::string_view const _from{ luaG_tostring(L1, kIdxTop) }; |
112 | lua_pushcfunction(L1, LG_nameof); // L1: ... v ... lane_name LG_nameof | 112 | lua_pushcfunction(L1, LG_nameof); // L1: ... v ... lane_name LG_nameof |
113 | lua_pushvalue(L1, L1_i); // L1: ... v ... lane_name LG_nameof t | 113 | lua_pushvalue(L1, L1_i); // L1: ... v ... lane_name LG_nameof t |
114 | lua_call(L1, 1, 2); // L1: ... v ... lane_name "type" "name"|nil | 114 | lua_call(L1, 1, 2); // L1: ... v ... lane_name "type" "name"|nil |
115 | std::string_view const _typewhat{ (luaG_type(L1, -2) == LuaType::STRING) ? luaG_tostring(L1, -2) : luaG_typename(L1, -2) }; | 115 | StackIndex const _indexTypeWhat{ -2 }; |
116 | std::string_view const _typewhat{ (luaG_type(L1, _indexTypeWhat) == LuaType::STRING) ? luaG_tostring(L1, _indexTypeWhat) : luaG_typename(L1, _indexTypeWhat) }; | ||
116 | // second return value can be nil if the table was not found | 117 | // second return value can be nil if the table was not found |
117 | // probable reason: the function was removed from the source Lua state before Lanes was required. | 118 | // probable reason: the function was removed from the source Lua state before Lanes was required. |
118 | std::string_view _what, _gotchaA, _gotchaB; | 119 | std::string_view _what, _gotchaA, _gotchaB; |
@@ -123,7 +124,8 @@ THE SOFTWARE. | |||
123 | } else { | 124 | } else { |
124 | _gotchaA = ""; | 125 | _gotchaA = ""; |
125 | _gotchaB = ""; | 126 | _gotchaB = ""; |
126 | _what = (luaG_type(L1, -1) == LuaType::STRING) ? luaG_tostring(L1, -1) : luaG_typename(L1, -1); | 127 | StackIndex const _indexWhat{ kIdxTop }; |
128 | _what = (luaG_type(L1, _indexWhat) == LuaType::STRING) ? luaG_tostring(L1, _indexWhat) : luaG_typename(L1, _indexWhat); | ||
127 | } | 129 | } |
128 | raise_luaL_error(L1, "%s%s '%s' not found in %s origin transfer database.%s", _typewhat.data(), _gotchaA.data(), _what.data(), _from.empty() ? "main" : _from.data(), _gotchaB.data()); | 130 | raise_luaL_error(L1, "%s%s '%s' not found in %s origin transfer database.%s", _typewhat.data(), _gotchaA.data(), _what.data(), _from.empty() ? "main" : _from.data(), _gotchaB.data()); |
129 | } | 131 | } |
@@ -139,15 +141,15 @@ THE SOFTWARE. | |||
139 | static constexpr RegistryUniqueKey kMtIdRegKey{ 0xA8895DCF4EC3FE3Cull }; | 141 | static constexpr RegistryUniqueKey kMtIdRegKey{ 0xA8895DCF4EC3FE3Cull }; |
140 | 142 | ||
141 | // get a unique ID for metatable at [i]. | 143 | // get a unique ID for metatable at [i]. |
142 | [[nodiscard]] static lua_Integer get_mt_id(Universe* U_, lua_State* L_, int idx_) | 144 | [[nodiscard]] static lua_Integer get_mt_id(Universe* U_, lua_State* L_, StackIndex const idx_) |
143 | { | 145 | { |
144 | idx_ = luaG_absindex(L_, idx_); | 146 | StackIndex const _absidx{ luaG_absindex(L_, idx_) }; |
145 | 147 | ||
146 | STACK_GROW(L_, 3); | 148 | STACK_GROW(L_, 3); |
147 | 149 | ||
148 | STACK_CHECK_START_REL(L_, 0); | 150 | STACK_CHECK_START_REL(L_, 0); |
149 | std::ignore = kMtIdRegKey.getSubTable(L_, 0, 0); // L_: ... _R[kMtIdRegKey] | 151 | std::ignore = kMtIdRegKey.getSubTable(L_, 0, 0); // L_: ... _R[kMtIdRegKey] |
150 | lua_pushvalue(L_, idx_); // L_: ... _R[kMtIdRegKey] {mt} | 152 | lua_pushvalue(L_, _absidx); // L_: ... _R[kMtIdRegKey] {mt} |
151 | lua_rawget(L_, -2); // L_: ... _R[kMtIdRegKey] mtk? | 153 | lua_rawget(L_, -2); // L_: ... _R[kMtIdRegKey] mtk? |
152 | 154 | ||
153 | lua_Integer _id{ lua_tointeger(L_, -1) }; // 0 for nil | 155 | lua_Integer _id{ lua_tointeger(L_, -1) }; // 0 for nil |
@@ -158,12 +160,12 @@ static constexpr RegistryUniqueKey kMtIdRegKey{ 0xA8895DCF4EC3FE3Cull }; | |||
158 | _id = U_->nextMetatableId.fetch_add(1, std::memory_order_relaxed); | 160 | _id = U_->nextMetatableId.fetch_add(1, std::memory_order_relaxed); |
159 | 161 | ||
160 | // Create two-way references: id_uint <-> table | 162 | // Create two-way references: id_uint <-> table |
161 | lua_pushvalue(L_, idx_); // L_: ... _R[kMtIdRegKey] {mt} | 163 | lua_pushvalue(L_, _absidx); // L_: ... _R[kMtIdRegKey] {mt} |
162 | lua_pushinteger(L_, _id); // L_: ... _R[kMtIdRegKey] {mt} id | 164 | lua_pushinteger(L_, _id); // L_: ... _R[kMtIdRegKey] {mt} id |
163 | lua_rawset(L_, -3); // L_: ... _R[kMtIdRegKey] | 165 | lua_rawset(L_, -3); // L_: ... _R[kMtIdRegKey] |
164 | 166 | ||
165 | lua_pushinteger(L_, _id); // L_: ... _R[kMtIdRegKey] id | 167 | lua_pushinteger(L_, _id); // L_: ... _R[kMtIdRegKey] id |
166 | lua_pushvalue(L_, idx_); // L_: ... _R[kMtIdRegKey] id {mt} | 168 | lua_pushvalue(L_, _absidx); // L_: ... _R[kMtIdRegKey] id {mt} |
167 | lua_rawset(L_, -3); // L_: ... _R[kMtIdRegKey] | 169 | lua_rawset(L_, -3); // L_: ... _R[kMtIdRegKey] |
168 | } | 170 | } |
169 | lua_pop(L_, 1); // L_: ... | 171 | lua_pop(L_, 1); // L_: ... |
@@ -223,7 +225,7 @@ void InterCopyContext::copyFunction() const | |||
223 | } | 225 | } |
224 | 226 | ||
225 | { | 227 | { |
226 | std::string_view const _bytecode{ luaG_tostring(L1, -1) }; // L1: ... b | 228 | std::string_view const _bytecode{ luaG_tostring(L1, kIdxTop) }; // L1: ... b |
227 | LUA_ASSERT(L1, !_bytecode.empty()); | 229 | LUA_ASSERT(L1, !_bytecode.empty()); |
228 | STACK_GROW(L2, 2); | 230 | STACK_GROW(L2, 2); |
229 | // Note: Line numbers seem to be taken precisely from the | 231 | // Note: Line numbers seem to be taken precisely from the |
@@ -282,7 +284,7 @@ void InterCopyContext::copyFunction() const | |||
282 | STACK_CHECK(L1, 0); | 284 | STACK_CHECK(L1, 0); |
283 | 285 | ||
284 | // Set upvalues (originally set to 'nil' by 'lua_load') | 286 | // Set upvalues (originally set to 'nil' by 'lua_load') |
285 | for (int const _func_index{ lua_gettop(L2) - _n }; _n > 0; --_n) { | 287 | for (StackIndex const _func_index{ lua_gettop(L2) - _n }; _n > 0; --_n) { |
286 | // assign upvalue, popping it from the stack | 288 | // assign upvalue, popping it from the stack |
287 | [[maybe_unused]] std::string_view const _upname{ lua_setupvalue(L2, _func_index, _n) };// L2: ... {cache} ... function | 289 | [[maybe_unused]] std::string_view const _upname{ lua_setupvalue(L2, _func_index, _n) };// L2: ... {cache} ... function |
288 | LUA_ASSERT(L1, !_upname.empty()); // not having enough slots? | 290 | LUA_ASSERT(L1, !_upname.empty()); // not having enough slots? |
@@ -325,10 +327,10 @@ void InterCopyContext::lookupNativeFunction() const | |||
325 | // anything other than function or table should not happen! | 327 | // anything other than function or table should not happen! |
326 | if (!lua_isfunction(L2, -1) && !lua_istable(L2, -1)) { | 328 | if (!lua_isfunction(L2, -1) && !lua_istable(L2, -1)) { |
327 | kLaneNameRegKey.pushValue(L1); // L1: ... f ... lane_name | 329 | kLaneNameRegKey.pushValue(L1); // L1: ... f ... lane_name |
328 | std::string_view const _from{ luaG_tostring(L1, -1) }; | 330 | std::string_view const _from{ luaG_tostring(L1, kIdxTop) }; |
329 | lua_pop(L1, 1); // L1: ... f ... | 331 | lua_pop(L1, 1); // L1: ... f ... |
330 | kLaneNameRegKey.pushValue(L2); // L1: ... f ... L2: {} f lane_name | 332 | kLaneNameRegKey.pushValue(L2); // L1: ... f ... L2: {} f lane_name |
331 | std::string_view const _to{ luaG_tostring(L2, -1) }; | 333 | std::string_view const _to{ luaG_tostring(L2, kIdxTop) }; |
332 | lua_pop(L2, 1); // L2: {} f | 334 | lua_pop(L2, 1); // L2: {} f |
333 | raise_luaL_error( | 335 | raise_luaL_error( |
334 | getErrL(), | 336 | getErrL(), |
@@ -433,17 +435,17 @@ void InterCopyContext::copyCachedFunction() const | |||
433 | return false; | 435 | return false; |
434 | } else if (!lua_istable(L2, -1)) { // this can happen if someone decides to replace same already registered item (for a example a standard lib function) with a table | 436 | } else if (!lua_istable(L2, -1)) { // this can happen if someone decides to replace same already registered item (for a example a standard lib function) with a table |
435 | kLaneNameRegKey.pushValue(L1); // L1: ... t ... lane_name | 437 | kLaneNameRegKey.pushValue(L1); // L1: ... t ... lane_name |
436 | std::string_view const _from{ luaG_tostring(L1, -1) }; | 438 | std::string_view const _from{ luaG_tostring(L1, kIdxTop) }; |
437 | lua_pop(L1, 1); // L1: ... t ... | 439 | lua_pop(L1, 1); // L1: ... t ... |
438 | kLaneNameRegKey.pushValue(L2); // L1: ... t ... L2: {} t lane_name | 440 | kLaneNameRegKey.pushValue(L2); // L1: ... t ... L2: {} t lane_name |
439 | std::string_view const _to{ luaG_tostring(L2, -1) }; | 441 | std::string_view const _to{ luaG_tostring(L2, kIdxTop) }; |
440 | lua_pop(L2, 1); // L1: ... t ... L2: {} t | 442 | lua_pop(L2, 1); // L1: ... t ... L2: {} t |
441 | raise_luaL_error( | 443 | raise_luaL_error( |
442 | getErrL(), | 444 | getErrL(), |
443 | "%s: source table '%s' found as %s in %s destination transfer database.", | 445 | "%s: source table '%s' found as %s in %s destination transfer database.", |
444 | _from.empty() ? "main" : _from.data(), | 446 | _from.empty() ? "main" : _from.data(), |
445 | _fqn.data(), | 447 | _fqn.data(), |
446 | luaG_typename(L2, -1).data(), | 448 | luaG_typename(L2, kIdxTop).data(), |
447 | _to.empty() ? "main" : _to.data()); | 449 | _to.empty() ? "main" : _to.data()); |
448 | } | 450 | } |
449 | lua_remove(L2, -2); // L1: ... t ... L2: t | 451 | lua_remove(L2, -2); // L1: ... t ... L2: t |
@@ -490,13 +492,13 @@ void InterCopyContext::interCopyKeyValuePair() const | |||
490 | _valPath = (char*) alloca(name.size() + 32 + 3); // +3 for [] and terminating 0 | 492 | _valPath = (char*) alloca(name.size() + 32 + 3); // +3 for [] and terminating 0 |
491 | sprintf(_valPath, "%s[" LUA_NUMBER_FMT "]", name.data(), key); | 493 | sprintf(_valPath, "%s[" LUA_NUMBER_FMT "]", name.data(), key); |
492 | } else if (luaG_type(L1, _key_i) == LuaType::LIGHTUSERDATA) { | 494 | } else if (luaG_type(L1, _key_i) == LuaType::LIGHTUSERDATA) { |
493 | void* const key{ lua_touserdata(L1, _key_i) }; | 495 | void* const _key{ lua_touserdata(L1, _key_i) }; |
494 | _valPath = (char*) alloca(name.size() + 16 + 5); // +5 for [U:] and terminating 0 | 496 | _valPath = (char*) alloca(name.size() + 16 + 5); // +5 for [U:] and terminating 0 |
495 | sprintf(_valPath, "%s[U:%p]", name.data(), key); | 497 | sprintf(_valPath, "%s[U:%p]", name.data(), _key); |
496 | } else if (luaG_type(L1, _key_i) == LuaType::BOOLEAN) { | 498 | } else if (luaG_type(L1, _key_i) == LuaType::BOOLEAN) { |
497 | int const key{ lua_toboolean(L1, _key_i) }; | 499 | int const _key{ lua_toboolean(L1, _key_i) }; |
498 | _valPath = (char*) alloca(name.size() + 8); // +8 for [], 'false' and terminating 0 | 500 | _valPath = (char*) alloca(name.size() + 8); // +8 for [], 'false' and terminating 0 |
499 | sprintf(_valPath, "%s[%s]", name.data(), key ? "true" : "false"); | 501 | sprintf(_valPath, "%s[%s]", name.data(), _key ? "true" : "false"); |
500 | } | 502 | } |
501 | } | 503 | } |
502 | 504 | ||
@@ -533,7 +535,7 @@ LuaType InterCopyContext::processConversion() const | |||
533 | } | 535 | } |
534 | // we have a metatable // L1: ... mt | 536 | // we have a metatable // L1: ... mt |
535 | static constexpr std::string_view kConvertField{ "__lanesconvert" }; | 537 | static constexpr std::string_view kConvertField{ "__lanesconvert" }; |
536 | LuaType const _converterType{ luaG_getfield(L1, -1, kConvertField) }; // L1: ... mt kConvertField | 538 | LuaType const _converterType{ luaG_getfield(L1, kIdxTop, kConvertField) }; // L1: ... mt kConvertField |
537 | switch (_converterType) { | 539 | switch (_converterType) { |
538 | case LuaType::NIL: | 540 | case LuaType::NIL: |
539 | // no __lanesconvert, nothing to do | 541 | // no __lanesconvert, nothing to do |
@@ -541,7 +543,7 @@ LuaType InterCopyContext::processConversion() const | |||
541 | break; | 543 | break; |
542 | 544 | ||
543 | case LuaType::LIGHTUSERDATA: | 545 | case LuaType::LIGHTUSERDATA: |
544 | if (kNilSentinel.equals(L1, -1)) { | 546 | if (kNilSentinel.equals(L1, kIdxTop)) { |
545 | DEBUGSPEW_CODE(DebugSpew(U) << "converted " << luaG_typename(L1, _val_type) << " to nil" << std::endl); | 547 | DEBUGSPEW_CODE(DebugSpew(U) << "converted " << luaG_typename(L1, _val_type) << " to nil" << std::endl); |
546 | lua_replace(L1, L1_i); // L1: ... mt | 548 | lua_replace(L1, L1_i); // L1: ... mt |
547 | lua_pop(L1, 1); // L1: ... | 549 | lua_pop(L1, 1); // L1: ... |
@@ -553,7 +555,7 @@ LuaType InterCopyContext::processConversion() const | |||
553 | 555 | ||
554 | case LuaType::STRING: | 556 | case LuaType::STRING: |
555 | // kConvertField == "decay" -> replace source value with it's pointer | 557 | // kConvertField == "decay" -> replace source value with it's pointer |
556 | if (std::string_view const _mode{ luaG_tostring(L1, -1) }; _mode == "decay") { | 558 | if (std::string_view const _mode{ luaG_tostring(L1, kIdxTop) }; _mode == "decay") { |
557 | lua_pop(L1, 1); // L1: ... mt | 559 | lua_pop(L1, 1); // L1: ... mt |
558 | lua_pushlightuserdata(L1, const_cast<void*>(lua_topointer(L1, L1_i))); // L1: ... mt decayed | 560 | lua_pushlightuserdata(L1, const_cast<void*>(lua_topointer(L1, L1_i))); // L1: ... mt decayed |
559 | lua_replace(L1, L1_i); // L1: ... mt | 561 | lua_replace(L1, L1_i); // L1: ... mt |
@@ -592,7 +594,7 @@ LuaType InterCopyContext::processConversion() const | |||
592 | } | 594 | } |
593 | STACK_CHECK(L1, 1); | 595 | STACK_CHECK(L1, 1); |
594 | 596 | ||
595 | lua_Integer const _mt_id{ get_mt_id(U, L1, -1) }; // Unique id for the metatable | 597 | lua_Integer const _mt_id{ get_mt_id(U, L1, kIdxTop) }; // Unique id for the metatable |
596 | 598 | ||
597 | STACK_CHECK_START_REL(L2, 0); | 599 | STACK_CHECK_START_REL(L2, 0); |
598 | STACK_GROW(L2, 4); | 600 | STACK_GROW(L2, 4); |
@@ -693,7 +695,7 @@ LuaType InterCopyContext::processConversion() const | |||
693 | } | 695 | } |
694 | 696 | ||
695 | // no __lanesclone? -> not clonable | 697 | // no __lanesclone? -> not clonable |
696 | if (luaG_getfield(L1, -1, "__lanesclone") == LuaType::NIL) { // L1: ... mt nil | 698 | if (luaG_getfield(L1, kIdxTop, "__lanesclone") == LuaType::NIL) { // L1: ... mt nil |
697 | lua_pop(L1, 2); // L1: ... | 699 | lua_pop(L1, 2); // L1: ... |
698 | STACK_CHECK(L1, 0); | 700 | STACK_CHECK(L1, 0); |
699 | return false; | 701 | return false; |
@@ -703,7 +705,7 @@ LuaType InterCopyContext::processConversion() const | |||
703 | 705 | ||
704 | // we need to copy over the uservalues of the userdata as well | 706 | // we need to copy over the uservalues of the userdata as well |
705 | { | 707 | { |
706 | int const _mt{ luaG_absindex(L1, -2) }; // L1: ... mt __lanesclone | 708 | StackIndex const _mt{ luaG_absindex(L1, StackIndex{ -2 }) }; // L1: ... mt __lanesclone |
707 | size_t const userdata_size{ lua_rawlen(L1, _L1_i) }; | 709 | size_t const userdata_size{ lua_rawlen(L1, _L1_i) }; |
708 | // extract all the uservalues, but don't transfer them yet | 710 | // extract all the uservalues, but don't transfer them yet |
709 | int const _nuv{ luaG_getalluservalues(L1, _L1_i) }; // L1: ... mt __lanesclone [uv]* | 711 | int const _nuv{ luaG_getalluservalues(L1, _L1_i) }; // L1: ... mt __lanesclone [uv]* |
@@ -738,13 +740,13 @@ LuaType InterCopyContext::processConversion() const | |||
738 | // assign uservalues | 740 | // assign uservalues |
739 | int _uvi{ _nuv }; | 741 | int _uvi{ _nuv }; |
740 | while (_uvi > 0) { | 742 | while (_uvi > 0) { |
741 | _c.L1_i = SourceIndex{ luaG_absindex(L1, -1) }; | 743 | _c.L1_i = SourceIndex{ luaG_absindex(L1, kIdxTop) }; |
742 | if (_c.interCopyOne() != InterCopyResult::Success) { // L2: ... u uv | 744 | if (_c.interCopyOne() != InterCopyResult::Success) { // L2: ... u uv |
743 | raise_luaL_error(getErrL(), "Cannot copy upvalue type '%s'", luaL_typename(L1, -1)); | 745 | raise_luaL_error(getErrL(), "Cannot copy upvalue type '%s'", luaL_typename(L1, -1)); |
744 | } | 746 | } |
745 | lua_pop(L1, 1); // L1: ... mt __lanesclone [uv]* | 747 | lua_pop(L1, 1); // L1: ... mt __lanesclone [uv]* |
746 | // this pops the value from the stack | 748 | // this pops the value from the stack |
747 | lua_setiuservalue(L2, -2, _uvi); // L2: ... u | 749 | lua_setiuservalue(L2, StackIndex{ -2 }, _uvi); // L2: ... u |
748 | --_uvi; | 750 | --_uvi; |
749 | } | 751 | } |
750 | // when we are done, all uservalues are popped from the source stack, and we want only the single transferred value in the destination | 752 | // when we are done, all uservalues are popped from the source stack, and we want only the single transferred value in the destination |
@@ -792,11 +794,11 @@ LuaType InterCopyContext::processConversion() const | |||
792 | // transfer all uservalues of the source in the destination | 794 | // transfer all uservalues of the source in the destination |
793 | { | 795 | { |
794 | InterCopyContext _c{ U, L2, L1, L2_cache_i, {}, VT::NORMAL, mode, name }; | 796 | InterCopyContext _c{ U, L2, L1, L2_cache_i, {}, VT::NORMAL, mode, name }; |
795 | int const _clone_i{ lua_gettop(L2) }; | 797 | StackIndex const _clone_i{ lua_gettop(L2) }; |
796 | STACK_GROW(L2, _nuv); | 798 | STACK_GROW(L2, _nuv); |
797 | int _uvi{ _nuv }; | 799 | int _uvi{ _nuv }; |
798 | while (_uvi) { | 800 | while (_uvi) { |
799 | _c.L1_i = SourceIndex{ luaG_absindex(L1, -1) }; | 801 | _c.L1_i = SourceIndex{ luaG_absindex(L1, kIdxTop) }; |
800 | if (_c.interCopyOne() != InterCopyResult::Success) { // L1: ... deep ... [uv]* L2: deep uv | 802 | if (_c.interCopyOne() != InterCopyResult::Success) { // L1: ... deep ... [uv]* L2: deep uv |
801 | raise_luaL_error(getErrL(), "Cannot copy upvalue type '%s'", luaL_typename(L1, -1)); | 803 | raise_luaL_error(getErrL(), "Cannot copy upvalue type '%s'", luaL_typename(L1, -1)); |
802 | } | 804 | } |
@@ -862,7 +864,7 @@ LuaType InterCopyContext::processConversion() const | |||
862 | _source = lua_touserdata(L1, -1); | 864 | _source = lua_touserdata(L1, -1); |
863 | void* _clone{ nullptr }; | 865 | void* _clone{ nullptr }; |
864 | // get the number of bytes to allocate for the clone | 866 | // get the number of bytes to allocate for the clone |
865 | size_t const userdata_size{ lua_rawlen(L1, -1) }; | 867 | size_t const userdata_size{ lua_rawlen(L1, kIdxTop) }; |
866 | { | 868 | { |
867 | // extract uservalues (don't transfer them yet) | 869 | // extract uservalues (don't transfer them yet) |
868 | int const _nuv{ luaG_getalluservalues(L1, source_i) }; // L1: ... u [uv]* | 870 | int const _nuv{ luaG_getalluservalues(L1, source_i) }; // L1: ... u [uv]* |
@@ -880,13 +882,13 @@ LuaType InterCopyContext::processConversion() const | |||
880 | InterCopyContext _c{ *this }; | 882 | InterCopyContext _c{ *this }; |
881 | int _uvi{ _nuv }; | 883 | int _uvi{ _nuv }; |
882 | while (_uvi > 0) { | 884 | while (_uvi > 0) { |
883 | _c.L1_i = SourceIndex{ luaG_absindex(L1, -1) }; | 885 | _c.L1_i = SourceIndex{ luaG_absindex(L1, kIdxTop) }; |
884 | if (_c.interCopyOne() != InterCopyResult::Success) { // L2: ... mt u uv | 886 | if (_c.interCopyOne() != InterCopyResult::Success) { // L2: ... mt u uv |
885 | raise_luaL_error(getErrL(), "Cannot copy upvalue type '%s'", luaL_typename(L1, -1)); | 887 | raise_luaL_error(getErrL(), "Cannot copy upvalue type '%s'", luaL_typename(L1, -1)); |
886 | } | 888 | } |
887 | lua_pop(L1, 1); // L1: ... u [uv]* | 889 | lua_pop(L1, 1); // L1: ... u [uv]* |
888 | // this pops the value from the stack | 890 | // this pops the value from the stack |
889 | lua_setiuservalue(L2, -2, _uvi); // L2: ... mt u | 891 | lua_setiuservalue(L2, StackIndex{ -2 }, _uvi); // L2: ... mt u |
890 | --_uvi; | 892 | --_uvi; |
891 | } | 893 | } |
892 | // when we are done, all uservalues are popped from the stack, we can pop the source as well | 894 | // when we are done, all uservalues are popped from the stack, we can pop the source as well |
@@ -897,7 +899,7 @@ LuaType InterCopyContext::processConversion() const | |||
897 | // perform the custom cloning part | 899 | // perform the custom cloning part |
898 | lua_insert(L2, -2); // L2: ... u mt | 900 | lua_insert(L2, -2); // L2: ... u mt |
899 | // __lanesclone should always exist because we wouldn't be restoring data from a userdata_clone_sentinel closure to begin with | 901 | // __lanesclone should always exist because we wouldn't be restoring data from a userdata_clone_sentinel closure to begin with |
900 | LuaType const _funcType{ luaG_getfield(L2, -1, "__lanesclone") }; // L2: ... u mt __lanesclone | 902 | LuaType const _funcType{ luaG_getfield(L2, kIdxTop, "__lanesclone") }; // L2: ... u mt __lanesclone |
901 | if (_funcType != LuaType::FUNCTION) { | 903 | if (_funcType != LuaType::FUNCTION) { |
902 | raise_luaL_error(getErrL(), "INTERNAL ERROR: __lanesclone is a %s, not a function", luaG_typename(L2, _funcType).data()); | 904 | raise_luaL_error(getErrL(), "INTERNAL ERROR: __lanesclone is a %s, not a function", luaG_typename(L2, _funcType).data()); |
903 | } | 905 | } |
@@ -1191,7 +1193,7 @@ namespace { | |||
1191 | { | 1193 | { |
1192 | private: | 1194 | private: |
1193 | lua_State* const L2; | 1195 | lua_State* const L2; |
1194 | int const top_L2; | 1196 | StackIndex const top_L2; |
1195 | DEBUGSPEW_CODE(DebugSpewIndentScope scope); | 1197 | DEBUGSPEW_CODE(DebugSpewIndentScope scope); |
1196 | 1198 | ||
1197 | public: | 1199 | public: |
@@ -1246,7 +1248,7 @@ namespace { | |||
1246 | STACK_CHECK(L1, 0); | 1248 | STACK_CHECK(L1, 0); |
1247 | } | 1249 | } |
1248 | if (_result == InterCopyResult::Success) { | 1250 | if (_result == InterCopyResult::Success) { |
1249 | luaG_setfield(L2, -2, _entry); // set package[entry] | 1251 | luaG_setfield(L2, StackIndex{ -2 }, _entry); // set package[entry] |
1250 | } else { | 1252 | } else { |
1251 | std::string_view const _msg{ luaG_pushstring(L1, "failed to copy package.%s", _entry.data()) }; | 1253 | std::string_view const _msg{ luaG_pushstring(L1, "failed to copy package.%s", _entry.data()) }; |
1252 | // raise the error when copying from lane to lane, else just leave it on the stack to be raised later | 1254 | // raise the error when copying from lane to lane, else just leave it on the stack to be raised later |
@@ -1273,7 +1275,7 @@ namespace { | |||
1273 | DEBUGSPEW_CODE(DebugSpew(U) << "InterCopyContext::interCopy()" << std::endl); | 1275 | DEBUGSPEW_CODE(DebugSpew(U) << "InterCopyContext::interCopy()" << std::endl); |
1274 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ U }); | 1276 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ U }); |
1275 | 1277 | ||
1276 | int const _top_L1{ lua_gettop(L1) }; | 1278 | StackIndex const _top_L1{ lua_gettop(L1) }; |
1277 | int const _available{ (L1_i != 0) ? (_top_L1 - L1_i + 1) : _top_L1 }; | 1279 | int const _available{ (L1_i != 0) ? (_top_L1 - L1_i + 1) : _top_L1 }; |
1278 | if (n_ > _available) { | 1280 | if (n_ > _available) { |
1279 | // requesting to copy more than is available? | 1281 | // requesting to copy more than is available? |
@@ -1289,17 +1291,17 @@ namespace { | |||
1289 | * function entries, avoiding the same entries to be passed on as multiple | 1291 | * function entries, avoiding the same entries to be passed on as multiple |
1290 | * copies. ESSENTIAL i.e. for handling upvalue tables in the right manner! | 1292 | * copies. ESSENTIAL i.e. for handling upvalue tables in the right manner! |
1291 | */ | 1293 | */ |
1292 | int const _top_L2{ lua_gettop(L2) }; // L2: ... | 1294 | StackIndex const _top_L2{ lua_gettop(L2) }; // L2: ... |
1293 | lua_newtable(L2); // L2: ... cache | 1295 | lua_newtable(L2); // L2: ... cache |
1294 | 1296 | ||
1295 | InterCopyContext _c{ U, L2, L1, CacheIndex{ _top_L2 + 1 }, {}, VT::NORMAL, mode, "?" }; | 1297 | InterCopyContext _c{ U, L2, L1, CacheIndex{ _top_L2 + 1 }, {}, VT::NORMAL, mode, "?" }; |
1296 | InterCopyResult _copyok{ InterCopyResult::Success }; | 1298 | InterCopyResult _copyok{ InterCopyResult::Success }; |
1297 | STACK_CHECK_START_REL(L1, 0); | 1299 | STACK_CHECK_START_REL(L1, 0); |
1298 | // if L1_i is specified, start here, else take the _n items off the top of the stack | 1300 | // if L1_i is specified, start here, else take the _n items off the top of the stack |
1299 | for (int _i{ L1_i != 0 ? L1_i : (_top_L1 - n_ + 1) }, _j{ 1 }; _j <= n_; ++_i, ++_j) { | 1301 | for (StackIndex _i{ L1_i != 0 ? L1_i : (_top_L1 - n_ + 1) }, _j{ 1 }; _j <= n_; ++_i, ++_j) { |
1300 | char _tmpBuf[16]; | 1302 | char _tmpBuf[16]; |
1301 | if (U->verboseErrors) { | 1303 | if (U->verboseErrors) { |
1302 | sprintf(_tmpBuf, "arg_%d", _j); | 1304 | sprintf(_tmpBuf, "arg_%d", _j.operator int()); |
1303 | _c.name = _tmpBuf; | 1305 | _c.name = _tmpBuf; |
1304 | } | 1306 | } |
1305 | _c.L1_i = SourceIndex{ _i }; | 1307 | _c.L1_i = SourceIndex{ _i }; |
diff --git a/src/intercopycontext.h b/src/intercopycontext.h index 8d4b68f..a9be267 100644 --- a/src/intercopycontext.h +++ b/src/intercopycontext.h | |||
@@ -23,8 +23,8 @@ enum class InterCopyResult | |||
23 | 23 | ||
24 | // ################################################################################################# | 24 | // ################################################################################################# |
25 | 25 | ||
26 | using CacheIndex = Unique<int>; | 26 | DECLARE_UNIQUE_TYPE(CacheIndex, StackIndex); |
27 | using SourceIndex = Unique<int>; | 27 | DECLARE_UNIQUE_TYPE(SourceIndex, StackIndex); |
28 | class InterCopyContext | 28 | class InterCopyContext |
29 | { | 29 | { |
30 | public: | 30 | public: |
diff --git a/src/keeper.cpp b/src/keeper.cpp index 58796b8..46f580b 100644 --- a/src/keeper.cpp +++ b/src/keeper.cpp | |||
@@ -82,10 +82,10 @@ class KeyUD | |||
82 | 82 | ||
83 | [[nodiscard]] bool changeLimit(LindaLimit limit_); | 83 | [[nodiscard]] bool changeLimit(LindaLimit limit_); |
84 | [[nodiscard]] static KeyUD* Create(KeeperState K_); | 84 | [[nodiscard]] static KeyUD* Create(KeeperState K_); |
85 | [[nodiscard]] static KeyUD* GetPtr(KeeperState K_, int idx_); | 85 | [[nodiscard]] static KeyUD* GetPtr(KeeperState K_, StackIndex idx_); |
86 | void peek(KeeperState K_, int count_) const; // keepercall_get | 86 | void peek(KeeperState K_, int count_) const; // keepercall_get |
87 | [[nodiscard]] int pop(KeeperState K_, int minCount_, int maxCount_); // keepercall_receive[_batched] | 87 | [[nodiscard]] int pop(KeeperState K_, int minCount_, int maxCount_); // keepercall_receive[_batched] |
88 | void prepareAccess(KeeperState K_, int idx_) const; | 88 | void prepareAccess(KeeperState K_, StackIndex idx_) const; |
89 | [[nodiscard]] bool push(KeeperState K_, int count_, bool enforceLimit_); // keepercall_send and keepercall_set | 89 | [[nodiscard]] bool push(KeeperState K_, int count_, bool enforceLimit_); // keepercall_send and keepercall_set |
90 | void pushFillStatus(KeeperState K_) const; | 90 | void pushFillStatus(KeeperState K_) const; |
91 | static void PushFillStatus(KeeperState K_, KeyUD const* key_); | 91 | static void PushFillStatus(KeeperState K_, KeyUD const* key_); |
@@ -116,14 +116,14 @@ KeyUD* KeyUD::Create(KeeperState const K_) | |||
116 | KeyUD* const _key{ new (K_) KeyUD{} }; | 116 | KeyUD* const _key{ new (K_) KeyUD{} }; |
117 | STACK_CHECK(K_, 1); | 117 | STACK_CHECK(K_, 1); |
118 | lua_newtable(K_); | 118 | lua_newtable(K_); |
119 | lua_setiuservalue(K_, -2, kContentsTableIndex); | 119 | lua_setiuservalue(K_, StackIndex{ -2 }, kContentsTableIndex); |
120 | STACK_CHECK(K_, 1); | 120 | STACK_CHECK(K_, 1); |
121 | return _key; | 121 | return _key; |
122 | } | 122 | } |
123 | 123 | ||
124 | // ################################################################################################# | 124 | // ################################################################################################# |
125 | 125 | ||
126 | KeyUD* KeyUD::GetPtr(KeeperState const K_, int idx_) | 126 | KeyUD* KeyUD::GetPtr(KeeperState const K_, StackIndex const idx_) |
127 | { | 127 | { |
128 | return luaG_tofulluserdata<KeyUD>(K_, idx_); | 128 | return luaG_tofulluserdata<KeyUD>(K_, idx_); |
129 | } | 129 | } |
@@ -137,7 +137,7 @@ KeyUD* KeyUD::GetPtr(KeeperState const K_, int idx_) | |||
137 | void KeyUD::peek(KeeperState const K_, int const count_) const | 137 | void KeyUD::peek(KeeperState const K_, int const count_) const |
138 | { | 138 | { |
139 | STACK_CHECK_START_ABS(K_, 1); | 139 | STACK_CHECK_START_ABS(K_, 1); |
140 | LUA_ASSERT(K_, KeyUD::GetPtr(K_, -1) == this); // K_: KeyUD | 140 | LUA_ASSERT(K_, KeyUD::GetPtr(K_, kIdxTop) == this); // K_: KeyUD |
141 | if (count <= 0) { // no data is available | 141 | if (count <= 0) { // no data is available |
142 | lua_pop(K_, 1); // K_: | 142 | lua_pop(K_, 1); // K_: |
143 | lua_pushinteger(K_, 0); // K_: 0 | 143 | lua_pushinteger(K_, 0); // K_: 0 |
@@ -145,7 +145,7 @@ void KeyUD::peek(KeeperState const K_, int const count_) const | |||
145 | } | 145 | } |
146 | 146 | ||
147 | // read <count_> value off the fifo, if possible | 147 | // read <count_> value off the fifo, if possible |
148 | prepareAccess(K_, -1); // K_: fifo | 148 | prepareAccess(K_, kIdxTop); // K_: fifo |
149 | int const _count{ std::min(count_, count) }; | 149 | int const _count{ std::min(count_, count) }; |
150 | lua_pushinteger(K_, _count); // K_: fifo _count | 150 | lua_pushinteger(K_, _count); // K_: fifo _count |
151 | lua_insert(K_, 1); // K_: _count fifo | 151 | lua_insert(K_, 1); // K_: _count fifo |
@@ -171,9 +171,9 @@ int KeyUD::pop(KeeperState const K_, int const minCount_, int const maxCount_) | |||
171 | return 0; | 171 | return 0; |
172 | } | 172 | } |
173 | int const _popCount{ std::min(count, maxCount_) }; | 173 | int const _popCount{ std::min(count, maxCount_) }; |
174 | LUA_ASSERT(K_, KeyUD::GetPtr(K_, -1) == this); // K_: ... this | 174 | LUA_ASSERT(K_, KeyUD::GetPtr(K_, kIdxTop) == this); // K_: ... this |
175 | prepareAccess(K_, -1); // K_: ... fifo | 175 | prepareAccess(K_, kIdxTop); // K_: ... fifo |
176 | int const _fifo_idx{ lua_gettop(K_) }; | 176 | StackIndex const _fifo_idx{ lua_gettop(K_) }; |
177 | // each iteration pushes a value on the stack! | 177 | // each iteration pushes a value on the stack! |
178 | STACK_GROW(K_, _popCount + 2); | 178 | STACK_GROW(K_, _popCount + 2); |
179 | // skip first item, we will push it last | 179 | // skip first item, we will push it last |
@@ -202,9 +202,9 @@ int KeyUD::pop(KeeperState const K_, int const minCount_, int const maxCount_) | |||
202 | 202 | ||
203 | // expects 'this' at the specified index | 203 | // expects 'this' at the specified index |
204 | // replaces it by its uservalue on the stack (the table holding the fifo values) | 204 | // replaces it by its uservalue on the stack (the table holding the fifo values) |
205 | void KeyUD::prepareAccess(KeeperState const K_, int const idx_) const | 205 | void KeyUD::prepareAccess(KeeperState const K_, StackIndex const idx_) const |
206 | { | 206 | { |
207 | int const _idx{ luaG_absindex(K_, idx_) }; | 207 | StackIndex const _idx{ luaG_absindex(K_, idx_) }; |
208 | LUA_ASSERT(K_, KeyUD::GetPtr(K_, idx_) == this); | 208 | LUA_ASSERT(K_, KeyUD::GetPtr(K_, idx_) == this); |
209 | // we can replace the key userdata in the stack without fear of it being GCed, there are other references around | 209 | // we can replace the key userdata in the stack without fear of it being GCed, there are other references around |
210 | lua_getiuservalue(K_, _idx, kContentsTableIndex); | 210 | lua_getiuservalue(K_, _idx, kContentsTableIndex); |
@@ -217,7 +217,7 @@ void KeyUD::prepareAccess(KeeperState const K_, int const idx_) const | |||
217 | // out: nothing, removes all pushed values from the stack | 217 | // out: nothing, removes all pushed values from the stack |
218 | bool KeyUD::push(KeeperState const K_, int const count_, bool const enforceLimit_) | 218 | bool KeyUD::push(KeeperState const K_, int const count_, bool const enforceLimit_) |
219 | { | 219 | { |
220 | int const _fifoIdx{ luaG_absindex(K_, -1 - count_) }; | 220 | StackIndex const _fifoIdx{ luaG_absindex(K_, StackIndex{ -1 - count_ }) }; |
221 | LUA_ASSERT(K_, KeyUD::GetPtr(K_, _fifoIdx) == this); // K_: this val... | 221 | LUA_ASSERT(K_, KeyUD::GetPtr(K_, _fifoIdx) == this); // K_: this val... |
222 | if (enforceLimit_ && (limit >= 0) && (count + count_ > limit)) { // not enough room | 222 | if (enforceLimit_ && (limit >= 0) && (count + count_ > limit)) { // not enough room |
223 | return false; | 223 | return false; |
@@ -270,13 +270,13 @@ void KeyUD::PushFillStatus(KeeperState const K_, KeyUD const* const key_) | |||
270 | // expects 'this' on top of the stack | 270 | // expects 'this' on top of the stack |
271 | bool KeyUD::reset(KeeperState const K_) | 271 | bool KeyUD::reset(KeeperState const K_) |
272 | { | 272 | { |
273 | LUA_ASSERT(K_, KeyUD::GetPtr(K_, -1) == this); | 273 | LUA_ASSERT(K_, KeyUD::GetPtr(K_, kIdxTop) == this); |
274 | STACK_CHECK_START_REL(K_, 0); | 274 | STACK_CHECK_START_REL(K_, 0); |
275 | bool const _wasFull{ (limit > 0) && (count >= limit) }; | 275 | bool const _wasFull{ (limit > 0) && (count >= limit) }; |
276 | // empty the KeyUD: replace uservalue with a virgin table, reset counters, but leave limit unchanged! | 276 | // empty the KeyUD: replace uservalue with a virgin table, reset counters, but leave limit unchanged! |
277 | // if we have an actual limit, use it to preconfigure the table | 277 | // if we have an actual limit, use it to preconfigure the table |
278 | lua_createtable(K_, (limit <= 0) ? 0 : limit, 0); // K_: KeysDB key val... KeyUD {} | 278 | lua_createtable(K_, (limit <= 0) ? 0 : limit, 0); // K_: KeysDB key val... KeyUD {} |
279 | lua_setiuservalue(K_, -2, kContentsTableIndex); // K_: KeysDB key val... KeyUD | 279 | lua_setiuservalue(K_, StackIndex{ -2 }, kContentsTableIndex); // K_: KeysDB key val... KeyUD |
280 | first = 1; | 280 | first = 1; |
281 | count = 0; | 281 | count = 0; |
282 | STACK_CHECK(K_, 0); | 282 | STACK_CHECK(K_, 0); |
@@ -290,20 +290,20 @@ bool KeyUD::reset(KeeperState const K_) | |||
290 | // out: the KeysDB table of the linda is pushed at the top of the stack | 290 | // out: the KeysDB table of the linda is pushed at the top of the stack |
291 | // xxh64 of string "kLindasRegKey" generated at https://www.pelock.com/products/hash-calculator | 291 | // xxh64 of string "kLindasRegKey" generated at https://www.pelock.com/products/hash-calculator |
292 | static constexpr RegistryUniqueKey kLindasRegKey{ 0x3AE0D5243A88B962ull }; | 292 | static constexpr RegistryUniqueKey kLindasRegKey{ 0x3AE0D5243A88B962ull }; |
293 | static void PushKeysDB(KeeperState const K_, int const idx_) | 293 | static void PushKeysDB(KeeperState const K_, StackIndex const idx_) |
294 | { | 294 | { |
295 | STACK_GROW(K_, 5); | 295 | STACK_GROW(K_, 5); |
296 | STACK_CHECK_START_REL(K_, 0); | 296 | STACK_CHECK_START_REL(K_, 0); |
297 | int const _idx{ luaG_absindex(K_, idx_) }; | 297 | StackIndex const _absidx{ luaG_absindex(K_, idx_) }; |
298 | kLindasRegKey.pushValue(K_); // K_: ... LindasDB | 298 | kLindasRegKey.pushValue(K_); // K_: ... LindasDB |
299 | lua_pushvalue(K_, _idx); // K_: ... LindasDB linda | 299 | lua_pushvalue(K_, _absidx); // K_: ... LindasDB linda |
300 | lua_rawget(K_, -2); // K_: ... LindasDB KeysDB | 300 | lua_rawget(K_, -2); // K_: ... LindasDB KeysDB |
301 | STACK_CHECK(K_, 2); | 301 | STACK_CHECK(K_, 2); |
302 | if (lua_isnil(K_, -1)) { | 302 | if (lua_isnil(K_, -1)) { |
303 | lua_pop(K_, 1); // K_: ... LindasDB | 303 | lua_pop(K_, 1); // K_: ... LindasDB |
304 | // add a new KeysDB table for this linda | 304 | // add a new KeysDB table for this linda |
305 | lua_newtable(K_); // K_: ... LindasDB KeysDB | 305 | lua_newtable(K_); // K_: ... LindasDB KeysDB |
306 | lua_pushvalue(K_, _idx); // K_: ... LindasDB KeysDB linda | 306 | lua_pushvalue(K_, _absidx); // K_: ... LindasDB KeysDB linda |
307 | lua_pushvalue(K_, -2); // K_: ... LindasDB KeysDB linda KeysDB | 307 | lua_pushvalue(K_, -2); // K_: ... LindasDB KeysDB linda KeysDB |
308 | lua_rawset(K_, -4); // K_: ... LindasDB KeysDB | 308 | lua_rawset(K_, -4); // K_: ... LindasDB KeysDB |
309 | } | 309 | } |
@@ -326,12 +326,12 @@ int keepercall_count(lua_State* const L_) | |||
326 | switch (lua_gettop(_K)) { | 326 | switch (lua_gettop(_K)) { |
327 | // no key is specified: return a table giving the count of all known keys | 327 | // no key is specified: return a table giving the count of all known keys |
328 | case 1: // _K: linda | 328 | case 1: // _K: linda |
329 | PushKeysDB(_K, 1); // _K: linda KeysDB | 329 | PushKeysDB(_K, StackIndex{ 1 }); // _K: linda KeysDB |
330 | lua_newtable(_K); // _K: linda KeysDB out | 330 | lua_newtable(_K); // _K: linda KeysDB out |
331 | lua_replace(_K, 1); // _K: out KeysDB | 331 | lua_replace(_K, 1); // _K: out KeysDB |
332 | lua_pushnil(_K); // _K: out KeysDB nil | 332 | lua_pushnil(_K); // _K: out KeysDB nil |
333 | while (lua_next(_K, 2)) { // _K: out KeysDB key KeyUD | 333 | while (lua_next(_K, 2)) { // _K: out KeysDB key KeyUD |
334 | KeyUD* const _key{ KeyUD::GetPtr(_K, -1) }; | 334 | KeyUD* const _key{ KeyUD::GetPtr(_K, kIdxTop) }; |
335 | lua_pop(_K, 1); // _K: out KeysDB key | 335 | lua_pop(_K, 1); // _K: out KeysDB key |
336 | lua_pushvalue(_K, -1); // _K: out KeysDB key key | 336 | lua_pushvalue(_K, -1); // _K: out KeysDB key key |
337 | lua_pushinteger(_K, _key->count); // _K: out KeysDB key key count | 337 | lua_pushinteger(_K, _key->count); // _K: out KeysDB key key count |
@@ -342,13 +342,13 @@ int keepercall_count(lua_State* const L_) | |||
342 | 342 | ||
343 | // 1 key is specified: return its count | 343 | // 1 key is specified: return its count |
344 | case 2: // _K: linda key | 344 | case 2: // _K: linda key |
345 | PushKeysDB(_K, 1); // _K: linda key KeysDB | 345 | PushKeysDB(_K, StackIndex{ 1 }); // _K: linda key KeysDB |
346 | lua_replace(_K, 1); // _K: KeysDB key | 346 | lua_replace(_K, 1); // _K: KeysDB key |
347 | lua_rawget(_K, -2); // _K: KeysDB KeyUD|nil | 347 | lua_rawget(_K, -2); // _K: KeysDB KeyUD|nil |
348 | if (lua_isnil(_K, -1)) { // the key is unknown // _K: KeysDB nil | 348 | if (lua_isnil(_K, -1)) { // the key is unknown // _K: KeysDB nil |
349 | lua_remove(_K, -2); // _K: nil | 349 | lua_remove(_K, -2); // _K: nil |
350 | } else { // the key is known // _K: KeysDB KeyUD | 350 | } else { // the key is known // _K: KeysDB KeyUD |
351 | KeyUD* const _key{ KeyUD::GetPtr(_K, -1) }; | 351 | KeyUD* const _key{ KeyUD::GetPtr(_K, kIdxTop) }; |
352 | lua_pushinteger(_K, _key->count); // _K: KeysDB KeyUD count | 352 | lua_pushinteger(_K, _key->count); // _K: KeysDB KeyUD count |
353 | lua_replace(_K, -3); // _K: count KeyUD | 353 | lua_replace(_K, -3); // _K: count KeyUD |
354 | lua_pop(_K, 1); // _K: count | 354 | lua_pop(_K, 1); // _K: count |
@@ -358,14 +358,14 @@ int keepercall_count(lua_State* const L_) | |||
358 | // a variable number of keys is specified: return a table of their counts | 358 | // a variable number of keys is specified: return a table of their counts |
359 | default: // _K: linda keys... key#1 | 359 | default: // _K: linda keys... key#1 |
360 | lua_pushvalue(_K, 2); // duplicate the first key of the list // _K: linda keys... key#1 | 360 | lua_pushvalue(_K, 2); // duplicate the first key of the list // _K: linda keys... key#1 |
361 | PushKeysDB(_K, 1); // _K: linda keys... key#1 KeysDB | 361 | PushKeysDB(_K, StackIndex{ 1 }); // _K: linda keys... key#1 KeysDB |
362 | lua_newtable(_K); // _K: linda keys... key#1 KeysDB out | 362 | lua_newtable(_K); // _K: linda keys... key#1 KeysDB out |
363 | lua_replace(_K, 1); // _K: out keys... key#1 KeysDB | 363 | lua_replace(_K, 1); // _K: out keys... key#1 KeysDB |
364 | lua_replace(_K, 2); // the list of keys is the same, but for key#1 moved at the end // _K: out KeysDB keys... | 364 | lua_replace(_K, 2); // the list of keys is the same, but for key#1 moved at the end // _K: out KeysDB keys... |
365 | while (lua_gettop(_K) > 2) { | 365 | while (lua_gettop(_K) > 2) { |
366 | lua_pushvalue(_K, -1); // _K: out KeysDB keys... key | 366 | lua_pushvalue(_K, -1); // _K: out KeysDB keys... key |
367 | lua_rawget(_K, 2); // _K: out KeysDB keys... KeyUD|nil | 367 | lua_rawget(_K, 2); // _K: out KeysDB keys... KeyUD|nil |
368 | KeyUD* const _key{ KeyUD::GetPtr(_K, -1) }; | 368 | KeyUD* const _key{ KeyUD::GetPtr(_K, kIdxTop) }; |
369 | lua_pop(_K, 1); // _K: out KeysDB keys... | 369 | lua_pop(_K, 1); // _K: out KeysDB keys... |
370 | if (_key != nullptr) { // the key is known | 370 | if (_key != nullptr) { // the key is known |
371 | lua_pushinteger(_K, _key->count); // _K: out KeysDB keys... count | 371 | lua_pushinteger(_K, _key->count); // _K: out KeysDB keys... count |
@@ -410,11 +410,11 @@ int keepercall_get(lua_State* const L_) | |||
410 | _count = static_cast<int>(lua_tointeger(_K, 3)); // linda:get() made sure _count >= 1 | 410 | _count = static_cast<int>(lua_tointeger(_K, 3)); // linda:get() made sure _count >= 1 |
411 | lua_pop(_K, 1); // _K: linda key | 411 | lua_pop(_K, 1); // _K: linda key |
412 | } | 412 | } |
413 | PushKeysDB(_K, 1); // _K: linda key KeysDB | 413 | PushKeysDB(_K, StackIndex{ 1 }); // _K: linda key KeysDB |
414 | lua_replace(_K, 1); // _K: KeysDB key | 414 | lua_replace(_K, 1); // _K: KeysDB key |
415 | lua_rawget(_K, 1); // _K: KeysDB KeyUD | 415 | lua_rawget(_K, 1); // _K: KeysDB KeyUD |
416 | lua_remove(_K, 1); // _K: KeyUD | 416 | lua_remove(_K, 1); // _K: KeyUD |
417 | KeyUD const* const _key{ KeyUD::GetPtr(_K, -1) }; | 417 | KeyUD const* const _key{ KeyUD::GetPtr(_K, kIdxTop) }; |
418 | if (_key != nullptr) { | 418 | if (_key != nullptr) { |
419 | _key->peek(_K, _count); // _K: N val... | 419 | _key->peek(_K, _count); // _K: N val... |
420 | } else { | 420 | } else { |
@@ -438,11 +438,11 @@ int keepercall_limit(lua_State* const L_) | |||
438 | bool const _reading{ lua_gettop(_K) == 2 }; | 438 | bool const _reading{ lua_gettop(_K) == 2 }; |
439 | LindaLimit const _limit{ static_cast<LindaLimit::type>(luaL_optinteger(_K, 3, -1)) }; // -1 if we read nil because the argument is absent | 439 | LindaLimit const _limit{ static_cast<LindaLimit::type>(luaL_optinteger(_K, 3, -1)) }; // -1 if we read nil because the argument is absent |
440 | lua_settop(_K, 2); // _K: linda key | 440 | lua_settop(_K, 2); // _K: linda key |
441 | PushKeysDB(_K, 1); // _K: linda key KeysDB | 441 | PushKeysDB(_K, StackIndex{ 1 }); // _K: linda key KeysDB |
442 | lua_replace(_K, 1); // _K: KeysDB key | 442 | lua_replace(_K, 1); // _K: KeysDB key |
443 | lua_pushvalue(_K, -1); // _K: KeysDB key key | 443 | lua_pushvalue(_K, -1); // _K: KeysDB key key |
444 | lua_rawget(_K, -3); // _K: KeysDB key KeyUD|nil | 444 | lua_rawget(_K, -3); // _K: KeysDB key KeyUD|nil |
445 | KeyUD* _key{ KeyUD::GetPtr(_K, -1) }; | 445 | KeyUD* _key{ KeyUD::GetPtr(_K, kIdxTop) }; |
446 | if (_reading) { | 446 | if (_reading) { |
447 | // remove any clutter on the stack | 447 | // remove any clutter on the stack |
448 | lua_settop(_K, 0); // _K: | 448 | lua_settop(_K, 0); // _K: |
@@ -476,14 +476,14 @@ int keepercall_limit(lua_State* const L_) | |||
476 | int keepercall_receive(lua_State* const L_) | 476 | int keepercall_receive(lua_State* const L_) |
477 | { | 477 | { |
478 | KeeperState const _K{ L_ }; | 478 | KeeperState const _K{ L_ }; |
479 | int const _top{ lua_gettop(_K) }; | 479 | StackIndex const _top{ lua_gettop(_K) }; |
480 | PushKeysDB(_K, 1); // _K: linda keys... KeysDB | 480 | PushKeysDB(_K, StackIndex{ 1 }); // _K: linda keys... KeysDB |
481 | lua_replace(_K, 1); // _K: KeysDB keys... | 481 | lua_replace(_K, 1); // _K: KeysDB keys... |
482 | 482 | ||
483 | for (int const _keyIdx : std::ranges::iota_view{ 2, _top + 1 }) { | 483 | for (StackIndex const _keyIdx : std::ranges::iota_view{ StackIndex{ 2 }, _top + 1 }) { |
484 | lua_pushvalue(_K, _keyIdx); // _K: KeysDB keys... key[i] | 484 | lua_pushvalue(_K, _keyIdx); // _K: KeysDB keys... key[i] |
485 | lua_rawget(_K, 1); // _K: KeysDB keys... KeyUD | 485 | lua_rawget(_K, 1); // _K: KeysDB keys... KeyUD |
486 | KeyUD* const _key{ KeyUD::GetPtr(_K, -1) }; | 486 | KeyUD* const _key{ KeyUD::GetPtr(_K, kIdxTop) }; |
487 | if (_key != nullptr) { // it's fine to attempt a read on a key that wasn't yet written to | 487 | if (_key != nullptr) { // it's fine to attempt a read on a key that wasn't yet written to |
488 | int const _popped{ _key->pop(_K, 1, 1) }; // _K: KeysDB keys... val | 488 | int const _popped{ _key->pop(_K, 1, 1) }; // _K: KeysDB keys... val |
489 | if (_popped > 0) { | 489 | if (_popped > 0) { |
@@ -514,12 +514,12 @@ int keepercall_receive_batched(lua_State* const L_) | |||
514 | int const _max_count{ static_cast<int>(luaL_optinteger(_K, 4, _min_count)) }; | 514 | int const _max_count{ static_cast<int>(luaL_optinteger(_K, 4, _min_count)) }; |
515 | lua_settop(_K, 2); // _K: linda key | 515 | lua_settop(_K, 2); // _K: linda key |
516 | lua_insert(_K, 1); // _K: key linda | 516 | lua_insert(_K, 1); // _K: key linda |
517 | PushKeysDB(_K, 2); // _K: key linda KeysDB | 517 | PushKeysDB(_K, StackIndex{ 2 }); // _K: key linda KeysDB |
518 | lua_remove(_K, 2); // _K: key KeysDB | 518 | lua_remove(_K, 2); // _K: key KeysDB |
519 | lua_pushvalue(_K, 1); // _K: key KeysDB key | 519 | lua_pushvalue(_K, 1); // _K: key KeysDB key |
520 | lua_rawget(_K, 2); // _K: key KeysDB KeyUD | 520 | lua_rawget(_K, 2); // _K: key KeysDB KeyUD |
521 | lua_remove(_K, 2); // _K: key KeyUD | 521 | lua_remove(_K, 2); // _K: key KeyUD |
522 | KeyUD* const _key{ KeyUD::GetPtr(_K, -1) }; | 522 | KeyUD* const _key{ KeyUD::GetPtr(_K, kIdxTop) }; |
523 | if (_key == nullptr || _key->pop(_K, _min_count, _max_count) == 0) { // _K: [key val...]|crap | 523 | if (_key == nullptr || _key->pop(_K, _min_count, _max_count) == 0) { // _K: [key val...]|crap |
524 | // Lua will adjust the stack for us when we return | 524 | // Lua will adjust the stack for us when we return |
525 | return 0; | 525 | return 0; |
@@ -538,7 +538,7 @@ int keepercall_send(lua_State* const L_) | |||
538 | KeeperState const _K{ L_ }; | 538 | KeeperState const _K{ L_ }; |
539 | int const _n{ lua_gettop(_K) - 2 }; | 539 | int const _n{ lua_gettop(_K) - 2 }; |
540 | STACK_CHECK_START_REL(_K, 0); // _K: linda key val... | 540 | STACK_CHECK_START_REL(_K, 0); // _K: linda key val... |
541 | PushKeysDB(_K, 1); // _K: linda key val... KeysDB | 541 | PushKeysDB(_K, StackIndex{ 1 }); // _K: linda key val... KeysDB |
542 | // get the fifo associated to this key in this linda, create it if it doesn't exist | 542 | // get the fifo associated to this key in this linda, create it if it doesn't exist |
543 | lua_pushvalue(_K, 2); // _K: linda key val... KeysDB key | 543 | lua_pushvalue(_K, 2); // _K: linda key val... KeysDB key |
544 | lua_rawget(_K, -2); // _K: linda key val... KeysDB KeyUD|nil | 544 | lua_rawget(_K, -2); // _K: linda key val... KeysDB KeyUD|nil |
@@ -553,7 +553,7 @@ int keepercall_send(lua_State* const L_) | |||
553 | lua_replace(_K, 2); // _K: linda KeyUD val... KeysDB | 553 | lua_replace(_K, 2); // _K: linda KeyUD val... KeysDB |
554 | lua_pop(_K, 1); // _K: linda KeyUD val... | 554 | lua_pop(_K, 1); // _K: linda KeyUD val... |
555 | STACK_CHECK(_K, 0); | 555 | STACK_CHECK(_K, 0); |
556 | KeyUD* const _key{ KeyUD::GetPtr(_K, 2) }; | 556 | KeyUD* const _key{ KeyUD::GetPtr(_K, StackIndex{ 2 }) }; |
557 | if (_key && _key->push(_K, _n, true)) { // not enough room? | 557 | if (_key && _key->push(_K, _n, true)) { // not enough room? |
558 | lua_settop(_K, 0); // _K: | 558 | lua_settop(_K, 0); // _K: |
559 | lua_pushboolean(_K, 1); // _K: true | 559 | lua_pushboolean(_K, 1); // _K: true |
@@ -576,11 +576,11 @@ int keepercall_set(lua_State* const L_) | |||
576 | STACK_GROW(_K, 6); | 576 | STACK_GROW(_K, 6); |
577 | 577 | ||
578 | // retrieve KeysDB associated with the linda | 578 | // retrieve KeysDB associated with the linda |
579 | PushKeysDB(_K, 1); // _K: linda key val... KeysDB | 579 | PushKeysDB(_K, StackIndex{ 1 }); // _K: linda key val... KeysDB |
580 | lua_replace(_K, 1); // _K: KeysDB key val... | 580 | lua_replace(_K, 1); // _K: KeysDB key val... |
581 | lua_pushvalue(_K, 2); // _K: KeysDB key val... key | 581 | lua_pushvalue(_K, 2); // _K: KeysDB key val... key |
582 | lua_rawget(_K, 1); // _K: KeysDB key val KeyUD|nil | 582 | lua_rawget(_K, 1); // _K: KeysDB key val KeyUD|nil |
583 | KeyUD* _key{ KeyUD::GetPtr(_K, -1) }; | 583 | KeyUD* _key{ KeyUD::GetPtr(_K, kIdxTop) }; |
584 | 584 | ||
585 | if (lua_gettop(_K) == 3) { // no value to set // _K: KeysDB key KeyUD|nil | 585 | if (lua_gettop(_K) == 3) { // no value to set // _K: KeysDB key KeyUD|nil |
586 | // empty the KeyUD for the specified key: replace uservalue with a virgin table, reset counters, but leave limit unchanged! | 586 | // empty the KeyUD for the specified key: replace uservalue with a virgin table, reset counters, but leave limit unchanged! |
@@ -633,11 +633,11 @@ int keepercall_set(lua_State* const L_) | |||
633 | * | 633 | * |
634 | * Returns: number of return values (pushed to 'L'), unset in case of error | 634 | * Returns: number of return values (pushed to 'L'), unset in case of error |
635 | */ | 635 | */ |
636 | KeeperCallResult keeper_call(KeeperState K_, keeper_api_t func_, lua_State* L_, Linda* linda_, int starting_index_) | 636 | KeeperCallResult keeper_call(KeeperState const K_, keeper_api_t const func_, lua_State* const L_, Linda* const linda_, StackIndex const starting_index_) |
637 | { | 637 | { |
638 | KeeperCallResult _result; | 638 | KeeperCallResult _result; |
639 | int const _args{ starting_index_ ? (lua_gettop(L_) - starting_index_ + 1) : 0 }; // L: ... args... K_: | 639 | StackIndex const _args{ starting_index_ ? (lua_gettop(L_) - starting_index_ + 1) : 0 }; // L: ... args... K_: |
640 | int const _top_K{ lua_gettop(K_) }; | 640 | StackIndex const _top_K{ lua_gettop(K_) }; |
641 | // if we didn't do anything wrong, the keeper stack should be clean | 641 | // if we didn't do anything wrong, the keeper stack should be clean |
642 | LUA_ASSERT(L_, _top_K == 0); | 642 | LUA_ASSERT(L_, _top_K == 0); |
643 | 643 | ||
@@ -743,8 +743,8 @@ int Keeper::PushLindaStorage(Linda& linda_, DestState const L_) | |||
743 | InterCopyContext _c{ linda_.U, L_, SourceState{ _K }, {}, {}, {}, LookupMode::FromKeeper, {} }; | 743 | InterCopyContext _c{ linda_.U, L_, SourceState{ _K }, {}, {}, {}, LookupMode::FromKeeper, {} }; |
744 | lua_pushnil(_K); // _K: KeysDB nil L_: out | 744 | lua_pushnil(_K); // _K: KeysDB nil L_: out |
745 | while (lua_next(_K, -2)) { // _K: KeysDB key KeyUD L_: out | 745 | while (lua_next(_K, -2)) { // _K: KeysDB key KeyUD L_: out |
746 | KeyUD* const _key{ KeyUD::GetPtr(_K, -1) }; | 746 | KeyUD* const _key{ KeyUD::GetPtr(_K, kIdxTop) }; |
747 | _key->prepareAccess(_K, -1); // _K: KeysDB key fifo L_: out | 747 | _key->prepareAccess(_K, kIdxTop); // _K: KeysDB key fifo L_: out |
748 | lua_pushvalue(_K, -2); // _K: KeysDB key fifo key L_: out | 748 | lua_pushvalue(_K, -2); // _K: KeysDB key fifo key L_: out |
749 | if (_c.interMove(1) != InterCopyResult::Success) { // _K: KeysDB key fifo L_: out key | 749 | if (_c.interMove(1) != InterCopyResult::Success) { // _K: KeysDB key fifo L_: out key |
750 | raise_luaL_error(L_, "Internal error reading Keeper contents"); | 750 | raise_luaL_error(L_, "Internal error reading Keeper contents"); |
@@ -928,7 +928,7 @@ void Keepers::initialize(Universe& U_, lua_State* L_, int const nbKeepers_, int | |||
928 | // copy package.path and package.cpath from the source state | 928 | // copy package.path and package.cpath from the source state |
929 | if (luaG_getmodule(L, LUA_LOADLIBNAME) != LuaType::NIL) { // L_: settings package _K: | 929 | if (luaG_getmodule(L, LUA_LOADLIBNAME) != LuaType::NIL) { // L_: settings package _K: |
930 | // when copying with mode LookupMode::ToKeeper, error message is pushed at the top of the stack, not raised immediately | 930 | // when copying with mode LookupMode::ToKeeper, error message is pushed at the top of the stack, not raised immediately |
931 | InterCopyContext _c{ U, DestState{ _K }, SourceState{ L }, {}, SourceIndex{ luaG_absindex(L, -1) }, {}, LookupMode::ToKeeper, {} }; | 931 | InterCopyContext _c{ U, DestState{ _K }, SourceState{ L }, {}, SourceIndex{ luaG_absindex(L, kIdxTop) }, {}, LookupMode::ToKeeper, {} }; |
932 | if (_c.interCopyPackage() != InterCopyResult::Success) { // L_: settings ... error_msg _K: | 932 | if (_c.interCopyPackage() != InterCopyResult::Success) { // L_: settings ... error_msg _K: |
933 | // if something went wrong, the error message is at the top of the stack | 933 | // if something went wrong, the error message is at the top of the stack |
934 | lua_remove(L, -2); // L_: settings error_msg | 934 | lua_remove(L, -2); // L_: settings error_msg |
diff --git a/src/keeper.h b/src/keeper.h index 04bf834..e505361 100644 --- a/src/keeper.h +++ b/src/keeper.h | |||
@@ -7,9 +7,9 @@ class Linda; | |||
7 | enum class LookupMode; | 7 | enum class LookupMode; |
8 | class Universe; | 8 | class Universe; |
9 | 9 | ||
10 | using KeeperState = Unique<lua_State*>; | 10 | DECLARE_UNIQUE_TYPE(KeeperState,lua_State*); |
11 | using LindaLimit = Unique<int>; | 11 | DECLARE_UNIQUE_TYPE(LindaLimit, int); |
12 | using KeeperIndex = Unique<int>; | 12 | DECLARE_UNIQUE_TYPE(KeeperIndex, int); |
13 | 13 | ||
14 | // ################################################################################################# | 14 | // ################################################################################################# |
15 | 15 | ||
@@ -86,5 +86,5 @@ using keeper_api_t = lua_CFunction; | |||
86 | [[nodiscard]] int keepercall_send(lua_State* L_); | 86 | [[nodiscard]] int keepercall_send(lua_State* L_); |
87 | [[nodiscard]] int keepercall_set(lua_State* L_); | 87 | [[nodiscard]] int keepercall_set(lua_State* L_); |
88 | 88 | ||
89 | using KeeperCallResult = Unique<std::optional<int>>; | 89 | DECLARE_UNIQUE_TYPE(KeeperCallResult, std::optional<int>); |
90 | [[nodiscard]] KeeperCallResult keeper_call(KeeperState K_, keeper_api_t func_, lua_State* L_, Linda* linda_, int starting_index_); | 90 | [[nodiscard]] KeeperCallResult keeper_call(KeeperState K_, keeper_api_t func_, lua_State* L_, Linda* linda_, StackIndex starting_index_); |
diff --git a/src/lane.cpp b/src/lane.cpp index baba0fa..d4d409f 100644 --- a/src/lane.cpp +++ b/src/lane.cpp | |||
@@ -47,7 +47,7 @@ static constexpr UniqueKey kCachedTostring{ 0xAB5EA23BCEA0C35Cull }; | |||
47 | // lane:get_threadname() | 47 | // lane:get_threadname() |
48 | static LUAG_FUNC(get_threadname) | 48 | static LUAG_FUNC(get_threadname) |
49 | { | 49 | { |
50 | Lane* const _lane{ ToLane(L_, 1) }; | 50 | Lane* const _lane{ ToLane(L_, StackIndex{ 1 }) }; |
51 | luaL_argcheck(L_, lua_gettop(L_) == 1, 2, "too many arguments"); | 51 | luaL_argcheck(L_, lua_gettop(L_) == 1, 2, "too many arguments"); |
52 | luaG_pushstring(L_, _lane->getDebugName()); | 52 | luaG_pushstring(L_, _lane->getDebugName()); |
53 | return 1; | 53 | return 1; |
@@ -70,7 +70,7 @@ static LUAG_FUNC(set_finalizer) | |||
70 | // Get the current finalizer table (if any), create one if it doesn't exist | 70 | // Get the current finalizer table (if any), create one if it doesn't exist |
71 | std::ignore = kFinalizerRegKey.getSubTable(L_, 1, 0); // L_: finalizer {finalisers} | 71 | std::ignore = kFinalizerRegKey.getSubTable(L_, 1, 0); // L_: finalizer {finalisers} |
72 | // must cast to int, not lua_Integer, because LuaJIT signature of lua_rawseti is not the same as PUC-Lua. | 72 | // must cast to int, not lua_Integer, because LuaJIT signature of lua_rawseti is not the same as PUC-Lua. |
73 | int const _idx{ static_cast<int>(lua_rawlen(L_, -1) + 1) }; | 73 | int const _idx{ static_cast<int>(lua_rawlen(L_, kIdxTop) + 1) }; |
74 | lua_pushvalue(L_, 1); // L_: finalizer {finalisers} finalizer | 74 | lua_pushvalue(L_, 1); // L_: finalizer {finalisers} finalizer |
75 | lua_rawseti(L_, -2, _idx); // L_: finalizer {finalisers} | 75 | lua_rawseti(L_, -2, _idx); // L_: finalizer {finalisers} |
76 | // no need to adjust the stack, Lua does this for us | 76 | // no need to adjust the stack, Lua does this for us |
@@ -85,12 +85,12 @@ static LUAG_FUNC(set_finalizer) | |||
85 | static LUAG_FUNC(lane_threadname) | 85 | static LUAG_FUNC(lane_threadname) |
86 | { | 86 | { |
87 | // C s_lane structure is a light userdata upvalue | 87 | // C s_lane structure is a light userdata upvalue |
88 | Lane* const _lane{ luaG_tolightuserdata<Lane>(L_, lua_upvalueindex(1)) }; | 88 | Lane* const _lane{ luaG_tolightuserdata<Lane>(L_, StackIndex{ lua_upvalueindex(1) }) }; |
89 | 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 | 89 | 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 |
90 | if (lua_gettop(L_) == 1) { | 90 | if (lua_gettop(L_) == 1) { |
91 | lua_settop(L_, 1); | 91 | lua_settop(L_, 1); |
92 | STACK_CHECK_START_REL(L_, 0); | 92 | STACK_CHECK_START_REL(L_, 0); |
93 | _lane->changeDebugName(-1); | 93 | _lane->changeDebugName(kIdxTop); |
94 | STACK_CHECK(L_, 0); | 94 | STACK_CHECK(L_, 0); |
95 | return 0; | 95 | return 0; |
96 | } else if (lua_gettop(L_) == 0) { | 96 | } else if (lua_gettop(L_) == 0) { |
@@ -113,19 +113,19 @@ static LUAG_FUNC(lane_threadname) | |||
113 | // | 113 | // |
114 | static LUAG_FUNC(thread_join) | 114 | static LUAG_FUNC(thread_join) |
115 | { | 115 | { |
116 | Lane* const _lane{ ToLane(L_, 1) }; | 116 | Lane* const _lane{ ToLane(L_, StackIndex{ 1 }) }; |
117 | 117 | ||
118 | std::chrono::time_point<std::chrono::steady_clock> _until{ std::chrono::time_point<std::chrono::steady_clock>::max() }; | 118 | std::chrono::time_point<std::chrono::steady_clock> _until{ std::chrono::time_point<std::chrono::steady_clock>::max() }; |
119 | if (luaG_type(L_, 2) == LuaType::NUMBER) { // we don't want to use lua_isnumber() because of autocoercion | 119 | if (luaG_type(L_, StackIndex{ 2 }) == LuaType::NUMBER) { // we don't want to use lua_isnumber() because of autocoercion |
120 | lua_Duration const duration{ lua_tonumber(L_, 2) }; | 120 | lua_Duration const duration{ lua_tonumber(L_, 2) }; |
121 | if (duration.count() >= 0.0) { | 121 | if (duration.count() >= 0.0) { |
122 | _until = std::chrono::steady_clock::now() + std::chrono::duration_cast<std::chrono::steady_clock::duration>(duration); | 122 | _until = std::chrono::steady_clock::now() + std::chrono::duration_cast<std::chrono::steady_clock::duration>(duration); |
123 | } else { | 123 | } else { |
124 | raise_luaL_argerror(L_, 2, "duration cannot be < 0"); | 124 | raise_luaL_argerror(L_, StackIndex{ 2 }, "duration cannot be < 0"); |
125 | } | 125 | } |
126 | 126 | ||
127 | } else if (!lua_isnoneornil(L_, 2)) { | 127 | } else if (!lua_isnoneornil(L_, 2)) { |
128 | raise_luaL_argerror(L_, 2, "incorrect duration type"); | 128 | raise_luaL_argerror(L_, StackIndex{ 2 }, "incorrect duration type"); |
129 | } | 129 | } |
130 | 130 | ||
131 | lua_settop(L_, 1); // L_: lane | 131 | lua_settop(L_, 1); // L_: lane |
@@ -150,7 +150,7 @@ static LUAG_FUNC(thread_join) | |||
150 | if (_stored == 0) { | 150 | if (_stored == 0) { |
151 | raise_luaL_error(L_, _lane->L ? "First return value must be non-nil when using join()" : "Can't join() more than once or after indexing"); | 151 | raise_luaL_error(L_, _lane->L ? "First return value must be non-nil when using join()" : "Can't join() more than once or after indexing"); |
152 | } | 152 | } |
153 | lua_getiuservalue(L_, 1, 1); // L_: lane {uv} | 153 | lua_getiuservalue(L_, StackIndex{ 1 }, 1); // L_: lane {uv} |
154 | for (int _i = 2; _i <= _stored; ++_i) { | 154 | for (int _i = 2; _i <= _stored; ++_i) { |
155 | lua_rawgeti(L_, 2, _i); // L_: lane {uv} results2...N | 155 | lua_rawgeti(L_, 2, _i); // L_: lane {uv} results2...N |
156 | } | 156 | } |
@@ -163,7 +163,7 @@ static LUAG_FUNC(thread_join) | |||
163 | case Lane::Error: | 163 | case Lane::Error: |
164 | { | 164 | { |
165 | LUA_ASSERT(L_, _stored == 2 || _stored == 3); | 165 | LUA_ASSERT(L_, _stored == 2 || _stored == 3); |
166 | lua_getiuservalue(L_, 1, 1); // L_: lane {uv} | 166 | lua_getiuservalue(L_, StackIndex{ 1 }, 1); // L_: lane {uv} |
167 | lua_rawgeti(L_, 2, 2); // L_: lane {uv} <error> | 167 | lua_rawgeti(L_, 2, 2); // L_: lane {uv} <error> |
168 | lua_rawgeti(L_, 2, 3); // L_: lane {uv} <error> <trace>|nil | 168 | lua_rawgeti(L_, 2, 3); // L_: lane {uv} <error> <trace>|nil |
169 | if (lua_isnil(L_, -1)) { | 169 | if (lua_isnil(L_, -1)) { |
@@ -178,11 +178,11 @@ static LUAG_FUNC(thread_join) | |||
178 | 178 | ||
179 | case Lane::Cancelled: | 179 | case Lane::Cancelled: |
180 | LUA_ASSERT(L_, _stored == 2); | 180 | LUA_ASSERT(L_, _stored == 2); |
181 | lua_getiuservalue(L_, 1, 1); // L_: lane {uv} | 181 | lua_getiuservalue(L_, StackIndex{ 1 }, 1); // L_: lane {uv} |
182 | lua_rawgeti(L_, 2, 2); // L_: lane {uv} cancel_error | 182 | lua_rawgeti(L_, 2, 2); // L_: lane {uv} cancel_error |
183 | lua_rawgeti(L_, 2, 1); // L_: lane {uv} cancel_error nil | 183 | lua_rawgeti(L_, 2, 1); // L_: lane {uv} cancel_error nil |
184 | lua_replace(L_, -3); // L_: lane nil cancel_error | 184 | lua_replace(L_, -3); // L_: lane nil cancel_error |
185 | LUA_ASSERT(L_, lua_isnil(L_, -2) && kCancelError.equals(L_, -1)); | 185 | LUA_ASSERT(L_, lua_isnil(L_, -2) && kCancelError.equals(L_, kIdxTop)); |
186 | _ret = 2; | 186 | _ret = 2; |
187 | break; | 187 | break; |
188 | 188 | ||
@@ -199,8 +199,8 @@ static LUAG_FUNC(thread_join) | |||
199 | 199 | ||
200 | LUAG_FUNC(thread_resume) | 200 | LUAG_FUNC(thread_resume) |
201 | { | 201 | { |
202 | static constexpr int kSelf{ 1 }; | 202 | static constexpr StackIndex kIdxSelf{ 1 }; |
203 | Lane* const _lane{ ToLane(L_, kSelf) }; | 203 | Lane* const _lane{ ToLane(L_, kIdxSelf) }; |
204 | lua_State* const _L2{ _lane->L }; | 204 | lua_State* const _L2{ _lane->L }; |
205 | 205 | ||
206 | // wait until the lane yields | 206 | // wait until the lane yields |
@@ -225,7 +225,7 @@ LUAG_FUNC(thread_resume) | |||
225 | STACK_CHECK_START_ABS(_L2, _nresults); | 225 | STACK_CHECK_START_ABS(_L2, _nresults); |
226 | 226 | ||
227 | // clear any fetched returned values that we might have stored previously | 227 | // clear any fetched returned values that we might have stored previously |
228 | _lane->resetResultsStorage(L_, 1); | 228 | _lane->resetResultsStorage(L_, kIdxSelf); |
229 | 229 | ||
230 | // to retrieve the yielded value of the coroutine on our stack | 230 | // to retrieve the yielded value of the coroutine on our stack |
231 | InterCopyContext _cin{ _lane->U, DestState{ L_ }, SourceState{ _L2 }, {}, {}, {}, {}, {} }; | 231 | InterCopyContext _cin{ _lane->U, DestState{ L_ }, SourceState{ _L2 }, {}, {}, {}, {}, {} }; |
@@ -254,9 +254,9 @@ LUAG_FUNC(thread_resume) | |||
254 | // Else If key is found in the environment, return it | 254 | // Else If key is found in the environment, return it |
255 | static int thread_index_number(lua_State* L_) | 255 | static int thread_index_number(lua_State* L_) |
256 | { | 256 | { |
257 | static constexpr int kSelf{ 1 }; | 257 | static constexpr StackIndex kIdxSelf{ 1 }; |
258 | 258 | ||
259 | Lane* const _lane{ ToLane(L_, kSelf) }; | 259 | Lane* const _lane{ ToLane(L_, kIdxSelf) }; |
260 | LUA_ASSERT(L_, lua_gettop(L_) == 2); // L_: lane n | 260 | LUA_ASSERT(L_, lua_gettop(L_) == 2); // L_: lane n |
261 | int const _key{ static_cast<int>(lua_tointeger(L_, 2)) }; | 261 | int const _key{ static_cast<int>(lua_tointeger(L_, 2)) }; |
262 | lua_pop(L_, 1); // L_: lane | 262 | lua_pop(L_, 1); // L_: lane |
@@ -284,13 +284,13 @@ static int thread_index_number(lua_State* L_) | |||
284 | // Else raise an error | 284 | // Else raise an error |
285 | static int thread_index_string(lua_State* L_) | 285 | static int thread_index_string(lua_State* L_) |
286 | { | 286 | { |
287 | static constexpr int kSelf{ 1 }; | 287 | static constexpr StackIndex kIdxSelf{ 1 }; |
288 | static constexpr int kKey{ 2 }; | 288 | static constexpr StackIndex kIdxKey{ 2 }; |
289 | 289 | ||
290 | Lane* const _lane{ ToLane(L_, kSelf) }; | 290 | Lane* const _lane{ ToLane(L_, kIdxSelf) }; |
291 | LUA_ASSERT(L_, lua_gettop(L_) == 2); // L_: lane "key" | 291 | LUA_ASSERT(L_, lua_gettop(L_) == 2); // L_: lane "key" |
292 | 292 | ||
293 | std::string_view const _keystr{ luaG_tostring(L_, kKey) }; | 293 | std::string_view const _keystr{ luaG_tostring(L_, kIdxKey) }; |
294 | lua_settop(L_, 2); // keep only our original arguments on the stack | 294 | lua_settop(L_, 2); // keep only our original arguments on the stack |
295 | if (_keystr == "status") { | 295 | if (_keystr == "status") { |
296 | _lane->pushStatusString(L_); // L_: lane "key" "<status>" | 296 | _lane->pushStatusString(L_); // L_: lane "key" "<status>" |
@@ -301,7 +301,7 @@ static int thread_index_string(lua_State* L_) | |||
301 | return 1; | 301 | return 1; |
302 | } | 302 | } |
303 | // return self.metatable[key] | 303 | // return self.metatable[key] |
304 | lua_getmetatable(L_, kSelf); // L_: lane "key" mt | 304 | lua_getmetatable(L_, kIdxSelf); // L_: lane "key" mt |
305 | lua_replace(L_, -3); // L_: mt "key" | 305 | lua_replace(L_, -3); // L_: mt "key" |
306 | lua_rawget(L_, -2); // L_: mt value | 306 | lua_rawget(L_, -2); // L_: mt value |
307 | // only "cancel" and "join" are registered as functions, any other string will raise an error | 307 | // only "cancel" and "join" are registered as functions, any other string will raise an error |
@@ -316,9 +316,9 @@ static int thread_index_string(lua_State* L_) | |||
316 | // lane:__index(key,usr) -> value | 316 | // lane:__index(key,usr) -> value |
317 | static LUAG_FUNC(thread_index) | 317 | static LUAG_FUNC(thread_index) |
318 | { | 318 | { |
319 | static constexpr int kSelf{ 1 }; | 319 | static constexpr StackIndex kIdxSelf{ 1 }; |
320 | static constexpr int kKey{ 2 }; | 320 | static constexpr StackIndex kKey{ 2 }; |
321 | Lane* const _lane{ ToLane(L_, kSelf) }; | 321 | Lane* const _lane{ ToLane(L_, kIdxSelf) }; |
322 | LUA_ASSERT(L_, lua_gettop(L_) == 2); | 322 | LUA_ASSERT(L_, lua_gettop(L_) == 2); |
323 | 323 | ||
324 | switch (luaG_type(L_, kKey)) { | 324 | switch (luaG_type(L_, kKey)) { |
@@ -329,17 +329,17 @@ static LUAG_FUNC(thread_index) | |||
329 | return thread_index_string(L_); // stack modification is undefined, returned value is at the top | 329 | return thread_index_string(L_); // stack modification is undefined, returned value is at the top |
330 | 330 | ||
331 | default: // unknown key | 331 | default: // unknown key |
332 | lua_getmetatable(L_, kSelf); // L_: mt | 332 | lua_getmetatable(L_, kIdxSelf); // L_: mt |
333 | kCachedError.pushKey(L_); // L_: mt kCachedError | 333 | kCachedError.pushKey(L_); // L_: mt kCachedError |
334 | lua_rawget(L_, -2); // L_: mt error() | 334 | lua_rawget(L_, -2); // L_: mt error() |
335 | if (luaG_type(L_, -1) != LuaType::FUNCTION) { | 335 | if (luaG_type(L_, kIdxTop) != LuaType::FUNCTION) { |
336 | raise_luaL_error(L_, "INTERNAL ERROR: cached error() is a %s, not a function", luaG_typename(L_, -1).data()); | 336 | raise_luaL_error(L_, "INTERNAL ERROR: cached error() is a %s, not a function", luaG_typename(L_, kIdxTop).data()); |
337 | } | 337 | } |
338 | luaG_pushstring(L_, "Unknown key: "); // L_: mt error() "Unknown key: " | 338 | luaG_pushstring(L_, "Unknown key: "); // L_: mt error() "Unknown key: " |
339 | kCachedTostring.pushKey(L_); // L_: mt error() "Unknown key: " kCachedTostring | 339 | kCachedTostring.pushKey(L_); // L_: mt error() "Unknown key: " kCachedTostring |
340 | lua_rawget(L_, -4); // L_: mt error() "Unknown key: " tostring() | 340 | lua_rawget(L_, -4); // L_: mt error() "Unknown key: " tostring() |
341 | if (luaG_type(L_, -1) != LuaType::FUNCTION) { | 341 | if (luaG_type(L_, kIdxTop) != LuaType::FUNCTION) { |
342 | raise_luaL_error(L_, "INTERNAL ERROR: cached tostring() is a %s, not a function", luaG_typename(L_, -1).data()); | 342 | raise_luaL_error(L_, "INTERNAL ERROR: cached tostring() is a %s, not a function", luaG_typename(L_, kIdxTop).data()); |
343 | } | 343 | } |
344 | lua_pushvalue(L_, kKey); // L_: mt error() "Unknown key: " tostring() k | 344 | lua_pushvalue(L_, kKey); // L_: mt error() "Unknown key: " tostring() k |
345 | lua_call(L_, 1, 1); // L_: mt error() "Unknown key: " "k" | 345 | lua_call(L_, 1, 1); // L_: mt error() "Unknown key: " "k" |
@@ -417,7 +417,7 @@ int Lane::LuaErrorHandler(lua_State* L_) | |||
417 | 417 | ||
418 | // Don't do stack survey for cancelled lanes. | 418 | // Don't do stack survey for cancelled lanes. |
419 | // | 419 | // |
420 | if (kCancelError.equals(L_, 1)) { | 420 | if (kCancelError.equals(L_, StackIndex{ 1 })) { |
421 | return 1; // just pass on | 421 | return 1; // just pass on |
422 | } | 422 | } |
423 | 423 | ||
@@ -436,6 +436,7 @@ int Lane::LuaErrorHandler(lua_State* L_) | |||
436 | // table of { "sourcefile.lua:<line>", ... } | 436 | // table of { "sourcefile.lua:<line>", ... } |
437 | // | 437 | // |
438 | lua_newtable(L_); // L_: some_error {} | 438 | lua_newtable(L_); // L_: some_error {} |
439 | StackIndex const kIdxTraceTbl{ luaG_absindex(L_, kIdxTop) }; | ||
439 | 440 | ||
440 | // Best to start from level 1, but in some cases it might be a C function | 441 | // Best to start from level 1, but in some cases it might be a C function |
441 | // and we don't get '.currentline' for that. It's okay - just keep level | 442 | // and we don't get '.currentline' for that. It's okay - just keep level |
@@ -446,27 +447,27 @@ int Lane::LuaErrorHandler(lua_State* L_) | |||
446 | lua_getinfo(L_, _extended ? "Sln" : "Sl", &_ar); | 447 | lua_getinfo(L_, _extended ? "Sln" : "Sl", &_ar); |
447 | if (_extended) { | 448 | if (_extended) { |
448 | lua_newtable(L_); // L_: some_error {} {} | 449 | lua_newtable(L_); // L_: some_error {} {} |
449 | 450 | StackIndex const kIdxFrameTbl{ luaG_absindex(L_, kIdxTop) }; | |
450 | lua_pushstring(L_, _ar.source); // L_: some_error {} {} source | 451 | lua_pushstring(L_, _ar.source); // L_: some_error {} {} source |
451 | luaG_setfield(L_, -2, std::string_view{ "source" }); // L_: some_error {} {} | 452 | luaG_setfield(L_, kIdxFrameTbl, std::string_view{ "source" }); // L_: some_error {} {} |
452 | 453 | ||
453 | lua_pushinteger(L_, _ar.currentline); // L_: some_error {} {} currentline | 454 | lua_pushinteger(L_, _ar.currentline); // L_: some_error {} {} currentline |
454 | luaG_setfield(L_, -2, std::string_view{ "currentline" }); // L_: some_error {} {} | 455 | luaG_setfield(L_, kIdxFrameTbl, std::string_view{ "currentline" }); // L_: some_error {} {} |
455 | 456 | ||
456 | lua_pushstring(L_, _ar.name ? _ar.name : "<?>"); // L_: some_error {} {} name | 457 | lua_pushstring(L_, _ar.name ? _ar.name : "<?>"); // L_: some_error {} {} name |
457 | luaG_setfield(L_, -2, std::string_view{ "name" }); // L_: some_error {} {} | 458 | luaG_setfield(L_, kIdxFrameTbl, std::string_view{ "name" }); // L_: some_error {} {} |
458 | 459 | ||
459 | lua_pushstring(L_, _ar.namewhat); // L_: some_error {} {} namewhat | 460 | lua_pushstring(L_, _ar.namewhat); // L_: some_error {} {} namewhat |
460 | luaG_setfield(L_, -2, std::string_view{ "namewhat" }); // L_: some_error {} {} | 461 | luaG_setfield(L_, kIdxFrameTbl, std::string_view{ "namewhat" }); // L_: some_error {} {} |
461 | 462 | ||
462 | lua_pushstring(L_, _ar.what); // L_: some_error {} {} what | 463 | lua_pushstring(L_, _ar.what); // L_: some_error {} {} what |
463 | luaG_setfield(L_, -2, std::string_view{ "what" }); // L_: some_error {} {} | 464 | luaG_setfield(L_, kIdxFrameTbl, std::string_view{ "what" }); // L_: some_error {} {} |
464 | } else if (_ar.currentline > 0) { | 465 | } else if (_ar.currentline > 0) { |
465 | luaG_pushstring(L_, "%s:%d", _ar.short_src, _ar.currentline); // L_: some_error {} "blah:blah" | 466 | luaG_pushstring(L_, "%s:%d", _ar.short_src, _ar.currentline); // L_: some_error {} "blah:blah" |
466 | } else { | 467 | } else { |
467 | luaG_pushstring(L_, "%s:?", _ar.short_src); // L_: some_error {} "blah" | 468 | luaG_pushstring(L_, "%s:?", _ar.short_src); // L_: some_error {} "blah" |
468 | } | 469 | } |
469 | lua_rawseti(L_, -2, static_cast<lua_Integer>(_n)); // L_: some_error {} | 470 | lua_rawseti(L_, kIdxTraceTbl, static_cast<lua_Integer>(_n)); // L_: some_error {} |
470 | } | 471 | } |
471 | 472 | ||
472 | // store the stack trace table in the registry | 473 | // store the stack trace table in the registry |
@@ -480,10 +481,10 @@ int Lane::LuaErrorHandler(lua_State* L_) | |||
480 | // ########################################## Finalizer ############################################ | 481 | // ########################################## Finalizer ############################################ |
481 | // ################################################################################################# | 482 | // ################################################################################################# |
482 | 483 | ||
483 | [[nodiscard]] static int PushStackTrace(lua_State* const L_, Lane::ErrorTraceLevel const errorTraceLevel_, LuaError const rc_, [[maybe_unused]] int const stk_base_) | 484 | [[nodiscard]] static int PushStackTrace(lua_State* const L_, Lane::ErrorTraceLevel const errorTraceLevel_, LuaError const rc_, [[maybe_unused]] StackIndex const stk_base_) |
484 | { | 485 | { |
485 | // Lua 5.1 error handler is limited to one return value; it stored the stack trace in the registry | 486 | // Lua 5.1 error handler is limited to one return value; it stored the stack trace in the registry |
486 | int const _top{ lua_gettop(L_) }; | 487 | StackIndex const _top{ lua_gettop(L_) }; |
487 | switch (rc_) { | 488 | switch (rc_) { |
488 | case LuaError::OK: // no error, body return values are on the stack | 489 | case LuaError::OK: // no error, body return values are on the stack |
489 | break; | 490 | break; |
@@ -499,7 +500,7 @@ int Lane::LuaErrorHandler(lua_State* L_) | |||
499 | 500 | ||
500 | // For cancellation the error message is kCancelError, and a stack trace isn't placed | 501 | // For cancellation the error message is kCancelError, and a stack trace isn't placed |
501 | // For other errors, the message can be whatever was thrown, and we should have a stack trace table | 502 | // For other errors, the message can be whatever was thrown, and we should have a stack trace table |
502 | LUA_ASSERT(L_, luaG_type(L_, 1 + stk_base_) == (kCancelError.equals(L_, stk_base_) ? LuaType::NIL : LuaType::TABLE)); | 503 | LUA_ASSERT(L_, luaG_type(L_, StackIndex{ 1 + stk_base_ }) == (kCancelError.equals(L_, stk_base_) ? LuaType::NIL : LuaType::TABLE)); |
503 | // Just leaving the stack trace table on the stack is enough to get it through to the master. | 504 | // Just leaving the stack trace table on the stack is enough to get it through to the master. |
504 | } else { | 505 | } else { |
505 | // any kind of error can be thrown with error(), or through a lane/linda cancellation | 506 | // any kind of error can be thrown with error(), or through a lane/linda cancellation |
@@ -544,7 +545,7 @@ int Lane::LuaErrorHandler(lua_State* L_) | |||
544 | 545 | ||
545 | STACK_GROW(_L, 5); | 546 | STACK_GROW(_L, 5); |
546 | 547 | ||
547 | int const _finalizers{ lua_gettop(_L) }; | 548 | StackIndex const _finalizers{ lua_gettop(_L) }; |
548 | // always push something as error handler, to have the same stack structure | 549 | // always push something as error handler, to have the same stack structure |
549 | int const _error_handler{ (errorTraceLevel_ != Lane::Minimal) | 550 | int const _error_handler{ (errorTraceLevel_ != Lane::Minimal) |
550 | ? (lua_pushcfunction(_L, Lane::LuaErrorHandler), lua_gettop(_L)) | 551 | ? (lua_pushcfunction(_L, Lane::LuaErrorHandler), lua_gettop(_L)) |
@@ -581,7 +582,8 @@ int Lane::LuaErrorHandler(lua_State* L_) | |||
581 | // if no error from the main body, finalizer doesn't receive any argument, else it gets the error message and optional stack trace | 582 | // if no error from the main body, finalizer doesn't receive any argument, else it gets the error message and optional stack trace |
582 | _rc = ToLuaError(lua_pcall(_L, _args, 0, _error_handler)); // _L: ... finalizers error_handler() err_msg2? | 583 | _rc = ToLuaError(lua_pcall(_L, _args, 0, _error_handler)); // _L: ... finalizers error_handler() err_msg2? |
583 | if (_rc != LuaError::OK) { | 584 | if (_rc != LuaError::OK) { |
584 | _finalizer_pushed = 1 + PushStackTrace(_L, errorTraceLevel_, _rc, lua_gettop(_L)); // _L: ... finalizers error_handler() err_msg2? trace | 585 | StackIndex const _top{ lua_gettop(_L) }; |
586 | _finalizer_pushed = 1 + PushStackTrace(_L, errorTraceLevel_, _rc, _top); // _L: ... finalizers error_handler() err_msg2? trace | ||
585 | // If one finalizer fails, don't run the others. Return this | 587 | // If one finalizer fails, don't run the others. Return this |
586 | // as the 'real' error, replacing what we could have had (or not) | 588 | // as the 'real' error, replacing what we could have had (or not) |
587 | // from the actual code. | 589 | // from the actual code. |
@@ -610,7 +612,7 @@ int Lane::LuaErrorHandler(lua_State* L_) | |||
610 | 612 | ||
611 | if (lane_->isCoroutine()) { | 613 | if (lane_->isCoroutine()) { |
612 | // only the coroutine thread should remain on the master state when we are done | 614 | // only the coroutine thread should remain on the master state when we are done |
613 | LUA_ASSERT(_L, lua_gettop(_L) == 1 && luaG_type(_L, 1) == LuaType::THREAD); | 615 | LUA_ASSERT(_L, lua_gettop(_L) == 1 && luaG_type(_L, StackIndex{ 1 }) == LuaType::THREAD); |
614 | } | 616 | } |
615 | 617 | ||
616 | return _rc; | 618 | return _rc; |
@@ -670,7 +672,7 @@ static void PrepareLaneHelpers(Lane* const lane_) | |||
670 | lua_State* const _L{ lane_->L }; | 672 | lua_State* const _L{ lane_->L }; |
671 | // Tie "set_finalizer()" to the state | 673 | // Tie "set_finalizer()" to the state |
672 | lua_pushcfunction(_L, LG_set_finalizer); | 674 | lua_pushcfunction(_L, LG_set_finalizer); |
673 | tools::PopulateFuncLookupTable(_L, -1, "set_finalizer"); | 675 | tools::PopulateFuncLookupTable(_L, kIdxTop, "set_finalizer"); |
674 | lua_setglobal(_L, "set_finalizer"); | 676 | lua_setglobal(_L, "set_finalizer"); |
675 | 677 | ||
676 | // Tie "lane_threadname()" to the state | 678 | // Tie "lane_threadname()" to the state |
@@ -681,7 +683,7 @@ static void PrepareLaneHelpers(Lane* const lane_) | |||
681 | 683 | ||
682 | // Tie "cancel_test()" to the state | 684 | // Tie "cancel_test()" to the state |
683 | lua_pushcfunction(_L, LG_cancel_test); | 685 | lua_pushcfunction(_L, LG_cancel_test); |
684 | tools::PopulateFuncLookupTable(_L, -1, "cancel_test"); | 686 | tools::PopulateFuncLookupTable(_L, kIdxTop, "cancel_test"); |
685 | lua_setglobal(_L, "cancel_test"); | 687 | lua_setglobal(_L, "cancel_test"); |
686 | } | 688 | } |
687 | 689 | ||
@@ -752,7 +754,7 @@ static void lane_main(Lane* const lane_) | |||
752 | } | 754 | } |
753 | 755 | ||
754 | // in case of error and if it exists, fetch stack trace from registry and push it | 756 | // in case of error and if it exists, fetch stack trace from registry and push it |
755 | lane_->nresults += PushStackTrace(_L, lane_->errorTraceLevel, _rc, 1); // L: retvals|error [trace] | 757 | lane_->nresults += PushStackTrace(_L, lane_->errorTraceLevel, _rc, StackIndex{ 1 }); // L: retvals|error [trace] |
756 | 758 | ||
757 | DEBUGSPEW_CODE(DebugSpew(lane_->U) << "Lane " << _L << " body: " << GetErrcodeName(_rc) << " (" << (kCancelError.equals(_L, 1) ? "cancelled" : luaG_typename(_L, 1)) << ")" << std::endl); | 759 | DEBUGSPEW_CODE(DebugSpew(lane_->U) << "Lane " << _L << " body: " << GetErrcodeName(_rc) << " (" << (kCancelError.equals(_L, 1) ? "cancelled" : luaG_typename(_L, 1)) << ")" << std::endl); |
758 | // Call finalizers, if the script has set them up. | 760 | // Call finalizers, if the script has set them up. |
@@ -782,7 +784,7 @@ static void lane_main(Lane* const lane_) | |||
782 | } | 784 | } |
783 | 785 | ||
784 | // leave results (1..top) or error message + stack trace (1..2) on the stack - master will copy them | 786 | // leave results (1..top) or error message + stack trace (1..2) on the stack - master will copy them |
785 | Lane::Status const _st{ (_rc == LuaError::OK) ? Lane::Done : kCancelError.equals(_L, 1) ? Lane::Cancelled : Lane::Error }; | 787 | Lane::Status const _st{ (_rc == LuaError::OK) ? Lane::Done : kCancelError.equals(_L, StackIndex{ 1 }) ? Lane::Cancelled : Lane::Error }; |
786 | // 'doneMutex' protects the -> Done|Error|Cancelled state change, and the Running|Suspended|Resuming state change too | 788 | // 'doneMutex' protects the -> Done|Error|Cancelled state change, and the Running|Suspended|Resuming state change too |
787 | std::lock_guard _guard{ lane_->doneMutex }; | 789 | std::lock_guard _guard{ lane_->doneMutex }; |
788 | lane_->status = _st; | 790 | lane_->status = _st; |
@@ -794,7 +796,7 @@ static void lane_main(Lane* const lane_) | |||
794 | #if LUA_VERSION_NUM >= 504 | 796 | #if LUA_VERSION_NUM >= 504 |
795 | static LUAG_FUNC(lane_close) | 797 | static LUAG_FUNC(lane_close) |
796 | { | 798 | { |
797 | [[maybe_unused]] Lane* const _lane{ ToLane(L_, 1) }; // L_: lane err|nil | 799 | [[maybe_unused]] Lane* const _lane{ ToLane(L_, StackIndex{ 1 }) }; // L_: lane err|nil |
798 | // drop the error if any | 800 | // drop the error if any |
799 | lua_settop(L_, 1); // L_: lane | 801 | lua_settop(L_, 1); // L_: lane |
800 | 802 | ||
@@ -823,10 +825,10 @@ static LUAG_FUNC(lane_close) | |||
823 | static LUAG_FUNC(lane_gc) | 825 | static LUAG_FUNC(lane_gc) |
824 | { | 826 | { |
825 | bool _have_gc_cb{ false }; | 827 | bool _have_gc_cb{ false }; |
826 | Lane* const _lane{ ToLane(L_, 1) }; // L_: ud | 828 | Lane* const _lane{ ToLane(L_, StackIndex{ 1 }) }; // L_: ud |
827 | 829 | ||
828 | // if there a gc callback? | 830 | // if there a gc callback? |
829 | lua_getiuservalue(L_, 1, 1); // L_: ud uservalue | 831 | lua_getiuservalue(L_, StackIndex{ 1 }, 1); // L_: ud uservalue |
830 | kLaneGC.pushKey(L_); // L_: ud uservalue __gc | 832 | kLaneGC.pushKey(L_); // L_: ud uservalue __gc |
831 | lua_rawget(L_, -2); // L_: ud uservalue gc_cb|nil | 833 | lua_rawget(L_, -2); // L_: ud uservalue gc_cb|nil |
832 | if (!lua_isnil(L_, -1)) { | 834 | if (!lua_isnil(L_, -1)) { |
@@ -932,7 +934,7 @@ CancelResult Lane::cancel(CancelOp const op_, int const hookCount_, std::chrono: | |||
932 | 934 | ||
933 | // ################################################################################################# | 935 | // ################################################################################################# |
934 | 936 | ||
935 | [[nodiscard]] CancelResult Lane::cancelHard(std::chrono::time_point<std::chrono::steady_clock> until_, bool wakeLane_) | 937 | [[nodiscard]] CancelResult Lane::cancelHard(std::chrono::time_point<std::chrono::steady_clock> const until_, bool const wakeLane_) |
936 | { | 938 | { |
937 | cancelRequest = CancelRequest::Hard; // it's now signaled to stop | 939 | cancelRequest = CancelRequest::Hard; // it's now signaled to stop |
938 | // lane_->thread.get_stop_source().request_stop(); | 940 | // lane_->thread.get_stop_source().request_stop(); |
@@ -949,7 +951,7 @@ CancelResult Lane::cancel(CancelOp const op_, int const hookCount_, std::chrono: | |||
949 | 951 | ||
950 | // ################################################################################################# | 952 | // ################################################################################################# |
951 | 953 | ||
952 | [[nodiscard]] CancelResult Lane::cancelSoft(std::chrono::time_point<std::chrono::steady_clock> until_, bool wakeLane_) | 954 | [[nodiscard]] CancelResult Lane::cancelSoft(std::chrono::time_point<std::chrono::steady_clock> const until_, bool const wakeLane_) |
953 | { | 955 | { |
954 | cancelRequest = CancelRequest::Soft; // it's now signaled to stop | 956 | cancelRequest = CancelRequest::Soft; // it's now signaled to stop |
955 | // negative timeout: we don't want to truly abort the lane, we just want it to react to cancel_test() on its own | 957 | // negative timeout: we don't want to truly abort the lane, we just want it to react to cancel_test() on its own |
@@ -966,9 +968,9 @@ CancelResult Lane::cancel(CancelOp const op_, int const hookCount_, std::chrono: | |||
966 | 968 | ||
967 | // ################################################################################################# | 969 | // ################################################################################################# |
968 | 970 | ||
969 | void Lane::changeDebugName(int const nameIdx_) | 971 | void Lane::changeDebugName(StackIndex const nameIdx_) |
970 | { | 972 | { |
971 | int const _nameIdx{ luaG_absindex(L, nameIdx_) }; | 973 | StackIndex const _nameIdx{ luaG_absindex(L, nameIdx_) }; |
972 | luaL_checktype(L, _nameIdx, LUA_TSTRING); // L: ... "name" ... | 974 | luaL_checktype(L, _nameIdx, LUA_TSTRING); // L: ... "name" ... |
973 | STACK_CHECK_START_REL(L, 0); | 975 | STACK_CHECK_START_REL(L, 0); |
974 | // 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... | 976 | // 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... |
@@ -1064,11 +1066,11 @@ void Lane::pushStatusString(lua_State* L_) const | |||
1064 | 1066 | ||
1065 | void Lane::pushIndexedResult(lua_State* const L_, int const key_) const | 1067 | void Lane::pushIndexedResult(lua_State* const L_, int const key_) const |
1066 | { | 1068 | { |
1067 | static constexpr int kSelf{ 1 }; | 1069 | static constexpr StackIndex kIdxSelf{ 1 }; |
1068 | LUA_ASSERT(L_, ToLane(L_, kSelf) == this); // L_: lane ... | 1070 | LUA_ASSERT(L_, ToLane(L_, kIdxSelf) == this); // L_: lane ... |
1069 | STACK_GROW(L_, 3); | 1071 | STACK_GROW(L_, 3); |
1070 | 1072 | ||
1071 | lua_getiuservalue(L_, kSelf, 1); // L_: lane ... {uv} | 1073 | lua_getiuservalue(L_, kIdxSelf, 1); // L_: lane ... {uv} |
1072 | if (status != Lane::Error) { | 1074 | if (status != Lane::Error) { |
1073 | lua_rawgeti(L_, -1, key_); // L_: lane ... {uv} uv[i] | 1075 | lua_rawgeti(L_, -1, key_); // L_: lane ... {uv} uv[i] |
1074 | lua_remove(L_, -2); // L_: lane ... uv[i] | 1076 | lua_remove(L_, -2); // L_: lane ... uv[i] |
@@ -1083,7 +1085,7 @@ void Lane::pushIndexedResult(lua_State* const L_, int const key_) const | |||
1083 | lua_remove(L_, -2); // L_: lane ... <error> | 1085 | lua_remove(L_, -2); // L_: lane ... <error> |
1084 | return; | 1086 | return; |
1085 | } | 1087 | } |
1086 | lua_getmetatable(L_, kSelf); // L_: lane ... {uv} <error> {mt} | 1088 | lua_getmetatable(L_, kIdxSelf); // L_: lane ... {uv} <error> {mt} |
1087 | lua_replace(L_, -3); // L_: lane ... {mt} <error> | 1089 | lua_replace(L_, -3); // L_: lane ... {mt} <error> |
1088 | // Note: Lua 5.1 interpreter is not prepared to show | 1090 | // Note: Lua 5.1 interpreter is not prepared to show |
1089 | // non-string errors, so we use 'tostring()' here | 1091 | // non-string errors, so we use 'tostring()' here |
@@ -1127,11 +1129,11 @@ void Lane::pushIndexedResult(lua_State* const L_, int const key_) const | |||
1127 | 1129 | ||
1128 | // replace the current uservalue (a table holding the returned values of the lane body) | 1130 | // replace the current uservalue (a table holding the returned values of the lane body) |
1129 | // by a new empty one, but transfer the gc_cb that is stored in there so that it is not lost | 1131 | // by a new empty one, but transfer the gc_cb that is stored in there so that it is not lost |
1130 | void Lane::resetResultsStorage(lua_State* const L_, int const self_idx_) | 1132 | void Lane::resetResultsStorage(lua_State* const L_, StackIndex const self_idx_) |
1131 | { | 1133 | { |
1132 | STACK_GROW(L_, 4); | 1134 | STACK_GROW(L_, 4); |
1133 | STACK_CHECK_START_REL(L_, 0); | 1135 | STACK_CHECK_START_REL(L_, 0); |
1134 | int const _self_idx{ luaG_absindex(L_, self_idx_) }; | 1136 | StackIndex const _self_idx{ luaG_absindex(L_, self_idx_) }; |
1135 | LUA_ASSERT(L_, ToLane(L_, _self_idx) == this); // L_: ... self ... | 1137 | LUA_ASSERT(L_, ToLane(L_, _self_idx) == this); // L_: ... self ... |
1136 | // create the new table | 1138 | // create the new table |
1137 | lua_newtable(L_); // L_: ... self ... {} | 1139 | lua_newtable(L_); // L_: ... self ... {} |
@@ -1154,12 +1156,12 @@ void Lane::resetResultsStorage(lua_State* const L_, int const self_idx_) | |||
1154 | // ################################################################################################# | 1156 | // ################################################################################################# |
1155 | 1157 | ||
1156 | // intern the debug name in the caller lua state so that the pointer remains valid after the lane's state is closed | 1158 | // intern the debug name in the caller lua state so that the pointer remains valid after the lane's state is closed |
1157 | void Lane::securizeDebugName(lua_State* L_) | 1159 | void Lane::securizeDebugName(lua_State* const L_) |
1158 | { | 1160 | { |
1159 | STACK_CHECK_START_REL(L_, 0); | 1161 | STACK_CHECK_START_REL(L_, 0); |
1160 | STACK_GROW(L_, 3); | 1162 | STACK_GROW(L_, 3); |
1161 | // a Lane's uservalue should be a table | 1163 | // a Lane's uservalue should be a table |
1162 | lua_getiuservalue(L_, 1, 1); // L_: lane ... {uv} | 1164 | lua_getiuservalue(L_, StackIndex{ 1 }, 1); // L_: lane ... {uv} |
1163 | LUA_ASSERT(L_, lua_istable(L_, -1)); | 1165 | LUA_ASSERT(L_, lua_istable(L_, -1)); |
1164 | // we don't care about the actual key, so long as it's unique and can't collide with anything. | 1166 | // we don't care about the actual key, so long as it's unique and can't collide with anything. |
1165 | lua_newtable(L_); // L_: lane ... {uv} {} | 1167 | lua_newtable(L_); // L_: lane ... {uv} {} |
@@ -1174,7 +1176,7 @@ void Lane::securizeDebugName(lua_State* L_) | |||
1174 | 1176 | ||
1175 | // ################################################################################################# | 1177 | // ################################################################################################# |
1176 | 1178 | ||
1177 | void Lane::startThread(int priority_) | 1179 | void Lane::startThread(int const priority_) |
1178 | { | 1180 | { |
1179 | thread = std::thread([this]() { lane_main(this); }); | 1181 | thread = std::thread([this]() { lane_main(this); }); |
1180 | if (priority_ != kThreadPrioDefault) { | 1182 | if (priority_ != kThreadPrioDefault) { |
@@ -1189,12 +1191,12 @@ void Lane::startThread(int priority_) | |||
1189 | // t[i] = result #i | 1191 | // t[i] = result #i |
1190 | int Lane::storeResults(lua_State* const L_) | 1192 | int Lane::storeResults(lua_State* const L_) |
1191 | { | 1193 | { |
1192 | static constexpr int kSelf{ 1 }; | 1194 | static constexpr StackIndex kIdxSelf{ 1 }; |
1193 | LUA_ASSERT(L_, ToLane(L_, kSelf) == this); | 1195 | LUA_ASSERT(L_, ToLane(L_, kIdxSelf) == this); |
1194 | 1196 | ||
1195 | STACK_CHECK_START_REL(L_, 0); | 1197 | STACK_CHECK_START_REL(L_, 0); |
1196 | lua_getiuservalue(L_, kSelf, 1); // L_: lane ... {uv} | 1198 | lua_getiuservalue(L_, kIdxSelf, 1); // L_: lane ... {uv} |
1197 | int const _tidx{ lua_gettop(L_) }; | 1199 | StackIndex const _tidx{ lua_gettop(L_) }; |
1198 | 1200 | ||
1199 | int _stored{}; | 1201 | int _stored{}; |
1200 | if (nresults == 0) { | 1202 | if (nresults == 0) { |
@@ -1252,7 +1254,7 @@ int Lane::storeResults(lua_State* const L_) | |||
1252 | case Lane::Cancelled: | 1254 | case Lane::Cancelled: |
1253 | _stored = 2; | 1255 | _stored = 2; |
1254 | // we should have a single value, kCancelError, in the stack of L | 1256 | // we should have a single value, kCancelError, in the stack of L |
1255 | LUA_ASSERT(L_, nresults == 1 && lua_gettop(L) == 1 && kCancelError.equals(L, 1)); | 1257 | LUA_ASSERT(L_, nresults == 1 && lua_gettop(L) == 1 && kCancelError.equals(L, StackIndex{ 1 })); |
1256 | // store nil, cancel_error in the results | 1258 | // store nil, cancel_error in the results |
1257 | lua_pushnil(L_); // L_: lane ... {uv} nil | 1259 | lua_pushnil(L_); // L_: lane ... {uv} nil |
1258 | lua_rawseti(L_, _tidx, 1); // L_: lane ... {uv} | 1260 | lua_rawseti(L_, _tidx, 1); // L_: lane ... {uv} |
@@ -146,7 +146,7 @@ class Lane | |||
146 | public: | 146 | public: |
147 | 147 | ||
148 | CancelResult cancel(CancelOp op_, int hookCount_, std::chrono::time_point<std::chrono::steady_clock> until_, bool wakeLane_); | 148 | CancelResult cancel(CancelOp op_, int hookCount_, std::chrono::time_point<std::chrono::steady_clock> until_, bool wakeLane_); |
149 | void changeDebugName(int const nameIdx_); | 149 | void changeDebugName(StackIndex nameIdx_); |
150 | void closeState() | 150 | void closeState() |
151 | { | 151 | { |
152 | lua_State* _L{ S }; | 152 | lua_State* _L{ S }; |
@@ -173,7 +173,7 @@ class Lane | |||
173 | static void PushMetatable(lua_State* L_); | 173 | static void PushMetatable(lua_State* L_); |
174 | void pushStatusString(lua_State* L_) const; | 174 | void pushStatusString(lua_State* L_) const; |
175 | void pushIndexedResult(lua_State* L_, int key_) const; | 175 | void pushIndexedResult(lua_State* L_, int key_) const; |
176 | void resetResultsStorage(lua_State* const L_, int gc_cb_idx_); | 176 | void resetResultsStorage(lua_State* L_, StackIndex self_idx_); |
177 | void selfdestructAdd(); | 177 | void selfdestructAdd(); |
178 | [[nodiscard]] bool selfdestructRemove(); | 178 | [[nodiscard]] bool selfdestructRemove(); |
179 | void securizeDebugName(lua_State* L_); | 179 | void securizeDebugName(lua_State* L_); |
@@ -190,7 +190,7 @@ class Lane | |||
190 | // 'Lane' are malloc/free'd and the handle only carries a pointer. | 190 | // 'Lane' are malloc/free'd and the handle only carries a pointer. |
191 | // This is not deep userdata since the handle is not portable among lanes. | 191 | // This is not deep userdata since the handle is not portable among lanes. |
192 | // | 192 | // |
193 | [[nodiscard]] inline Lane* ToLane(lua_State* L_, int i_) | 193 | [[nodiscard]] inline Lane* ToLane(lua_State* const L_, StackIndex const i_) |
194 | { | 194 | { |
195 | return *(static_cast<Lane**>(luaL_checkudata(L_, i_, kLaneMetatableName))); | 195 | return *(static_cast<Lane**>(luaL_checkudata(L_, i_, kLaneMetatableName))); |
196 | } | 196 | } |
diff --git a/src/lanes.cpp b/src/lanes.cpp index c820568..3aef572 100644 --- a/src/lanes.cpp +++ b/src/lanes.cpp | |||
@@ -169,12 +169,12 @@ 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_tostring(L_, 1) == "indefinitely") { | 172 | if (luaG_tostring(L_, StackIndex{ 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 |
176 | } else if (!lua_isnumber(L_, 1)) { | 176 | } else if (!lua_isnumber(L_, 1)) { |
177 | raise_luaL_argerror(L_, 1, "invalid duration"); | 177 | raise_luaL_argerror(L_, StackIndex{ 1 }, "invalid duration"); |
178 | } | 178 | } |
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 |
@@ -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_tostring(L_, 1) }; // L_: "name" ... | 196 | std::string_view const _name{ luaG_tostring(L_, StackIndex{ 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); |
@@ -202,7 +202,7 @@ LUAG_FUNC(require) | |||
202 | lua_pushvalue(L_, lua_upvalueindex(1)); // L_: "name" ... require | 202 | lua_pushvalue(L_, lua_upvalueindex(1)); // L_: "name" ... require |
203 | lua_insert(L_, 1); // L_: require "name" ... | 203 | lua_insert(L_, 1); // L_: require "name" ... |
204 | lua_call(L_, _nargs, 1); // L_: module | 204 | lua_call(L_, _nargs, 1); // L_: module |
205 | tools::PopulateFuncLookupTable(L_, -1, _name); | 205 | tools::PopulateFuncLookupTable(L_, kIdxTop, _name); |
206 | DEBUGSPEW_CODE(DebugSpew(_U) << "lanes.require '" << _name << "' END" << std::endl); | 206 | DEBUGSPEW_CODE(DebugSpew(_U) << "lanes.require '" << _name << "' END" << std::endl); |
207 | STACK_CHECK(L_, 0); | 207 | STACK_CHECK(L_, 0); |
208 | return 1; | 208 | return 1; |
@@ -215,8 +215,8 @@ 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_checkstring(L_, 1) }; | 218 | std::string_view const _name{ luaG_checkstring(L_, StackIndex{ 1 }) }; |
219 | LuaType const _mod_type{ luaG_type(L_, 2) }; | 219 | LuaType const _mod_type{ luaG_type(L_, StackIndex{ 2 }) }; |
220 | // ignore extra arguments, just in case | 220 | // ignore extra arguments, just in case |
221 | lua_settop(L_, 2); | 221 | lua_settop(L_, 2); |
222 | luaL_argcheck(L_, (_mod_type == LuaType::TABLE) || (_mod_type == LuaType::FUNCTION), 2, "unexpected module type"); | 222 | luaL_argcheck(L_, (_mod_type == LuaType::TABLE) || (_mod_type == LuaType::FUNCTION), 2, "unexpected module type"); |
@@ -224,7 +224,7 @@ LUAG_FUNC(register) | |||
224 | STACK_CHECK_START_REL(L_, 0); // "name" mod_table | 224 | STACK_CHECK_START_REL(L_, 0); // "name" mod_table |
225 | DEBUGSPEW_CODE(DebugSpew(_U) << "lanes.register '" << _name << "' BEGIN" << std::endl); | 225 | DEBUGSPEW_CODE(DebugSpew(_U) << "lanes.register '" << _name << "' BEGIN" << std::endl); |
226 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); | 226 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); |
227 | tools::PopulateFuncLookupTable(L_, -1, _name); | 227 | tools::PopulateFuncLookupTable(L_, kIdxTop, _name); |
228 | DEBUGSPEW_CODE(DebugSpew(_U) << "lanes.register '" << _name << "' END" << std::endl); | 228 | DEBUGSPEW_CODE(DebugSpew(_U) << "lanes.register '" << _name << "' END" << std::endl); |
229 | STACK_CHECK(L_, 0); | 229 | STACK_CHECK(L_, 0); |
230 | return 0; | 230 | return 0; |
@@ -249,17 +249,17 @@ LUAG_FUNC(register) | |||
249 | // | 249 | // |
250 | LUAG_FUNC(lane_new) | 250 | LUAG_FUNC(lane_new) |
251 | { | 251 | { |
252 | static constexpr int kFuncIdx{ 1 }; | 252 | static constexpr StackIndex kFuncIdx{ 1 }; |
253 | static constexpr int kLibsIdx{ 2 }; | 253 | static constexpr StackIndex kLibsIdx{ 2 }; |
254 | static constexpr int kPrioIdx{ 3 }; | 254 | static constexpr StackIndex kPrioIdx{ 3 }; |
255 | static constexpr int kGlobIdx{ 4 }; | 255 | static constexpr StackIndex kGlobIdx{ 4 }; |
256 | static constexpr int kPackIdx{ 5 }; | 256 | static constexpr StackIndex kPackIdx{ 5 }; |
257 | static constexpr int kRequIdx{ 6 }; | 257 | static constexpr StackIndex kRequIdx{ 6 }; |
258 | static constexpr int kGcCbIdx{ 7 }; | 258 | static constexpr StackIndex kGcCbIdx{ 7 }; |
259 | static constexpr int kNameIdx{ 8 }; | 259 | static constexpr StackIndex kNameIdx{ 8 }; |
260 | static constexpr int kErTlIdx{ 9 }; | 260 | static constexpr StackIndex kErTlIdx{ 9 }; |
261 | static constexpr int kAsCoro{ 10 }; | 261 | static constexpr StackIndex kAsCoro{ 10 }; |
262 | static constexpr int kFixedArgsIdx{ 10 }; | 262 | static constexpr StackIndex kFixedArgsIdx{ 10 }; |
263 | 263 | ||
264 | int const _nargs{ lua_gettop(L_) - kFixedArgsIdx }; | 264 | int const _nargs{ lua_gettop(L_) - kFixedArgsIdx }; |
265 | LUA_ASSERT(L_, _nargs >= 0); | 265 | LUA_ASSERT(L_, _nargs >= 0); |
@@ -342,7 +342,7 @@ LUAG_FUNC(lane_new) | |||
342 | lua_newtable(L); // L: ... lane {uv} | 342 | lua_newtable(L); // L: ... lane {uv} |
343 | 343 | ||
344 | // Store the gc_cb callback in the uservalue | 344 | // Store the gc_cb callback in the uservalue |
345 | int const _gc_cb_idx{ lua_isnoneornil(L, kGcCbIdx) ? 0 : kGcCbIdx }; | 345 | StackIndex const _gc_cb_idx{ lua_isnoneornil(L, kGcCbIdx) ? 0 : kGcCbIdx }; |
346 | if (_gc_cb_idx > 0) { | 346 | if (_gc_cb_idx > 0) { |
347 | kLaneGC.pushKey(L); // L: ... lane {uv} k | 347 | kLaneGC.pushKey(L); // L: ... lane {uv} k |
348 | lua_pushvalue(L, _gc_cb_idx); // L: ... lane {uv} k gc_cb | 348 | lua_pushvalue(L, _gc_cb_idx); // L: ... lane {uv} k gc_cb |
@@ -350,11 +350,11 @@ LUAG_FUNC(lane_new) | |||
350 | } | 350 | } |
351 | STACK_CHECK(L, 2); | 351 | STACK_CHECK(L, 2); |
352 | // store the uservalue in the Lane full userdata | 352 | // store the uservalue in the Lane full userdata |
353 | lua_setiuservalue(L, -2, 1); // L: ... lane | 353 | lua_setiuservalue(L, StackIndex{ -2 }, 1); // L: ... lane |
354 | 354 | ||
355 | lua_State* const _L2{ lane->L }; | 355 | lua_State* const _L2{ lane->L }; |
356 | STACK_CHECK_START_REL(_L2, 0); | 356 | STACK_CHECK_START_REL(_L2, 0); |
357 | int const _name_idx{ lua_isnoneornil(L, kNameIdx) ? 0 : kNameIdx }; | 357 | StackIndex const _name_idx{ lua_isnoneornil(L, kNameIdx) ? 0 : kNameIdx }; |
358 | std::string_view const _debugName{ (_name_idx > 0) ? luaG_tostring(L, _name_idx) : std::string_view{} }; | 358 | std::string_view const _debugName{ (_name_idx > 0) ? luaG_tostring(L, _name_idx) : std::string_view{} }; |
359 | if (!_debugName.empty()) | 359 | if (!_debugName.empty()) |
360 | { | 360 | { |
@@ -366,7 +366,7 @@ LUAG_FUNC(lane_new) | |||
366 | lua_getinfo(L, ">S", &_ar); // L: ... lane | 366 | lua_getinfo(L, ">S", &_ar); // L: ... lane |
367 | luaG_pushstring(_L2, "%s:%d", _ar.short_src, _ar.linedefined); // L: ... lane L2: "<name>" | 367 | luaG_pushstring(_L2, "%s:%d", _ar.short_src, _ar.linedefined); // L: ... lane L2: "<name>" |
368 | } | 368 | } |
369 | lane->changeDebugName(-1); | 369 | lane->changeDebugName(kIdxTop); |
370 | lua_pop(_L2, 1); // L: ... lane L2: | 370 | lua_pop(_L2, 1); // L: ... lane L2: |
371 | } | 371 | } |
372 | STACK_CHECK(_L2, 0); | 372 | STACK_CHECK(_L2, 0); |
@@ -412,7 +412,7 @@ LUAG_FUNC(lane_new) | |||
412 | STACK_CHECK_START_REL(L_, 0); | 412 | STACK_CHECK_START_REL(L_, 0); |
413 | 413 | ||
414 | // package | 414 | // package |
415 | int const _package_idx{ lua_isnoneornil(L_, kPackIdx) ? 0 : kPackIdx }; | 415 | StackIndex const _package_idx{ lua_isnoneornil(L_, kPackIdx) ? 0 : kPackIdx }; |
416 | if (_package_idx != 0) { | 416 | if (_package_idx != 0) { |
417 | DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: update 'package'" << std::endl); | 417 | DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: update 'package'" << std::endl); |
418 | // when copying with mode LookupMode::LaneBody, should raise an error in case of problem, not leave it one the stack | 418 | // when copying with mode LookupMode::LaneBody, should raise an error in case of problem, not leave it one the stack |
@@ -424,7 +424,7 @@ LUAG_FUNC(lane_new) | |||
424 | STACK_CHECK(_L2, 0); | 424 | STACK_CHECK(_L2, 0); |
425 | 425 | ||
426 | // modules to require in the target lane *before* the function is transfered! | 426 | // modules to require in the target lane *before* the function is transfered! |
427 | int const _required_idx{ lua_isnoneornil(L_, kRequIdx) ? 0 : kRequIdx }; | 427 | StackIndex const _required_idx{ lua_isnoneornil(L_, kRequIdx) ? 0 : kRequIdx }; |
428 | if (_required_idx != 0) { | 428 | if (_required_idx != 0) { |
429 | int _nbRequired{ 1 }; | 429 | int _nbRequired{ 1 }; |
430 | DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: process 'required' list" << std::endl); | 430 | DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: process 'required' list" << std::endl); |
@@ -436,11 +436,11 @@ LUAG_FUNC(lane_new) | |||
436 | 436 | ||
437 | lua_pushnil(L_); // L_: [fixed] args... nil L2: | 437 | lua_pushnil(L_); // L_: [fixed] args... nil L2: |
438 | while (lua_next(L_, _required_idx) != 0) { // L_: [fixed] args... n "modname" L2: | 438 | while (lua_next(L_, _required_idx) != 0) { // L_: [fixed] args... n "modname" L2: |
439 | if (luaG_type(L_, -1) != LuaType::STRING || luaG_type(L_, -2) != LuaType::NUMBER || lua_tonumber(L_, -2) != _nbRequired) { | 439 | if (luaG_type(L_, kIdxTop) != LuaType::STRING || luaG_type(L_, StackIndex{ -2 }) != LuaType::NUMBER || lua_tonumber(L_, -2) != _nbRequired) { |
440 | raise_luaL_error(L_, "required module list should be a list of strings"); | 440 | raise_luaL_error(L_, "required module list should be a list of strings"); |
441 | } else { | 441 | } else { |
442 | // require the module in the target state, and populate the lookup table there too | 442 | // require the module in the target state, and populate the lookup table there too |
443 | std::string_view const _name{ luaG_tostring(L_, -1) }; | 443 | std::string_view const _name{ luaG_tostring(L_, kIdxTop) }; |
444 | DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: require '" << _name << "'" << std::endl); | 444 | DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: require '" << _name << "'" << std::endl); |
445 | 445 | ||
446 | // require the module in the target lane | 446 | // require the module in the target lane |
@@ -459,7 +459,7 @@ LUAG_FUNC(lane_new) | |||
459 | } | 459 | } |
460 | // here the module was successfully required // L_: [fixed] args... n "modname" L2: ret | 460 | // here the module was successfully required // L_: [fixed] args... n "modname" L2: ret |
461 | // after requiring the module, register the functions it exported in our name<->function database | 461 | // after requiring the module, register the functions it exported in our name<->function database |
462 | tools::PopulateFuncLookupTable(_L2, -1, _name); | 462 | tools::PopulateFuncLookupTable(_L2, kIdxTop, _name); |
463 | lua_pop(_L2, 1); // L_: [fixed] args... n "modname" L2: | 463 | lua_pop(_L2, 1); // L_: [fixed] args... n "modname" L2: |
464 | } | 464 | } |
465 | } | 465 | } |
@@ -473,7 +473,7 @@ LUAG_FUNC(lane_new) | |||
473 | // Appending the specified globals to the global environment | 473 | // Appending the specified globals to the global environment |
474 | // *after* stdlibs have been loaded and modules required, in case we transfer references to native functions they exposed... | 474 | // *after* stdlibs have been loaded and modules required, in case we transfer references to native functions they exposed... |
475 | // | 475 | // |
476 | int const _globals_idx{ lua_isnoneornil(L_, kGlobIdx) ? 0 : kGlobIdx }; | 476 | StackIndex const _globals_idx{ lua_isnoneornil(L_, kGlobIdx) ? 0 : kGlobIdx }; |
477 | if (_globals_idx != 0) { | 477 | if (_globals_idx != 0) { |
478 | DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: transfer globals" << std::endl); | 478 | DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: transfer globals" << std::endl); |
479 | if (!lua_istable(L_, _globals_idx)) { | 479 | if (!lua_istable(L_, _globals_idx)) { |
@@ -603,7 +603,7 @@ LUAG_FUNC(wakeup_conv) | |||
603 | 603 | ||
604 | STACK_CHECK_START_REL(L_, 0); | 604 | STACK_CHECK_START_REL(L_, 0); |
605 | auto _readInteger = [L = L_](std::string_view const& name_) { | 605 | auto _readInteger = [L = L_](std::string_view const& name_) { |
606 | std::ignore = luaG_getfield(L, 1, name_); | 606 | std::ignore = luaG_getfield(L, StackIndex{ 1 }, name_); |
607 | lua_Integer const val{ lua_tointeger(L, -1) }; | 607 | lua_Integer const val{ lua_tointeger(L, -1) }; |
608 | lua_pop(L, 1); | 608 | lua_pop(L, 1); |
609 | return static_cast<int>(val); | 609 | return static_cast<int>(val); |
@@ -619,7 +619,7 @@ LUAG_FUNC(wakeup_conv) | |||
619 | // If Lua table has '.isdst' we trust that. If it does not, we'll let | 619 | // If Lua table has '.isdst' we trust that. If it does not, we'll let |
620 | // 'mktime' decide on whether the time is within DST or not (value -1). | 620 | // 'mktime' decide on whether the time is within DST or not (value -1). |
621 | // | 621 | // |
622 | int const _isdst{ (luaG_getfield(L_, 1, "isdst") == LuaType::BOOLEAN) ? lua_toboolean(L_, -1) : -1 }; | 622 | int const _isdst{ (luaG_getfield(L_, StackIndex{ 1 }, "isdst") == LuaType::BOOLEAN) ? lua_toboolean(L_, -1) : -1 }; |
623 | lua_pop(L_, 1); | 623 | lua_pop(L_, 1); |
624 | STACK_CHECK(L_, 0); | 624 | STACK_CHECK(L_, 0); |
625 | 625 | ||
@@ -682,8 +682,8 @@ LUAG_FUNC(configure) | |||
682 | 682 | ||
683 | Universe* _U{ Universe::Get(L_) }; | 683 | Universe* _U{ Universe::Get(L_) }; |
684 | bool const _from_master_state{ _U == nullptr }; | 684 | bool const _from_master_state{ _U == nullptr }; |
685 | std::string_view const _name{ luaG_checkstring(L_, lua_upvalueindex(1)) }; | 685 | std::string_view const _name{ luaG_checkstring(L_, StackIndex{ lua_upvalueindex(1) }) }; |
686 | LUA_ASSERT(L_, luaG_type(L_, 1) == LuaType::TABLE); | 686 | LUA_ASSERT(L_, luaG_type(L_, StackIndex{ 1 }) == LuaType::TABLE); |
687 | 687 | ||
688 | STACK_GROW(L_, 4); | 688 | STACK_GROW(L_, 4); |
689 | STACK_CHECK_START_ABS(L_, 1); // L_: settings | 689 | STACK_CHECK_START_ABS(L_, 1); // L_: settings |
@@ -759,7 +759,7 @@ LUAG_FUNC(configure) | |||
759 | // register all native functions found in that module in the transferable functions database | 759 | // register all native functions found in that module in the transferable functions database |
760 | // we process it before _G because we don't want to find the module when scanning _G (this would generate longer names) | 760 | // we process it before _G because we don't want to find the module when scanning _G (this would generate longer names) |
761 | // for example in package.loaded["lanes.core"].* | 761 | // for example in package.loaded["lanes.core"].* |
762 | tools::PopulateFuncLookupTable(L_, -1, _name); | 762 | tools::PopulateFuncLookupTable(L_, kIdxTop, _name); |
763 | STACK_CHECK(L_, 2); | 763 | STACK_CHECK(L_, 2); |
764 | 764 | ||
765 | // record all existing C/JIT-fast functions | 765 | // record all existing C/JIT-fast functions |
@@ -769,7 +769,7 @@ LUAG_FUNC(configure) | |||
769 | // because we will do it after on_state_create() is called, | 769 | // because we will do it after on_state_create() is called, |
770 | // and we don't want to skip _G because of caching in case globals are created then | 770 | // and we don't want to skip _G because of caching in case globals are created then |
771 | luaG_pushglobaltable(L_); // L_: settings M _G | 771 | luaG_pushglobaltable(L_); // L_: settings M _G |
772 | tools::PopulateFuncLookupTable(L_, -1, {}); | 772 | tools::PopulateFuncLookupTable(L_, kIdxTop, {}); |
773 | lua_pop(L_, 1); // L_: settings M | 773 | lua_pop(L_, 1); // L_: settings M |
774 | } | 774 | } |
775 | lua_pop(L_, 1); // L_: settings | 775 | lua_pop(L_, 1); // L_: settings |
diff --git a/src/linda.cpp b/src/linda.cpp index 3f5fd33..bd40f5e 100644 --- a/src/linda.cpp +++ b/src/linda.cpp | |||
@@ -280,7 +280,7 @@ void Linda::setName(std::string_view const& name_) | |||
280 | LUAG_FUNC(linda_cancel) | 280 | LUAG_FUNC(linda_cancel) |
281 | { | 281 | { |
282 | Linda* const _linda{ ToLinda<false>(L_, StackIndex{ 1 }) }; | 282 | Linda* const _linda{ ToLinda<false>(L_, StackIndex{ 1 }) }; |
283 | std::string_view const _who{ luaG_optstring(L_, 2, "both") }; | 283 | std::string_view const _who{ luaG_optstring(L_, StackIndex{ 2 }, "both") }; |
284 | // make sure we got 2 arguments: the linda and the cancellation mode | 284 | // make sure we got 2 arguments: the linda and the cancellation mode |
285 | luaL_argcheck(L_, lua_gettop(L_) <= 2, 2, "wrong number of arguments"); | 285 | luaL_argcheck(L_, lua_gettop(L_) <= 2, 2, "wrong number of arguments"); |
286 | 286 | ||
@@ -371,7 +371,7 @@ LUAG_FUNC(linda_count) | |||
371 | CheckKeyTypes(L_, StackIndex{ 2 }, StackIndex{ lua_gettop(L_) }); | 371 | CheckKeyTypes(L_, StackIndex{ 2 }, StackIndex{ lua_gettop(L_) }); |
372 | 372 | ||
373 | Keeper* const _keeper{ _linda->whichKeeper() }; | 373 | Keeper* const _keeper{ _linda->whichKeeper() }; |
374 | KeeperCallResult const _pushed{ keeper_call(_keeper->K, KEEPER_API(count), L_, _linda, 2) }; | 374 | KeeperCallResult const _pushed{ keeper_call(_keeper->K, KEEPER_API(count), L_, _linda, StackIndex{ 2 }) }; |
375 | return OptionalValue(_pushed, L_, "tried to count an invalid key"); | 375 | return OptionalValue(_pushed, L_, "tried to count an invalid key"); |
376 | } | 376 | } |
377 | }; | 377 | }; |
@@ -435,7 +435,7 @@ LUAG_FUNC(linda_get) | |||
435 | KeeperCallResult _pushed; | 435 | KeeperCallResult _pushed; |
436 | if (_linda->cancelRequest == CancelRequest::None) { | 436 | if (_linda->cancelRequest == CancelRequest::None) { |
437 | Keeper* const _keeper{ _linda->whichKeeper() }; | 437 | Keeper* const _keeper{ _linda->whichKeeper() }; |
438 | _pushed = keeper_call(_keeper->K, KEEPER_API(get), L_, _linda, 2); | 438 | _pushed = keeper_call(_keeper->K, KEEPER_API(get), L_, _linda, StackIndex{ 2 }); |
439 | } else { // linda is cancelled | 439 | } else { // linda is cancelled |
440 | // do nothing and return nil,lanes.cancel_error | 440 | // do nothing and return nil,lanes.cancel_error |
441 | lua_pushnil(L_); | 441 | lua_pushnil(L_); |
@@ -468,10 +468,10 @@ LUAG_FUNC(linda_limit) | |||
468 | int const _nargs{ lua_gettop(L_) }; | 468 | int const _nargs{ lua_gettop(L_) }; |
469 | luaL_argcheck(L_, _nargs == 2 || _nargs == 3, 2, "wrong number of arguments"); | 469 | luaL_argcheck(L_, _nargs == 2 || _nargs == 3, 2, "wrong number of arguments"); |
470 | // make sure we got a numeric limit, or "unlimited", (or nothing) | 470 | // make sure we got a numeric limit, or "unlimited", (or nothing) |
471 | bool const _unlimited{ luaG_tostring(L_, 3) == "unlimited" }; | 471 | bool const _unlimited{ luaG_tostring(L_, StackIndex{ 3 }) == "unlimited" }; |
472 | LindaLimit const _val{ _unlimited ? std::numeric_limits<LindaLimit::type>::max() : LindaLimit{ static_cast<LindaLimit::type>(luaL_optinteger(L_, 3, 0)) } }; | 472 | LindaLimit const _val{ _unlimited ? std::numeric_limits<LindaLimit::type>::max() : LindaLimit{ static_cast<LindaLimit::type>(luaL_optinteger(L_, 3, 0)) } }; |
473 | if (_val < 0) { | 473 | if (_val < 0) { |
474 | raise_luaL_argerror(L_, 3, "limit must be >= 0"); | 474 | raise_luaL_argerror(L_, StackIndex{ 3 }, "limit must be >= 0"); |
475 | } | 475 | } |
476 | // make sure the key is of a valid type | 476 | // make sure the key is of a valid type |
477 | CheckKeyTypes(L_, StackIndex{ 2 }, StackIndex{ 2 }); | 477 | CheckKeyTypes(L_, StackIndex{ 2 }, StackIndex{ 2 }); |
@@ -479,23 +479,23 @@ LUAG_FUNC(linda_limit) | |||
479 | KeeperCallResult _pushed; | 479 | KeeperCallResult _pushed; |
480 | if (_linda->cancelRequest == CancelRequest::None) { | 480 | if (_linda->cancelRequest == CancelRequest::None) { |
481 | if (_unlimited) { | 481 | if (_unlimited) { |
482 | LUA_ASSERT(L_, lua_gettop(L_) == 3 && luaG_tostring(L_, 3) == "unlimited"); | 482 | LUA_ASSERT(L_, lua_gettop(L_) == 3 && luaG_tostring(L_, StackIndex{ 3 }) == "unlimited"); |
483 | // inside the Keeper, unlimited is signified with a -1 limit (can't use nil because of nil kNilSentinel conversions!) | 483 | // inside the Keeper, unlimited is signified with a -1 limit (can't use nil because of nil kNilSentinel conversions!) |
484 | lua_pop(L_, 1); // L_: linda key | 484 | lua_pop(L_, 1); // L_: linda key |
485 | lua_pushinteger(L_, -1); // L_: linda key nil | 485 | lua_pushinteger(L_, -1); // L_: linda key nil |
486 | } | 486 | } |
487 | Keeper* const _keeper{ _linda->whichKeeper() }; | 487 | Keeper* const _keeper{ _linda->whichKeeper() }; |
488 | _pushed = keeper_call(_keeper->K, KEEPER_API(limit), L_, _linda, 2); | 488 | _pushed = keeper_call(_keeper->K, KEEPER_API(limit), L_, _linda, StackIndex{ 2 }); |
489 | LUA_ASSERT(L_, _pushed.has_value() && (_pushed.value() == 2) && luaG_type(L_, -1) == LuaType::STRING); | 489 | LUA_ASSERT(L_, _pushed.has_value() && (_pushed.value() == 2) && luaG_type(L_, kIdxTop) == LuaType::STRING); |
490 | if (_nargs == 3) { // 3 args: setting the limit | 490 | if (_nargs == 3) { // 3 args: setting the limit |
491 | // changing the limit: no error, boolean value saying if we should wake blocked writer threads | 491 | // changing the limit: no error, boolean value saying if we should wake blocked writer threads |
492 | LUA_ASSERT(L_, luaG_type(L_, -2) == LuaType::BOOLEAN); // L_: bool string | 492 | LUA_ASSERT(L_, luaG_type(L_, StackIndex{ -2 }) == LuaType::BOOLEAN); // L_: bool string |
493 | if (lua_toboolean(L_, -2)) { | 493 | if (lua_toboolean(L_, -2)) { |
494 | _linda->readHappened.notify_all(); // To be done from within the 'K' locking area | 494 | _linda->readHappened.notify_all(); // To be done from within the 'K' locking area |
495 | } | 495 | } |
496 | } else { // 2 args: reading the limit | 496 | } else { // 2 args: reading the limit |
497 | // reading the limit: a number >=0 or "unlimited" | 497 | // reading the limit: a number >=0 or "unlimited" |
498 | LUA_ASSERT(L_, luaG_type(L_, -2) == LuaType::NUMBER || luaG_tostring(L_, -2) == "unlimited"); | 498 | LUA_ASSERT(L_, luaG_type(L_, StackIndex{ -2 }) == LuaType::NUMBER || luaG_tostring(L_, StackIndex{ -2 }) == "unlimited"); |
499 | } | 499 | } |
500 | } else { // linda is cancelled | 500 | } else { // linda is cancelled |
501 | // do nothing and return nil,lanes.cancel_error | 501 | // do nothing and return nil,lanes.cancel_error |
@@ -530,12 +530,12 @@ LUAG_FUNC(linda_receive) | |||
530 | StackIndex _key_i{ 2 }; // index of first key, if timeout not there | 530 | StackIndex _key_i{ 2 }; // index of first key, if timeout not there |
531 | 531 | ||
532 | std::chrono::time_point<std::chrono::steady_clock> _until{ std::chrono::time_point<std::chrono::steady_clock>::max() }; | 532 | std::chrono::time_point<std::chrono::steady_clock> _until{ std::chrono::time_point<std::chrono::steady_clock>::max() }; |
533 | if (luaG_type(L_, 2) == LuaType::NUMBER) { // we don't want to use lua_isnumber() because of autocoercion | 533 | if (luaG_type(L_, StackIndex{ 2 }) == LuaType::NUMBER) { // we don't want to use lua_isnumber() because of autocoercion |
534 | lua_Duration const _duration{ lua_tonumber(L_, 2) }; | 534 | lua_Duration const _duration{ lua_tonumber(L_, 2) }; |
535 | if (_duration.count() >= 0.0) { | 535 | if (_duration.count() >= 0.0) { |
536 | _until = std::chrono::steady_clock::now() + std::chrono::duration_cast<std::chrono::steady_clock::duration>(_duration); | 536 | _until = std::chrono::steady_clock::now() + std::chrono::duration_cast<std::chrono::steady_clock::duration>(_duration); |
537 | } else { | 537 | } else { |
538 | raise_luaL_argerror(L_, 2, "duration cannot be < 0"); | 538 | raise_luaL_argerror(L_, StackIndex{ 2 }, "duration cannot be < 0"); |
539 | } | 539 | } |
540 | ++_key_i; | 540 | ++_key_i; |
541 | } else if (lua_isnil(L_, 2)) { // alternate explicit "infinite timeout" by passing nil before the key | 541 | } else if (lua_isnil(L_, 2)) { // alternate explicit "infinite timeout" by passing nil before the key |
@@ -555,14 +555,14 @@ LUAG_FUNC(linda_receive) | |||
555 | // we expect a user-defined amount of return value | 555 | // we expect a user-defined amount of return value |
556 | _expected_pushed_min = (int) luaL_checkinteger(L_, _key_i + 1); | 556 | _expected_pushed_min = (int) luaL_checkinteger(L_, _key_i + 1); |
557 | if (_expected_pushed_min < 1) { | 557 | if (_expected_pushed_min < 1) { |
558 | raise_luaL_argerror(L_, _key_i + 1, "bad min count"); | 558 | raise_luaL_argerror(L_, StackIndex{ _key_i + 1 }, "bad min count"); |
559 | } | 559 | } |
560 | _expected_pushed_max = (int) luaL_optinteger(L_, _key_i + 2, _expected_pushed_min); | 560 | _expected_pushed_max = (int) luaL_optinteger(L_, _key_i + 2, _expected_pushed_min); |
561 | // don't forget to count the key in addition to the values | 561 | // don't forget to count the key in addition to the values |
562 | ++_expected_pushed_min; | 562 | ++_expected_pushed_min; |
563 | ++_expected_pushed_max; | 563 | ++_expected_pushed_max; |
564 | if (_expected_pushed_min > _expected_pushed_max) { | 564 | if (_expected_pushed_min > _expected_pushed_max) { |
565 | raise_luaL_argerror(L_, _key_i + 2, "batched min/max error"); | 565 | raise_luaL_argerror(L_, StackIndex{ _key_i + 2 }, "batched min/max error"); |
566 | } | 566 | } |
567 | } else { | 567 | } else { |
568 | // make sure the keys are of a valid type | 568 | // make sure the keys are of a valid type |
@@ -686,12 +686,12 @@ LUAG_FUNC(linda_send) | |||
686 | StackIndex _key_i{ 2 }; // index of first key, if timeout not there | 686 | StackIndex _key_i{ 2 }; // index of first key, if timeout not there |
687 | 687 | ||
688 | std::chrono::time_point<std::chrono::steady_clock> _until{ std::chrono::time_point<std::chrono::steady_clock>::max() }; | 688 | std::chrono::time_point<std::chrono::steady_clock> _until{ std::chrono::time_point<std::chrono::steady_clock>::max() }; |
689 | if (luaG_type(L_, 2) == LuaType::NUMBER) { // we don't want to use lua_isnumber() because of autocoercion | 689 | if (luaG_type(L_, StackIndex{ 2 }) == LuaType::NUMBER) { // we don't want to use lua_isnumber() because of autocoercion |
690 | lua_Duration const _duration{ lua_tonumber(L_, 2) }; | 690 | lua_Duration const _duration{ lua_tonumber(L_, 2) }; |
691 | if (_duration.count() >= 0.0) { | 691 | if (_duration.count() >= 0.0) { |
692 | _until = std::chrono::steady_clock::now() + std::chrono::duration_cast<std::chrono::steady_clock::duration>(_duration); | 692 | _until = std::chrono::steady_clock::now() + std::chrono::duration_cast<std::chrono::steady_clock::duration>(_duration); |
693 | } else { | 693 | } else { |
694 | raise_luaL_argerror(L_, 2, "duration cannot be < 0"); | 694 | raise_luaL_argerror(L_, StackIndex{ 2 }, "duration cannot be < 0"); |
695 | } | 695 | } |
696 | ++_key_i; | 696 | ++_key_i; |
697 | } else if (lua_isnil(L_, 2)) { // alternate explicit "infinite timeout" by passing nil before the key | 697 | } else if (lua_isnil(L_, 2)) { // alternate explicit "infinite timeout" by passing nil before the key |
@@ -828,9 +828,9 @@ LUAG_FUNC(linda_set) | |||
828 | KeeperCallResult _pushed; | 828 | KeeperCallResult _pushed; |
829 | if (_linda->cancelRequest == CancelRequest::None) { | 829 | if (_linda->cancelRequest == CancelRequest::None) { |
830 | Keeper* const _keeper{ _linda->whichKeeper() }; | 830 | Keeper* const _keeper{ _linda->whichKeeper() }; |
831 | _pushed = keeper_call(_keeper->K, KEEPER_API(set), L_, _linda, 2); | 831 | _pushed = keeper_call(_keeper->K, KEEPER_API(set), L_, _linda, StackIndex{ 2 }); |
832 | if (_pushed.has_value()) { // no error? | 832 | if (_pushed.has_value()) { // no error? |
833 | LUA_ASSERT(L_, _pushed.value() == 2 && luaG_type(L_, -1) == LuaType::STRING && luaG_type(L_, -2) == LuaType::BOOLEAN); | 833 | LUA_ASSERT(L_, _pushed.value() == 2 && luaG_type(L_, kIdxTop) == LuaType::STRING && luaG_type(L_, StackIndex{ -2 }) == LuaType::BOOLEAN); |
834 | 834 | ||
835 | if (_has_data) { | 835 | if (_has_data) { |
836 | // we put some data in the slot, tell readers that they should wake | 836 | // we put some data in the slot, tell readers that they should wake |
@@ -922,13 +922,13 @@ namespace { | |||
922 | */ | 922 | */ |
923 | LUAG_FUNC(linda) | 923 | LUAG_FUNC(linda) |
924 | { | 924 | { |
925 | static constexpr int kLastArg{ LUA_VERSION_NUM >= 504 ? 3 : 2}; | 925 | static constexpr StackIndex kLastArg{ LUA_VERSION_NUM >= 504 ? 3 : 2 }; |
926 | int const _top{ lua_gettop(L_) }; | 926 | StackIndex const _top{ lua_gettop(L_) }; |
927 | luaL_argcheck(L_, _top <= kLastArg, _top, "too many arguments"); | 927 | luaL_argcheck(L_, _top <= kLastArg, _top, "too many arguments"); |
928 | int _closeHandlerIdx{}; | 928 | StackIndex _closeHandlerIdx{}; |
929 | int _nameIdx{}; | 929 | StackIndex _nameIdx{}; |
930 | int _groupIdx{}; | 930 | StackIndex _groupIdx{}; |
931 | for (int const _i : std::ranges::iota_view{ 1, _top + 1 }) { | 931 | for (StackIndex const _i : std::ranges::iota_view{ StackIndex{ 1 }, StackIndex{ _top + 1 }}) { |
932 | switch (luaG_type(L_, _i)) { | 932 | switch (luaG_type(L_, _i)) { |
933 | #if LUA_VERSION_NUM >= 504 // to-be-closed support starts with Lua 5.4 | 933 | #if LUA_VERSION_NUM >= 504 // to-be-closed support starts with Lua 5.4 |
934 | case LuaType::FUNCTION: | 934 | case LuaType::FUNCTION: |
@@ -985,11 +985,11 @@ LUAG_FUNC(linda) | |||
985 | LindaFactory::Instance.pushDeepUserdata(DestState{ L_ }, _nuv); // L_: name group close_handler linda | 985 | LindaFactory::Instance.pushDeepUserdata(DestState{ L_ }, _nuv); // L_: name group close_handler linda |
986 | if (_closeHandlerIdx != 0) { | 986 | if (_closeHandlerIdx != 0) { |
987 | lua_replace(L_, 2); // L_: name linda close_handler | 987 | lua_replace(L_, 2); // L_: name linda close_handler |
988 | lua_setiuservalue(L_, 2, 1); // L_: name linda | 988 | lua_setiuservalue(L_, StackIndex{ 2 }, 1); // L_: name linda |
989 | } | 989 | } |
990 | // depending on whether we have a handler or not, the stack is not in the same state at this point | 990 | // depending on whether we have a handler or not, the stack is not in the same state at this point |
991 | // just make sure we have our Linda at the top | 991 | // just make sure we have our Linda at the top |
992 | LUA_ASSERT(L_, ToLinda<true>(L_, StackIndex{ -1 })); | 992 | LUA_ASSERT(L_, ToLinda<true>(L_, kIdxTop)); |
993 | return 1; | 993 | return 1; |
994 | } else { // no to-be-closed support | 994 | } else { // no to-be-closed support |
995 | // ensure we have name, group in that order on the stack | 995 | // ensure we have name, group in that order on the stack |
diff --git a/src/linda.h b/src/linda.h index 4551443..ea660d9 100644 --- a/src/linda.h +++ b/src/linda.h | |||
@@ -13,7 +13,7 @@ static constexpr UniqueKey kLindaBatched{ 0xB8234DF772646567ull, "linda.batched" | |||
13 | 13 | ||
14 | // ################################################################################################# | 14 | // ################################################################################################# |
15 | 15 | ||
16 | using LindaGroup = Unique<int>; | 16 | DECLARE_UNIQUE_TYPE(LindaGroup, int); |
17 | 17 | ||
18 | class Linda | 18 | class Linda |
19 | : public DeepPrelude // Deep userdata MUST start with this header | 19 | : public DeepPrelude // Deep userdata MUST start with this header |
diff --git a/src/lindafactory.cpp b/src/lindafactory.cpp index d5ebc9b..e5903fb 100644 --- a/src/lindafactory.cpp +++ b/src/lindafactory.cpp | |||
@@ -80,7 +80,7 @@ void LindaFactory::deleteDeepObjectInternal(lua_State* L_, DeepPrelude* o_) cons | |||
80 | Keeper* const _keeper{ _need_acquire_release ? _linda->acquireKeeper() : _myKeeper }; | 80 | Keeper* const _keeper{ _need_acquire_release ? _linda->acquireKeeper() : _myKeeper }; |
81 | LUA_ASSERT(L_, _keeper == _myKeeper); // should always be the same | 81 | LUA_ASSERT(L_, _keeper == _myKeeper); // should always be the same |
82 | // hopefully this won't ever raise an error as we would jump to the closest pcall site while forgetting to release the keeper mutex... | 82 | // hopefully this won't ever raise an error as we would jump to the closest pcall site while forgetting to release the keeper mutex... |
83 | [[maybe_unused]] KeeperCallResult const result{ keeper_call(_keeper->K, KEEPER_API(destruct), L_, _linda, 0) }; | 83 | [[maybe_unused]] KeeperCallResult const result{ keeper_call(_keeper->K, KEEPER_API(destruct), L_, _linda, StackIndex{ 0 }) }; |
84 | LUA_ASSERT(L_, result.has_value() && result.value() == 0); | 84 | LUA_ASSERT(L_, result.has_value() && result.value() == 0); |
85 | if (_need_acquire_release) { | 85 | if (_need_acquire_release) { |
86 | _linda->releaseKeeper(_keeper); | 86 | _linda->releaseKeeper(_keeper); |
@@ -105,7 +105,7 @@ std::string_view LindaFactory::moduleName() const | |||
105 | DeepPrelude* LindaFactory::newDeepObjectInternal(lua_State* const L_) const | 105 | DeepPrelude* LindaFactory::newDeepObjectInternal(lua_State* const L_) const |
106 | { | 106 | { |
107 | // we always expect name and group at the bottom of the stack (either can be nil). any extra stuff we ignore and keep unmodified | 107 | // we always expect name and group at the bottom of the stack (either can be nil). any extra stuff we ignore and keep unmodified |
108 | std::string_view _linda_name{ luaG_tostring(L_, 1) }; | 108 | std::string_view _linda_name{ luaG_tostring(L_, StackIndex{ 1 }) }; |
109 | LindaGroup _linda_group{ static_cast<int>(lua_tointeger(L_, 2)) }; | 109 | LindaGroup _linda_group{ static_cast<int>(lua_tointeger(L_, 2)) }; |
110 | 110 | ||
111 | // store in the linda the location of the script that created it | 111 | // store in the linda the location of the script that created it |
@@ -118,7 +118,7 @@ DeepPrelude* LindaFactory::newDeepObjectInternal(lua_State* const L_) const | |||
118 | _linda_name = luaG_pushstring(L_, "<unresolved>"); | 118 | _linda_name = luaG_pushstring(L_, "<unresolved>"); |
119 | } | 119 | } |
120 | // since the name is not empty, it is at slot 1, and we can replace "auto" with the result, just in case | 120 | // since the name is not empty, it is at slot 1, and we can replace "auto" with the result, just in case |
121 | LUA_ASSERT(L_, luaG_tostring(L_, 1) == "auto"); | 121 | LUA_ASSERT(L_, luaG_tostring(L_, StackIndex{ 1 }) == "auto"); |
122 | lua_replace(L_, 1); | 122 | lua_replace(L_, 1); |
123 | } | 123 | } |
124 | 124 | ||
diff --git a/src/luaerrors.h b/src/luaerrors.h index 7bc08da..cf04f6c 100644 --- a/src/luaerrors.h +++ b/src/luaerrors.h | |||
@@ -1,5 +1,7 @@ | |||
1 | #pragma once | 1 | #pragma once |
2 | 2 | ||
3 | #include "unique.hpp" | ||
4 | |||
3 | // ################################################################################################# | 5 | // ################################################################################################# |
4 | 6 | ||
5 | // use this instead of Lua's lua_error | 7 | // use this instead of Lua's lua_error |
@@ -23,7 +25,7 @@ template <typename... ARGS> | |||
23 | 25 | ||
24 | // use this instead of Lua's luaL_argerror | 26 | // use this instead of Lua's luaL_argerror |
25 | template <typename... ARGS> | 27 | template <typename... ARGS> |
26 | [[noreturn]] static inline void raise_luaL_argerror(lua_State* const L_, int const arg_, std::string_view const& extramsg_) | 28 | [[noreturn]] static inline void raise_luaL_argerror(lua_State* const L_, StackIndex const arg_, std::string_view const& extramsg_) |
27 | { | 29 | { |
28 | std::ignore = luaL_argerror(L_, arg_, extramsg_.data()); // doesn't return | 30 | std::ignore = luaL_argerror(L_, arg_, extramsg_.data()); // doesn't return |
29 | assert(false); // we should never get here, but i'm paranoid | 31 | assert(false); // we should never get here, but i'm paranoid |
@@ -34,7 +36,7 @@ template <typename... ARGS> | |||
34 | #if LUA_VERSION_NUM >= 504 | 36 | #if LUA_VERSION_NUM >= 504 |
35 | // use this instead of Lua's luaL_typeerror | 37 | // use this instead of Lua's luaL_typeerror |
36 | template <typename... ARGS> | 38 | template <typename... ARGS> |
37 | [[noreturn]] static inline void raise_luaL_typeerror(lua_State* const L_, int const arg_, std::string_view const& tname_) | 39 | [[noreturn]] static inline void raise_luaL_typeerror(lua_State* const L_, StackIndex const arg_, std::string_view const& tname_) |
38 | { | 40 | { |
39 | std::ignore = luaL_typeerror(L_, arg_, tname_.data()); // doesn't return | 41 | std::ignore = luaL_typeerror(L_, arg_, tname_.data()); // doesn't return |
40 | assert(false); // we should never get here, but i'm paranoid | 42 | assert(false); // we should never get here, but i'm paranoid |
diff --git a/src/macros_and_utils.h b/src/macros_and_utils.h index e73abef..f22d124 100644 --- a/src/macros_and_utils.h +++ b/src/macros_and_utils.h | |||
@@ -25,9 +25,8 @@ using lua_Duration = std::chrono::template duration<lua_Number>; | |||
25 | 25 | ||
26 | // ################################################################################################# | 26 | // ################################################################################################# |
27 | 27 | ||
28 | using SourceState = Unique<lua_State*>; | 28 | DECLARE_UNIQUE_TYPE(SourceState, lua_State*); |
29 | using DestState = Unique<lua_State*>; | 29 | DECLARE_UNIQUE_TYPE(DestState, lua_State*); |
30 | using StackIndex = Unique<int>; | ||
31 | 30 | ||
32 | // ################################################################################################# | 31 | // ################################################################################################# |
33 | 32 | ||
diff --git a/src/nameof.cpp b/src/nameof.cpp index 3c82603..fd31a28 100644 --- a/src/nameof.cpp +++ b/src/nameof.cpp | |||
@@ -34,10 +34,10 @@ THE SOFTWARE. | |||
34 | // Return some name helping to identify an object | 34 | // Return some name helping to identify an object |
35 | [[nodiscard]] static int DiscoverObjectNameRecur(lua_State* L_, int shortest_, int depth_) | 35 | [[nodiscard]] static int DiscoverObjectNameRecur(lua_State* L_, int shortest_, int depth_) |
36 | { | 36 | { |
37 | static constexpr int kWhat{ 1 }; // the object to investigate // L_: o "r" {c} {fqn} ... {?} | 37 | static constexpr StackIndex kWhat{ 1 }; // the object to investigate // L_: o "r" {c} {fqn} ... {?} |
38 | static constexpr int kResult{ 2 }; // where the result string is stored | 38 | static constexpr StackIndex kResult{ 2 }; // where the result string is stored |
39 | static constexpr int kCache{ 3 }; // a cache | 39 | static constexpr StackIndex kCache{ 3 }; // a cache |
40 | static constexpr int kFQN{ 4 }; // the name compositing stack | 40 | static constexpr StackIndex kFQN{ 4 }; // the name compositing stack |
41 | // no need to scan this table if the name we will discover is longer than one we already know | 41 | // no need to scan this table if the name we will discover is longer than one we already know |
42 | if (shortest_ <= depth_ + 1) { | 42 | if (shortest_ <= depth_ + 1) { |
43 | return shortest_; | 43 | return shortest_; |
@@ -80,7 +80,7 @@ THE SOFTWARE. | |||
80 | STACK_CHECK(L_, 0); | 80 | STACK_CHECK(L_, 0); |
81 | break; | 81 | break; |
82 | } | 82 | } |
83 | switch (luaG_type(L_, -1)) { // L_: o "r" {c} {fqn} ... {?} k v | 83 | switch (luaG_type(L_, kIdxTop)) { // L_: o "r" {c} {fqn} ... {?} k v |
84 | default: // nil, boolean, light userdata, number and string aren't identifiable | 84 | default: // nil, boolean, light userdata, number and string aren't identifiable |
85 | break; | 85 | break; |
86 | 86 | ||
@@ -126,7 +126,7 @@ THE SOFTWARE. | |||
126 | // search in the object's uservalues | 126 | // search in the object's uservalues |
127 | { | 127 | { |
128 | int _uvi{ 1 }; | 128 | int _uvi{ 1 }; |
129 | while (lua_getiuservalue(L_, -1, _uvi) != LUA_TNONE) { // L_: o "r" {c} {fqn} ... {?} k U {u} | 129 | while (lua_getiuservalue(L_, kIdxTop, _uvi) != LUA_TNONE) { // L_: o "r" {c} {fqn} ... {?} k U {u} |
130 | if (lua_istable(L_, -1)) { // if it is a table, look inside | 130 | if (lua_istable(L_, -1)) { // if it is a table, look inside |
131 | ++depth_; | 131 | ++depth_; |
132 | luaG_pushstring(L_, "uservalue"); // L_: o "r" {c} {fqn} ... {?} k v {u} "uservalue" | 132 | luaG_pushstring(L_, "uservalue"); // L_: o "r" {c} {fqn} ... {?} k v {u} "uservalue" |
@@ -167,13 +167,13 @@ THE SOFTWARE. | |||
167 | // "type", "name" = lanes.nameof(o) | 167 | // "type", "name" = lanes.nameof(o) |
168 | LUAG_FUNC(nameof) | 168 | LUAG_FUNC(nameof) |
169 | { | 169 | { |
170 | int const _what{ lua_gettop(L_) }; | 170 | StackIndex const _what{ lua_gettop(L_) }; |
171 | if (_what > 1) { | 171 | if (_what > 1) { |
172 | raise_luaL_argerror(L_, _what, "too many arguments."); | 172 | raise_luaL_argerror(L_, _what, "too many arguments."); |
173 | } | 173 | } |
174 | 174 | ||
175 | // nil, boolean, light userdata, number and string aren't identifiable | 175 | // nil, boolean, light userdata, number and string aren't identifiable |
176 | if (luaG_type(L_, 1) < LuaType::TABLE) { | 176 | if (luaG_type(L_, StackIndex{ 1 }) < LuaType::TABLE) { |
177 | lua_pushstring(L_, luaL_typename(L_, 1)); // L_: o "type" | 177 | lua_pushstring(L_, luaL_typename(L_, 1)); // L_: o "type" |
178 | lua_insert(L_, -2); // L_: "type" o | 178 | lua_insert(L_, -2); // L_: "type" o |
179 | return 2; | 179 | return 2; |
@@ -197,7 +197,7 @@ LUAG_FUNC(nameof) | |||
197 | lua_pop(L_, 1); // L_: o nil {c} {fqn} | 197 | lua_pop(L_, 1); // L_: o nil {c} {fqn} |
198 | luaG_pushstring(L_, "_R"); // L_: o nil {c} {fqn} "_R" | 198 | luaG_pushstring(L_, "_R"); // L_: o nil {c} {fqn} "_R" |
199 | lua_rawseti(L_, -2, 1); // L_: o nil {c} {fqn} | 199 | lua_rawseti(L_, -2, 1); // L_: o nil {c} {fqn} |
200 | lua_pushvalue(L_, LUA_REGISTRYINDEX); // L_: o nil {c} {fqn} _R | 200 | lua_pushvalue(L_, kIdxRegistry); // L_: o nil {c} {fqn} _R |
201 | std::ignore = DiscoverObjectNameRecur(L_, std::numeric_limits<int>::max(), 1); | 201 | std::ignore = DiscoverObjectNameRecur(L_, std::numeric_limits<int>::max(), 1); |
202 | } | 202 | } |
203 | lua_pop(L_, 3); // L_: o "result" | 203 | lua_pop(L_, 3); // L_: o "result" |
diff --git a/src/state.cpp b/src/state.cpp index aa6e6a9..4664486 100644 --- a/src/state.cpp +++ b/src/state.cpp | |||
@@ -103,7 +103,7 @@ namespace { | |||
103 | luaL_requiref(L_, _name.data(), _libfunc, !_isLanesCore); // L_: {lib} | 103 | luaL_requiref(L_, _name.data(), _libfunc, !_isLanesCore); // L_: {lib} |
104 | // lanes.core doesn't declare a global, so scan it here and now | 104 | // lanes.core doesn't declare a global, so scan it here and now |
105 | if (_isLanesCore) { | 105 | if (_isLanesCore) { |
106 | tools::PopulateFuncLookupTable(L_, -1, _name); | 106 | tools::PopulateFuncLookupTable(L_, kIdxTop, _name); |
107 | } | 107 | } |
108 | lua_pop(L_, 1); // L_: | 108 | lua_pop(L_, 1); // L_: |
109 | STACK_CHECK(L_, 0); | 109 | STACK_CHECK(L_, 0); |
@@ -282,7 +282,7 @@ namespace state { | |||
282 | STACK_CHECK(_L, 0); | 282 | STACK_CHECK(_L, 0); |
283 | // after all this, register everything we find in our name<->function database | 283 | // after all this, register everything we find in our name<->function database |
284 | luaG_pushglobaltable(_L); // L: _G | 284 | luaG_pushglobaltable(_L); // L: _G |
285 | tools::PopulateFuncLookupTable(_L, -1, {}); | 285 | tools::PopulateFuncLookupTable(_L, kIdxTop, {}); |
286 | lua_pop(_L, 1); // L: | 286 | lua_pop(_L, 1); // L: |
287 | STACK_CHECK(_L, 0); | 287 | STACK_CHECK(_L, 0); |
288 | 288 | ||
@@ -324,7 +324,7 @@ namespace state { | |||
324 | lua_newtable(L_); // L_: out | 324 | lua_newtable(L_); // L_: out |
325 | for (luaL_Reg const& _entry : local::sLibs) { | 325 | for (luaL_Reg const& _entry : local::sLibs) { |
326 | lua_pushboolean(L_, 1); // L_: out true | 326 | lua_pushboolean(L_, 1); // L_: out true |
327 | luaG_setfield(L_, -2, std::string_view{ _entry.name }); // out[name] = true // L_: out | 327 | luaG_setfield(L_, StackIndex{ -2 }, std::string_view{ _entry.name }); // out[name] = true // L_: out |
328 | } | 328 | } |
329 | STACK_CHECK(L_, 1); | 329 | STACK_CHECK(L_, 1); |
330 | return 1; | 330 | return 1; |
diff --git a/src/tools.cpp b/src/tools.cpp index d580f67..d0204a6 100644 --- a/src/tools.cpp +++ b/src/tools.cpp | |||
@@ -66,7 +66,7 @@ static constexpr int kWriterReturnCode{ 666 }; | |||
66 | * +-----------------+-------------------+------------+----------+ | 66 | * +-----------------+-------------------+------------+----------+ |
67 | */ | 67 | */ |
68 | 68 | ||
69 | FuncSubType luaG_getfuncsubtype(lua_State* const L_, int const i_) | 69 | FuncSubType luaG_getfuncsubtype(lua_State* const L_, StackIndex const i_) |
70 | { | 70 | { |
71 | if (lua_tocfunction(L_, i_)) { // nullptr for LuaJIT-fast && bytecode functions | 71 | if (lua_tocfunction(L_, i_)) { // nullptr for LuaJIT-fast && bytecode functions |
72 | return FuncSubType::Native; | 72 | return FuncSubType::Native; |
@@ -92,7 +92,7 @@ FuncSubType luaG_getfuncsubtype(lua_State* const L_, int const i_) | |||
92 | namespace tools { | 92 | namespace tools { |
93 | 93 | ||
94 | // inspired from tconcat() in ltablib.c | 94 | // inspired from tconcat() in ltablib.c |
95 | std::string_view PushFQN(lua_State* const L_, int const t_, int const last_) | 95 | std::string_view PushFQN(lua_State* const L_, StackIndex const t_, int const last_) |
96 | { | 96 | { |
97 | STACK_CHECK_START_REL(L_, 0); | 97 | STACK_CHECK_START_REL(L_, 0); |
98 | // Lua 5.4 pushes &b as light userdata on the stack. be aware of it... | 98 | // Lua 5.4 pushes &b as light userdata on the stack. be aware of it... |
@@ -111,7 +111,7 @@ namespace tools { | |||
111 | // &b is popped at that point (-> replaced by the result) | 111 | // &b is popped at that point (-> replaced by the result) |
112 | luaL_pushresult(&_b); // L_: ... {} ... "<result>" | 112 | luaL_pushresult(&_b); // L_: ... {} ... "<result>" |
113 | STACK_CHECK(L_, 1); | 113 | STACK_CHECK(L_, 1); |
114 | return luaG_tostring(L_, -1); | 114 | return luaG_tostring(L_, kIdxTop); |
115 | } | 115 | } |
116 | 116 | ||
117 | } // namespace tools | 117 | } // namespace tools |
@@ -126,12 +126,12 @@ namespace tools { | |||
126 | * if we already had an entry of type [o] = ..., replace the name if the new one is shorter | 126 | * if we already had an entry of type [o] = ..., replace the name if the new one is shorter |
127 | * pops the processed object from the stack | 127 | * pops the processed object from the stack |
128 | */ | 128 | */ |
129 | static void update_lookup_entry(lua_State* L_, int ctxBase_, int depth_) | 129 | static void update_lookup_entry(lua_State* const L_, StackIndex const ctxBase_, int const depth_) |
130 | { | 130 | { |
131 | // slot 1 in the stack contains the table that receives everything we found | 131 | // slot 1 in the stack contains the table that receives everything we found |
132 | int const _dest{ ctxBase_ }; | 132 | StackIndex const _dest{ ctxBase_ }; |
133 | // slot 2 contains a table that, when concatenated, produces the fully qualified name of scanned elements in the table provided at slot _i | 133 | // slot 2 contains a table that, when concatenated, produces the fully qualified name of scanned elements in the table provided at slot _i |
134 | int const _fqn{ ctxBase_ + 1 }; | 134 | StackIndex const _fqn{ ctxBase_ + 1 }; |
135 | 135 | ||
136 | DEBUGSPEW_CODE(Universe* const _U{ Universe::Get(L_) }); | 136 | DEBUGSPEW_CODE(Universe* const _U{ Universe::Get(L_) }); |
137 | DEBUGSPEW_CODE(DebugSpew(_U) << "update_lookup_entry()" << std::endl); | 137 | DEBUGSPEW_CODE(DebugSpew(_U) << "update_lookup_entry()" << std::endl); |
@@ -141,14 +141,14 @@ static void update_lookup_entry(lua_State* L_, int ctxBase_, int depth_) | |||
141 | // first, raise an error if the function is already known | 141 | // first, raise an error if the function is already known |
142 | lua_pushvalue(L_, -1); // L_: ... {bfc} k o o | 142 | lua_pushvalue(L_, -1); // L_: ... {bfc} k o o |
143 | lua_rawget(L_, _dest); // L_: ... {bfc} k o name? | 143 | lua_rawget(L_, _dest); // L_: ... {bfc} k o name? |
144 | std::string_view const _prevName{ luaG_tostring(L_, -1) }; // nullptr if we got nil (first encounter of this object) | 144 | std::string_view const _prevName{ luaG_tostring(L_, kIdxTop) }; // nullptr if we got nil (first encounter of this object) |
145 | // push name in fqn stack (note that concatenation will crash if name is a not string or a number) | 145 | // push name in fqn stack (note that concatenation will crash if name is a not string or a number) |
146 | lua_pushvalue(L_, -3); // L_: ... {bfc} k o name? k | 146 | lua_pushvalue(L_, -3); // L_: ... {bfc} k o name? k |
147 | LUA_ASSERT(L_, luaG_type(L_, -1) == LuaType::NUMBER || luaG_type(L_, -1) == LuaType::STRING); | 147 | LUA_ASSERT(L_, luaG_type(L_, kIdxTop) == LuaType::NUMBER || luaG_type(L_, kIdxTop) == LuaType::STRING); |
148 | ++depth_; | 148 | int const _deeper{ depth_ + 1 }; |
149 | lua_rawseti(L_, _fqn, depth_); // L_: ... {bfc} k o name? | 149 | lua_rawseti(L_, _fqn, _deeper); // L_: ... {bfc} k o name? |
150 | // generate name | 150 | // generate name |
151 | std::string_view const _newName{ tools::PushFQN(L_, _fqn, depth_) }; // L_: ... {bfc} k o name? "f.q.n" | 151 | std::string_view const _newName{ tools::PushFQN(L_, _fqn, _deeper) }; // L_: ... {bfc} k o name? "f.q.n" |
152 | // Lua 5.2 introduced a hash randomizer seed which causes table iteration to yield a different key order | 152 | // Lua 5.2 introduced a hash randomizer seed which causes table iteration to yield a different key order |
153 | // on different VMs even when the tables are populated the exact same way. | 153 | // on different VMs even when the tables are populated the exact same way. |
154 | // Also, when Lua is built with compatibility options (such as LUA_COMPAT_ALL), some base libraries register functions under multiple names. | 154 | // Also, when Lua is built with compatibility options (such as LUA_COMPAT_ALL), some base libraries register functions under multiple names. |
@@ -183,21 +183,20 @@ static void update_lookup_entry(lua_State* L_, int ctxBase_, int depth_) | |||
183 | lua_rawset(L_, _dest); // L_: ... {bfc} k | 183 | lua_rawset(L_, _dest); // L_: ... {bfc} k |
184 | // remove table name from fqn stack | 184 | // remove table name from fqn stack |
185 | lua_pushnil(L_); // L_: ... {bfc} k nil | 185 | lua_pushnil(L_); // L_: ... {bfc} k nil |
186 | lua_rawseti(L_, _fqn, depth_); // L_: ... {bfc} k | 186 | lua_rawseti(L_, _fqn, _deeper); // L_: ... {bfc} k |
187 | } | 187 | } |
188 | --depth_; | ||
189 | STACK_CHECK(L_, -1); | 188 | STACK_CHECK(L_, -1); |
190 | } | 189 | } |
191 | 190 | ||
192 | // ################################################################################################# | 191 | // ################################################################################################# |
193 | 192 | ||
194 | static void populate_func_lookup_table_recur(lua_State* L_, int dbIdx_, int i_, int depth_) | 193 | static void populate_func_lookup_table_recur(lua_State* const L_, StackIndex const dbIdx_, StackIndex const i_, int const depth_) |
195 | { | 194 | { |
196 | // slot dbIdx_ contains the lookup database table | 195 | // slot dbIdx_ contains the lookup database table |
197 | // slot dbIdx_ + 1 contains a table that, when concatenated, produces the fully qualified name of scanned elements in the table provided at slot i_ | 196 | // slot dbIdx_ + 1 contains a table that, when concatenated, produces the fully qualified name of scanned elements in the table provided at slot i_ |
198 | int const _fqn{ dbIdx_ + 1 }; | 197 | StackIndex const _fqn{ dbIdx_ + 1 }; |
199 | // slot dbIdx_ + 2 contains a cache that stores all already visited tables to avoid infinite recursion loops | 198 | // slot dbIdx_ + 2 contains a cache that stores all already visited tables to avoid infinite recursion loops |
200 | int const _cache{ dbIdx_ + 2 }; | 199 | StackIndex const _cache{ dbIdx_ + 2 }; |
201 | DEBUGSPEW_CODE(Universe* const _U{ Universe::Get(L_) }); | 200 | DEBUGSPEW_CODE(Universe* const _U{ Universe::Get(L_) }); |
202 | DEBUGSPEW_CODE(DebugSpew(_U) << "populate_func_lookup_table_recur()" << std::endl); | 201 | DEBUGSPEW_CODE(DebugSpew(_U) << "populate_func_lookup_table_recur()" << std::endl); |
203 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); | 202 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); |
@@ -253,7 +252,7 @@ static void populate_func_lookup_table_recur(lua_State* L_, int dbIdx_, int i_, | |||
253 | lua_rawset(L_, breadthFirstCache); // L_: ... {i_} {bfc} k {} | 252 | lua_rawset(L_, breadthFirstCache); // L_: ... {i_} {bfc} k {} |
254 | // generate a name, and if we already had one name, keep whichever is the shorter | 253 | // generate a name, and if we already had one name, keep whichever is the shorter |
255 | update_lookup_entry(L_, dbIdx_, depth_); // L_: ... {i_} {bfc} k | 254 | update_lookup_entry(L_, dbIdx_, depth_); // L_: ... {i_} {bfc} k |
256 | } else if (lua_isfunction(L_, -1) && (luaG_getfuncsubtype(L_, -1) != FuncSubType::Bytecode)) { | 255 | } else if (lua_isfunction(L_, -1) && (luaG_getfuncsubtype(L_, kIdxTop) != FuncSubType::Bytecode)) { |
257 | // generate a name, and if we already had one name, keep whichever is the shorter | 256 | // generate a name, and if we already had one name, keep whichever is the shorter |
258 | // this pops the function from the stack | 257 | // this pops the function from the stack |
259 | update_lookup_entry(L_, dbIdx_, depth_); // L_: ... {i_} {bfc} k | 258 | update_lookup_entry(L_, dbIdx_, depth_); // L_: ... {i_} {bfc} k |
@@ -263,7 +262,7 @@ static void populate_func_lookup_table_recur(lua_State* L_, int dbIdx_, int i_, | |||
263 | STACK_CHECK(L_, 2); | 262 | STACK_CHECK(L_, 2); |
264 | } | 263 | } |
265 | // now process the tables we encountered at that depth | 264 | // now process the tables we encountered at that depth |
266 | ++depth_; | 265 | int const _deeper{ depth_ + 1 }; |
267 | lua_pushnil(L_); // L_: ... {i_} {bfc} nil | 266 | lua_pushnil(L_); // L_: ... {i_} {bfc} nil |
268 | while (lua_next(L_, breadthFirstCache) != 0) { // L_: ... {i_} {bfc} k {} | 267 | while (lua_next(L_, breadthFirstCache) != 0) { // L_: ... {i_} {bfc} k {} |
269 | DEBUGSPEW_CODE(std::string_view const _key{ (luaG_type(L_, -2) == LuaType::STRING) ? luaG_tostring(L_, -2) : std::string_view{ "<not a string>" } }); | 268 | DEBUGSPEW_CODE(std::string_view const _key{ (luaG_type(L_, -2) == LuaType::STRING) ? luaG_tostring(L_, -2) : std::string_view{ "<not a string>" } }); |
@@ -272,7 +271,7 @@ static void populate_func_lookup_table_recur(lua_State* L_, int dbIdx_, int i_, | |||
272 | // un-visit this table in case we do need to process it | 271 | // un-visit this table in case we do need to process it |
273 | lua_pushvalue(L_, -1); // L_: ... {i_} {bfc} k {} {} | 272 | lua_pushvalue(L_, -1); // L_: ... {i_} {bfc} k {} {} |
274 | lua_rawget(L_, _cache); // L_: ... {i_} {bfc} k {} n | 273 | lua_rawget(L_, _cache); // L_: ... {i_} {bfc} k {} n |
275 | LUA_ASSERT(L_, luaG_type(L_, -1) == LuaType::NUMBER); | 274 | LUA_ASSERT(L_, luaG_type(L_, kIdxTop) == LuaType::NUMBER); |
276 | _visit_count = lua_tointeger(L_, -1) - 1; | 275 | _visit_count = lua_tointeger(L_, -1) - 1; |
277 | lua_pop(L_, 1); // L_: ... {i_} {bfc} k {} | 276 | lua_pop(L_, 1); // L_: ... {i_} {bfc} k {} |
278 | lua_pushvalue(L_, -1); // L_: ... {i_} {bfc} k {} {} | 277 | lua_pushvalue(L_, -1); // L_: ... {i_} {bfc} k {} {} |
@@ -284,15 +283,14 @@ static void populate_func_lookup_table_recur(lua_State* L_, int dbIdx_, int i_, | |||
284 | lua_rawset(L_, _cache); // L_: ... {i_} {bfc} k {} | 283 | lua_rawset(L_, _cache); // L_: ... {i_} {bfc} k {} |
285 | // push table name in fqn stack (note that concatenation will crash if name is a not string!) | 284 | // push table name in fqn stack (note that concatenation will crash if name is a not string!) |
286 | lua_pushvalue(L_, -2); // L_: ... {i_} {bfc} k {} k | 285 | lua_pushvalue(L_, -2); // L_: ... {i_} {bfc} k {} k |
287 | lua_rawseti(L_, _fqn, depth_); // L_: ... {i_} {bfc} k {} | 286 | lua_rawseti(L_, _fqn, _deeper); // L_: ... {i_} {bfc} k {} |
288 | populate_func_lookup_table_recur(L_, dbIdx_, lua_gettop(L_), depth_); | 287 | populate_func_lookup_table_recur(L_, dbIdx_, StackIndex{ lua_gettop(L_) }, _deeper); |
289 | lua_pop(L_, 1); // L_: ... {i_} {bfc} k | 288 | lua_pop(L_, 1); // L_: ... {i_} {bfc} k |
290 | STACK_CHECK(L_, 2); | 289 | STACK_CHECK(L_, 2); |
291 | } | 290 | } |
292 | // remove table name from fqn stack | 291 | // remove table name from fqn stack |
293 | lua_pushnil(L_); // L_: ... {i_} {bfc} nil | 292 | lua_pushnil(L_); // L_: ... {i_} {bfc} nil |
294 | lua_rawseti(L_, _fqn, depth_); // L_: ... {i_} {bfc} | 293 | lua_rawseti(L_, _fqn, _deeper); // L_: ... {i_} {bfc} |
295 | --depth_; | ||
296 | // we are done with our cache | 294 | // we are done with our cache |
297 | lua_pop(L_, 1); // L_: ... {i_} | 295 | lua_pop(L_, 1); // L_: ... {i_} |
298 | STACK_CHECK(L_, 0); | 296 | STACK_CHECK(L_, 0); |
@@ -304,9 +302,9 @@ static void populate_func_lookup_table_recur(lua_State* L_, int dbIdx_, int i_, | |||
304 | namespace tools { | 302 | namespace tools { |
305 | 303 | ||
306 | // create a "fully.qualified.name" <-> function equivalence database | 304 | // create a "fully.qualified.name" <-> function equivalence database |
307 | void PopulateFuncLookupTable(lua_State* const L_, int const i_, std::string_view const& name_) | 305 | void PopulateFuncLookupTable(lua_State* const L_, StackIndex const i_, std::string_view const& name_) |
308 | { | 306 | { |
309 | int const _in_base{ luaG_absindex(L_, i_) }; | 307 | StackIndex const _in_base{ luaG_absindex(L_, i_) }; |
310 | DEBUGSPEW_CODE(Universe* _U = Universe::Get(L_)); | 308 | DEBUGSPEW_CODE(Universe* _U = Universe::Get(L_)); |
311 | std::string_view _name{ name_.empty() ? std::string_view{} : name_ }; | 309 | std::string_view _name{ name_.empty() ? std::string_view{} : name_ }; |
312 | DEBUGSPEW_CODE(DebugSpew(_U) << L_ << ": PopulateFuncLookupTable('" << _name << "')" << std::endl); | 310 | DEBUGSPEW_CODE(DebugSpew(_U) << L_ << ": PopulateFuncLookupTable('" << _name << "')" << std::endl); |
@@ -314,7 +312,7 @@ namespace tools { | |||
314 | STACK_GROW(L_, 3); | 312 | STACK_GROW(L_, 3); |
315 | STACK_CHECK_START_REL(L_, 0); | 313 | STACK_CHECK_START_REL(L_, 0); |
316 | kLookupRegKey.pushValue(L_); // L_: {} | 314 | kLookupRegKey.pushValue(L_); // L_: {} |
317 | int const _dbIdx{ lua_gettop(L_) }; | 315 | StackIndex const _dbIdx{ lua_gettop(L_) }; |
318 | STACK_CHECK(L_, 1); | 316 | STACK_CHECK(L_, 1); |
319 | LUA_ASSERT(L_, lua_istable(L_, -1)); | 317 | LUA_ASSERT(L_, lua_istable(L_, -1)); |
320 | if (luaG_type(L_, _in_base) == LuaType::FUNCTION) { // for example when a module is a simple function | 318 | if (luaG_type(L_, _in_base) == LuaType::FUNCTION) { // for example when a module is a simple function |
diff --git a/src/tools.h b/src/tools.h index 5127ea0..34cbb8f 100644 --- a/src/tools.h +++ b/src/tools.h | |||
@@ -18,7 +18,7 @@ enum class FuncSubType | |||
18 | FastJIT | 18 | FastJIT |
19 | }; | 19 | }; |
20 | 20 | ||
21 | [[nodiscard]] FuncSubType luaG_getfuncsubtype(lua_State* L_, int i_); | 21 | [[nodiscard]] FuncSubType luaG_getfuncsubtype(lua_State* L_, StackIndex i_); |
22 | 22 | ||
23 | // ################################################################################################# | 23 | // ################################################################################################# |
24 | 24 | ||
@@ -31,7 +31,7 @@ static constexpr RegistryUniqueKey kLookupRegKey{ 0xBF1FC5CF3C6DD47Bull }; // re | |||
31 | // ################################################################################################# | 31 | // ################################################################################################# |
32 | 32 | ||
33 | namespace tools { | 33 | namespace tools { |
34 | void PopulateFuncLookupTable(lua_State* const L_, int const i_, std::string_view const& name_); | 34 | void PopulateFuncLookupTable(lua_State* L_, StackIndex i_, std::string_view const& name_); |
35 | [[nodiscard]] std::string_view PushFQN(lua_State* L_, int t_, int last_); | 35 | [[nodiscard]] std::string_view PushFQN(lua_State* L_, StackIndex t_, int last_); |
36 | void SerializeRequire(lua_State* L_); | 36 | void SerializeRequire(lua_State* L_); |
37 | } // namespace tools | 37 | } // namespace tools |
diff --git a/src/unique.hpp b/src/unique.hpp index aeb7a67..846708e 100644 --- a/src/unique.hpp +++ b/src/unique.hpp | |||
@@ -3,7 +3,7 @@ | |||
3 | // ################################################################################################# | 3 | // ################################################################################################# |
4 | 4 | ||
5 | // A unique type generator | 5 | // A unique type generator |
6 | template <typename T, auto = [] {}, typename specialization = void> | 6 | template <typename T, typename TAG, typename specialization = void> |
7 | class Unique | 7 | class Unique |
8 | { | 8 | { |
9 | private: | 9 | private: |
@@ -11,13 +11,15 @@ class Unique | |||
11 | 11 | ||
12 | public: | 12 | public: |
13 | using type = T; | 13 | using type = T; |
14 | Unique() = default; | 14 | constexpr Unique() = default; |
15 | operator T() const { return val; } | 15 | operator T() const { return val; } |
16 | explicit Unique(T b_) | 16 | Unique& operator=(T const&) = delete; |
17 | Unique& operator=(T&&) = delete; | ||
18 | explicit constexpr Unique(T b_) | ||
17 | : val{ b_ } | 19 | : val{ b_ } |
18 | { | 20 | { |
19 | } | 21 | } |
20 | // pre-imcrement | 22 | // pre-increment |
21 | auto& operator++() | 23 | auto& operator++() |
22 | { | 24 | { |
23 | ++val; | 25 | ++val; |
@@ -26,12 +28,12 @@ class Unique | |||
26 | // post-increment | 28 | // post-increment |
27 | auto operator++(int) | 29 | auto operator++(int) |
28 | { | 30 | { |
29 | return Unique<T>{ std::exchange(val, val + 1) }; | 31 | return Unique<T, TAG>{ std::exchange(val, val + 1) }; |
30 | } | 32 | } |
31 | }; | 33 | }; |
32 | 34 | ||
33 | template <typename T, auto lambda> | 35 | template <typename T, typename TAG> |
34 | class Unique<T, lambda, std::enable_if_t<!std::is_scalar_v<T>>> | 36 | class Unique<T, TAG, std::enable_if_t<!std::is_scalar_v<T>>> |
35 | : public T | 37 | : public T |
36 | { | 38 | { |
37 | public: | 39 | public: |
@@ -42,3 +44,9 @@ class Unique<T, lambda, std::enable_if_t<!std::is_scalar_v<T>>> | |||
42 | { | 44 | { |
43 | } | 45 | } |
44 | }; | 46 | }; |
47 | |||
48 | #define DECLARE_UNIQUE_TYPE(_name, _type) using _name = Unique<_type, class Unique_##_name##_Tag> | ||
49 | |||
50 | // putting this here to break a header circular dependency until I find a better place | ||
51 | DECLARE_UNIQUE_TYPE(StackIndex, int); | ||
52 | static constexpr StackIndex kIdxTop{ -1 }; | ||
diff --git a/src/uniquekey.h b/src/uniquekey.h index debfee4..14b6d84 100644 --- a/src/uniquekey.h +++ b/src/uniquekey.h | |||
@@ -27,7 +27,7 @@ class UniqueKey | |||
27 | inline constexpr std::weak_ordering operator<=>(UniqueKey const& rhs_) const { return storage <=> rhs_.storage; } | 27 | inline constexpr std::weak_ordering operator<=>(UniqueKey const& rhs_) const { return storage <=> rhs_.storage; } |
28 | inline constexpr auto operator==(UniqueKey const& rhs_) const { return storage == rhs_.storage; } | 28 | inline constexpr auto operator==(UniqueKey const& rhs_) const { return storage == rhs_.storage; } |
29 | // --------------------------------------------------------------------------------------------- | 29 | // --------------------------------------------------------------------------------------------- |
30 | bool equals(lua_State* const L_, int const i_) const | 30 | bool equals(lua_State* const L_, StackIndex const i_) const |
31 | { | 31 | { |
32 | return lua_touserdata(L_, i_) == std::bit_cast<void*>(storage); | 32 | return lua_touserdata(L_, i_) == std::bit_cast<void*>(storage); |
33 | } | 33 | } |
@@ -50,8 +50,8 @@ class RegistryUniqueKey | |||
50 | void pushValue(lua_State* const L_) const | 50 | void pushValue(lua_State* const L_) const |
51 | { | 51 | { |
52 | STACK_CHECK_START_REL(L_, 0); | 52 | STACK_CHECK_START_REL(L_, 0); |
53 | pushKey(L_); | 53 | pushKey(L_); // L_: ... key |
54 | lua_rawget(L_, LUA_REGISTRYINDEX); | 54 | lua_rawget(L_, kIdxRegistry); // L_: ... value |
55 | STACK_CHECK(L_, 1); | 55 | STACK_CHECK(L_, 1); |
56 | } | 56 | } |
57 | // --------------------------------------------------------------------------------------------- | 57 | // --------------------------------------------------------------------------------------------- |
@@ -59,9 +59,9 @@ class RegistryUniqueKey | |||
59 | void setValue(lua_State* const L_, OP operation_) const | 59 | void setValue(lua_State* const L_, OP operation_) const |
60 | { | 60 | { |
61 | // Note we can't check stack consistency because operation is not always a push (could be insert, replace, whatever) | 61 | // Note we can't check stack consistency because operation is not always a push (could be insert, replace, whatever) |
62 | pushKey(L_); // ... key | 62 | pushKey(L_); // L_: ... key |
63 | operation_(L_); // ... key value | 63 | operation_(L_); // L_: ... key value |
64 | lua_rawset(L_, LUA_REGISTRYINDEX); // ... | 64 | lua_rawset(L_, kIdxRegistry); // L_: ... |
65 | } | 65 | } |
66 | // --------------------------------------------------------------------------------------------- | 66 | // --------------------------------------------------------------------------------------------- |
67 | template <typename T> | 67 | template <typename T> |
@@ -69,9 +69,9 @@ class RegistryUniqueKey | |||
69 | { | 69 | { |
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_); // L_: ... {}|nil |
73 | T* const value{ luaG_tolightuserdata<T>(L_, -1) }; // lightuserdata/nil | 73 | T* const value{ luaG_tolightuserdata<T>(L_, kIdxTop) }; |
74 | lua_pop(L_, 1); | 74 | lua_pop(L_, 1); // L_: ... |
75 | STACK_CHECK(L_, 0); | 75 | STACK_CHECK(L_, 0); |
76 | return value; | 76 | return value; |
77 | } | 77 | } |
@@ -80,9 +80,9 @@ class RegistryUniqueKey | |||
80 | { | 80 | { |
81 | STACK_GROW(L_, 1); | 81 | STACK_GROW(L_, 1); |
82 | STACK_CHECK_START_REL(L_, 0); | 82 | STACK_CHECK_START_REL(L_, 0); |
83 | pushValue(L_); | 83 | pushValue(L_); // L_: ... bool|nil |
84 | bool const value{ lua_toboolean(L_, -1) ? true : false }; // bool/nil | 84 | bool const value{ lua_toboolean(L_, -1) ? true : false }; |
85 | lua_pop(L_, 1); | 85 | lua_pop(L_, 1); // L_: ... |
86 | STACK_CHECK(L_, 0); | 86 | STACK_CHECK(L_, 0); |
87 | return value; | 87 | return value; |
88 | } | 88 | } |
diff --git a/src/universe.cpp b/src/universe.cpp index 3800dbb..c435dad 100644 --- a/src/universe.cpp +++ b/src/universe.cpp | |||
@@ -100,7 +100,7 @@ void Universe::callOnStateCreate(lua_State* const L_, lua_State* const from_, Lo | |||
100 | } | 100 | } |
101 | kConfigRegKey.pushValue(L_); // L_: config | 101 | kConfigRegKey.pushValue(L_); // L_: config |
102 | STACK_CHECK(L_, 1); | 102 | STACK_CHECK(L_, 1); |
103 | LuaType const _funcType{ luaG_getfield(L_, -1, kOnStateCreate) }; // L_: config on_state_create() | 103 | LuaType const _funcType{ luaG_getfield(L_, kIdxTop, kOnStateCreate) }; // L_: config on_state_create() |
104 | if (_funcType != LuaType::FUNCTION) { | 104 | if (_funcType != LuaType::FUNCTION) { |
105 | raise_luaL_error(L_, "INTERNAL ERROR: %s is a %s, not a function", kOnStateCreate.data(), luaG_typename(L_, _funcType).data()); | 105 | raise_luaL_error(L_, "INTERNAL ERROR: %s is a %s, not a function", kOnStateCreate.data(), luaG_typename(L_, _funcType).data()); |
106 | } | 106 | } |
@@ -111,29 +111,28 @@ void Universe::callOnStateCreate(lua_State* const L_, lua_State* const from_, Lo | |||
111 | std::string_view const _stateType{ mode_ == LookupMode::LaneBody ? "lane" : "keeper" }; | 111 | std::string_view const _stateType{ mode_ == LookupMode::LaneBody ? "lane" : "keeper" }; |
112 | luaG_pushstring(L_, _stateType); // L_: on_state_create() "<type>" | 112 | luaG_pushstring(L_, _stateType); // L_: on_state_create() "<type>" |
113 | if (lua_pcall(L_, 1, 0, 0) != LUA_OK) { | 113 | if (lua_pcall(L_, 1, 0, 0) != LUA_OK) { |
114 | raise_luaL_error(from_, "%s failed in %s: \"%s\"", kOnStateCreate.data(), _stateType.data(), lua_isstring(L_, -1) ? luaG_tostring(L_, -1).data() : luaG_typename(L_, -1).data()); | 114 | raise_luaL_error(from_, "%s failed in %s: \"%s\"", kOnStateCreate.data(), _stateType.data(), lua_isstring(L_, -1) ? luaG_tostring(L_, kIdxTop).data() : luaG_typename(L_, kIdxTop).data()); |
115 | } | 115 | } |
116 | STACK_CHECK(L_, 0); | 116 | STACK_CHECK(L_, 0); |
117 | } | 117 | } |
118 | 118 | ||
119 | |||
120 | |||
121 | // ################################################################################################# | 119 | // ################################################################################################# |
122 | 120 | ||
123 | // only called from the master state | 121 | // only called from the master state |
124 | [[nodiscard]] Universe* Universe::Create(lua_State* const L_) | 122 | [[nodiscard]] Universe* Universe::Create(lua_State* const L_) |
125 | { | 123 | { |
126 | LUA_ASSERT(L_, Universe::Get(L_) == nullptr); | 124 | LUA_ASSERT(L_, Universe::Get(L_) == nullptr); |
125 | static constexpr StackIndex kIdxSettings{ 1 }; | ||
127 | LUA_ASSERT(L_, lua_gettop(L_) == 1 && lua_istable(L_, 1)); | 126 | LUA_ASSERT(L_, lua_gettop(L_) == 1 && lua_istable(L_, 1)); |
128 | STACK_CHECK_START_REL(L_, 0); // L_: settings | 127 | STACK_CHECK_START_REL(L_, 0); // L_: settings |
129 | std::ignore = luaG_getfield(L_, 1, "nb_user_keepers"); // L_: settings nb_user_keepers | 128 | std::ignore = luaG_getfield(L_, kIdxSettings, "nb_user_keepers"); // L_: settings nb_user_keepers |
130 | int const _nbUserKeepers{ static_cast<int>(lua_tointeger(L_, -1)) + 1}; | 129 | int const _nbUserKeepers{ static_cast<int>(lua_tointeger(L_, -1)) + 1}; |
131 | lua_pop(L_, 1); // L_: settings | 130 | lua_pop(L_, 1); // L_: settings |
132 | if (_nbUserKeepers < 1) { | 131 | if (_nbUserKeepers < 1) { |
133 | raise_luaL_error(L_, "Bad number of additional keepers (%d)", _nbUserKeepers); | 132 | raise_luaL_error(L_, "Bad number of additional keepers (%d)", _nbUserKeepers); |
134 | } | 133 | } |
135 | STACK_CHECK(L_, 0); | 134 | STACK_CHECK(L_, 0); |
136 | std::ignore = luaG_getfield(L_, 1, "keepers_gc_threshold"); // L_: settings keepers_gc_threshold | 135 | std::ignore = luaG_getfield(L_, kIdxSettings, "keepers_gc_threshold"); // L_: settings keepers_gc_threshold |
137 | int const _keepers_gc_threshold{ static_cast<int>(lua_tointeger(L_, -1)) }; | 136 | int const _keepers_gc_threshold{ static_cast<int>(lua_tointeger(L_, -1)) }; |
138 | lua_pop(L_, 1); // L_: settings | 137 | lua_pop(L_, 1); // L_: settings |
139 | STACK_CHECK(L_, 0); | 138 | STACK_CHECK(L_, 0); |
@@ -146,22 +145,22 @@ void Universe::callOnStateCreate(lua_State* const L_, lua_State* const from_, Lo | |||
146 | 145 | ||
147 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); | 146 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); |
148 | lua_createtable(L_, 0, 1); // L_: settings universe {mt} | 147 | lua_createtable(L_, 0, 1); // L_: settings universe {mt} |
149 | std::ignore = luaG_getfield(L_, 1, "shutdown_timeout"); // L_: settings universe {mt} shutdown_timeout | 148 | std::ignore = luaG_getfield(L_, kIdxSettings, "shutdown_timeout"); // L_: settings universe {mt} shutdown_timeout |
150 | lua_pushcclosure(L_, LG_universe_gc, 1); // L_: settings universe {mt} LG_universe_gc | 149 | lua_pushcclosure(L_, LG_universe_gc, 1); // L_: settings universe {mt} LG_universe_gc |
151 | lua_setfield(L_, -2, "__gc"); // L_: settings universe {mt} | 150 | lua_setfield(L_, -2, "__gc"); // L_: settings universe {mt} |
152 | lua_setmetatable(L_, -2); // L_: settings universe | 151 | lua_setmetatable(L_, -2); // L_: settings universe |
153 | lua_pop(L_, 1); // L_: settings | 152 | lua_pop(L_, 1); // L_: settings |
154 | 153 | ||
155 | std::ignore = luaG_getfield(L_, 1, "strip_functions"); // L_: settings strip_functions | 154 | std::ignore = luaG_getfield(L_, kIdxSettings, "strip_functions"); // L_: settings strip_functions |
156 | _U->stripFunctions = lua_toboolean(L_, -1) ? true : false; | 155 | _U->stripFunctions = lua_toboolean(L_, -1) ? true : false; |
157 | lua_pop(L_, 1); // L_: settings | 156 | lua_pop(L_, 1); // L_: settings |
158 | 157 | ||
159 | std::ignore = luaG_getfield(L_, 1, "verbose_errors"); // L_: settings verbose_errors | 158 | std::ignore = luaG_getfield(L_, kIdxSettings, "verbose_errors"); // L_: settings verbose_errors |
160 | _U->verboseErrors = lua_toboolean(L_, -1) ? true : false; | 159 | _U->verboseErrors = lua_toboolean(L_, -1) ? true : false; |
161 | lua_pop(L_, 1); // L_: settings | 160 | lua_pop(L_, 1); // L_: settings |
162 | 161 | ||
163 | // tracking | 162 | // tracking |
164 | std::ignore = luaG_getfield(L_, 1, "track_lanes"); // L_: settings track_lanes | 163 | std::ignore = luaG_getfield(L_, kIdxSettings, "track_lanes"); // L_: settings track_lanes |
165 | if (lua_toboolean(L_, -1)) { | 164 | if (lua_toboolean(L_, -1)) { |
166 | _U->tracker.activate(); | 165 | _U->tracker.activate(); |
167 | } | 166 | } |
@@ -182,7 +181,7 @@ void Universe::callOnStateCreate(lua_State* const L_, lua_State* const from_, Lo | |||
182 | STACK_CHECK(L_, 1); | 181 | STACK_CHECK(L_, 1); |
183 | 182 | ||
184 | // Proxy userdata contents is only a 'DeepPrelude*' pointer | 183 | // Proxy userdata contents is only a 'DeepPrelude*' pointer |
185 | _U->timerLinda = *luaG_tofulluserdata<DeepPrelude*>(L_, -1); | 184 | _U->timerLinda = *luaG_tofulluserdata<DeepPrelude*>(L_, kIdxTop); |
186 | // increment refcount so that this linda remains alive as long as the universe exists. | 185 | // increment refcount so that this linda remains alive as long as the universe exists. |
187 | _U->timerLinda->refcount.fetch_add(1, std::memory_order_relaxed); | 186 | _U->timerLinda->refcount.fetch_add(1, std::memory_order_relaxed); |
188 | lua_pop(L_, 1); // L_: settings | 187 | lua_pop(L_, 1); // L_: settings |
@@ -224,13 +223,13 @@ void Universe::initializeAllocatorFunction(lua_State* const L_) | |||
224 | // start by just grabbing whatever allocator was provided to the master state | 223 | // start by just grabbing whatever allocator was provided to the master state |
225 | protectedAllocator.initFrom(L_); | 224 | protectedAllocator.initFrom(L_); |
226 | STACK_CHECK_START_REL(L_, 1); // L_: settings | 225 | STACK_CHECK_START_REL(L_, 1); // L_: settings |
227 | switch (luaG_getfield(L_, -1, "allocator")) { // L_: settings allocator|nil|"protected" | 226 | switch (luaG_getfield(L_, kIdxTop, "allocator")) { // L_: settings allocator|nil|"protected" |
228 | case LuaType::NIL: | 227 | case LuaType::NIL: |
229 | // nothing else to do | 228 | // nothing else to do |
230 | break; | 229 | break; |
231 | 230 | ||
232 | case LuaType::STRING: | 231 | case LuaType::STRING: |
233 | LUA_ASSERT(L_, luaG_tostring(L_, -1) == "protected"); | 232 | LUA_ASSERT(L_, luaG_tostring(L_, kIdxTop) == "protected"); |
234 | // set the original allocator to call from inside protection by the mutex | 233 | // set the original allocator to call from inside protection by the mutex |
235 | protectedAllocator.installIn(L_); | 234 | protectedAllocator.installIn(L_); |
236 | // before a state is created, this function will be called to obtain the allocator | 235 | // before a state is created, this function will be called to obtain the allocator |
@@ -255,14 +254,14 @@ void Universe::initializeAllocatorFunction(lua_State* const L_) | |||
255 | break; | 254 | break; |
256 | 255 | ||
257 | default: // should be filtered out in lanes.lua | 256 | default: // should be filtered out in lanes.lua |
258 | raise_luaL_error(L_, "Bad config.allocator type %s", luaG_typename(L_, -1).data()); | 257 | raise_luaL_error(L_, "Bad config.allocator type %s", luaG_typename(L_, kIdxTop).data()); |
259 | } | 258 | } |
260 | lua_pop(L_, 1); // L_: settings | 259 | lua_pop(L_, 1); // L_: settings |
261 | STACK_CHECK(L_, 1); | 260 | STACK_CHECK(L_, 1); |
262 | 261 | ||
263 | std::ignore = luaG_getfield(L_, -1, "internal_allocator"); // L_: settings "libc"|"allocator" | 262 | std::ignore = luaG_getfield(L_, kIdxTop, "internal_allocator"); // L_: settings "libc"|"allocator" |
264 | LUA_ASSERT(L_, lua_isstring(L_, -1)); // should be the case due to lanes.lua parameter validation | 263 | LUA_ASSERT(L_, lua_isstring(L_, kIdxTop)); // should be the case due to lanes.lua parameter validation |
265 | std::string_view const _allocator{ luaG_tostring(L_, -1) }; | 264 | std::string_view const _allocator{ luaG_tostring(L_, kIdxTop) }; |
266 | if (_allocator == "libc") { | 265 | if (_allocator == "libc") { |
267 | internalAllocator = lanes::AllocatorDefinition{ lanes::AllocatorDefinition::kAllocatorVersion, libc_lua_Alloc, nullptr }; | 266 | internalAllocator = lanes::AllocatorDefinition{ lanes::AllocatorDefinition::kAllocatorVersion, libc_lua_Alloc, nullptr }; |
268 | } else { | 267 | } else { |
@@ -284,7 +283,7 @@ int Universe::InitializeFinalizer(lua_State* const L_) | |||
284 | 283 | ||
285 | // make sure we are only called from the Master Lua State! | 284 | // make sure we are only called from the Master Lua State! |
286 | kUniverseFullRegKey.pushValue(L_); // L_: f U | 285 | kUniverseFullRegKey.pushValue(L_); // L_: f U |
287 | if (luaG_type(L_, -1) != LuaType::USERDATA) { | 286 | if (luaG_type(L_, kIdxTop) != LuaType::USERDATA) { |
288 | raise_luaL_error(L_, "lanes.%s called from inside a lane", kFinally); | 287 | raise_luaL_error(L_, "lanes.%s called from inside a lane", kFinally); |
289 | } | 288 | } |
290 | lua_pop(L_, 1); // L_: f | 289 | lua_pop(L_, 1); // L_: f |
@@ -300,8 +299,8 @@ int Universe::InitializeFinalizer(lua_State* const L_) | |||
300 | void Universe::initializeOnStateCreate(lua_State* const L_) | 299 | void Universe::initializeOnStateCreate(lua_State* const L_) |
301 | { | 300 | { |
302 | STACK_CHECK_START_REL(L_, 0); // L_: settings | 301 | STACK_CHECK_START_REL(L_, 0); // L_: settings |
303 | if (luaG_getfield(L_, -1, kOnStateCreate) != LuaType::NIL) { // L_: settings on_state_create|nil | 302 | if (luaG_getfield(L_, kIdxTop, kOnStateCreate) != LuaType::NIL) { // L_: settings on_state_create|nil |
304 | LUA_ASSERT(L_, luaG_type(L_, -1) == LuaType::FUNCTION); // ensured by lanes.lua parameter validation | 303 | LUA_ASSERT(L_, luaG_type(L_, kIdxTop) == LuaType::FUNCTION); // ensured by lanes.lua parameter validation |
305 | // store C function pointer in an internal variable | 304 | // store C function pointer in an internal variable |
306 | lua_CFunction const _func{ lua_tocfunction(L_, -1) }; // L_: settings on_state_create | 305 | lua_CFunction const _func{ lua_tocfunction(L_, -1) }; // L_: settings on_state_create |
307 | if (_func) { | 306 | if (_func) { |
@@ -314,7 +313,7 @@ void Universe::initializeOnStateCreate(lua_State* const L_) | |||
314 | // remove this C function from the config table so that it doesn't cause problems | 313 | // remove this C function from the config table so that it doesn't cause problems |
315 | // when we transfer the config table in newly created Lua states | 314 | // when we transfer the config table in newly created Lua states |
316 | lua_pushnil(L_); // L_: settings on_state_create nil | 315 | lua_pushnil(L_); // L_: settings on_state_create nil |
317 | luaG_setfield(L_, -3, kOnStateCreate); // L_: settings on_state_create | 316 | luaG_setfield(L_, StackIndex{ -3 }, kOnStateCreate); // L_: settings on_state_create |
318 | } else { | 317 | } else { |
319 | // the function is still in the config table. we indicate this with the uintptr_t alternative (actual value is irrelevant) | 318 | // the function is still in the config table. we indicate this with the uintptr_t alternative (actual value is irrelevant) |
320 | onStateCreateFunc.emplace<uintptr_t>(std::bit_cast<uintptr_t>(kOnStateCreate.data())); | 319 | onStateCreateFunc.emplace<uintptr_t>(std::bit_cast<uintptr_t>(kOnStateCreate.data())); |
@@ -339,7 +338,7 @@ lanes::AllocatorDefinition Universe::resolveAllocator(lua_State* const L_, std:: | |||
339 | lua_pushcclosure(L_, provideAllocator, 0); // L_: provideAllocator() | 338 | lua_pushcclosure(L_, provideAllocator, 0); // L_: provideAllocator() |
340 | luaG_pushstring(L_, hint_); // L_: provideAllocator() "<hint>" | 339 | luaG_pushstring(L_, hint_); // L_: provideAllocator() "<hint>" |
341 | lua_call(L_, 1, 1); // L_: result | 340 | lua_call(L_, 1, 1); // L_: result |
342 | lanes::AllocatorDefinition* const _def{ luaG_tofulluserdata<lanes::AllocatorDefinition>(L_, -1) }; | 341 | lanes::AllocatorDefinition* const _def{ luaG_tofulluserdata<lanes::AllocatorDefinition>(L_, kIdxTop) }; |
343 | if (!_def || _def->version != lanes::AllocatorDefinition::kAllocatorVersion) { | 342 | if (!_def || _def->version != lanes::AllocatorDefinition::kAllocatorVersion) { |
344 | raise_luaL_error(L_, "Bad config.allocator function, must provide a valid AllocatorDefinition"); | 343 | raise_luaL_error(L_, "Bad config.allocator function, must provide a valid AllocatorDefinition"); |
345 | } | 344 | } |
@@ -414,7 +413,7 @@ LUAG_FUNC(universe_gc) | |||
414 | { | 413 | { |
415 | lua_Duration const _shutdown_timeout{ lua_tonumber(L_, lua_upvalueindex(1)) }; | 414 | lua_Duration const _shutdown_timeout{ lua_tonumber(L_, lua_upvalueindex(1)) }; |
416 | STACK_CHECK_START_ABS(L_, 1); | 415 | STACK_CHECK_START_ABS(L_, 1); |
417 | Universe* const _U{ luaG_tofulluserdata<Universe>(L_, 1) }; // L_: U | 416 | Universe* const _U{ luaG_tofulluserdata<Universe>(L_, StackIndex{ 1 }) }; // L_: U |
418 | 417 | ||
419 | // attempt to terminate all lanes with increasingly stronger cancel methods | 418 | // attempt to terminate all lanes with increasingly stronger cancel methods |
420 | bool const _allLanesTerminated{ | 419 | bool const _allLanesTerminated{ |
@@ -433,7 +432,7 @@ LUAG_FUNC(universe_gc) | |||
433 | STACK_CHECK(L_, 2); | 432 | STACK_CHECK(L_, 2); |
434 | 433 | ||
435 | // if some lanes are still running here, we have no other choice than crashing or freezing and let the client figure out what's wrong | 434 | // if some lanes are still running here, we have no other choice than crashing or freezing and let the client figure out what's wrong |
436 | bool const _throw{ luaG_tostring(L_, -1) == "throw" }; | 435 | bool const _throw{ luaG_tostring(L_, kIdxTop) == "throw" }; |
437 | lua_pop(L_, 1); // L_: U | 436 | lua_pop(L_, 1); // L_: U |
438 | 437 | ||
439 | while (_U->selfdestructFirst != SELFDESTRUCT_END) { | 438 | while (_U->selfdestructFirst != SELFDESTRUCT_END) { |