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