static bool inter_copy_one(lua_State* from, lua_State* to, int cache, int i){ //int top_to = lua_gettop(to); ASSERT(lua_istable(to, cache)); if(lua_checkstack(to, 2) != 1) return false; // todo: output errors bool ret = true; switch(lua_type(from, i)){ case LUA_TNIL: lua_pushnil(to); break; case LUA_TBOOLEAN: lua_pushboolean(to, lua_toboolean(from, i)); break; case LUA_TLIGHTUSERDATA: lua_pushlightuserdata(to, lua_touserdata(from, i)); break; case LUA_TNUMBER: lua_pushnumber(to, lua_tonumber(from, i)); break; case LUA_TSTRING: { size_t len; const char *s = lua_tolstring(from, i, &len); lua_pushlstring(to, s, len); } break; case LUA_TTABLE: ret = inter_copy_table(from, to, cache, i); break; case LUA_TFUNCTION: ret = inter_copy_func(from, to, cache, i); break; case LUA_TUSERDATA: ret = inter_copy_userdata(from, to, cache, i); break; case LUA_TTHREAD: ret = false; break; }; return ret; }
static void push_cached_func( lua_State *L2, uint_t L2_cache_i, lua_State *L, uint_t i ) { // TBD: Merge this and same code for tables ASSERT_L( hijacked_tostring ); ASSERT_L( L2_cache_i != 0 ); STACK_GROW(L,2); STACK_GROW(L2,3); STACK_CHECK(L) lua_pushcfunction( L, hijacked_tostring ); lua_pushvalue( L, i ); lua_call( L, 1 /*args*/, 1 /*retvals*/ ); // // [-1]: "function: 0x...." STACK_END(L,1) ASSERT_L( lua_type(L,-1) == LUA_TSTRING ); // L2_cache[id_str]= function // STACK_CHECK(L2) // We don't need to use the from state ('L') in ID since the life span // is only for the duration of a copy (both states are locked). // lua_pushstring( L2, lua_tostring(L,-1) ); lua_pop(L,1); // remove the 'tostring(tbl)' value (in L!) //fprintf( stderr, "<< ID: %s >>\n", lua_tostring(L2,-1) ); lua_pushvalue( L2, -1 ); lua_rawget( L2, L2_cache_i ); // // [-2]: identity string ("function: 0x...") // [-1]: function|nil|true (true means: we're working on it; recursive) if (lua_isnil(L2,-1)) { lua_pop(L2,1); // Set to 'true' for the duration of creation; need to find self-references // via upvalues // lua_pushboolean(L2,TRUE); lua_setfield( L2, L2_cache_i, lua_tostring(L2,-2) ); inter_copy_func( L2, L2_cache_i, L, i ); // pushes a copy of the func lua_pushvalue(L2,-1); lua_insert(L2,-3); // // [-3]: function (2nd ref) // [-2]: identity string // [-1]: function lua_rawset(L2,L2_cache_i); // // [-1]: function (tied to 'L2_cache' table') } else if (lua_isboolean(L2,-1)) { // Loop in preparing upvalues; either direct or via a table // // Note: This excludes the case where a function directly addresses // itself as an upvalue (recursive lane creation). // luaL_error( L, "Recursive use of upvalues; cannot copy the function" ); } else { lua_remove(L2,-2); } STACK_END(L2,1) // // L2 [-1]: function ASSERT_L( lua_isfunction(L2,-1) ); }