aboutsummaryrefslogtreecommitdiff
path: root/src/deep.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/deep.cpp')
-rw-r--r--src/deep.cpp64
1 files changed, 28 insertions, 36 deletions
diff --git a/src/deep.cpp b/src/deep.cpp
index 11e1ea7..6358745 100644
--- a/src/deep.cpp
+++ b/src/deep.cpp
@@ -66,28 +66,30 @@ static constexpr RegistryUniqueKey kDeepProxyCacheRegKey{ 0xEBCD49AE1A3DD35Eull
66 * Sets up [-1]<->[-2] two-way lookups, and ensures the lookup table exists. 66 * Sets up [-1]<->[-2] two-way lookups, and ensures the lookup table exists.
67 * Pops the both values off the stack. 67 * Pops the both values off the stack.
68 */ 68 */
69static void set_deep_lookup(lua_State* L_) 69void DeepFactory::storeDeepLookup(lua_State* L_) const
70{ 70{
71 // the deep metatable is at the top of the stack // L_: mt
71 STACK_GROW(L_, 3); 72 STACK_GROW(L_, 3);
72 STACK_CHECK_START_REL(L_, 2); // L_: a b 73 STACK_CHECK_START_REL(L_, 0); // L_: mt
73 push_registry_subtable(L_, kDeepLookupRegKey); // L_: a b {} 74 push_registry_subtable(L_, kDeepLookupRegKey); // L_: mt {}
74 STACK_CHECK(L_, 3); 75 lua_pushvalue(L_, -2); // L_: mt {} mt
75 lua_insert(L_, -3); // L_: {} a b 76 lua_pushlightuserdata(L_, std::bit_cast<void*>(this)); // L_: mt {} mt factory
76 lua_pushvalue(L_, -1); // L_: {} a b b 77 lua_rawset(L_, -3); // L_: mt {}
77 lua_pushvalue(L_, -3); // L_: {} a b b a 78 STACK_CHECK(L_, 1);
78 lua_rawset(L_, -5); // L_: {} a b 79
79 lua_rawset(L_, -3); // L_: {} 80 lua_pushlightuserdata(L_, std::bit_cast<void*>(this)); // L_: mt {} factory
80 lua_pop(L_, 1); // L_: 81 lua_pushvalue(L_, -3); // L_: mt {} factory mt
82 lua_rawset(L_, -3); // L_: mt {}
83 STACK_CHECK(L_, 1);
84
85 lua_pop(L_, 1); // L_: mt
81 STACK_CHECK(L_, 0); 86 STACK_CHECK(L_, 0);
82} 87}
83 88
84// ################################################################################################# 89// #################################################################################################
85 90
86/* 91// Pops the key (metatable or factory) off the stack, and replaces with the deep lookup value (factory/metatable/nil).
87 * Pops the key (metatable or factory) off the stack, and replaces with the 92static void LookupDeep(lua_State* L_)
88 * deep lookup value (factory/metatable/nil).
89 */
90static void get_deep_lookup(lua_State* L_)
91{ 93{
92 STACK_GROW(L_, 1); 94 STACK_GROW(L_, 1);
93 STACK_CHECK_START_REL(L_, 1); // L_: a 95 STACK_CHECK_START_REL(L_, 1); // L_: a
@@ -102,11 +104,8 @@ static void get_deep_lookup(lua_State* L_)
102 104
103// ################################################################################################# 105// #################################################################################################
104 106
105/* 107// Return the registered factory for 'index' (deep userdata proxy), or nullptr if 'index' is not a deep userdata proxy.
106 * Return the registered factory for 'index' (deep userdata proxy), 108[[nodiscard]] static inline DeepFactory* LookupFactory(lua_State* L_, int index_, LookupMode mode_)
107 * or nullptr if 'index' is not a deep userdata proxy.
108 */
109[[nodiscard]] static inline DeepFactory* get_factory(lua_State* L_, int index_, LookupMode mode_)
110{ 109{
111 // when looking inside a keeper, we are 100% sure the object is a deep userdata 110 // when looking inside a keeper, we are 100% sure the object is a deep userdata
112 if (mode_ == LookupMode::FromKeeper) { 111 if (mode_ == LookupMode::FromKeeper) {
@@ -125,7 +124,7 @@ static void get_deep_lookup(lua_State* L_)
125 } 124 }
126 125
127 // replace metatable with the factory pointer, if it is actually a deep userdata 126 // replace metatable with the factory pointer, if it is actually a deep userdata
128 get_deep_lookup(L_); // L_: deep ... factory|nil 127 LookupDeep(L_); // L_: deep ... factory|nil
129 128
130 DeepFactory* const ret{ lua_tolightuserdata<DeepFactory>(L_, -1) }; // nullptr if not a userdata 129 DeepFactory* const ret{ lua_tolightuserdata<DeepFactory>(L_, -1) }; // nullptr if not a userdata
131 lua_pop(L_, 1); 130 lua_pop(L_, 1);
@@ -211,7 +210,7 @@ char const* DeepFactory::PushDeepProxy(DestState L_, DeepPrelude* prelude_, int
211 // Get/create metatable for 'factory' (in this state) 210 // Get/create metatable for 'factory' (in this state)
212 DeepFactory& factory = prelude_->m_factory; 211 DeepFactory& factory = prelude_->m_factory;
213 lua_pushlightuserdata(L_, std::bit_cast<void*>(&factory)); // L_: DPC proxy factory 212 lua_pushlightuserdata(L_, std::bit_cast<void*>(&factory)); // L_: DPC proxy factory
214 get_deep_lookup(L_); // L_: DPC proxy metatable? 213 LookupDeep(L_); // L_: DPC proxy metatable|nil
215 214
216 if (lua_isnil(L_, -1)) { // No metatable yet. 215 if (lua_isnil(L_, -1)) { // No metatable yet.
217 lua_pop(L_, 1); // L_: DPC proxy 216 lua_pop(L_, 1); // L_: DPC proxy
@@ -240,12 +239,10 @@ char const* DeepFactory::PushDeepProxy(DestState L_, DeepPrelude* prelude_, int
240 // Add our own '__gc' method wrapping the original 239 // Add our own '__gc' method wrapping the original
241 lua_pushcclosure(L_, deep_userdata_gc, 1); // DPC proxy metatable deep_userdata_gc 240 lua_pushcclosure(L_, deep_userdata_gc, 1); // DPC proxy metatable deep_userdata_gc
242 } 241 }
243 lua_setfield(L_, -2, "__gc"); // DPC proxy metatable 242 lua_setfield(L_, -2, "__gc"); // L_: DPC proxy metatable
244 243
245 // Memorize for later rounds 244 // Memorize for later rounds
246 lua_pushvalue(L_, -1); // L_: DPC proxy metatable metatable 245 factory.storeDeepLookup(L_);
247 lua_pushlightuserdata(L_, std::bit_cast<void*>(&factory)); // L_: DPC proxy metatable metatable factory
248 set_deep_lookup(L_); // L_: DPC proxy metatable
249 246
250 // 2 - cause the target state to require the module that exported the factory 247 // 2 - cause the target state to require the module that exported the factory
251 if (char const* const modname{ factory.moduleName() }; modname) { // we actually got a module name 248 if (char const* const modname{ factory.moduleName() }; modname) { // we actually got a module name
@@ -361,7 +358,7 @@ DeepPrelude* DeepFactory::toDeep(lua_State* L_, int index_) const
361{ 358{
362 STACK_CHECK_START_REL(L_, 0); 359 STACK_CHECK_START_REL(L_, 0);
363 // ensure it is actually a deep userdata we created 360 // ensure it is actually a deep userdata we created
364 if (get_factory(L_, index_, LookupMode::LaneBody) != this) { 361 if (LookupFactory(L_, index_, LookupMode::LaneBody) != this) {
365 return nullptr; // no metatable, or wrong kind 362 return nullptr; // no metatable, or wrong kind
366 } 363 }
367 STACK_CHECK(L_, 0); 364 STACK_CHECK(L_, 0);
@@ -372,16 +369,11 @@ DeepPrelude* DeepFactory::toDeep(lua_State* L_, int index_) const
372 369
373// ################################################################################################# 370// #################################################################################################
374 371
375/* 372// Copy deep userdata between two separate Lua states (from L1 to L2)
376 * Copy deep userdata between two separate Lua states (from L1 to L2) 373// Returns false if not a deep userdata, else true (unless an error occured)
377 * 374[[nodiscard]] bool InterCopyContext::tryCopyDeep() const
378 * Returns:
379 * the id function of the copied value, or nullptr for non-deep userdata
380 * (not copied)
381 */
382[[nodiscard]] bool InterCopyContext::copyDeep() const
383{ 375{
384 DeepFactory* const factory{ get_factory(L1, L1_i, mode) }; 376 DeepFactory* const factory{ LookupFactory(L1, L1_i, mode) };
385 if (factory == nullptr) { 377 if (factory == nullptr) {
386 return false; // not a deep userdata 378 return false; // not a deep userdata
387 } 379 }