diff --git a/luprex/cpp/core/world-pairtab.cpp b/luprex/cpp/core/world-pairtab.cpp index 81004b60..e5210bda 100644 --- a/luprex/cpp/core/world-pairtab.cpp +++ b/luprex/cpp/core/world-pairtab.cpp @@ -20,47 +20,23 @@ int World::number_lua_tables(const IdVector &basis) { // This is conceptually recursive, but we're going to use an // explicit stack (the lua stack). lua_State *L = state(); - LuaVar tnmap, ntmap, tangibles, tab, key, val, xid; - LuaOldStack LS(L, tnmap, ntmap, tangibles, tab, key, val, xid); - LS.set(tnmap, LuaNewTable); - LS.set(ntmap, LuaNewTable); - LS.rawset(LuaRegistry, "tnmap", tnmap); - LS.rawset(LuaRegistry, "ntmap", ntmap); - LS.rawget(tangibles, LuaRegistry, "tangibles"); int nextid = 1; - int top = lua_gettop(L); + { + LuaVar tnmap, ntmap, tangibles, tab, key, val, xid; + LuaExtStack LS(L, tnmap, ntmap, tangibles, tab, key, val, xid); + LS.set(tnmap, LuaNewTable); + LS.set(ntmap, LuaNewTable); + LS.rawset(LuaRegistry, "tnmap", tnmap); + LS.rawset(LuaRegistry, "ntmap", ntmap); + LS.rawget(tangibles, LuaRegistry, "tangibles"); + int top = lua_gettop(L); - // Push all subtables onto the stack. Note that we may push - // the same table twice, that's OK. - for (int64_t id : basis) { - LS.rawget(tab, tangibles, id); - assert(LS.istable(tab)); - // Traverse subtables. - LS.set(key, LuaNil); - while (LS.next(tab, key, val)) { - if (LS.istable(val) && LS.gettabletype(val)==LUA_TT_GENERAL) { - lua_checkstack(L, 10); - lua_pushvalue(L, val.index()); - } - } - } - - // Pop tables from the stack one by one. If the table is not - // already numbered, number it and push subtables onto the stack. - while (lua_gettop(L) > top) { - lua_replace(L, tab.index()); - LS.rawget(xid, tnmap, tab); - if (LS.isnil(xid)) { - int id = nextid++; - LS.rawset(tnmap, tab, id); - LS.rawset(ntmap, id, tab); - // Traverse the metatable. - LS.getmetatable(val, tab); - if (LS.istable(val) && LS.gettabletype(val)==LUA_TT_GENERAL) { - lua_checkstack(L, 10); - lua_pushvalue(L, val.index()); - } - // Traverse the subtables. + // Push all subtables onto the stack. Note that we may push + // the same table twice, that's OK. + for (int64_t id : basis) { + LS.rawget(tab, tangibles, id); + assert(LS.istable(tab)); + // Traverse subtables. LS.set(key, LuaNil); while (LS.next(tab, key, val)) { if (LS.istable(val) && LS.gettabletype(val)==LUA_TT_GENERAL) { @@ -69,9 +45,34 @@ int World::number_lua_tables(const IdVector &basis) { } } } + + // Pop tables from the stack one by one. If the table is not + // already numbered, number it and push subtables onto the stack. + while (lua_gettop(L) > top) { + lua_replace(L, tab.index()); + LS.rawget(xid, tnmap, tab); + if (LS.isnil(xid)) { + int id = nextid++; + LS.rawset(tnmap, tab, id); + LS.rawset(ntmap, id, tab); + // Traverse the metatable. + LS.getmetatable(val, tab); + if (LS.istable(val) && LS.gettabletype(val)==LUA_TT_GENERAL) { + lua_checkstack(L, 10); + lua_pushvalue(L, val.index()); + } + // Traverse the subtables. + LS.set(key, LuaNil); + while (LS.next(tab, key, val)) { + if (LS.istable(val) && LS.gettabletype(val)==LUA_TT_GENERAL) { + lua_checkstack(L, 10); + lua_pushvalue(L, val.index()); + } + } + } + } } - LS.result(); assert(stack_is_clear()); return nextid - 1; } @@ -79,8 +80,8 @@ int World::number_lua_tables(const IdVector &basis) { void World::pair_lua_tables(const IdVector &basis, lua_State *master) { lua_State *synch = state(); LuaVar stangibles, mtangibles, sntmap, mntmap, stnmap, mtnmap, stab, mtab, skey, mkey, sval, mval, sidx, midx; - LuaOldStack SLS(synch, stangibles, stab, skey, sval, sntmap, stnmap, sidx); - LuaOldStack MLS(master, mtangibles, mtab, mkey, mval, mntmap, mtnmap, midx); + LuaExtStack SLS(synch, stangibles, stab, skey, sval, sntmap, stnmap, sidx); + LuaExtStack MLS(master, mtangibles, mtab, mkey, mval, mntmap, mtnmap, midx); // Fetch the tangible databases SLS.rawget(stangibles, LuaRegistry, "tangibles"); @@ -168,63 +169,29 @@ void World::pair_lua_tables(const IdVector &basis, lua_State *master) { lua_pushvalue(synch, sval.index()); } } - - MLS.result(); - SLS.result(); } int World::number_remaining_tables(const IdVector &basis, lua_State *master) { // This is conceptually recursive, but we're going to use an // explicit stack (the lua stack). - lua_State *L = master; - LuaVar tnmap, ntmap, tangibles, tab, key, val, xid; - LuaOldStack LS(L, tnmap, ntmap, tangibles, tab, key, val, xid); - LS.rawget(tnmap, LuaRegistry, "tnmap"); - LS.rawget(ntmap, LuaRegistry, "ntmap"); - LS.rawget(tangibles, LuaRegistry, "tangibles"); - int ntables = LS.rawlen(ntmap); eng::vector visited; - visited.assign(ntables + 1, false); - int top = lua_gettop(L); + int ntables; + { + lua_State *L = master; + LuaVar tnmap, ntmap, tangibles, tab, key, val, xid; + LuaExtStack LS(L, tnmap, ntmap, tangibles, tab, key, val, xid); + LS.rawget(tnmap, LuaRegistry, "tnmap"); + LS.rawget(ntmap, LuaRegistry, "ntmap"); + LS.rawget(tangibles, LuaRegistry, "tangibles"); + ntables = LS.rawlen(ntmap); + visited.assign(ntables + 1, false); + int top = lua_gettop(L); - // Push all subtables onto the stack. Note that we may push - // the same table twice, that's OK. - for (int64_t id : basis) { - LS.rawget(tab, tangibles, id); - assert(LS.istable(tab)); - LS.set(key, LuaNil); - while (LS.next(tab, key, val)) { - if (LS.istable(val) && LS.gettabletype(val)==LUA_TT_GENERAL) { - lua_checkstack(L, 10); - lua_pushvalue(L, val.index()); - } - } - } - - // Pop tables from the stack one by one. If the table is not - // numbered, number it. If it is not visited, visit it. - while (lua_gettop(L) > top) { - lua_replace(L, tab.index()); - int id = 0; - LS.rawget(xid, tnmap, tab); - if (!LS.isnumber(xid)) { - id = visited.size(); - LS.rawset(tnmap, tab, id); - LS.rawset(ntmap, id, tab); - visited.push_back(false); - } else { - id = LS.cknumber(xid); - assert((id >= 0) && (id < int(visited.size()))); - } - if (!visited[id]) { - visited[id] = true; - // Traverse the metatable. - LS.getmetatable(val, tab); - if (LS.istable(val) && LS.gettabletype(val)==LUA_TT_GENERAL) { - lua_checkstack(L, 10); - lua_pushvalue(L, val.index()); - } - // Traverse the subtables. + // Push all subtables onto the stack. Note that we may push + // the same table twice, that's OK. + for (int64_t id : basis) { + LS.rawget(tab, tangibles, id); + assert(LS.istable(tab)); LS.set(key, LuaNil); while (LS.next(tab, key, val)) { if (LS.istable(val) && LS.gettabletype(val)==LUA_TT_GENERAL) { @@ -233,35 +200,68 @@ int World::number_remaining_tables(const IdVector &basis, lua_State *master) { } } } - } - LS.result(); + // Pop tables from the stack one by one. If the table is not + // numbered, number it. If it is not visited, visit it. + while (lua_gettop(L) > top) { + lua_replace(L, tab.index()); + int id = 0; + LS.rawget(xid, tnmap, tab); + if (!LS.isnumber(xid)) { + id = visited.size(); + LS.rawset(tnmap, tab, id); + LS.rawset(ntmap, id, tab); + visited.push_back(false); + } else { + id = LS.cknumber(xid); + assert((id >= 0) && (id < int(visited.size()))); + } + if (!visited[id]) { + visited[id] = true; + // Traverse the metatable. + LS.getmetatable(val, tab); + if (LS.istable(val) && LS.gettabletype(val)==LUA_TT_GENERAL) { + lua_checkstack(L, 10); + lua_pushvalue(L, val.index()); + } + // Traverse the subtables. + LS.set(key, LuaNil); + while (LS.next(tab, key, val)) { + if (LS.istable(val) && LS.gettabletype(val)==LUA_TT_GENERAL) { + lua_checkstack(L, 10); + lua_pushvalue(L, val.index()); + } + } + } + } + } assert(stack_is_clear()); return visited.size() - 1 - ntables; } void World::create_new_tables(int n) { - LuaVar tnmap, ntmap, tab; - LuaOldStack LS(state(), tnmap, ntmap, tab); - LS.rawget(tnmap, LuaRegistry, "tnmap"); - LS.rawget(ntmap, LuaRegistry, "ntmap"); - assert(LS.istable(tnmap)); - assert(LS.istable(ntmap)); - int ntables = LS.rawlen(ntmap); - int nextid = ntables + 1; - for (int i = 0; i < n; i++) { - int id = nextid++; - LS.newtable(tab); - LS.rawset(ntmap, id, tab); - LS.rawset(tnmap, tab, id); + { + LuaVar tnmap, ntmap, tab; + LuaExtStack LS(state(), tnmap, ntmap, tab); + LS.rawget(tnmap, LuaRegistry, "tnmap"); + LS.rawget(ntmap, LuaRegistry, "ntmap"); + assert(LS.istable(tnmap)); + assert(LS.istable(ntmap)); + int ntables = LS.rawlen(ntmap); + int nextid = ntables + 1; + for (int i = 0; i < n; i++) { + int id = nextid++; + LS.newtable(tab); + LS.rawset(ntmap, id, tab); + LS.rawset(tnmap, tab, id); + } } - LS.result(); assert(stack_is_clear()); } void World::unnumber_lua_tables() { // All we have to do is remove these tables from the registry. - LuaOldStack LS(state()); + LuaExtStack LS(state()); LS.rawset(LuaRegistry, "tnmap", LuaNil); LS.rawset(LuaRegistry, "ntmap", LuaNil); }