From 972f0095c68c689c68b2fb887e720035f1171f01 Mon Sep 17 00:00:00 2001 From: jyelon Date: Mon, 10 Apr 2023 17:58:44 -0400 Subject: [PATCH] Work on SourceDB:rebuild --- luprex/cpp/core/source.cpp | 78 +++++++++++++++--------------- luprex/cpp/core/source.hpp | 32 +++++++++--- luprex/cpp/core/world-core.cpp | 35 +++++++++----- luprex/cpp/core/world-diffxmit.cpp | 3 +- luprex/cpp/core/world.hpp | 6 ++- 5 files changed, 94 insertions(+), 60 deletions(-) diff --git a/luprex/cpp/core/source.cpp b/luprex/cpp/core/source.cpp index 7a940a48..636f6b2d 100644 --- a/luprex/cpp/core/source.cpp +++ b/luprex/cpp/core/source.cpp @@ -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 SourceDB::modules() { + eng::vector 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"); diff --git a/luprex/cpp/core/source.hpp b/luprex/cpp/core/source.hpp index bb86aca7..30afd7b1 100644 --- a/luprex/cpp/core/source.hpp +++ b/luprex/cpp/core/source.hpp @@ -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 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 diff --git a/luprex/cpp/core/world-core.cpp b/luprex/cpp/core/world-core.cpp index fb1f2543..37683807 100644 --- a/luprex/cpp/core/world-core.cpp +++ b/luprex/cpp/core/world-core.cpp @@ -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()); } diff --git a/luprex/cpp/core/world-diffxmit.cpp b/luprex/cpp/core/world-diffxmit.cpp index cee9ceba..99e979f8 100644 --- a/luprex/cpp/core/world-diffxmit.cpp +++ b/luprex/cpp/core/world-diffxmit.cpp @@ -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); } } diff --git a/luprex/cpp/core/world.hpp b/luprex/cpp/core/world.hpp index 67744725..3980bf40 100644 --- a/luprex/cpp/core/world.hpp +++ b/luprex/cpp/core/world.hpp @@ -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: /////////////////////////////////////////////////////////// //