diff options
Diffstat (limited to 'src/deep.c')
-rw-r--r-- | src/deep.c | 654 |
1 files changed, 327 insertions, 327 deletions
@@ -73,17 +73,17 @@ static DECLARE_CONST_UNIQUE_KEY( DEEP_PROXY_CACHE_KEY, 0x05773d6fc26be106); | |||
73 | */ | 73 | */ |
74 | static void set_deep_lookup( lua_State* L) | 74 | static void set_deep_lookup( lua_State* L) |
75 | { | 75 | { |
76 | STACK_GROW( L, 3); | 76 | STACK_GROW( L, 3); |
77 | STACK_CHECK( L, 2); // a b | 77 | STACK_CHECK( L, 2); // a b |
78 | push_registry_subtable( L, DEEP_LOOKUP_KEY); // a b {} | 78 | push_registry_subtable( L, DEEP_LOOKUP_KEY); // a b {} |
79 | STACK_MID( L, 3); | 79 | STACK_MID( L, 3); |
80 | lua_insert( L, -3); // {} a b | 80 | lua_insert( L, -3); // {} a b |
81 | lua_pushvalue( L, -1); // {} a b b | 81 | lua_pushvalue( L, -1); // {} a b b |
82 | lua_pushvalue( L,-3); // {} a b b a | 82 | lua_pushvalue( L,-3); // {} a b b a |
83 | lua_rawset( L, -5); // {} a b | 83 | lua_rawset( L, -5); // {} a b |
84 | lua_rawset( L, -3); // {} | 84 | lua_rawset( L, -3); // {} |
85 | lua_pop( L, 1); // | 85 | lua_pop( L, 1); // |
86 | STACK_END( L, 0); | 86 | STACK_END( L, 0); |
87 | } | 87 | } |
88 | 88 | ||
89 | /* | 89 | /* |
@@ -92,16 +92,16 @@ static void set_deep_lookup( lua_State* L) | |||
92 | */ | 92 | */ |
93 | static void get_deep_lookup( lua_State* L) | 93 | static void get_deep_lookup( lua_State* L) |
94 | { | 94 | { |
95 | STACK_GROW( L, 1); | 95 | STACK_GROW( L, 1); |
96 | STACK_CHECK( L, 1); // a | 96 | STACK_CHECK( L, 1); // a |
97 | REGISTRY_GET( L, DEEP_LOOKUP_KEY); // a {} | 97 | REGISTRY_GET( L, DEEP_LOOKUP_KEY); // a {} |
98 | if( !lua_isnil( L, -1)) | 98 | if( !lua_isnil( L, -1)) |
99 | { | 99 | { |
100 | lua_insert( L, -2); // {} a | 100 | lua_insert( L, -2); // {} a |
101 | lua_rawget( L, -2); // {} b | 101 | lua_rawget( L, -2); // {} b |
102 | } | 102 | } |
103 | lua_remove( L, -2); // a|b | 103 | lua_remove( L, -2); // a|b |
104 | STACK_END( L, 1); | 104 | STACK_END( L, 1); |
105 | } | 105 | } |
106 | 106 | ||
107 | /* | 107 | /* |
@@ -110,44 +110,44 @@ static void get_deep_lookup( lua_State* L) | |||
110 | */ | 110 | */ |
111 | static inline luaG_IdFunction get_idfunc( lua_State* L, int index, LookupMode mode_) | 111 | static inline luaG_IdFunction get_idfunc( lua_State* L, int index, LookupMode mode_) |
112 | { | 112 | { |
113 | // when looking inside a keeper, we are 100% sure the object is a deep userdata | 113 | // when looking inside a keeper, we are 100% sure the object is a deep userdata |
114 | if( mode_ == eLM_FromKeeper) | 114 | if( mode_ == eLM_FromKeeper) |
115 | { | 115 | { |
116 | DeepPrelude** proxy = (DeepPrelude**) lua_touserdata( L, index); | 116 | DeepPrelude** proxy = (DeepPrelude**) lua_touserdata( L, index); |
117 | // we can (and must) cast and fetch the internally stored idfunc | 117 | // we can (and must) cast and fetch the internally stored idfunc |
118 | return (*proxy)->idfunc; | 118 | return (*proxy)->idfunc; |
119 | } | 119 | } |
120 | else | 120 | else |
121 | { | 121 | { |
122 | // essentially we are making sure that the metatable of the object we want to copy is stored in our metatable/idfunc database | 122 | // essentially we are making sure that the metatable of the object we want to copy is stored in our metatable/idfunc database |
123 | // it is the only way to ensure that the userdata is indeed a deep userdata! | 123 | // it is the only way to ensure that the userdata is indeed a deep userdata! |
124 | // of course, we could just trust the caller, but we won't | 124 | // of course, we could just trust the caller, but we won't |
125 | luaG_IdFunction ret; | 125 | luaG_IdFunction ret; |
126 | STACK_GROW( L, 1); | 126 | STACK_GROW( L, 1); |
127 | STACK_CHECK( L, 0); | 127 | STACK_CHECK( L, 0); |
128 | 128 | ||
129 | if( !lua_getmetatable( L, index)) // deep ... metatable? | 129 | if( !lua_getmetatable( L, index)) // deep ... metatable? |
130 | { | 130 | { |
131 | return NULL; // no metatable: can't be a deep userdata object! | 131 | return NULL; // no metatable: can't be a deep userdata object! |
132 | } | 132 | } |
133 | 133 | ||
134 | // replace metatable with the idfunc pointer, if it is actually a deep userdata | 134 | // replace metatable with the idfunc pointer, if it is actually a deep userdata |
135 | get_deep_lookup( L); // deep ... idfunc|nil | 135 | get_deep_lookup( L); // deep ... idfunc|nil |
136 | 136 | ||
137 | ret = (luaG_IdFunction) lua_touserdata( L, -1); // NULL if not a userdata | 137 | ret = (luaG_IdFunction) lua_touserdata( L, -1); // NULL if not a userdata |
138 | lua_pop( L, 1); | 138 | lua_pop( L, 1); |
139 | STACK_END( L, 0); | 139 | STACK_END( L, 0); |
140 | return ret; | 140 | return ret; |
141 | } | 141 | } |
142 | } | 142 | } |
143 | 143 | ||
144 | 144 | ||
145 | void free_deep_prelude( lua_State* L, DeepPrelude* prelude_) | 145 | void free_deep_prelude( lua_State* L, DeepPrelude* prelude_) |
146 | { | 146 | { |
147 | // Call 'idfunc( "delete", deep_ptr )' to make deep cleanup | 147 | // Call 'idfunc( "delete", deep_ptr )' to make deep cleanup |
148 | lua_pushlightuserdata( L, prelude_); | 148 | lua_pushlightuserdata( L, prelude_); |
149 | ASSERT_L( prelude_->idfunc); | 149 | ASSERT_L( prelude_->idfunc); |
150 | prelude_->idfunc( L, eDO_delete); | 150 | prelude_->idfunc( L, eDO_delete); |
151 | } | 151 | } |
152 | 152 | ||
153 | 153 | ||
@@ -159,38 +159,38 @@ void free_deep_prelude( lua_State* L, DeepPrelude* prelude_) | |||
159 | */ | 159 | */ |
160 | static int deep_userdata_gc( lua_State* L) | 160 | static int deep_userdata_gc( lua_State* L) |
161 | { | 161 | { |
162 | DeepPrelude** proxy = (DeepPrelude**) lua_touserdata( L, 1); | 162 | DeepPrelude** proxy = (DeepPrelude**) lua_touserdata( L, 1); |
163 | DeepPrelude* p = *proxy; | 163 | DeepPrelude* p = *proxy; |
164 | Universe* U = universe_get( L); | 164 | Universe* U = universe_get( L); |
165 | int v; | 165 | int v; |
166 | 166 | ||
167 | // can work without a universe if creating a deep userdata from some external C module when Lanes isn't loaded | 167 | // can work without a universe if creating a deep userdata from some external C module when Lanes isn't loaded |
168 | // in that case, we are not multithreaded and locking isn't necessary anyway | 168 | // in that case, we are not multithreaded and locking isn't necessary anyway |
169 | if( U) MUTEX_LOCK( &U->deep_lock); | 169 | if( U) MUTEX_LOCK( &U->deep_lock); |
170 | v = -- (p->refcount); | 170 | v = -- (p->refcount); |
171 | if (U) MUTEX_UNLOCK( &U->deep_lock); | 171 | if (U) MUTEX_UNLOCK( &U->deep_lock); |
172 | 172 | ||
173 | if( v == 0) | 173 | if( v == 0) |
174 | { | 174 | { |
175 | // retrieve wrapped __gc | 175 | // retrieve wrapped __gc |
176 | lua_pushvalue( L, lua_upvalueindex( 1)); // self __gc? | 176 | lua_pushvalue( L, lua_upvalueindex( 1)); // self __gc? |
177 | if( !lua_isnil( L, -1)) | 177 | if( !lua_isnil( L, -1)) |
178 | { | 178 | { |
179 | lua_insert( L, -2); // __gc self | 179 | lua_insert( L, -2); // __gc self |
180 | lua_call( L, 1, 0); // | 180 | lua_call( L, 1, 0); // |
181 | } | 181 | } |
182 | // 'idfunc' expects a clean stack to work on | 182 | // 'idfunc' expects a clean stack to work on |
183 | lua_settop( L, 0); | 183 | lua_settop( L, 0); |
184 | free_deep_prelude( L, p); | 184 | free_deep_prelude( L, p); |
185 | 185 | ||
186 | // top was set to 0, then userdata was pushed. "delete" might want to pop the userdata (we don't care), but should not push anything! | 186 | // top was set to 0, then userdata was pushed. "delete" might want to pop the userdata (we don't care), but should not push anything! |
187 | if ( lua_gettop( L) > 1) | 187 | if ( lua_gettop( L) > 1) |
188 | { | 188 | { |
189 | luaL_error( L, "Bad idfunc(eDO_delete): should not push anything"); | 189 | luaL_error( L, "Bad idfunc(eDO_delete): should not push anything"); |
190 | } | 190 | } |
191 | } | 191 | } |
192 | *proxy = NULL; // make sure we don't use it any more, just in case | 192 | *proxy = NULL; // make sure we don't use it any more, just in case |
193 | return 0; | 193 | return 0; |
194 | } | 194 | } |
195 | 195 | ||
196 | 196 | ||
@@ -205,155 +205,155 @@ static int deep_userdata_gc( lua_State* L) | |||
205 | */ | 205 | */ |
206 | char const* push_deep_proxy( Universe* U, lua_State* L, DeepPrelude* prelude, int nuv_, LookupMode mode_) | 206 | char const* push_deep_proxy( Universe* U, lua_State* L, DeepPrelude* prelude, int nuv_, LookupMode mode_) |
207 | { | 207 | { |
208 | DeepPrelude** proxy; | 208 | DeepPrelude** proxy; |
209 | 209 | ||
210 | // Check if a proxy already exists | 210 | // Check if a proxy already exists |
211 | push_registry_subtable_mode( L, DEEP_PROXY_CACHE_KEY, "v"); // DPC | 211 | push_registry_subtable_mode( L, DEEP_PROXY_CACHE_KEY, "v"); // DPC |
212 | lua_pushlightuserdata( L, prelude); // DPC deep | 212 | lua_pushlightuserdata( L, prelude); // DPC deep |
213 | lua_rawget( L, -2); // DPC proxy | 213 | lua_rawget( L, -2); // DPC proxy |
214 | if ( !lua_isnil( L, -1)) | 214 | if ( !lua_isnil( L, -1)) |
215 | { | 215 | { |
216 | lua_remove( L, -2); // proxy | 216 | lua_remove( L, -2); // proxy |
217 | return NULL; | 217 | return NULL; |
218 | } | 218 | } |
219 | else | 219 | else |
220 | { | 220 | { |
221 | lua_pop( L, 1); // DPC | 221 | lua_pop( L, 1); // DPC |
222 | } | 222 | } |
223 | 223 | ||
224 | // can work without a universe if creating a deep userdata from some external C module when Lanes isn't loaded | 224 | // can work without a universe if creating a deep userdata from some external C module when Lanes isn't loaded |
225 | // in that case, we are not multithreaded and locking isn't necessary anyway | 225 | // in that case, we are not multithreaded and locking isn't necessary anyway |
226 | if( U) MUTEX_LOCK( &U->deep_lock); | 226 | if( U) MUTEX_LOCK( &U->deep_lock); |
227 | ++ (prelude->refcount); // one more proxy pointing to this deep data | 227 | ++ (prelude->refcount); // one more proxy pointing to this deep data |
228 | if( U) MUTEX_UNLOCK( &U->deep_lock); | 228 | if( U) MUTEX_UNLOCK( &U->deep_lock); |
229 | 229 | ||
230 | STACK_GROW( L, 7); | 230 | STACK_GROW( L, 7); |
231 | STACK_CHECK( L, 0); | 231 | STACK_CHECK( L, 0); |
232 | 232 | ||
233 | // a new full userdata, fitted with the specified number of uservalue slots (always 1 for Lua < 5.4) | 233 | // a new full userdata, fitted with the specified number of uservalue slots (always 1 for Lua < 5.4) |
234 | proxy = lua_newuserdatauv( L, sizeof(DeepPrelude*), nuv_); // DPC proxy | 234 | proxy = lua_newuserdatauv( L, sizeof(DeepPrelude*), nuv_); // DPC proxy |
235 | ASSERT_L( proxy); | 235 | ASSERT_L( proxy); |
236 | *proxy = prelude; | 236 | *proxy = prelude; |
237 | 237 | ||
238 | // Get/create metatable for 'idfunc' (in this state) | 238 | // Get/create metatable for 'idfunc' (in this state) |
239 | lua_pushlightuserdata( L, (void*)(ptrdiff_t)(prelude->idfunc)); // DPC proxy idfunc | 239 | lua_pushlightuserdata( L, (void*)(ptrdiff_t)(prelude->idfunc)); // DPC proxy idfunc |
240 | get_deep_lookup( L); // DPC proxy metatable? | 240 | get_deep_lookup( L); // DPC proxy metatable? |
241 | 241 | ||
242 | if( lua_isnil( L, -1)) // // No metatable yet. | 242 | if( lua_isnil( L, -1)) // // No metatable yet. |
243 | { | 243 | { |
244 | char const* modname; | 244 | char const* modname; |
245 | int oldtop = lua_gettop( L); // DPC proxy nil | 245 | int oldtop = lua_gettop( L); // DPC proxy nil |
246 | lua_pop( L, 1); // DPC proxy | 246 | lua_pop( L, 1); // DPC proxy |
247 | // 1 - make one and register it | 247 | // 1 - make one and register it |
248 | if( mode_ != eLM_ToKeeper) | 248 | if( mode_ != eLM_ToKeeper) |
249 | { | 249 | { |
250 | (void) prelude->idfunc( L, eDO_metatable); // DPC proxy metatable | 250 | (void) prelude->idfunc( L, eDO_metatable); // DPC proxy metatable |
251 | if( lua_gettop( L) - oldtop != 0 || !lua_istable( L, -1)) | 251 | if( lua_gettop( L) - oldtop != 0 || !lua_istable( L, -1)) |
252 | { | 252 | { |
253 | lua_settop( L, oldtop); // DPC proxy X | 253 | lua_settop( L, oldtop); // DPC proxy X |
254 | lua_pop( L, 3); // | 254 | lua_pop( L, 3); // |
255 | return "Bad idfunc(eOP_metatable): unexpected pushed value"; | 255 | return "Bad idfunc(eOP_metatable): unexpected pushed value"; |
256 | } | 256 | } |
257 | // if the metatable contains a __gc, we will call it from our own | 257 | // if the metatable contains a __gc, we will call it from our own |
258 | lua_getfield( L, -1, "__gc"); // DPC proxy metatable __gc | 258 | lua_getfield( L, -1, "__gc"); // DPC proxy metatable __gc |
259 | } | 259 | } |
260 | else | 260 | else |
261 | { | 261 | { |
262 | // keepers need a minimal metatable that only contains our own __gc | 262 | // keepers need a minimal metatable that only contains our own __gc |
263 | lua_newtable( L); // DPC proxy metatable | 263 | lua_newtable( L); // DPC proxy metatable |
264 | lua_pushnil( L); // DPC proxy metatable nil | 264 | lua_pushnil( L); // DPC proxy metatable nil |
265 | } | 265 | } |
266 | if( lua_isnil( L, -1)) | 266 | if( lua_isnil( L, -1)) |
267 | { | 267 | { |
268 | // Add our own '__gc' method | 268 | // Add our own '__gc' method |
269 | lua_pop( L, 1); // DPC proxy metatable | 269 | lua_pop( L, 1); // DPC proxy metatable |
270 | lua_pushcfunction( L, deep_userdata_gc); // DPC proxy metatable deep_userdata_gc | 270 | lua_pushcfunction( L, deep_userdata_gc); // DPC proxy metatable deep_userdata_gc |
271 | } | 271 | } |
272 | else | 272 | else |
273 | { | 273 | { |
274 | // Add our own '__gc' method wrapping the original | 274 | // Add our own '__gc' method wrapping the original |
275 | lua_pushcclosure( L, deep_userdata_gc, 1); // DPC proxy metatable deep_userdata_gc | 275 | lua_pushcclosure( L, deep_userdata_gc, 1); // DPC proxy metatable deep_userdata_gc |
276 | } | 276 | } |
277 | lua_setfield( L, -2, "__gc"); // DPC proxy metatable | 277 | lua_setfield( L, -2, "__gc"); // DPC proxy metatable |
278 | 278 | ||
279 | // Memorize for later rounds | 279 | // Memorize for later rounds |
280 | lua_pushvalue( L, -1); // DPC proxy metatable metatable | 280 | lua_pushvalue( L, -1); // DPC proxy metatable metatable |
281 | lua_pushlightuserdata( L, (void*)(ptrdiff_t)(prelude->idfunc)); // DPC proxy metatable metatable idfunc | 281 | lua_pushlightuserdata( L, (void*)(ptrdiff_t)(prelude->idfunc)); // DPC proxy metatable metatable idfunc |
282 | set_deep_lookup( L); // DPC proxy metatable | 282 | set_deep_lookup( L); // DPC proxy metatable |
283 | 283 | ||
284 | // 2 - cause the target state to require the module that exported the idfunc | 284 | // 2 - cause the target state to require the module that exported the idfunc |
285 | // this is needed because we must make sure the shared library is still loaded as long as we hold a pointer on the idfunc | 285 | // this is needed because we must make sure the shared library is still loaded as long as we hold a pointer on the idfunc |
286 | { | 286 | { |
287 | int oldtop_module = lua_gettop( L); | 287 | int oldtop_module = lua_gettop( L); |
288 | modname = (char const*) prelude->idfunc( L, eDO_module); // DPC proxy metatable | 288 | modname = (char const*) prelude->idfunc( L, eDO_module); // DPC proxy metatable |
289 | // make sure the function pushed nothing on the stack! | 289 | // make sure the function pushed nothing on the stack! |
290 | if( lua_gettop( L) - oldtop_module != 0) | 290 | if( lua_gettop( L) - oldtop_module != 0) |
291 | { | 291 | { |
292 | lua_pop( L, 3); // | 292 | lua_pop( L, 3); // |
293 | return "Bad idfunc(eOP_module): should not push anything"; | 293 | return "Bad idfunc(eOP_module): should not push anything"; |
294 | } | 294 | } |
295 | } | 295 | } |
296 | if( NULL != modname) // we actually got a module name | 296 | if( NULL != modname) // we actually got a module name |
297 | { | 297 | { |
298 | // L.registry._LOADED exists without having registered the 'package' library. | 298 | // L.registry._LOADED exists without having registered the 'package' library. |
299 | lua_getglobal( L, "require"); // DPC proxy metatable require() | 299 | lua_getglobal( L, "require"); // DPC proxy metatable require() |
300 | // check that the module is already loaded (or being loaded, we are happy either way) | 300 | // check that the module is already loaded (or being loaded, we are happy either way) |
301 | if( lua_isfunction( L, -1)) | 301 | if( lua_isfunction( L, -1)) |
302 | { | 302 | { |
303 | lua_pushstring( L, modname); // DPC proxy metatable require() "module" | 303 | lua_pushstring( L, modname); // DPC proxy metatable require() "module" |
304 | lua_getfield( L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); // DPC proxy metatable require() "module" _R._LOADED | 304 | lua_getfield( L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); // DPC proxy metatable require() "module" _R._LOADED |
305 | if( lua_istable( L, -1)) | 305 | if( lua_istable( L, -1)) |
306 | { | 306 | { |
307 | bool_t alreadyloaded; | 307 | bool_t alreadyloaded; |
308 | lua_pushvalue( L, -2); // DPC proxy metatable require() "module" _R._LOADED "module" | 308 | lua_pushvalue( L, -2); // DPC proxy metatable require() "module" _R._LOADED "module" |
309 | lua_rawget( L, -2); // DPC proxy metatable require() "module" _R._LOADED module | 309 | lua_rawget( L, -2); // DPC proxy metatable require() "module" _R._LOADED module |
310 | alreadyloaded = lua_toboolean( L, -1); | 310 | alreadyloaded = lua_toboolean( L, -1); |
311 | if( !alreadyloaded) // not loaded | 311 | if( !alreadyloaded) // not loaded |
312 | { | 312 | { |
313 | int require_result; | 313 | int require_result; |
314 | lua_pop( L, 2); // DPC proxy metatable require() "module" | 314 | lua_pop( L, 2); // DPC proxy metatable require() "module" |
315 | // require "modname" | 315 | // require "modname" |
316 | require_result = lua_pcall( L, 1, 0, 0); // DPC proxy metatable error? | 316 | require_result = lua_pcall( L, 1, 0, 0); // DPC proxy metatable error? |
317 | if( require_result != LUA_OK) | 317 | if( require_result != LUA_OK) |
318 | { | 318 | { |
319 | // failed, return the error message | 319 | // failed, return the error message |
320 | lua_pushfstring( L, "error while requiring '%s' identified by idfunc(eOP_module): ", modname); | 320 | lua_pushfstring( L, "error while requiring '%s' identified by idfunc(eOP_module): ", modname); |
321 | lua_insert( L, -2); // DPC proxy metatable prefix error | 321 | lua_insert( L, -2); // DPC proxy metatable prefix error |
322 | lua_concat( L, 2); // DPC proxy metatable error | 322 | lua_concat( L, 2); // DPC proxy metatable error |
323 | return lua_tostring( L, -1); | 323 | return lua_tostring( L, -1); |
324 | } | 324 | } |
325 | } | 325 | } |
326 | else // already loaded, we are happy | 326 | else // already loaded, we are happy |
327 | { | 327 | { |
328 | lua_pop( L, 4); // DPC proxy metatable | 328 | lua_pop( L, 4); // DPC proxy metatable |
329 | } | 329 | } |
330 | } | 330 | } |
331 | else // no L.registry._LOADED; can this ever happen? | 331 | else // no L.registry._LOADED; can this ever happen? |
332 | { | 332 | { |
333 | lua_pop( L, 6); // | 333 | lua_pop( L, 6); // |
334 | return "unexpected error while requiring a module identified by idfunc(eOP_module)"; | 334 | return "unexpected error while requiring a module identified by idfunc(eOP_module)"; |
335 | } | 335 | } |
336 | } | 336 | } |
337 | else // a module name, but no require() function :-( | 337 | else // a module name, but no require() function :-( |
338 | { | 338 | { |
339 | lua_pop( L, 4); // | 339 | lua_pop( L, 4); // |
340 | return "lanes receiving deep userdata should register the 'package' library"; | 340 | return "lanes receiving deep userdata should register the 'package' library"; |
341 | } | 341 | } |
342 | } | 342 | } |
343 | } | 343 | } |
344 | STACK_MID( L, 2); // DPC proxy metatable | 344 | STACK_MID( L, 2); // DPC proxy metatable |
345 | ASSERT_L( lua_isuserdata( L, -2)); | 345 | ASSERT_L( lua_isuserdata( L, -2)); |
346 | ASSERT_L( lua_istable( L, -1)); | 346 | ASSERT_L( lua_istable( L, -1)); |
347 | lua_setmetatable( L, -2); // DPC proxy | 347 | lua_setmetatable( L, -2); // DPC proxy |
348 | 348 | ||
349 | // If we're here, we obviously had to create a new proxy, so cache it. | 349 | // If we're here, we obviously had to create a new proxy, so cache it. |
350 | lua_pushlightuserdata( L, prelude); // DPC proxy deep | 350 | lua_pushlightuserdata( L, prelude); // DPC proxy deep |
351 | lua_pushvalue( L, -2); // DPC proxy deep proxy | 351 | lua_pushvalue( L, -2); // DPC proxy deep proxy |
352 | lua_rawset( L, -4); // DPC proxy | 352 | lua_rawset( L, -4); // DPC proxy |
353 | lua_remove( L, -2); // proxy | 353 | lua_remove( L, -2); // proxy |
354 | ASSERT_L( lua_isuserdata( L, -1)); | 354 | ASSERT_L( lua_isuserdata( L, -1)); |
355 | STACK_END( L, 0); | 355 | STACK_END( L, 0); |
356 | return NULL; | 356 | return NULL; |
357 | } | 357 | } |
358 | 358 | ||
359 | /* | 359 | /* |
@@ -380,42 +380,42 @@ char const* push_deep_proxy( Universe* U, lua_State* L, DeepPrelude* prelude, in | |||
380 | */ | 380 | */ |
381 | int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction idfunc, int nuv_) | 381 | int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction idfunc, int nuv_) |
382 | { | 382 | { |
383 | char const* errmsg; | 383 | char const* errmsg; |
384 | 384 | ||
385 | STACK_GROW( L, 1); | 385 | STACK_GROW( L, 1); |
386 | STACK_CHECK( L, 0); | 386 | STACK_CHECK( L, 0); |
387 | { | 387 | { |
388 | int const oldtop = lua_gettop( L); | 388 | int const oldtop = lua_gettop( L); |
389 | DeepPrelude* prelude = idfunc( L, eDO_new); | 389 | DeepPrelude* prelude = idfunc( L, eDO_new); |
390 | if( prelude == NULL) | 390 | if( prelude == NULL) |
391 | { | 391 | { |
392 | luaL_error( L, "idfunc(eDO_new) failed to create deep userdata (out of memory)"); | 392 | luaL_error( L, "idfunc(eDO_new) failed to create deep userdata (out of memory)"); |
393 | } | 393 | } |
394 | if( prelude->magic.value != DEEP_VERSION.value) | 394 | if( prelude->magic.value != DEEP_VERSION.value) |
395 | { | 395 | { |
396 | // just in case, don't leak the newly allocated deep userdata object | 396 | // just in case, don't leak the newly allocated deep userdata object |
397 | lua_pushlightuserdata( L, prelude); | 397 | lua_pushlightuserdata( L, prelude); |
398 | idfunc( L, eDO_delete); | 398 | idfunc( L, eDO_delete); |
399 | return luaL_error( L, "Bad idfunc(eDO_new): DEEP_VERSION is incorrect, rebuild your implementation with the latest deep implementation"); | 399 | return luaL_error( L, "Bad idfunc(eDO_new): DEEP_VERSION is incorrect, rebuild your implementation with the latest deep implementation"); |
400 | } | 400 | } |
401 | prelude->refcount = 0; // 'push_deep_proxy' will lift it to 1 | 401 | prelude->refcount = 0; // 'push_deep_proxy' will lift it to 1 |
402 | prelude->idfunc = idfunc; | 402 | prelude->idfunc = idfunc; |
403 | 403 | ||
404 | if( lua_gettop( L) - oldtop != 0) | 404 | if( lua_gettop( L) - oldtop != 0) |
405 | { | 405 | { |
406 | // just in case, don't leak the newly allocated deep userdata object | 406 | // just in case, don't leak the newly allocated deep userdata object |
407 | lua_pushlightuserdata( L, prelude); | 407 | lua_pushlightuserdata( L, prelude); |
408 | idfunc( L, eDO_delete); | 408 | idfunc( L, eDO_delete); |
409 | return luaL_error( L, "Bad idfunc(eDO_new): should not push anything on the stack"); | 409 | return luaL_error( L, "Bad idfunc(eDO_new): should not push anything on the stack"); |
410 | } | 410 | } |
411 | errmsg = push_deep_proxy( universe_get( L), L, prelude, nuv_, eLM_LaneBody); // proxy | 411 | errmsg = push_deep_proxy( universe_get( L), L, prelude, nuv_, eLM_LaneBody); // proxy |
412 | if( errmsg != NULL) | 412 | if( errmsg != NULL) |
413 | { | 413 | { |
414 | return luaL_error( L, errmsg); | 414 | return luaL_error( L, errmsg); |
415 | } | 415 | } |
416 | } | 416 | } |
417 | STACK_END( L, 1); | 417 | STACK_END( L, 1); |
418 | return 1; | 418 | return 1; |
419 | } | 419 | } |
420 | 420 | ||
421 | 421 | ||
@@ -427,19 +427,19 @@ int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction idfunc, int nuv_) | |||
427 | */ | 427 | */ |
428 | void* luaG_todeep( lua_State* L, luaG_IdFunction idfunc, int index) | 428 | void* luaG_todeep( lua_State* L, luaG_IdFunction idfunc, int index) |
429 | { | 429 | { |
430 | DeepPrelude** proxy; | 430 | DeepPrelude** proxy; |
431 | 431 | ||
432 | STACK_CHECK( L, 0); | 432 | STACK_CHECK( L, 0); |
433 | // ensure it is actually a deep userdata | 433 | // ensure it is actually a deep userdata |
434 | if( get_idfunc( L, index, eLM_LaneBody) != idfunc) | 434 | if( get_idfunc( L, index, eLM_LaneBody) != idfunc) |
435 | { | 435 | { |
436 | return NULL; // no metatable, or wrong kind | 436 | return NULL; // no metatable, or wrong kind |
437 | } | 437 | } |
438 | 438 | ||
439 | proxy = (DeepPrelude**) lua_touserdata( L, index); | 439 | proxy = (DeepPrelude**) lua_touserdata( L, index); |
440 | STACK_END( L, 0); | 440 | STACK_END( L, 0); |
441 | 441 | ||
442 | return *proxy; | 442 | return *proxy; |
443 | } | 443 | } |
444 | 444 | ||
445 | 445 | ||
@@ -452,50 +452,50 @@ void* luaG_todeep( lua_State* L, luaG_IdFunction idfunc, int index) | |||
452 | */ | 452 | */ |
453 | bool_t copydeep( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, LookupMode mode_, char const* upName_) | 453 | bool_t copydeep( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, LookupMode mode_, char const* upName_) |
454 | { | 454 | { |
455 | char const* errmsg; | 455 | char const* errmsg; |
456 | luaG_IdFunction idfunc = get_idfunc( L, i, mode_); | 456 | luaG_IdFunction idfunc = get_idfunc( L, i, mode_); |
457 | int nuv = 0; | 457 | int nuv = 0; |
458 | 458 | ||
459 | if( idfunc == NULL) | 459 | if( idfunc == NULL) |
460 | { | 460 | { |
461 | return FALSE; // not a deep userdata | 461 | return FALSE; // not a deep userdata |
462 | } | 462 | } |
463 | 463 | ||
464 | STACK_CHECK( L, 0); | 464 | STACK_CHECK( L, 0); |
465 | STACK_CHECK( L2, 0); | 465 | STACK_CHECK( L2, 0); |
466 | 466 | ||
467 | // extract all uservalues of the source | 467 | // extract all uservalues of the source |
468 | while( lua_getiuservalue( L, i, nuv + 1) != LUA_TNONE) // ... u [uv]* nil | 468 | while( lua_getiuservalue( L, i, nuv + 1) != LUA_TNONE) // ... u [uv]* nil |
469 | { | 469 | { |
470 | ++ nuv; | 470 | ++ nuv; |
471 | } | 471 | } |
472 | // last call returned TNONE and pushed nil, that we don't need | 472 | // last call returned TNONE and pushed nil, that we don't need |
473 | lua_pop( L, 1); // ... u [uv]* | 473 | lua_pop( L, 1); // ... u [uv]* |
474 | STACK_MID( L, nuv); | 474 | STACK_MID( L, nuv); |
475 | 475 | ||
476 | errmsg = push_deep_proxy( U, L2, *(DeepPrelude**) lua_touserdata( L, i), nuv, mode_); // u | 476 | errmsg = push_deep_proxy( U, L2, *(DeepPrelude**) lua_touserdata( L, i), nuv, mode_); // u |
477 | 477 | ||
478 | // transfer all uservalues of the source in the destination | 478 | // transfer all uservalues of the source in the destination |
479 | { | 479 | { |
480 | int const clone_i = lua_gettop( L2); | 480 | int const clone_i = lua_gettop( L2); |
481 | while( nuv) | 481 | while( nuv) |
482 | { | 482 | { |
483 | inter_copy_one( U, L2, L2_cache_i, L, lua_absindex( L, -1), VT_NORMAL, mode_, upName_); // u uv | 483 | inter_copy_one( U, L2, L2_cache_i, L, lua_absindex( L, -1), VT_NORMAL, mode_, upName_); // u uv |
484 | lua_pop( L, 1); // ... u [uv]* | 484 | lua_pop( L, 1); // ... u [uv]* |
485 | // this pops the value from the stack | 485 | // this pops the value from the stack |
486 | lua_setiuservalue( L2, clone_i, nuv); // u | 486 | lua_setiuservalue( L2, clone_i, nuv); // u |
487 | -- nuv; | 487 | -- nuv; |
488 | } | 488 | } |
489 | } | 489 | } |
490 | 490 | ||
491 | STACK_END( L2, 1); | 491 | STACK_END( L2, 1); |
492 | STACK_END( L, 0); | 492 | STACK_END( L, 0); |
493 | 493 | ||
494 | if( errmsg != NULL) | 494 | if( errmsg != NULL) |
495 | { | 495 | { |
496 | // raise the error in the proper state (not the keeper) | 496 | // raise the error in the proper state (not the keeper) |
497 | lua_State* errL = (mode_ == eLM_FromKeeper) ? L2 : L; | 497 | lua_State* errL = (mode_ == eLM_FromKeeper) ? L2 : L; |
498 | luaL_error( errL, errmsg); | 498 | luaL_error( errL, errmsg); |
499 | } | 499 | } |
500 | return TRUE; | 500 | return TRUE; |
501 | } \ No newline at end of file | 501 | } \ No newline at end of file |