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. eng::vector<eng::string> SourceDB::modules() {
// eng::vector<eng::string> result;
static eng::string source_load_lfunctions(lua_State *L) { LuaVar sourcedb, key, info, seq;
LuaVar sourcedb, key, info, seq, closure, err; LuaExtStack LS(lua_state_, sourcedb, key, info, seq);
LuaExtStack LS(L, sourcedb, key, info, seq, closure, err);
result.push_back("CORE");
// Get the source database. // Get the source database.
LS.rawget(sourcedb, LuaRegistry, "sourcedb"); LS.rawget(sourcedb, LuaRegistry, "sourcedb");
if (LS.type(sourcedb) != LUA_TTABLE) { if (!LS.istable(sourcedb)) {
LS.newtable(sourcedb); return result;
LS.rawset(LuaRegistry, "sourcedb", sourcedb);
} }
// Sort the keys by sequence number. // 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); indices[LS.ckinteger(seq)] = LS.ckstring(key);
} }
// Now call the closures in the proper order. for (const auto &pair : indices) {
eng::ostringstream errss; result.push_back(pair.second);
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;
}
} }
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() { eng::string SourceDB::rebuild_module(const eng::string &mod) {
lua_State *L = lua_state_; if (mod == "CORE") {
LuaExtStack LS(L); rebuild_core();
source_clear_globals(L); return "";
source_load_cfunctions(L); } else {
source_load_cconstants(L); LuaVar sourcedb, info, closure;
eng::string errs = source_load_lfunctions(L); LuaExtStack LS(lua_state_, sourcedb, info, closure);
return errs; 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() { void SourceDB::run_unittests() {
@@ -407,8 +409,8 @@ void SourceDB::init(lua_State *L) {
LS.setmetatable(nullstring, classtab); LS.setmetatable(nullstring, classtab);
// Rebuild the global environment. // Rebuild the global environment.
rebuild(); rebuild_core();
// We need to register all C functions with the eris permanents tables. // We need to register all C functions with the eris permanents tables.
LS.rawget(persist, LuaRegistry, "persist"); LS.rawget(persist, LuaRegistry, "persist");
LS.rawget(unpersist, LuaRegistry, "unpersist"); LS.rawget(unpersist, LuaRegistry, "unpersist");

View File

@@ -141,17 +141,33 @@ public:
// //
void update(const util::LuaSourceVec &source); void update(const util::LuaSourceVec &source);
// Rebuild // modules
// //
// Rebuild the lua environment: clear it out, then reinstall all the // Returns a list of all the modules. The first item in the list
// functions that should be there. See above for more information. // 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 eng::vector<eng::string> modules();
// containing one error per line, and returned. If the return value
// is the empty string, there were no errors.
//
eng::string rebuild();
// 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. // Difference transmission.
// //
// Note: The patch routine applies the differences to the source // 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. // Create the globaldb in the registry.
LS.rawset(LuaRegistry, "globaldb", LuaNewTable); LS.rawset(LuaRegistry, "globaldb", LuaNewTable);
// Initialize the SourceDB. At this stage, the sourcedb is // Initialize the SourceDB.
// empty, so it's just populating the lua builtins.
source_db_.init(state()); source_db_.init(state());
eng::string srcerrs = source_db_.rebuild();
// Clear the clock. // Clear the clock.
clock_ = 0; clock_ = 0;
// Initialize global variable state. // Initialize global variable state.
assign_seqno_ = 1; 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(); LS.result();
assert (stack_is_clear()); 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) { void World::update_source(const util::LuaSourceVec &source) {
assert(stack_is_clear()); assert(stack_is_clear());
source_db_.update(source); source_db_.update(source);
assert(stack_is_clear()); rebuild_sourcedb();
eng::string errs = source_db_.rebuild();
util::dprint(errs);
assert(stack_is_clear()); assert(stack_is_clear());
} }

View File

@@ -292,9 +292,8 @@ void World::patch_source(StreamBuffer *sb, DebugCollector *dbc) {
DebugBlock dbb(dbc, "patch_source"); DebugBlock dbb(dbc, "patch_source");
bool modified = source_db_.patch(sb, dbc); bool modified = source_db_.patch(sb, dbc);
if (modified) { if (modified) {
eng::string errs = source_db_.rebuild(); rebuild_sourcedb();
DebugLine(dbc) << "Source DB rebuilt"; 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::LuaSourcePtr &source);
void update_source(const util::LuaSourceVec &source); void update_source(const util::LuaSourceVec &source);
// Rebuild the source database.
//
void rebuild_sourcedb();
// Supply an HTTP response to an outstanding HTTP request. // Supply an HTTP response to an outstanding HTTP request.
// //
void http_response(const HttpParser &response); void http_response(const HttpParser &response);
@@ -416,7 +420,7 @@ public:
// Get a global variable as json. // Get a global variable as json.
// //
eng::string get_global_json(const eng::string &gvar); eng::string get_global_json(const eng::string &gvar);
public: public:
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
// //