Work on SourceDB:rebuild

This commit is contained in:
2023-04-10 17:58:44 -04:00
parent 005ce0629e
commit 972f0095c6
5 changed files with 94 additions and 60 deletions

View File

@@ -302,17 +302,17 @@ static void source_load_cconstants(lua_State *L) {
}
}
// Run all the closures from the source database.
//
static eng::string source_load_lfunctions(lua_State *L) {
LuaVar sourcedb, key, info, seq, closure, err;
LuaExtStack LS(L, sourcedb, key, info, seq, closure, err);
eng::vector<eng::string> SourceDB::modules() {
eng::vector<eng::string> result;
LuaVar sourcedb, key, info, seq;
LuaExtStack LS(lua_state_, sourcedb, key, info, seq);
result.push_back("CORE");
// Get the source database.
LS.rawget(sourcedb, LuaRegistry, "sourcedb");
if (LS.type(sourcedb) != LUA_TTABLE) {
LS.newtable(sourcedb);
LS.rawset(LuaRegistry, "sourcedb", sourcedb);
if (!LS.istable(sourcedb)) {
return result;
}
// Sort the keys by sequence number.
@@ -323,38 +323,40 @@ static eng::string source_load_lfunctions(lua_State *L) {
indices[LS.ckinteger(seq)] = LS.ckstring(key);
}
// Now call the closures in the proper order.
eng::ostringstream errss;
for (const auto &p : indices) {
LS.rawget(info, sourcedb, p.second);
LS.rawget(closure, info, "loadresult");
// If there's already an error in the sourcedb, collect it.
if (!LS.isfunction(closure)) {
errss << LS.ckstring(closure) << "\n";
continue;
}
// Call the closure. If there's an error, collect it.
lua_pushvalue(L, closure.index());
eng::string msg = traceback_pcall(L, 0, 0);
if (!msg.empty()) {
LS.set(err, msg);
errss << msg << std::endl;
}
for (const auto &pair : indices) {
result.push_back(pair.second);
}
return errss.str();
return result;
}
void SourceDB::rebuild_core() {
source_clear_globals(lua_state_);
source_load_cfunctions(lua_state_);
source_load_cconstants(lua_state_);
}
eng::string SourceDB::rebuild() {
lua_State *L = lua_state_;
LuaExtStack LS(L);
source_clear_globals(L);
source_load_cfunctions(L);
source_load_cconstants(L);
eng::string errs = source_load_lfunctions(L);
return errs;
eng::string SourceDB::rebuild_module(const eng::string &mod) {
if (mod == "CORE") {
rebuild_core();
return "";
} else {
LuaVar sourcedb, info, closure;
LuaExtStack LS(lua_state_, sourcedb, info, closure);
LS.rawget(sourcedb, LuaRegistry, "sourcedb");
if (!LS.istable(sourcedb)) {
return "SourceDB not initialized";
}
LS.rawget(info, sourcedb, mod);
if (!LS.istable(info)) {
return util::ss("No such module: ", mod);
}
LS.rawget(closure, info, "loadresult");
if (!LS.isfunction(closure)) {
return util::ss(mod, ":", LS.ckstring(closure));
}
lua_pushvalue(lua_state_, closure.index());
return traceback_pcall(lua_state_, 0, 0);
}
}
void SourceDB::run_unittests() {
@@ -407,8 +409,8 @@ void SourceDB::init(lua_State *L) {
LS.setmetatable(nullstring, classtab);
// Rebuild the global environment.
rebuild();
rebuild_core();
// We need to register all C functions with the eris permanents tables.
LS.rawget(persist, LuaRegistry, "persist");
LS.rawget(unpersist, LuaRegistry, "unpersist");

View File

@@ -141,17 +141,33 @@ public:
//
void update(const util::LuaSourceVec &source);
// Rebuild
// modules
//
// Rebuild the lua environment: clear it out, then reinstall all the
// functions that should be there. See above for more information.
// Returns a list of all the modules. The first item in the list
// is always the string "CORE" which represents the lua core
// functionality with all the builtins. This is then followed by
// all the lua sourcefiles in the correct order.
//
// Any error messages will be collected into a single long string
// containing one error per line, and returned. If the return value
// is the empty string, there were no errors.
//
eng::string rebuild();
eng::vector<eng::string> modules();
// rebuild_module
//
// To rebuild the lua environment, fetch the module list, then
// call rebuild_module on each module in turn. This will return
// an error message for the module, or empty string if no error.
//
// This is a thin wrapper around traceback_pcall. The return
// value is the return value of traceback_pcall.
//
eng::string rebuild_module(const eng::string &mod);
// rebuild_core
//
// This is equivalent to rebuild_module("CORE"). Clears the environment
// and installs all the builtins. No error conditions.
//
void rebuild_core();
// Difference transmission.
//
// Note: The patch routine applies the differences to the source

View File

@@ -67,21 +67,15 @@ World::World(WorldType wt) {
// Create the globaldb in the registry.
LS.rawset(LuaRegistry, "globaldb", LuaNewTable);
// Initialize the SourceDB. At this stage, the sourcedb is
// empty, so it's just populating the lua builtins.
// Initialize the SourceDB.
source_db_.init(state());
eng::string srcerrs = source_db_.rebuild();
// Clear the clock.
clock_ = 0;
// Initialize global variable state.
assign_seqno_ = 1;
// There shouldn't be any lua errors in the sourceDB at this
// point, since there's no lua code in the sourceDB.
assert(srcerrs == "");
LS.result();
assert (stack_is_clear());
}
@@ -372,12 +366,31 @@ void World::update_source(const util::LuaSourcePtr &source) {
}
}
// This is called from World::update_source, and also
// from World::patch_source in the difference transmitter.
//
// For the moment, errors are channeled to util::dprint,
// and 'print' statements just go to std::cerr. Neither
// of these is ideal. We need to get serious about setting
// up error handling.
//
// We also need to figure out a solution for what happens if
// some lua source file tries to modify, say, tangible state
// in top-level code.
//
void World::rebuild_sourcedb() {
for (const eng::string &mod: source_db_.modules()) {
eng::string err = source_db_.rebuild_module(mod);
if (!err.empty()) {
util::dprint(err);
}
}
}
void World::update_source(const util::LuaSourceVec &source) {
assert(stack_is_clear());
source_db_.update(source);
assert(stack_is_clear());
eng::string errs = source_db_.rebuild();
util::dprint(errs);
rebuild_sourcedb();
assert(stack_is_clear());
}

View File

@@ -292,9 +292,8 @@ void World::patch_source(StreamBuffer *sb, DebugCollector *dbc) {
DebugBlock dbb(dbc, "patch_source");
bool modified = source_db_.patch(sb, dbc);
if (modified) {
eng::string errs = source_db_.rebuild();
rebuild_sourcedb();
DebugLine(dbc) << "Source DB rebuilt";
util::dprint(errs);
}
}

View File

@@ -209,6 +209,10 @@ public:
void update_source(const util::LuaSourcePtr &source);
void update_source(const util::LuaSourceVec &source);
// Rebuild the source database.
//
void rebuild_sourcedb();
// Supply an HTTP response to an outstanding HTTP request.
//
void http_response(const HttpParser &response);
@@ -416,7 +420,7 @@ public:
// Get a global variable as json.
//
eng::string get_global_json(const eng::string &gvar);
public:
///////////////////////////////////////////////////////////
//