diff options
Diffstat (limited to 'src/deep.cpp')
-rw-r--r-- | src/deep.cpp | 53 |
1 files changed, 30 insertions, 23 deletions
diff --git a/src/deep.cpp b/src/deep.cpp index ac2905e..d0b8123 100644 --- a/src/deep.cpp +++ b/src/deep.cpp | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * DEEP.C Copyright (c) 2017, Benoit Germain | 2 | * DEEP.CPP Copyright (c) 2024, Benoit Germain |
3 | * | 3 | * |
4 | * Deep userdata support, separate in its own source file to help integration | 4 | * Deep userdata support, separate in its own source file to help integration |
5 | * without enforcing a Lanes dependency | 5 | * without enforcing a Lanes dependency |
@@ -9,7 +9,7 @@ | |||
9 | =============================================================================== | 9 | =============================================================================== |
10 | 10 | ||
11 | Copyright (C) 2002-10 Asko Kauppi <akauppi@gmail.com> | 11 | Copyright (C) 2002-10 Asko Kauppi <akauppi@gmail.com> |
12 | 2011-17 Benoit Germain <bnt.germain@gmail.com> | 12 | 2011-24 Benoit Germain <bnt.germain@gmail.com> |
13 | 13 | ||
14 | Permission is hereby granted, free of charge, to any person obtaining a copy | 14 | Permission is hereby granted, free of charge, to any person obtaining a copy |
15 | of this software and associated documentation files (the "Software"), to deal | 15 | of this software and associated documentation files (the "Software"), to deal |
@@ -41,13 +41,6 @@ THE SOFTWARE. | |||
41 | 41 | ||
42 | #include <bit> | 42 | #include <bit> |
43 | #include <cassert> | 43 | #include <cassert> |
44 | #include <ctype.h> | ||
45 | #include <stdio.h> | ||
46 | #include <string.h> | ||
47 | #include <stdlib.h> | ||
48 | #if !defined(__APPLE__) | ||
49 | #include <malloc.h> | ||
50 | #endif | ||
51 | 44 | ||
52 | /*-- Metatable copying --*/ | 45 | /*-- Metatable copying --*/ |
53 | 46 | ||
@@ -73,7 +66,7 @@ static constexpr UniqueKey DEEP_PROXY_CACHE_KEY{ 0x05773d6fc26be106ull }; | |||
73 | * 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. |
74 | * Pops the both values off the stack. | 67 | * Pops the both values off the stack. |
75 | */ | 68 | */ |
76 | static void set_deep_lookup( lua_State* L) | 69 | static void set_deep_lookup(lua_State* L) |
77 | { | 70 | { |
78 | STACK_GROW( L, 3); | 71 | STACK_GROW( L, 3); |
79 | STACK_CHECK_START_REL(L, 2); // a b | 72 | STACK_CHECK_START_REL(L, 2); // a b |
@@ -88,11 +81,13 @@ static void set_deep_lookup( lua_State* L) | |||
88 | STACK_CHECK( L, 0); | 81 | STACK_CHECK( L, 0); |
89 | } | 82 | } |
90 | 83 | ||
84 | // ################################################################################################ | ||
85 | |||
91 | /* | 86 | /* |
92 | * Pops the key (metatable or idfunc) off the stack, and replaces with the | 87 | * Pops the key (metatable or idfunc) off the stack, and replaces with the |
93 | * deep lookup value (idfunc/metatable/nil). | 88 | * deep lookup value (idfunc/metatable/nil). |
94 | */ | 89 | */ |
95 | static void get_deep_lookup( lua_State* L) | 90 | static void get_deep_lookup(lua_State* L) |
96 | { | 91 | { |
97 | STACK_GROW( L, 1); | 92 | STACK_GROW( L, 1); |
98 | STACK_CHECK_START_REL(L, 1); // a | 93 | STACK_CHECK_START_REL(L, 1); // a |
@@ -106,11 +101,13 @@ static void get_deep_lookup( lua_State* L) | |||
106 | STACK_CHECK( L, 1); | 101 | STACK_CHECK( L, 1); |
107 | } | 102 | } |
108 | 103 | ||
104 | // ################################################################################################ | ||
105 | |||
109 | /* | 106 | /* |
110 | * Return the registered ID function for 'index' (deep userdata proxy), | 107 | * Return the registered ID function for 'index' (deep userdata proxy), |
111 | * or nullptr if 'index' is not a deep userdata proxy. | 108 | * or nullptr if 'index' is not a deep userdata proxy. |
112 | */ | 109 | */ |
113 | static inline luaG_IdFunction get_idfunc( lua_State* L, int index, LookupMode mode_) | 110 | [[nodiscard]] static inline luaG_IdFunction get_idfunc(lua_State* L, int index, LookupMode mode_) |
114 | { | 111 | { |
115 | // 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 |
116 | if (mode_ == LookupMode::FromKeeper) | 113 | if (mode_ == LookupMode::FromKeeper) |
@@ -142,8 +139,9 @@ static inline luaG_IdFunction get_idfunc( lua_State* L, int index, LookupMode mo | |||
142 | } | 139 | } |
143 | } | 140 | } |
144 | 141 | ||
142 | // ################################################################################################ | ||
145 | 143 | ||
146 | void free_deep_prelude( lua_State* L, DeepPrelude* prelude_) | 144 | void free_deep_prelude(lua_State* L, DeepPrelude* prelude_) |
147 | { | 145 | { |
148 | ASSERT_L(prelude_->idfunc); | 146 | ASSERT_L(prelude_->idfunc); |
149 | STACK_CHECK_START_REL(L, 0); | 147 | STACK_CHECK_START_REL(L, 0); |
@@ -154,6 +152,7 @@ void free_deep_prelude( lua_State* L, DeepPrelude* prelude_) | |||
154 | STACK_CHECK(L, 0); | 152 | STACK_CHECK(L, 0); |
155 | } | 153 | } |
156 | 154 | ||
155 | // ################################################################################################ | ||
157 | 156 | ||
158 | /* | 157 | /* |
159 | * void= mt.__gc( proxy_ud ) | 158 | * void= mt.__gc( proxy_ud ) |
@@ -161,7 +160,7 @@ void free_deep_prelude( lua_State* L, DeepPrelude* prelude_) | |||
161 | * End of life for a proxy object; reduce the deep reference count and clean it up if reaches 0. | 160 | * End of life for a proxy object; reduce the deep reference count and clean it up if reaches 0. |
162 | * | 161 | * |
163 | */ | 162 | */ |
164 | static int deep_userdata_gc( lua_State* L) | 163 | [[nodiscard]] static int deep_userdata_gc(lua_State* L) |
165 | { | 164 | { |
166 | DeepPrelude** const proxy{ lua_tofulluserdata<DeepPrelude*>(L, 1) }; | 165 | DeepPrelude** const proxy{ lua_tofulluserdata<DeepPrelude*>(L, 1) }; |
167 | DeepPrelude* p = *proxy; | 166 | DeepPrelude* p = *proxy; |
@@ -193,6 +192,7 @@ static int deep_userdata_gc( lua_State* L) | |||
193 | return 0; | 192 | return 0; |
194 | } | 193 | } |
195 | 194 | ||
195 | // ################################################################################################ | ||
196 | 196 | ||
197 | /* | 197 | /* |
198 | * Push a proxy userdata on the stack. | 198 | * Push a proxy userdata on the stack. |
@@ -203,7 +203,7 @@ static int deep_userdata_gc( lua_State* L) | |||
203 | * used in this Lua state (metatable, registring it). Otherwise, increments the | 203 | * used in this Lua state (metatable, registring it). Otherwise, increments the |
204 | * reference count. | 204 | * reference count. |
205 | */ | 205 | */ |
206 | char const* push_deep_proxy(lua_State* L, DeepPrelude* prelude, int nuv_, LookupMode mode_) | 206 | char const* push_deep_proxy(Dest L, DeepPrelude* prelude, int nuv_, LookupMode mode_) |
207 | { | 207 | { |
208 | // Check if a proxy already exists | 208 | // Check if a proxy already exists |
209 | push_registry_subtable_mode( L, DEEP_PROXY_CACHE_KEY, "v"); // DPC | 209 | push_registry_subtable_mode( L, DEEP_PROXY_CACHE_KEY, "v"); // DPC |
@@ -278,7 +278,7 @@ char const* push_deep_proxy(lua_State* L, DeepPrelude* prelude, int nuv_, Lookup | |||
278 | // this is needed because we must make sure the shared library is still loaded as long as we hold a pointer on the idfunc | 278 | // this is needed because we must make sure the shared library is still loaded as long as we hold a pointer on the idfunc |
279 | { | 279 | { |
280 | int oldtop_module = lua_gettop( L); | 280 | int oldtop_module = lua_gettop( L); |
281 | modname = (char const*) prelude->idfunc( L, DeepOp::Module); // DPC proxy metatable | 281 | modname = (char const*) prelude->idfunc( L, DeepOp::Module); // DPC proxy metatable |
282 | // make sure the function pushed nothing on the stack! | 282 | // make sure the function pushed nothing on the stack! |
283 | if( lua_gettop( L) - oldtop_module != 0) | 283 | if( lua_gettop( L) - oldtop_module != 0) |
284 | { | 284 | { |
@@ -348,6 +348,8 @@ char const* push_deep_proxy(lua_State* L, DeepPrelude* prelude, int nuv_, Lookup | |||
348 | return nullptr; | 348 | return nullptr; |
349 | } | 349 | } |
350 | 350 | ||
351 | // ################################################################################################ | ||
352 | |||
351 | /* | 353 | /* |
352 | * Create a deep userdata | 354 | * Create a deep userdata |
353 | * | 355 | * |
@@ -370,7 +372,7 @@ char const* push_deep_proxy(lua_State* L, DeepPrelude* prelude, int nuv_, Lookup | |||
370 | * | 372 | * |
371 | * Returns: 'proxy' userdata for accessing the deep data via 'luaG_todeep()' | 373 | * Returns: 'proxy' userdata for accessing the deep data via 'luaG_todeep()' |
372 | */ | 374 | */ |
373 | int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction idfunc, int nuv_) | 375 | int luaG_newdeepuserdata(Dest L, luaG_IdFunction idfunc, int nuv_) |
374 | { | 376 | { |
375 | STACK_GROW( L, 1); | 377 | STACK_GROW( L, 1); |
376 | STACK_CHECK_START_REL(L, 0); | 378 | STACK_CHECK_START_REL(L, 0); |
@@ -409,6 +411,7 @@ int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction idfunc, int nuv_) | |||
409 | return 1; | 411 | return 1; |
410 | } | 412 | } |
411 | 413 | ||
414 | // ################################################################################################ | ||
412 | 415 | ||
413 | /* | 416 | /* |
414 | * Access deep userdata through a proxy. | 417 | * Access deep userdata through a proxy. |
@@ -430,6 +433,7 @@ DeepPrelude* luaG_todeep(lua_State* L, luaG_IdFunction idfunc, int index) | |||
430 | return *proxy; | 433 | return *proxy; |
431 | } | 434 | } |
432 | 435 | ||
436 | // ################################################################################################ | ||
433 | 437 | ||
434 | /* | 438 | /* |
435 | * Copy deep userdata between two separate Lua states (from L to L2) | 439 | * Copy deep userdata between two separate Lua states (from L to L2) |
@@ -438,7 +442,7 @@ DeepPrelude* luaG_todeep(lua_State* L, luaG_IdFunction idfunc, int index) | |||
438 | * the id function of the copied value, or nullptr for non-deep userdata | 442 | * the id function of the copied value, or nullptr for non-deep userdata |
439 | * (not copied) | 443 | * (not copied) |
440 | */ | 444 | */ |
441 | bool copydeep(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int i, LookupMode mode_, char const* upName_) | 445 | bool copydeep(Universe* U, Dest L2, int L2_cache_i, Source L, int i, LookupMode mode_, char const* upName_) |
442 | { | 446 | { |
443 | luaG_IdFunction const idfunc { get_idfunc(L, i, mode_) }; | 447 | luaG_IdFunction const idfunc { get_idfunc(L, i, mode_) }; |
444 | if (idfunc == nullptr) | 448 | if (idfunc == nullptr) |
@@ -466,22 +470,25 @@ bool copydeep(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int i, L | |||
466 | int const clone_i = lua_gettop( L2); | 470 | int const clone_i = lua_gettop( L2); |
467 | while( nuv) | 471 | while( nuv) |
468 | { | 472 | { |
469 | inter_copy_one( U, L2, L2_cache_i, L, lua_absindex( L, -1), VT::NORMAL, mode_, upName_); // u uv | 473 | if (!inter_copy_one(U, L2, L2_cache_i, L, lua_absindex(L, -1), VT::NORMAL, mode_, upName_)) // u uv |
474 | { | ||
475 | return luaL_error(L, "Cannot copy upvalue type '%s'", luaL_typename(L, -1)); | ||
476 | } | ||
470 | lua_pop( L, 1); // ... u [uv]* | 477 | lua_pop( L, 1); // ... u [uv]* |
471 | // this pops the value from the stack | 478 | // this pops the value from the stack |
472 | lua_setiuservalue( L2, clone_i, nuv); // u | 479 | lua_setiuservalue(L2, clone_i, nuv); // u |
473 | -- nuv; | 480 | -- nuv; |
474 | } | 481 | } |
475 | } | 482 | } |
476 | 483 | ||
477 | STACK_CHECK( L2, 1); | 484 | STACK_CHECK(L2, 1); |
478 | STACK_CHECK( L, 0); | 485 | STACK_CHECK(L, 0); |
479 | 486 | ||
480 | if (errmsg != nullptr) | 487 | if (errmsg != nullptr) |
481 | { | 488 | { |
482 | // raise the error in the proper state (not the keeper) | 489 | // raise the error in the proper state (not the keeper) |
483 | lua_State* const errL{ (mode_ == LookupMode::FromKeeper) ? L2 : L }; | 490 | lua_State* const errL{ (mode_ == LookupMode::FromKeeper) ? L2 : L }; |
484 | std::ignore = luaL_error(errL, errmsg); | 491 | luaL_error(errL, errmsg); // doesn't return |
485 | } | 492 | } |
486 | return true; | 493 | return true; |
487 | } \ No newline at end of file | 494 | } \ No newline at end of file |