diff options
Diffstat (limited to 'src/deep.cpp')
-rw-r--r-- | src/deep.cpp | 176 |
1 files changed, 88 insertions, 88 deletions
diff --git a/src/deep.cpp b/src/deep.cpp index af7e814..13932a4 100644 --- a/src/deep.cpp +++ b/src/deep.cpp | |||
@@ -107,12 +107,12 @@ static void get_deep_lookup(lua_State* L_) | |||
107 | * Return the registered factory for 'index' (deep userdata proxy), | 107 | * Return the registered factory for 'index' (deep userdata proxy), |
108 | * or nullptr if 'index' is not a deep userdata proxy. | 108 | * or nullptr if 'index' is not a deep userdata proxy. |
109 | */ | 109 | */ |
110 | [[nodiscard]] static inline DeepFactory* get_factory(lua_State* L_, int index, LookupMode mode_) | 110 | [[nodiscard]] static inline DeepFactory* get_factory(lua_State* L_, int index_, LookupMode mode_) |
111 | { | 111 | { |
112 | // when looking inside a keeper, we are 100% sure the object is a deep userdata | 112 | // when looking inside a keeper, we are 100% sure the object is a deep userdata |
113 | if (mode_ == LookupMode::FromKeeper) | 113 | if (mode_ == LookupMode::FromKeeper) |
114 | { | 114 | { |
115 | DeepPrelude* const proxy{ *lua_tofulluserdata<DeepPrelude*>(L_, index) }; | 115 | DeepPrelude* const proxy{ *lua_tofulluserdata<DeepPrelude*>(L_, index_) }; |
116 | // we can (and must) cast and fetch the internally stored factory | 116 | // we can (and must) cast and fetch the internally stored factory |
117 | return &proxy->m_factory; | 117 | return &proxy->m_factory; |
118 | } | 118 | } |
@@ -124,7 +124,7 @@ static void get_deep_lookup(lua_State* L_) | |||
124 | STACK_GROW( L_, 1); | 124 | STACK_GROW( L_, 1); |
125 | STACK_CHECK_START_REL(L_, 0); | 125 | STACK_CHECK_START_REL(L_, 0); |
126 | 126 | ||
127 | if (!lua_getmetatable( L_, index)) // deep ... metatable? | 127 | if (!lua_getmetatable( L_, index_)) // deep ... metatable? |
128 | { | 128 | { |
129 | return nullptr; // no metatable: can't be a deep userdata object! | 129 | return nullptr; // no metatable: can't be a deep userdata object! |
130 | } | 130 | } |
@@ -168,11 +168,11 @@ void DeepFactory::DeleteDeepObject(lua_State* L_, DeepPrelude* o_) | |||
168 | if (isLastRef) | 168 | if (isLastRef) |
169 | { | 169 | { |
170 | // retrieve wrapped __gc | 170 | // retrieve wrapped __gc |
171 | lua_pushvalue( L_, lua_upvalueindex( 1)); // self __gc? | 171 | lua_pushvalue(L_, lua_upvalueindex( 1)); // self __gc? |
172 | if (!lua_isnil( L_, -1)) | 172 | if (!lua_isnil(L_, -1)) |
173 | { | 173 | { |
174 | lua_insert( L_, -2); // __gc self | 174 | lua_insert(L_, -2); // __gc self |
175 | lua_call( L_, 1, 0); // | 175 | lua_call(L_, 1, 0); // |
176 | } | 176 | } |
177 | else | 177 | else |
178 | { | 178 | { |
@@ -195,138 +195,138 @@ void DeepFactory::DeleteDeepObject(lua_State* L_, DeepPrelude* o_) | |||
195 | * used in this Lua state (metatable, registring it). Otherwise, increments the | 195 | * used in this Lua state (metatable, registring it). Otherwise, increments the |
196 | * reference count. | 196 | * reference count. |
197 | */ | 197 | */ |
198 | char const* DeepFactory::PushDeepProxy(DestState L, DeepPrelude* prelude, int nuv_, LookupMode mode_) | 198 | char const* DeepFactory::PushDeepProxy(DestState L_, DeepPrelude* prelude_, int nuv_, LookupMode mode_) |
199 | { | 199 | { |
200 | // Check if a proxy already exists | 200 | // Check if a proxy already exists |
201 | push_registry_subtable_mode(L, kDeepProxyCacheRegKey, "v"); // DPC | 201 | push_registry_subtable_mode(L_, kDeepProxyCacheRegKey, "v"); // DPC |
202 | lua_pushlightuserdata(L, prelude); // DPC deep | 202 | lua_pushlightuserdata(L_, prelude_); // DPC deep |
203 | lua_rawget(L, -2); // DPC proxy | 203 | lua_rawget(L_, -2); // DPC proxy |
204 | if (!lua_isnil(L, -1)) | 204 | if (!lua_isnil(L_, -1)) |
205 | { | 205 | { |
206 | lua_remove(L, -2); // proxy | 206 | lua_remove(L_, -2); // proxy |
207 | return nullptr; | 207 | return nullptr; |
208 | } | 208 | } |
209 | else | 209 | else |
210 | { | 210 | { |
211 | lua_pop(L, 1); // DPC | 211 | lua_pop(L_, 1); // DPC |
212 | } | 212 | } |
213 | 213 | ||
214 | STACK_GROW(L, 7); | 214 | STACK_GROW(L_, 7); |
215 | STACK_CHECK_START_REL(L, 0); | 215 | STACK_CHECK_START_REL(L_, 0); |
216 | 216 | ||
217 | // a new full userdata, fitted with the specified number of uservalue slots (always 1 for Lua < 5.4) | 217 | // a new full userdata, fitted with the specified number of uservalue slots (always 1 for Lua < 5.4) |
218 | DeepPrelude** const proxy{ lua_newuserdatauv<DeepPrelude*>(L, nuv_) }; // DPC proxy | 218 | DeepPrelude** const proxy{ lua_newuserdatauv<DeepPrelude*>(L_, nuv_) }; // DPC proxy |
219 | LUA_ASSERT(L, proxy); | 219 | LUA_ASSERT(L_, proxy); |
220 | *proxy = prelude; | 220 | *proxy = prelude_; |
221 | prelude->m_refcount.fetch_add(1, std::memory_order_relaxed); // one more proxy pointing to this deep data | 221 | prelude_->m_refcount.fetch_add(1, std::memory_order_relaxed); // one more proxy pointing to this deep data |
222 | 222 | ||
223 | // Get/create metatable for 'factory' (in this state) | 223 | // Get/create metatable for 'factory' (in this state) |
224 | DeepFactory& factory = prelude->m_factory; | 224 | DeepFactory& factory = prelude_->m_factory; |
225 | lua_pushlightuserdata( L, std::bit_cast<void*>(&factory)); // DPC proxy factory | 225 | lua_pushlightuserdata(L_, std::bit_cast<void*>(&factory)); // DPC proxy factory |
226 | get_deep_lookup( L); // DPC proxy metatable? | 226 | get_deep_lookup(L_); // DPC proxy metatable? |
227 | 227 | ||
228 | if (lua_isnil( L, -1)) // // No metatable yet. | 228 | if (lua_isnil(L_, -1)) // // No metatable yet. |
229 | { | 229 | { |
230 | lua_pop(L, 1); // DPC proxy | 230 | lua_pop(L_, 1); // DPC proxy |
231 | int const oldtop{ lua_gettop(L) }; | 231 | int const oldtop{ lua_gettop(L_) }; |
232 | // 1 - make one and register it | 232 | // 1 - make one and register it |
233 | if (mode_ != LookupMode::ToKeeper) | 233 | if (mode_ != LookupMode::ToKeeper) |
234 | { | 234 | { |
235 | factory.createMetatable(L); // DPC proxy metatable | 235 | factory.createMetatable(L_); // DPC proxy metatable |
236 | if (lua_gettop(L) - oldtop != 1 || !lua_istable(L, -1)) | 236 | if (lua_gettop(L_) - oldtop != 1 || !lua_istable(L_, -1)) |
237 | { | 237 | { |
238 | // factory didn't push exactly 1 value, or the value it pushed is not a table: ERROR! | 238 | // factory didn't push exactly 1 value, or the value it pushed is not a table: ERROR! |
239 | lua_settop( L, oldtop); // DPC proxy X | 239 | lua_settop(L_, oldtop); // DPC proxy X |
240 | lua_pop( L, 3); // | 240 | lua_pop(L_, 3); // |
241 | return "Bad DeepFactory::createMetatable overload: unexpected pushed value"; | 241 | return "Bad DeepFactory::createMetatable overload: unexpected pushed value"; |
242 | } | 242 | } |
243 | // if the metatable contains a __gc, we will call it from our own | 243 | // if the metatable contains a __gc, we will call it from our own |
244 | lua_getfield( L, -1, "__gc"); // DPC proxy metatable __gc | 244 | lua_getfield(L_, -1, "__gc"); // DPC proxy metatable __gc |
245 | } | 245 | } |
246 | else | 246 | else |
247 | { | 247 | { |
248 | // keepers need a minimal metatable that only contains our own __gc | 248 | // keepers need a minimal metatable that only contains our own __gc |
249 | lua_newtable( L); // DPC proxy metatable | 249 | lua_newtable(L_); // DPC proxy metatable |
250 | lua_pushnil( L); // DPC proxy metatable nil | 250 | lua_pushnil(L_); // DPC proxy metatable nil |
251 | } | 251 | } |
252 | if (lua_isnil( L, -1)) | 252 | if (lua_isnil(L_, -1)) |
253 | { | 253 | { |
254 | // Add our own '__gc' method | 254 | // Add our own '__gc' method |
255 | lua_pop( L, 1); // DPC proxy metatable | 255 | lua_pop(L_, 1); // DPC proxy metatable |
256 | lua_pushcfunction( L, deep_userdata_gc); // DPC proxy metatable deep_userdata_gc | 256 | lua_pushcfunction(L_, deep_userdata_gc); // DPC proxy metatable deep_userdata_gc |
257 | } | 257 | } |
258 | else | 258 | else |
259 | { | 259 | { |
260 | // Add our own '__gc' method wrapping the original | 260 | // Add our own '__gc' method wrapping the original |
261 | lua_pushcclosure( L, deep_userdata_gc, 1); // DPC proxy metatable deep_userdata_gc | 261 | lua_pushcclosure(L_, deep_userdata_gc, 1); // DPC proxy metatable deep_userdata_gc |
262 | } | 262 | } |
263 | lua_setfield( L, -2, "__gc"); // DPC proxy metatable | 263 | lua_setfield(L_, -2, "__gc"); // DPC proxy metatable |
264 | 264 | ||
265 | // Memorize for later rounds | 265 | // Memorize for later rounds |
266 | lua_pushvalue( L, -1); // DPC proxy metatable metatable | 266 | lua_pushvalue(L_, -1); // DPC proxy metatable metatable |
267 | lua_pushlightuserdata(L, std::bit_cast<void*>(&factory)); // DPC proxy metatable metatable factory | 267 | lua_pushlightuserdata(L_, std::bit_cast<void*>(&factory)); // DPC proxy metatable metatable factory |
268 | set_deep_lookup( L); // DPC proxy metatable | 268 | set_deep_lookup(L_); // DPC proxy metatable |
269 | 269 | ||
270 | // 2 - cause the target state to require the module that exported the factory | 270 | // 2 - cause the target state to require the module that exported the factory |
271 | if (char const* const modname{ factory.moduleName() }; modname) // we actually got a module name | 271 | if (char const* const modname{ factory.moduleName() }; modname) // we actually got a module name |
272 | { | 272 | { |
273 | // L.registry._LOADED exists without having registered the 'package' library. | 273 | // L.registry._LOADED exists without having registered the 'package' library. |
274 | lua_getglobal( L, "require"); // DPC proxy metatable require() | 274 | lua_getglobal(L_, "require"); // DPC proxy metatable require() |
275 | // check that the module is already loaded (or being loaded, we are happy either way) | 275 | // check that the module is already loaded (or being loaded, we are happy either way) |
276 | if (lua_isfunction( L, -1)) | 276 | if (lua_isfunction(L_, -1)) |
277 | { | 277 | { |
278 | lua_pushstring( L, modname); // DPC proxy metatable require() "module" | 278 | lua_pushstring(L_, modname); // DPC proxy metatable require() "module" |
279 | lua_getfield( L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); // DPC proxy metatable require() "module" _R._LOADED | 279 | lua_getfield(L_, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); // DPC proxy metatable require() "module" _R._LOADED |
280 | if (lua_istable( L, -1)) | 280 | if (lua_istable(L_, -1)) |
281 | { | 281 | { |
282 | lua_pushvalue( L, -2); // DPC proxy metatable require() "module" _R._LOADED "module" | 282 | lua_pushvalue(L_, -2); // DPC proxy metatable require() "module" _R._LOADED "module" |
283 | lua_rawget( L, -2); // DPC proxy metatable require() "module" _R._LOADED module | 283 | lua_rawget(L_, -2); // DPC proxy metatable require() "module" _R._LOADED module |
284 | int const alreadyloaded = lua_toboolean( L, -1); | 284 | int const alreadyloaded = lua_toboolean(L_, -1); |
285 | if (!alreadyloaded) // not loaded | 285 | if (!alreadyloaded) // not loaded |
286 | { | 286 | { |
287 | int require_result; | 287 | int require_result; |
288 | lua_pop( L, 2); // DPC proxy metatable require() "module" | 288 | lua_pop(L_, 2); // DPC proxy metatable require() "module" |
289 | // require "modname" | 289 | // require "modname" |
290 | require_result = lua_pcall( L, 1, 0, 0); // DPC proxy metatable error? | 290 | require_result = lua_pcall(L_, 1, 0, 0); // DPC proxy metatable error? |
291 | if (require_result != LUA_OK) | 291 | if (require_result != LUA_OK) |
292 | { | 292 | { |
293 | // failed, return the error message | 293 | // failed, return the error message |
294 | lua_pushfstring( L, "error while requiring '%s' identified by DeepFactory::moduleName: ", modname); | 294 | lua_pushfstring(L_, "error while requiring '%s' identified by DeepFactory::moduleName: ", modname); |
295 | lua_insert( L, -2); // DPC proxy metatable prefix error | 295 | lua_insert(L_, -2); // DPC proxy metatable prefix error |
296 | lua_concat( L, 2); // DPC proxy metatable error | 296 | lua_concat(L_, 2); // DPC proxy metatable error |
297 | return lua_tostring( L, -1); | 297 | return lua_tostring(L_, -1); |
298 | } | 298 | } |
299 | } | 299 | } |
300 | else // already loaded, we are happy | 300 | else // already loaded, we are happy |
301 | { | 301 | { |
302 | lua_pop( L, 4); // DPC proxy metatable | 302 | lua_pop(L_, 4); // DPC proxy metatable |
303 | } | 303 | } |
304 | } | 304 | } |
305 | else // no L.registry._LOADED; can this ever happen? | 305 | else // no L.registry._LOADED; can this ever happen? |
306 | { | 306 | { |
307 | lua_pop( L, 6); // | 307 | lua_pop(L_, 6); // |
308 | return "unexpected error while requiring a module identified by DeepFactory::moduleName"; | 308 | return "unexpected error while requiring a module identified by DeepFactory::moduleName"; |
309 | } | 309 | } |
310 | } | 310 | } |
311 | else // a module name, but no require() function :-( | 311 | else // a module name, but no require() function :-( |
312 | { | 312 | { |
313 | lua_pop( L, 4); // | 313 | lua_pop(L_, 4); // |
314 | return "lanes receiving deep userdata should register the 'package' library"; | 314 | return "lanes receiving deep userdata should register the 'package' library"; |
315 | } | 315 | } |
316 | } | 316 | } |
317 | } | 317 | } |
318 | STACK_CHECK(L, 2); // DPC proxy metatable | 318 | STACK_CHECK(L_, 2); // DPC proxy metatable |
319 | LUA_ASSERT(L, lua_type_as_enum(L, -2) == LuaType::USERDATA); | 319 | LUA_ASSERT(L_, lua_type_as_enum(L_, -2) == LuaType::USERDATA); |
320 | LUA_ASSERT(L, lua_istable( L, -1)); | 320 | LUA_ASSERT(L_, lua_istable(L_, -1)); |
321 | lua_setmetatable( L, -2); // DPC proxy | 321 | lua_setmetatable(L_, -2); // DPC proxy |
322 | 322 | ||
323 | // If we're here, we obviously had to create a new proxy, so cache it. | 323 | // If we're here, we obviously had to create a new proxy, so cache it. |
324 | lua_pushlightuserdata( L, prelude); // DPC proxy deep | 324 | lua_pushlightuserdata(L_, prelude_); // DPC proxy deep |
325 | lua_pushvalue( L, -2); // DPC proxy deep proxy | 325 | lua_pushvalue(L_, -2); // DPC proxy deep proxy |
326 | lua_rawset( L, -4); // DPC proxy | 326 | lua_rawset(L_, -4); // DPC proxy |
327 | lua_remove( L, -2); // proxy | 327 | lua_remove(L_, -2); // proxy |
328 | LUA_ASSERT(L, lua_type_as_enum(L, -1) == LuaType::USERDATA); | 328 | LUA_ASSERT(L_, lua_type_as_enum(L_, -1) == LuaType::USERDATA); |
329 | STACK_CHECK(L, 0); | 329 | STACK_CHECK(L_, 0); |
330 | return nullptr; | 330 | return nullptr; |
331 | } | 331 | } |
332 | 332 | ||
@@ -347,40 +347,40 @@ char const* DeepFactory::PushDeepProxy(DestState L, DeepPrelude* prelude, int nu | |||
347 | * | 347 | * |
348 | * Returns: 'proxy' userdata for accessing the deep data via 'DeepFactory::toDeep()' | 348 | * Returns: 'proxy' userdata for accessing the deep data via 'DeepFactory::toDeep()' |
349 | */ | 349 | */ |
350 | int DeepFactory::pushDeepUserdata(DestState L, int nuv_) const | 350 | int DeepFactory::pushDeepUserdata(DestState L_, int nuv_) const |
351 | { | 351 | { |
352 | STACK_GROW( L, 1); | 352 | STACK_GROW(L_, 1); |
353 | STACK_CHECK_START_REL(L, 0); | 353 | STACK_CHECK_START_REL(L_, 0); |
354 | int const oldtop{ lua_gettop(L) }; | 354 | int const oldtop{ lua_gettop(L_) }; |
355 | DeepPrelude* const prelude{ newDeepObjectInternal(L) }; | 355 | DeepPrelude* const prelude{ newDeepObjectInternal(L_) }; |
356 | if (prelude == nullptr) | 356 | if (prelude == nullptr) |
357 | { | 357 | { |
358 | raise_luaL_error(L, "DeepFactory::newDeepObjectInternal failed to create deep userdata (out of memory)"); | 358 | raise_luaL_error(L_, "DeepFactory::newDeepObjectInternal failed to create deep userdata (out of memory)"); |
359 | } | 359 | } |
360 | 360 | ||
361 | if (prelude->m_magic != kDeepVersion) | 361 | if (prelude->m_magic != kDeepVersion) |
362 | { | 362 | { |
363 | // just in case, don't leak the newly allocated deep userdata object | 363 | // just in case, don't leak the newly allocated deep userdata object |
364 | deleteDeepObjectInternal(L, prelude); | 364 | deleteDeepObjectInternal(L_, prelude); |
365 | raise_luaL_error(L, "Bad Deep Factory: kDeepVersion is incorrect, rebuild your implementation with the latest deep implementation"); | 365 | raise_luaL_error(L_, "Bad Deep Factory: kDeepVersion is incorrect, rebuild your implementation with the latest deep implementation"); |
366 | } | 366 | } |
367 | 367 | ||
368 | LUA_ASSERT(L, prelude->m_refcount.load(std::memory_order_relaxed) == 0); // 'DeepFactory::PushDeepProxy' will lift it to 1 | 368 | LUA_ASSERT(L_, prelude->m_refcount.load(std::memory_order_relaxed) == 0); // 'DeepFactory::PushDeepProxy' will lift it to 1 |
369 | LUA_ASSERT(L, &prelude->m_factory == this); | 369 | LUA_ASSERT(L_, &prelude->m_factory == this); |
370 | 370 | ||
371 | if (lua_gettop( L) - oldtop != 0) | 371 | if (lua_gettop(L_) - oldtop != 0) |
372 | { | 372 | { |
373 | // just in case, don't leak the newly allocated deep userdata object | 373 | // just in case, don't leak the newly allocated deep userdata object |
374 | deleteDeepObjectInternal(L, prelude); | 374 | deleteDeepObjectInternal(L_, prelude); |
375 | raise_luaL_error(L, "Bad DeepFactory::newDeepObjectInternal overload: should not push anything on the stack"); | 375 | raise_luaL_error(L_, "Bad DeepFactory::newDeepObjectInternal overload: should not push anything on the stack"); |
376 | } | 376 | } |
377 | 377 | ||
378 | char const* const errmsg{ DeepFactory::PushDeepProxy(L, prelude, nuv_, LookupMode::LaneBody) }; // proxy | 378 | char const* const errmsg{ DeepFactory::PushDeepProxy(L_, prelude, nuv_, LookupMode::LaneBody) }; // proxy |
379 | if (errmsg != nullptr) | 379 | if (errmsg != nullptr) |
380 | { | 380 | { |
381 | raise_luaL_error(L, errmsg); | 381 | raise_luaL_error(L_, errmsg); |
382 | } | 382 | } |
383 | STACK_CHECK( L, 1); | 383 | STACK_CHECK(L_, 1); |
384 | return 1; | 384 | return 1; |
385 | } | 385 | } |
386 | 386 | ||
@@ -392,24 +392,24 @@ int DeepFactory::pushDeepUserdata(DestState L, int nuv_) const | |||
392 | * Reference count is not changed, and access to the deep userdata is not | 392 | * Reference count is not changed, and access to the deep userdata is not |
393 | * serialized. It is the module's responsibility to prevent conflicting usage. | 393 | * serialized. It is the module's responsibility to prevent conflicting usage. |
394 | */ | 394 | */ |
395 | DeepPrelude* DeepFactory::toDeep(lua_State* L_, int index) const | 395 | DeepPrelude* DeepFactory::toDeep(lua_State* L_, int index_) const |
396 | { | 396 | { |
397 | STACK_CHECK_START_REL(L_, 0); | 397 | STACK_CHECK_START_REL(L_, 0); |
398 | // ensure it is actually a deep userdata we created | 398 | // ensure it is actually a deep userdata we created |
399 | if (get_factory(L_, index, LookupMode::LaneBody) != this) | 399 | if (get_factory(L_, index_, LookupMode::LaneBody) != this) |
400 | { | 400 | { |
401 | return nullptr; // no metatable, or wrong kind | 401 | return nullptr; // no metatable, or wrong kind |
402 | } | 402 | } |
403 | STACK_CHECK(L_, 0); | 403 | STACK_CHECK(L_, 0); |
404 | 404 | ||
405 | DeepPrelude** const proxy{ lua_tofulluserdata<DeepPrelude*>(L_, index) }; | 405 | DeepPrelude** const proxy{ lua_tofulluserdata<DeepPrelude*>(L_, index_) }; |
406 | return *proxy; | 406 | return *proxy; |
407 | } | 407 | } |
408 | 408 | ||
409 | // ################################################################################################# | 409 | // ################################################################################################# |
410 | 410 | ||
411 | /* | 411 | /* |
412 | * Copy deep userdata between two separate Lua states (from L to L2) | 412 | * Copy deep userdata between two separate Lua states (from L1 to L2) |
413 | * | 413 | * |
414 | * Returns: | 414 | * Returns: |
415 | * the id function of the copied value, or nullptr for non-deep userdata | 415 | * the id function of the copied value, or nullptr for non-deep userdata |