Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
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) );
}