Work on SourceDB:rebuild
This commit is contained in:
@@ -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;
|
||||
for (const auto &pair : indices) {
|
||||
result.push_back(pair.second);
|
||||
}
|
||||
|
||||
// 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() {
|
||||
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,7 +409,7 @@ 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");
|
||||
|
||||
@@ -141,16 +141,32 @@ 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::vector<eng::string> modules();
|
||||
|
||||
// rebuild_module
|
||||
//
|
||||
eng::string rebuild();
|
||||
// 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.
|
||||
//
|
||||
|
||||
@@ -67,10 +67,8 @@ 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;
|
||||
@@ -78,10 +76,6 @@ World::World(WorldType wt) {
|
||||
// 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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user