aboutsummaryrefslogtreecommitdiff
path: root/src/deep.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/deep.c')
-rw-r--r--src/deep.c654
1 files changed, 327 insertions, 327 deletions
diff --git a/src/deep.c b/src/deep.c
index 3c7680d..c475dc5 100644
--- a/src/deep.c
+++ b/src/deep.c
@@ -73,17 +73,17 @@ static DECLARE_CONST_UNIQUE_KEY( DEEP_PROXY_CACHE_KEY, 0x05773d6fc26be106);
73*/ 73*/
74static void set_deep_lookup( lua_State* L) 74static 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*/
93static void get_deep_lookup( lua_State* L) 93static 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*/
111static inline luaG_IdFunction get_idfunc( lua_State* L, int index, LookupMode mode_) 111static 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
145void free_deep_prelude( lua_State* L, DeepPrelude* prelude_) 145void 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 */
160static int deep_userdata_gc( lua_State* L) 160static 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 */
206char const* push_deep_proxy( Universe* U, lua_State* L, DeepPrelude* prelude, int nuv_, LookupMode mode_) 206char 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*/
381int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction idfunc, int nuv_) 381int 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*/
428void* luaG_todeep( lua_State* L, luaG_IdFunction idfunc, int index) 428void* 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 */
453bool_t copydeep( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, LookupMode mode_, char const* upName_) 453bool_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