2020-11-13 18:17:47 -05:00
|
|
|
#include "lpx-classdb.hpp"
|
|
|
|
|
#include "lpx-table.hpp"
|
|
|
|
|
|
|
|
|
|
// Get an entry from the class database.
|
|
|
|
|
//
|
|
|
|
|
// DB, CLASSNAME
|
|
|
|
|
// if classname is already present, and is a table, return it.
|
|
|
|
|
// if classname is already present, and not a table, error.
|
|
|
|
|
// if classname is not present, create and initialize it.
|
2020-11-15 16:49:42 -05:00
|
|
|
//
|
2020-11-13 18:17:47 -05:00
|
|
|
int lpx_classdb_get(lua_State *L) {
|
2020-11-15 16:49:42 -05:00
|
|
|
LpxArg db, classname;
|
|
|
|
|
LpxRet classtab;
|
|
|
|
|
LpxVar action;
|
|
|
|
|
LpxStackManager LSM(L, db, classname, classtab, action);
|
2020-11-13 18:17:47 -05:00
|
|
|
|
2020-11-15 16:49:42 -05:00
|
|
|
LSM.checknometa(db);
|
|
|
|
|
luaL_checktype(L, classname, LUA_TSTRING);
|
|
|
|
|
LSM.rawget(classtab, db, classname);
|
|
|
|
|
if (lua_istable(L, classtab)) {
|
|
|
|
|
return LSM.retval();
|
|
|
|
|
} else if (!lua_isnil(L, classtab)) {
|
|
|
|
|
luaL_error(L, "%s is not a class", lua_tostring(L, classname));
|
|
|
|
|
}
|
|
|
|
|
LSM.newtable(classtab);
|
|
|
|
|
LSM.rawset(db, classname, classtab);
|
|
|
|
|
LSM.setfield(classtab, "__index", classtab);
|
|
|
|
|
LSM.setfield(classtab, "__class", classname);
|
|
|
|
|
LSM.newtable(action);
|
|
|
|
|
LSM.setfield(classtab, "action", action);
|
|
|
|
|
return LSM.retval();
|
2020-11-13 18:17:47 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Curried version of classdb.get where db is stored in an upvalue.
|
|
|
|
|
//
|
|
|
|
|
static int lpx_classdb_class(lua_State *L) {
|
|
|
|
|
lua_pushvalue(L, lua_upvalueindex(1));
|
2020-11-15 16:49:42 -05:00
|
|
|
lua_insert(L, -2);
|
2020-11-13 18:17:47 -05:00
|
|
|
return lpx_classdb_get(L);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int lpx_classdb_accessor(lua_State *L) {
|
2020-11-15 16:49:42 -05:00
|
|
|
luaL_checktype(L, -1, LUA_TTABLE);
|
|
|
|
|
lua_pushcclosure(L, LpxArgCheck<1, lpx_classdb_class>, 1);
|
2020-11-13 18:17:47 -05:00
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Reset a class database:
|
|
|
|
|
//
|
|
|
|
|
// Clear out all classes. Instead of replacing the class tables,
|
|
|
|
|
// it simply deletes all keys. That way, if somebody has a pointer
|
|
|
|
|
// to a class, the pointer is not invalidated.
|
|
|
|
|
//
|
|
|
|
|
// Caution: do not reset the global class database!
|
|
|
|
|
//
|
|
|
|
|
int lpx_classdb_reset(lua_State *L) {
|
2020-11-15 16:49:42 -05:00
|
|
|
LpxArg db;
|
|
|
|
|
LpxVar classname, classtab, action, key;
|
|
|
|
|
LpxStackManager LSM(L, db, classname, classtab, action, key);
|
|
|
|
|
|
2020-11-13 18:17:47 -05:00
|
|
|
luaL_checktype(L, db, LUA_TTABLE);
|
2020-11-15 16:49:42 -05:00
|
|
|
LSM.setnil(classname);
|
|
|
|
|
while (LSM.next(db, classname, classtab) != 0) {
|
|
|
|
|
if (lua_istable(L, classtab)) {
|
|
|
|
|
LSM.setstring(key, "action");
|
|
|
|
|
LSM.rawget(action, classtab, key);
|
|
|
|
|
if (lua_istable(L, action)) {
|
|
|
|
|
lua_pushvalue(L, action);
|
2020-11-13 18:17:47 -05:00
|
|
|
lpx_table_clear(L);
|
|
|
|
|
} else {
|
2020-11-15 16:49:42 -05:00
|
|
|
LSM.newtable(action);
|
2020-11-13 18:17:47 -05:00
|
|
|
}
|
2020-11-15 16:49:42 -05:00
|
|
|
lua_pushvalue(L, classtab);
|
2020-11-13 18:17:47 -05:00
|
|
|
lpx_table_clear(L);
|
2020-11-15 16:49:42 -05:00
|
|
|
LSM.setfield(classtab, "__index", classtab);
|
|
|
|
|
LSM.setfield(classtab, "__class", classname);
|
|
|
|
|
LSM.setfield(classtab, "action", action);
|
2020-11-13 18:17:47 -05:00
|
|
|
}
|
|
|
|
|
}
|
2020-11-15 16:49:42 -05:00
|
|
|
return LSM.retval();
|
2020-11-13 18:17:47 -05:00
|
|
|
}
|
|
|
|
|
|
2020-11-15 16:49:42 -05:00
|
|
|
// Create a classdb. That's just an empty table.
|
|
|
|
|
int lpx_classdb_create(lua_State *L) {
|
|
|
|
|
lua_newtable(L);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void luaopen_lpx_classdb(lua_State *L) {
|
|
|
|
|
LpxStackManager::reg(L, "classdb", "get", LpxArgCheck<2, lpx_classdb_get>);
|
|
|
|
|
LpxStackManager::reg(L, "classdb", "accessor", LpxArgCheck<1, lpx_classdb_accessor>);
|
|
|
|
|
LpxStackManager::reg(L, "classdb", "reset", LpxArgCheck<1, lpx_classdb_reset>);
|
|
|
|
|
LpxStackManager::reg(L, "classdb", "create", LpxArgCheck<0, lpx_classdb_create>);
|
|
|
|
|
|
|
|
|
|
// Insert the global function 'class', which is a closure with an upvalue.
|
2020-11-13 18:17:47 -05:00
|
|
|
lua_pushstring(L, "class");
|
|
|
|
|
lua_pushvalue(L, LUA_GLOBALSINDEX);
|
|
|
|
|
lpx_classdb_accessor(L);
|
|
|
|
|
lua_rawset(L, LUA_GLOBALSINDEX);
|
|
|
|
|
}
|