diff options
author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-12-02 11:53:09 +0100 |
---|---|---|
committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-12-02 11:53:09 +0100 |
commit | ca7657e24549acb8a2dd45fa81c309b5bf9f61ee (patch) | |
tree | 0124afa9a67d5f9d64fdbad4724bc715b7b502fb /src | |
parent | 0728e80bc2d3f5609f19b76f2bcf10412ce029b4 (diff) | |
download | lanes-ca7657e24549acb8a2dd45fa81c309b5bf9f61ee.tar.gz lanes-ca7657e24549acb8a2dd45fa81c309b5bf9f61ee.tar.bz2 lanes-ca7657e24549acb8a2dd45fa81c309b5bf9f61ee.zip |
Data transfer supports registered non-deep full userdata
Diffstat (limited to 'src')
-rw-r--r-- | src/intercopycontext.cpp | 98 | ||||
-rw-r--r-- | src/intercopycontext.hpp | 2 | ||||
-rw-r--r-- | src/tools.cpp | 29 |
3 files changed, 103 insertions, 26 deletions
diff --git a/src/intercopycontext.cpp b/src/intercopycontext.cpp index 568e4cb..1be4c53 100644 --- a/src/intercopycontext.cpp +++ b/src/intercopycontext.cpp | |||
@@ -55,7 +55,7 @@ static int buf_writer(lua_State* L_, void const* b_, size_t size_, void* ud_) | |||
55 | 55 | ||
56 | // function sentinel used to transfer native functions from/to keeper states | 56 | // function sentinel used to transfer native functions from/to keeper states |
57 | [[nodiscard]] | 57 | [[nodiscard]] |
58 | static int func_lookup_sentinel(lua_State* L_) | 58 | static int func_lookup_sentinel(lua_State* const L_) |
59 | { | 59 | { |
60 | raise_luaL_error(L_, "function lookup sentinel for %s, should never be called", lua_tostring(L_, lua_upvalueindex(1))); | 60 | raise_luaL_error(L_, "function lookup sentinel for %s, should never be called", lua_tostring(L_, lua_upvalueindex(1))); |
61 | } | 61 | } |
@@ -64,7 +64,7 @@ static int func_lookup_sentinel(lua_State* L_) | |||
64 | 64 | ||
65 | // function sentinel used to transfer native table from/to keeper states | 65 | // function sentinel used to transfer native table from/to keeper states |
66 | [[nodiscard]] | 66 | [[nodiscard]] |
67 | static int table_lookup_sentinel(lua_State* L_) | 67 | static int table_lookup_sentinel(lua_State* const L_) |
68 | { | 68 | { |
69 | raise_luaL_error(L_, "table lookup sentinel for %s, should never be called", lua_tostring(L_, lua_upvalueindex(1))); | 69 | raise_luaL_error(L_, "table lookup sentinel for %s, should never be called", lua_tostring(L_, lua_upvalueindex(1))); |
70 | } | 70 | } |
@@ -73,23 +73,32 @@ static int table_lookup_sentinel(lua_State* L_) | |||
73 | 73 | ||
74 | // function sentinel used to transfer cloned full userdata from/to keeper states | 74 | // function sentinel used to transfer cloned full userdata from/to keeper states |
75 | [[nodiscard]] | 75 | [[nodiscard]] |
76 | static int userdata_clone_sentinel(lua_State* L_) | 76 | static int userdata_clone_sentinel(lua_State* const L_) |
77 | { | 77 | { |
78 | raise_luaL_error(L_, "userdata clone sentinel for %s, should never be called", lua_tostring(L_, lua_upvalueindex(1))); | 78 | raise_luaL_error(L_, "userdata clone sentinel for %s, should never be called", lua_tostring(L_, lua_upvalueindex(1))); |
79 | } | 79 | } |
80 | 80 | ||
81 | // ################################################################################################# | 81 | // ################################################################################################# |
82 | 82 | ||
83 | // retrieve the name of a function/table in the lookup database | 83 | // function sentinel used to transfer native table from/to keeper states |
84 | [[nodiscard]] | ||
85 | static int userdata_lookup_sentinel(lua_State* const L_) | ||
86 | { | ||
87 | raise_luaL_error(L_, "userdata lookup sentinel for %s, should never be called", lua_tostring(L_, lua_upvalueindex(1))); | ||
88 | } | ||
89 | |||
90 | // ################################################################################################# | ||
91 | |||
92 | // retrieve the name of a function/table/userdata in the lookup database | ||
84 | [[nodiscard]] | 93 | [[nodiscard]] |
85 | std::string_view InterCopyContext::findLookupName() const | 94 | std::string_view InterCopyContext::findLookupName() const |
86 | { | 95 | { |
87 | LUA_ASSERT(L1, lua_isfunction(L1, L1_i) || lua_istable(L1, L1_i)); // L1: ... v ... | 96 | LUA_ASSERT(L1, lua_isfunction(L1, L1_i) || lua_istable(L1, L1_i) || luaG_type(L1, L1_i) == LuaType::USERDATA); |
88 | STACK_CHECK_START_REL(L1, 0); | 97 | STACK_CHECK_START_REL(L1, 0); // L1: ... v ... |
89 | STACK_GROW(L1, 3); // up to 3 slots are necessary on error | 98 | STACK_GROW(L1, 3); // up to 3 slots are necessary on error |
90 | if (mode == LookupMode::FromKeeper) { | 99 | if (mode == LookupMode::FromKeeper) { |
91 | lua_CFunction const _f{ lua_tocfunction(L1, L1_i) }; // should *always* be one of the function sentinels | 100 | lua_CFunction const _f{ lua_tocfunction(L1, L1_i) }; // should *always* be one of the sentinel functions |
92 | if (_f == func_lookup_sentinel || _f == table_lookup_sentinel || _f == userdata_clone_sentinel) { | 101 | if (_f == func_lookup_sentinel || _f == table_lookup_sentinel || _f == userdata_clone_sentinel || _f == userdata_lookup_sentinel) { |
93 | lua_getupvalue(L1, L1_i, 1); // L1: ... v ... "f.q.n" | 102 | lua_getupvalue(L1, L1_i, 1); // L1: ... v ... "f.q.n" |
94 | } else { | 103 | } else { |
95 | // if this is not a sentinel, this is some user-created table we wanted to lookup | 104 | // if this is not a sentinel, this is some user-created table we wanted to lookup |
@@ -110,8 +119,8 @@ std::string_view InterCopyContext::findLookupName() const | |||
110 | // popping doesn't invalidate the pointer since this is an interned string gotten from the lookup database | 119 | // popping doesn't invalidate the pointer since this is an interned string gotten from the lookup database |
111 | lua_pop(L1, (mode == LookupMode::FromKeeper) ? 1 : 2); // L1: ... v ... | 120 | lua_pop(L1, (mode == LookupMode::FromKeeper) ? 1 : 2); // L1: ... v ... |
112 | STACK_CHECK(L1, 0); | 121 | STACK_CHECK(L1, 0); |
113 | if (_fqn.empty() && !lua_istable(L1, L1_i)) { // raise an error if we try to send an unknown function (but not for tables) | 122 | if (_fqn.empty() && !lua_istable(L1, L1_i)) { // raise an error if we try to send an unknown function/userdata (but not for tables) |
114 | // try to discover the name of the function we want to send | 123 | // try to discover the name of the function/userdata we want to send |
115 | kLaneNameRegKey.pushValue(L1); // L1: ... v ... lane_name | 124 | kLaneNameRegKey.pushValue(L1); // L1: ... v ... lane_name |
116 | std::string_view const _from{ luaG_tostring(L1, kIdxTop) }; | 125 | std::string_view const _from{ luaG_tostring(L1, kIdxTop) }; |
117 | lua_pushcfunction(L1, LG_nameof); // L1: ... v ... lane_name LG_nameof | 126 | lua_pushcfunction(L1, LG_nameof); // L1: ... v ... lane_name LG_nameof |
@@ -331,7 +340,8 @@ void InterCopyContext::lookupNativeFunction() const | |||
331 | lua_rawget(L2, -2); // L1: ... f ... L2: {} f | 340 | lua_rawget(L2, -2); // L1: ... f ... L2: {} f |
332 | // nil means we don't know how to transfer stuff: user should do something | 341 | // nil means we don't know how to transfer stuff: user should do something |
333 | // anything other than function or table should not happen! | 342 | // anything other than function or table should not happen! |
334 | if (!lua_isfunction(L2, -1) && !lua_istable(L2, -1)) { | 343 | LuaType const _objType{ luaG_type(L2, kIdxTop) }; |
344 | if (_objType != LuaType::FUNCTION && _objType != LuaType::TABLE && _objType != LuaType::USERDATA) { | ||
335 | kLaneNameRegKey.pushValue(L1); // L1: ... f ... lane_name | 345 | kLaneNameRegKey.pushValue(L1); // L1: ... f ... lane_name |
336 | std::string_view const _from{ luaG_tostring(L1, kIdxTop) }; | 346 | std::string_view const _from{ luaG_tostring(L1, kIdxTop) }; |
337 | lua_pop(L1, 1); // L1: ... f ... | 347 | lua_pop(L1, 1); // L1: ... f ... |
@@ -340,9 +350,10 @@ void InterCopyContext::lookupNativeFunction() const | |||
340 | lua_pop(L2, 1); // L2: {} f | 350 | lua_pop(L2, 1); // L2: {} f |
341 | raise_luaL_error( | 351 | raise_luaL_error( |
342 | getErrL(), | 352 | getErrL(), |
343 | "%s%s: function '%s' not found in %s destination transfer database.", | 353 | "%s%s: %s '%s' not found in %s destination transfer database.", |
344 | lua_isnil(L2, -1) ? "" : "INTERNAL ERROR IN ", | 354 | lua_isnil(L2, -1) ? "" : "INTERNAL ERROR IN ", |
345 | _from.empty() ? "main" : _from.data(), | 355 | _from.empty() ? "main" : _from.data(), |
356 | luaG_typename(L2, _objType), | ||
346 | _fqn.data(), | 357 | _fqn.data(), |
347 | _to.empty() ? "main" : _to.data()); | 358 | _to.empty() ? "main" : _to.data()); |
348 | return; | 359 | return; |
@@ -397,8 +408,8 @@ void InterCopyContext::copyCachedFunction() const | |||
397 | LUA_ASSERT(L1, lua_isfunction(L2, -1)); | 408 | LUA_ASSERT(L1, lua_isfunction(L2, -1)); |
398 | } else { // function is native/LuaJIT: no need to cache | 409 | } else { // function is native/LuaJIT: no need to cache |
399 | lookupNativeFunction(); // L2: ... {cache} ... function | 410 | lookupNativeFunction(); // L2: ... {cache} ... function |
400 | // if the function was in fact a lookup sentinel, we can either get a function or a table here | 411 | // if the function was in fact a lookup sentinel, we can either get a function, table or full userdata here |
401 | LUA_ASSERT(L1, lua_isfunction(L2, -1) || lua_istable(L2, -1)); | 412 | LUA_ASSERT(L1, lua_isfunction(L2, kIdxTop) || lua_istable(L2, kIdxTop) || luaG_type(L2, kIdxTop) == LuaType::USERDATA); |
402 | } | 413 | } |
403 | } | 414 | } |
404 | 415 | ||
@@ -678,6 +689,59 @@ bool InterCopyContext::pushCachedTable() const | |||
678 | 689 | ||
679 | // ################################################################################################# | 690 | // ################################################################################################# |
680 | 691 | ||
692 | // Push a looked-up full userdata. | ||
693 | [[nodiscard]] | ||
694 | bool InterCopyContext::lookupUserdata() const | ||
695 | { | ||
696 | // get the name of the userdata we want to send | ||
697 | std::string_view const _fqn{ findLookupName() }; | ||
698 | // push the equivalent userdata in the destination's stack, retrieved from the lookup table | ||
699 | STACK_CHECK_START_REL(L2, 0); | ||
700 | STACK_GROW(L2, 3); // up to 3 slots are necessary on error | ||
701 | switch (mode) { | ||
702 | default: // shouldn't happen, in theory... | ||
703 | raise_luaL_error(getErrL(), "internal error: unknown lookup mode"); | ||
704 | break; | ||
705 | |||
706 | case LookupMode::ToKeeper: | ||
707 | // push a sentinel closure that holds the lookup name as upvalue | ||
708 | luaG_pushstring(L2, _fqn); // L1: ... f ... L2: "f.q.n" | ||
709 | lua_pushcclosure(L2, userdata_lookup_sentinel, 1); // L1: ... f ... L2: f | ||
710 | break; | ||
711 | |||
712 | case LookupMode::LaneBody: | ||
713 | case LookupMode::FromKeeper: | ||
714 | kLookupRegKey.pushValue(L2); // L1: ... f ... L2: {} | ||
715 | STACK_CHECK(L2, 1); | ||
716 | LUA_ASSERT(L1, lua_istable(L2, -1)); | ||
717 | luaG_pushstring(L2, _fqn); // L1: ... f ... L2: {} "f.q.n" | ||
718 | lua_rawget(L2, -2); // L1: ... f ... L2: {} f | ||
719 | // nil means we don't know how to transfer stuff: user should do something | ||
720 | // anything other than function or table should not happen! | ||
721 | if (!lua_isfunction(L2, -1) && !lua_istable(L2, -1)) { | ||
722 | kLaneNameRegKey.pushValue(L1); // L1: ... f ... lane_name | ||
723 | std::string_view const _from{ luaG_tostring(L1, kIdxTop) }; | ||
724 | lua_pop(L1, 1); // L1: ... f ... | ||
725 | kLaneNameRegKey.pushValue(L2); // L1: ... f ... L2: {} f lane_name | ||
726 | std::string_view const _to{ luaG_tostring(L2, kIdxTop) }; | ||
727 | lua_pop(L2, 1); // L2: {} f | ||
728 | raise_luaL_error( | ||
729 | getErrL(), | ||
730 | "%s%s: userdata '%s' not found in %s destination transfer database.", | ||
731 | lua_isnil(L2, -1) ? "" : "INTERNAL ERROR IN ", | ||
732 | _from.empty() ? "main" : _from.data(), | ||
733 | _fqn.data(), | ||
734 | _to.empty() ? "main" : _to.data()); | ||
735 | } | ||
736 | lua_remove(L2, -2); // L2: f | ||
737 | break; | ||
738 | } | ||
739 | STACK_CHECK(L2, 1); | ||
740 | return true; | ||
741 | } | ||
742 | |||
743 | // ################################################################################################# | ||
744 | |||
681 | [[nodiscard]] | 745 | [[nodiscard]] |
682 | bool InterCopyContext::tryCopyClonable() const | 746 | bool InterCopyContext::tryCopyClonable() const |
683 | { | 747 | { |
@@ -1099,6 +1163,12 @@ bool InterCopyContext::interCopyUserdata() const | |||
1099 | return true; | 1163 | return true; |
1100 | } | 1164 | } |
1101 | 1165 | ||
1166 | // Last, let's try to see if this userdata is special (aka is it some userdata that we registered in our lookup databases during module registration?) | ||
1167 | if (lookupUserdata()) { | ||
1168 | LUA_ASSERT(L1, luaG_type(L2, kIdxTop) == LuaType::USERDATA || (lua_tocfunction(L2, kIdxTop) == userdata_lookup_sentinel)); // from lookup data. can also be userdata_lookup_sentinel if this is a userdata we know | ||
1169 | return true; | ||
1170 | } | ||
1171 | |||
1102 | raise_luaL_error(getErrL(), "can't copy non-deep full userdata across lanes"); | 1172 | raise_luaL_error(getErrL(), "can't copy non-deep full userdata across lanes"); |
1103 | } | 1173 | } |
1104 | 1174 | ||
diff --git a/src/intercopycontext.hpp b/src/intercopycontext.hpp index 84d9e70..7008919 100644 --- a/src/intercopycontext.hpp +++ b/src/intercopycontext.hpp | |||
@@ -64,6 +64,8 @@ class InterCopyContext | |||
64 | 64 | ||
65 | // for use in inter_copy_userdata | 65 | // for use in inter_copy_userdata |
66 | [[nodiscard]] | 66 | [[nodiscard]] |
67 | bool lookupUserdata() const; | ||
68 | [[nodiscard]] | ||
67 | bool tryCopyClonable() const; | 69 | bool tryCopyClonable() const; |
68 | [[nodiscard]] | 70 | [[nodiscard]] |
69 | bool tryCopyDeep() const; | 71 | bool tryCopyDeep() const; |
diff --git a/src/tools.cpp b/src/tools.cpp index 827c4a4..cd64d13 100644 --- a/src/tools.cpp +++ b/src/tools.cpp | |||
@@ -123,7 +123,7 @@ namespace tools { | |||
123 | * receives 2 arguments: a name k and an object o | 123 | * receives 2 arguments: a name k and an object o |
124 | * add two entries ["fully.qualified.name"] = o | 124 | * add two entries ["fully.qualified.name"] = o |
125 | * and [o] = "fully.qualified.name" | 125 | * and [o] = "fully.qualified.name" |
126 | * where <o> is either a table or a function | 126 | * where <o> is either a table, a function, or a full userdata |
127 | * if we already had an entry of type [o] = ..., replace the name if the new one is shorter | 127 | * if we already had an entry of type [o] = ..., replace the name if the new one is shorter |
128 | * pops the processed object from the stack | 128 | * pops the processed object from the stack |
129 | */ | 129 | */ |
@@ -191,7 +191,7 @@ static void update_lookup_entry(lua_State* const L_, StackIndex const ctxBase_, | |||
191 | 191 | ||
192 | // ################################################################################################# | 192 | // ################################################################################################# |
193 | 193 | ||
194 | static void populate_func_lookup_table_recur(lua_State* const L_, StackIndex const dbIdx_, StackIndex const i_, int const depth_) | 194 | static void populate_lookup_table_recur(lua_State* const L_, StackIndex const dbIdx_, StackIndex const i_, int const depth_) |
195 | { | 195 | { |
196 | // slot dbIdx_ contains the lookup database table | 196 | // 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_ | 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_ |
@@ -199,7 +199,7 @@ static void populate_func_lookup_table_recur(lua_State* const L_, StackIndex con | |||
199 | // slot dbIdx_ + 2 contains a cache that stores all already visited tables to avoid infinite recursion loops | 199 | // slot dbIdx_ + 2 contains a cache that stores all already visited tables to avoid infinite recursion loops |
200 | StackIndex const _cache{ dbIdx_ + 2 }; | 200 | StackIndex const _cache{ dbIdx_ + 2 }; |
201 | DEBUGSPEW_CODE(Universe* const _U{ Universe::Get(L_) }); | 201 | DEBUGSPEW_CODE(Universe* const _U{ Universe::Get(L_) }); |
202 | DEBUGSPEW_CODE(DebugSpew(_U) << "populate_func_lookup_table_recur()" << std::endl); | 202 | DEBUGSPEW_CODE(DebugSpew(_U) << "populate_lookup_table_recur()" << std::endl); |
203 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); | 203 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); |
204 | 204 | ||
205 | STACK_GROW(L_, 6); | 205 | STACK_GROW(L_, 6); |
@@ -231,14 +231,14 @@ static void populate_func_lookup_table_recur(lua_State* const L_, StackIndex con | |||
231 | 231 | ||
232 | // we need to remember subtables to process them after functions encountered at the current depth (breadth-first search) | 232 | // we need to remember subtables to process them after functions encountered at the current depth (breadth-first search) |
233 | lua_newtable(L_); // L_: ... {i_} {bfc} | 233 | lua_newtable(L_); // L_: ... {i_} {bfc} |
234 | int const breadthFirstCache{ lua_gettop(L_) }; | 234 | StackIndex const _breadthFirstCache{ lua_gettop(L_) }; |
235 | // iterate over all entries in the processed table | 235 | // iterate over all entries in the processed table |
236 | lua_pushnil(L_); // L_: ... {i_} {bfc} nil | 236 | lua_pushnil(L_); // L_: ... {i_} {bfc} nil |
237 | while (lua_next(L_, i_) != 0) { // L_: ... {i_} {bfc} k v | 237 | while (lua_next(L_, i_) != 0) { // L_: ... {i_} {bfc} k v |
238 | // just for debug, not actually needed | 238 | // just for debug, not actually needed |
239 | // std::string_view const _key{ (luaG_type(L_, -2) == LuaType::STRING) ? luaG_tostring(L_, -2) : "not a string" }; | 239 | // std::string_view const _key{ (luaG_type(L_, -2) == LuaType::STRING) ? luaG_tostring(L_, -2) : "not a string" }; |
240 | // subtable: process it recursively | 240 | // subtable: process it recursively |
241 | if (lua_istable(L_, -1)) { // L_: ... {i_} {bfc} k {} | 241 | if (lua_istable(L_, kIdxTop)) { // L_: ... {i_} {bfc} k {} |
242 | // increment visit count to make sure we will actually scan it at this recursive level | 242 | // increment visit count to make sure we will actually scan it at this recursive level |
243 | lua_pushvalue(L_, -1); // L_: ... {i_} {bfc} k {} {} | 243 | lua_pushvalue(L_, -1); // L_: ... {i_} {bfc} k {} {} |
244 | lua_pushvalue(L_, -1); // L_: ... {i_} {bfc} k {} {} {} | 244 | lua_pushvalue(L_, -1); // L_: ... {i_} {bfc} k {} {} {} |
@@ -250,22 +250,26 @@ static void populate_func_lookup_table_recur(lua_State* const L_, StackIndex con | |||
250 | // store the table in the breadth-first cache | 250 | // store the table in the breadth-first cache |
251 | lua_pushvalue(L_, -2); // L_: ... {i_} {bfc} k {} k | 251 | lua_pushvalue(L_, -2); // L_: ... {i_} {bfc} k {} k |
252 | lua_pushvalue(L_, -2); // L_: ... {i_} {bfc} k {} k {} | 252 | lua_pushvalue(L_, -2); // L_: ... {i_} {bfc} k {} k {} |
253 | lua_rawset(L_, breadthFirstCache); // L_: ... {i_} {bfc} k {} | 253 | lua_rawset(L_, _breadthFirstCache); // L_: ... {i_} {bfc} k {} |
254 | // generate a name, and if we already had one name, keep whichever is the shorter | 254 | // 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 | 255 | update_lookup_entry(L_, dbIdx_, depth_); // L_: ... {i_} {bfc} k |
256 | } else if (lua_isfunction(L_, -1) && (luaG_getfuncsubtype(L_, kIdxTop) != FuncSubType::Bytecode)) { | 256 | } else if (lua_isfunction(L_, kIdxTop) && (luaG_getfuncsubtype(L_, kIdxTop) != FuncSubType::Bytecode)) { |
257 | // generate a name, and if we already had one name, keep whichever is the shorter | 257 | // generate a name, and if we already had one name, keep whichever is the shorter |
258 | // this pops the function from the stack | 258 | // this pops the function from the stack |
259 | update_lookup_entry(L_, dbIdx_, depth_); // L_: ... {i_} {bfc} k | 259 | update_lookup_entry(L_, dbIdx_, depth_); // L_: ... {i_} {bfc} k |
260 | } else if (luaG_type(L_, kIdxTop) == LuaType::USERDATA) { | ||
261 | // generate a name, and if we already had one name, keep whichever is the shorter | ||
262 | // this pops the userdata from the stack | ||
263 | update_lookup_entry(L_, dbIdx_, depth_); // L_: ... {i_} {bfc} k | ||
260 | } else { | 264 | } else { |
261 | lua_pop(L_, 1); // L_: ... {i_} {bfc} k | 265 | lua_pop(L_, 1); // L_: ... {i_} {bfc} k |
262 | } | 266 | } |
263 | STACK_CHECK(L_, 2); | 267 | STACK_CHECK(L_, 2); |
264 | } | 268 | } |
265 | // now process the tables we encountered at that depth | 269 | // now process the tables we encountered at that depth |
266 | int const _deeper{ depth_ + 1 }; | 270 | int const _deeper{ depth_ + 1 }; |
267 | lua_pushnil(L_); // L_: ... {i_} {bfc} nil | 271 | lua_pushnil(L_); // L_: ... {i_} {bfc} nil |
268 | while (lua_next(L_, breadthFirstCache) != 0) { // L_: ... {i_} {bfc} k {} | 272 | 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>" } }); | 273 | DEBUGSPEW_CODE(std::string_view const _key{ (luaG_type(L_, -2) == LuaType::STRING) ? luaG_tostring(L_, -2) : std::string_view{ "<not a string>" } }); |
270 | DEBUGSPEW_CODE(DebugSpew(_U) << "table '"<< _key <<"'" << std::endl); | 274 | DEBUGSPEW_CODE(DebugSpew(_U) << "table '"<< _key <<"'" << std::endl); |
271 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope2{ _U }); | 275 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope2{ _U }); |
@@ -285,7 +289,7 @@ static void populate_func_lookup_table_recur(lua_State* const L_, StackIndex con | |||
285 | // push table name in fqn stack (note that concatenation will crash if name is a not string!) | 289 | // 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 | 290 | lua_pushvalue(L_, -2); // L_: ... {i_} {bfc} k {} k |
287 | lua_rawseti(L_, _fqn, _deeper); // L_: ... {i_} {bfc} k {} | 291 | lua_rawseti(L_, _fqn, _deeper); // L_: ... {i_} {bfc} k {} |
288 | populate_func_lookup_table_recur(L_, dbIdx_, StackIndex{ lua_gettop(L_) }, _deeper); | 292 | populate_lookup_table_recur(L_, dbIdx_, StackIndex{ lua_gettop(L_) }, _deeper); |
289 | lua_pop(L_, 1); // L_: ... {i_} {bfc} k | 293 | lua_pop(L_, 1); // L_: ... {i_} {bfc} k |
290 | STACK_CHECK(L_, 2); | 294 | STACK_CHECK(L_, 2); |
291 | } | 295 | } |
@@ -316,7 +320,8 @@ namespace tools { | |||
316 | StackIndex const _dbIdx{ lua_gettop(L_) }; | 320 | StackIndex const _dbIdx{ lua_gettop(L_) }; |
317 | STACK_CHECK(L_, 1); | 321 | STACK_CHECK(L_, 1); |
318 | LUA_ASSERT(L_, lua_istable(L_, -1)); | 322 | LUA_ASSERT(L_, lua_istable(L_, -1)); |
319 | if (luaG_type(L_, _in_base) == LuaType::FUNCTION) { // for example when a module is a simple function | 323 | LuaType const _moduleType{ luaG_type(L_, _in_base) }; |
324 | if ((_moduleType == LuaType::FUNCTION) || (_moduleType == LuaType::USERDATA)) { // for example when a module is a simple function | ||
320 | if (_name.empty()) { | 325 | if (_name.empty()) { |
321 | _name = "nullptr"; | 326 | _name = "nullptr"; |
322 | } | 327 | } |
@@ -343,7 +348,7 @@ namespace tools { | |||
343 | // retrieve the cache, create it if we haven't done it yet | 348 | // retrieve the cache, create it if we haven't done it yet |
344 | std::ignore = kLookupCacheRegKey.getSubTable(L_, NArr{ 0 }, NRec{ 0 }); // L_: {} {fqn} {cache} | 349 | std::ignore = kLookupCacheRegKey.getSubTable(L_, NArr{ 0 }, NRec{ 0 }); // L_: {} {fqn} {cache} |
345 | // process everything we find in that table, filling in lookup data for all functions and tables we see there | 350 | // process everything we find in that table, filling in lookup data for all functions and tables we see there |
346 | populate_func_lookup_table_recur(L_, _dbIdx, _in_base, _startDepth); | 351 | populate_lookup_table_recur(L_, _dbIdx, _in_base, _startDepth); |
347 | lua_pop(L_, 3); // L_: | 352 | lua_pop(L_, 3); // L_: |
348 | } else { | 353 | } else { |
349 | lua_pop(L_, 1); // L_: | 354 | lua_pop(L_, 1); // L_: |