Implement tabletype tagging
This commit is contained in:
@@ -45,5 +45,6 @@ LuaDefine(globaldb_global, "f") {
|
|||||||
LS.newtable(globaltab);
|
LS.newtable(globaltab);
|
||||||
LS.rawset(globaldb, globalname, globaltab);
|
LS.rawset(globaldb, globalname, globaltab);
|
||||||
LS.rawset(globaltab, "__global", globalname);
|
LS.rawset(globaltab, "__global", globalname);
|
||||||
|
LS.settabletype(globaltab, LuaStack::TAB_GLOBALDB);
|
||||||
return LS.result();
|
return LS.result();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -171,29 +171,22 @@ void LuaStack::getclass(LuaSlot classtab, LuaSlot classname) const {
|
|||||||
LuaVar globtab, cname;
|
LuaVar globtab, cname;
|
||||||
LuaStack LS(L_, globtab, cname);
|
LuaStack LS(L_, globtab, cname);
|
||||||
|
|
||||||
|
if (!LS.isstring(classname)) {
|
||||||
|
luaL_error(L_, "Not a class name: %s", lua_tostring(L_, classname));
|
||||||
|
}
|
||||||
|
|
||||||
// Convert class name to a table.
|
// Convert class name to a table.
|
||||||
if (LS.isstring(classname)) {
|
if (LS.rawequal(classname, "_G")) {
|
||||||
if (LS.rawequal(classname, "_G")) {
|
luaL_error(L_, "_G is explicitly not allowed as a class name");
|
||||||
luaL_error(L_, "_G is explicitly not allowed as a class name");
|
}
|
||||||
}
|
LS.getglobaltable(globtab);
|
||||||
LS.getglobaltable(globtab);
|
LS.rawget(classtab, globtab, classname);
|
||||||
LS.rawget(classtab, globtab, classname);
|
if (!LS.istable(classtab)) {
|
||||||
if (!LS.istable(classtab)) {
|
luaL_error(L_, "Not a class: %s", lua_tostring(L_, classname));
|
||||||
luaL_error(L_, "Not a class: %s", lua_tostring(L_, classname));
|
}
|
||||||
}
|
LS.rawget(cname, classtab, "__class");
|
||||||
LS.rawget(cname, classtab, "__class");
|
if (!LS.rawequal(cname, classname)) {
|
||||||
if (!LS.rawequal(cname, classname)) {
|
luaL_error(L_, "Not a class: %s", lua_tostring(L_, classname));
|
||||||
luaL_error(L_, "Not a class: %s", lua_tostring(L_, classname));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
LS.set(classtab, classname);
|
|
||||||
if (!LS.istable(classtab)) {
|
|
||||||
luaL_error(L_, "class can be a string or a table");
|
|
||||||
}
|
|
||||||
LS.rawget(cname, classtab, "__class");
|
|
||||||
if (!LS.isstring(cname)) {
|
|
||||||
luaL_error(L_, "table is not a class");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// OK, we're done.
|
// OK, we're done.
|
||||||
@@ -230,6 +223,7 @@ void LuaStack::makeclass(LuaSlot classtab, LuaSlot classname) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Repair the special fields.
|
// Repair the special fields.
|
||||||
|
LS.settabletype(classtab, TAB_CLASS);
|
||||||
LS.rawset(classtab, "__index", classtab);
|
LS.rawset(classtab, "__index", classtab);
|
||||||
LS.rawset(classtab, "__class", classname);
|
LS.rawset(classtab, "__class", classname);
|
||||||
|
|
||||||
@@ -271,3 +265,21 @@ void LuaStack::check_nret(int xnret, int otop, int nret) const {
|
|||||||
luaL_error(L_, "expected %d return values", xnret);
|
luaL_error(L_, "expected %d return values", xnret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LuaStack::TableType LuaStack::gettabletype(LuaSlot tab) {
|
||||||
|
uint16_t bits = lua_getflagbits(L_, tab.index());
|
||||||
|
return TableType(bits & 0x000F);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LuaStack::settabletype(LuaSlot tab, TableType t) {
|
||||||
|
lua_modflagbits(L_, tab.index(), 0x000F, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LuaStack::getvisited(LuaSlot tab) {
|
||||||
|
uint16_t bits = lua_getflagbits(L_, tab.index());
|
||||||
|
return (bits & 0x0010);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LuaStack::setvisited(LuaSlot tab, bool visited) {
|
||||||
|
lua_modflagbits(L_, tab.index(), 0x0010, visited ? 0x0010 : 0);
|
||||||
|
}
|
||||||
|
|||||||
@@ -463,18 +463,6 @@ public:
|
|||||||
lua_rawseti(L_, tab, key);
|
lua_rawseti(L_, tab, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
// template<typename VT>
|
|
||||||
// void rawset(LuaSlot tab, const char *field, VT value) const {
|
|
||||||
// push_any_value(value);
|
|
||||||
// lua_rawset(L_, tab, field);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// template<typename RT>
|
|
||||||
// void rawget(RT &target, LuaSlot tab, const char *field) const {
|
|
||||||
// lua_rawget(L_, tab, field);
|
|
||||||
// pop_any_value(target);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Call invokes any C function. It pushes the arguments on the stack,
|
// Call invokes any C function. It pushes the arguments on the stack,
|
||||||
// calls the cfunction, verifies that the number of return values is as
|
// calls the cfunction, verifies that the number of return values is as
|
||||||
// expected, and pops the return values into LuaVars.
|
// expected, and pops the return values into LuaVars.
|
||||||
@@ -482,6 +470,23 @@ public:
|
|||||||
void call(T&... args) {
|
void call(T&... args) {
|
||||||
call_cfunction<0>(lua_gettop(L_), args...);
|
call_cfunction<0>(lua_gettop(L_), args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Lua flagbits manipulation: Table types.
|
||||||
|
enum TableType {
|
||||||
|
TAB_GENERAL, // A general-purpose table.
|
||||||
|
TAB_REGISTRY, // The registry table.
|
||||||
|
TAB_GLOBALENV, // The global environment table.
|
||||||
|
TAB_TANGIBLE, // A tangible's database.
|
||||||
|
TAB_TANGIBLEMETA, // A tangible's metatable.
|
||||||
|
TAB_GLOBALDB, // Part of the globaldb.
|
||||||
|
TAB_CLASS, // A class which is directly reachable from the global environment.
|
||||||
|
};
|
||||||
|
TableType gettabletype(LuaSlot tab);
|
||||||
|
void settabletype(LuaSlot tab, TableType t);
|
||||||
|
|
||||||
|
// Lua flagbits manipulation: visited bit.
|
||||||
|
bool getvisited(LuaSlot tab);
|
||||||
|
void setvisited(LuaSlot tab, bool visited);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ World::World(util::WorldType wt) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Prepare to manipulate the lua state.
|
// Prepare to manipulate the lua state.
|
||||||
LuaVar world;
|
LuaVar world, globtab;
|
||||||
LuaStack LS(state(), world);
|
LuaStack LS(state(), world, globtab);
|
||||||
|
|
||||||
// Put the world pointer into the lua registry.
|
// Put the world pointer into the lua registry.
|
||||||
World::store_global_pointer(state(), this);
|
World::store_global_pointer(state(), this);
|
||||||
@@ -47,6 +47,13 @@ World::World(util::WorldType wt) {
|
|||||||
// Clear the global GUI pointer.
|
// Clear the global GUI pointer.
|
||||||
Gui::store_global_pointer(state(), nullptr);
|
Gui::store_global_pointer(state(), nullptr);
|
||||||
|
|
||||||
|
// Set the tabletype of the registry.
|
||||||
|
LS.settabletype(LuaRegistry, LuaStack::TAB_REGISTRY);
|
||||||
|
|
||||||
|
// Set the tabletype of the global environment.
|
||||||
|
LS.getglobaltable(globtab);
|
||||||
|
LS.settabletype(globtab, LuaStack::TAB_GLOBALENV);
|
||||||
|
|
||||||
// Create the tangibles table in the registry.
|
// Create the tangibles table in the registry.
|
||||||
LS.rawset(LuaRegistry, "tangibles", LuaNewTable);
|
LS.rawset(LuaRegistry, "tangibles", LuaNewTable);
|
||||||
|
|
||||||
@@ -230,6 +237,10 @@ Tangible *World::tangible_make(lua_State *L, int64_t id, bool pushdb) {
|
|||||||
LS.set(metatab, LuaNewTable);
|
LS.set(metatab, LuaNewTable);
|
||||||
LS.setmetatable(database, metatab);
|
LS.setmetatable(database, metatab);
|
||||||
|
|
||||||
|
// Mark the tangible using the tabletype field.
|
||||||
|
LS.settabletype(database, LuaStack::TAB_TANGIBLE);
|
||||||
|
LS.settabletype(metatab, LuaStack::TAB_TANGIBLEMETA);
|
||||||
|
|
||||||
// Store the database into the tangibles table.
|
// Store the database into the tangibles table.
|
||||||
LS.rawget(tangibles, LuaRegistry, "tangibles");
|
LS.rawget(tangibles, LuaRegistry, "tangibles");
|
||||||
LS.rawset(tangibles, id, database);
|
LS.rawset(tangibles, id, database);
|
||||||
@@ -857,6 +868,33 @@ LuaDefine(world_getregistry, "f") {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LuaDefine(world_gettabletype, "f") {
|
||||||
|
LuaArg tab;
|
||||||
|
LuaRet ttype;
|
||||||
|
LuaStack LS(L, tab, ttype);
|
||||||
|
if (LS.istable(tab)) {
|
||||||
|
LuaStack::TableType tt = LS.gettabletype(tab);
|
||||||
|
LS.set(ttype, int(tt));
|
||||||
|
} else {
|
||||||
|
luaL_error(L, "Not a table");
|
||||||
|
}
|
||||||
|
return LS.result();
|
||||||
|
}
|
||||||
|
|
||||||
|
LuaDefine(world_settabletype, "f") {
|
||||||
|
LuaArg tab, ttype;
|
||||||
|
LuaStack LS(L, tab, ttype);
|
||||||
|
if (!LS.istable(tab)) {
|
||||||
|
luaL_error(L, "Not a table");
|
||||||
|
}
|
||||||
|
int tt = LS.ckinteger(ttype);
|
||||||
|
if ((tt < 0) || (tt > 15)) {
|
||||||
|
luaL_error(L, "table type out of range");
|
||||||
|
}
|
||||||
|
LS.settabletype(tab, LuaStack::TableType(tt));
|
||||||
|
return LS.result();
|
||||||
|
}
|
||||||
|
|
||||||
static bool worlds_identical(const std::unique_ptr<World> &w1, const std::unique_ptr<World> &w2) {
|
static bool worlds_identical(const std::unique_ptr<World> &w1, const std::unique_ptr<World> &w2) {
|
||||||
StreamBuffer sbw1, sbw2;
|
StreamBuffer sbw1, sbw2;
|
||||||
w1->serialize(&sbw1);
|
w1->serialize(&sbw1);
|
||||||
|
|||||||
Reference in New Issue
Block a user