From 9d593cc767b318d39017075a9644ba7269ca0280 Mon Sep 17 00:00:00 2001 From: jyelon Date: Fri, 7 Apr 2023 15:49:50 -0400 Subject: [PATCH] Convert sourcedb to new LuaStack stuff --- luprex/cpp/core/source.cpp | 150 +++++++++++++++++++------------------ luprex/cpp/core/source.hpp | 2 + luprex/cpp/core/util.hpp | 6 +- 3 files changed, 81 insertions(+), 77 deletions(-) diff --git a/luprex/cpp/core/source.cpp b/luprex/cpp/core/source.cpp index f13a8ac2..0ebcfe72 100644 --- a/luprex/cpp/core/source.cpp +++ b/luprex/cpp/core/source.cpp @@ -93,8 +93,8 @@ static void calculate_loadresult(LuaCoreStack &LS0, LuaSlot info, const eng::str void SourceDB::diff(const SourceDB &auth, StreamBuffer *sb) { LuaVar sdb, sfn, sinfo, shash, sseq; LuaVar mdb, mfn, minfo, mhash, mseq, mcode; - LuaOldStack SLS(lua_state_, sdb, sfn, sinfo, shash, sseq); - LuaOldStack MLS(auth.lua_state_, mdb, mfn, minfo, mhash, mseq, mcode); + LuaExtStack SLS(lua_state_, sdb, sfn, sinfo, shash, sseq); + LuaExtStack MLS(auth.lua_state_, mdb, mfn, minfo, mhash, mseq, mcode); sb->write_int32(0); int wc_after = sb->total_writes(); int nupdates = 0; @@ -145,14 +145,12 @@ void SourceDB::diff(const SourceDB &auth, StreamBuffer *sb) { } } sb->overwrite_int32(wc_after, nupdates); - MLS.result(); - SLS.result(); } bool SourceDB::patch(StreamBuffer *sb, DebugCollector *dbc) { lua_State *L = lua_state_; LuaVar db, info; - LuaOldStack LS(L, db, info); + LuaExtStack LS(L, db, info); LS.rawget(db, LuaRegistry, "sourcedb"); int nupdates = sb->read_int32(); for (int i = 0; i < nupdates; i++) { @@ -172,14 +170,13 @@ bool SourceDB::patch(StreamBuffer *sb, DebugCollector *dbc) { } } } - LS.result(); return (nupdates > 0); } void SourceDB::set(const eng::string &fn, const eng::string &code, int sequence) { lua_State *L = lua_state_; LuaVar db, info; - LuaOldStack LS(L, db, info); + LuaExtStack LS(L, db, info); LS.rawget(db, LuaRegistry, "sourcedb"); get_info_table(LS, db, info, fn); LS.rawset(info, "sequence", sequence); @@ -187,17 +184,15 @@ void SourceDB::set(const eng::string &fn, const eng::string &code, int sequence) LS.rawset(info, "fingerprint", ""); LS.rawset(info, "hash", util::hash_to_hex(util::hash_string(code))); calculate_loadresult(LS, info, fn, code); - LS.result(); } eng::string SourceDB::get(const eng::string &fn) { lua_State *L = lua_state_; LuaVar db, info, code, sequence, loadresult; - LuaOldStack LS(L, db, info, code, sequence, loadresult); + LuaExtStack LS(L, db, info, code, sequence, loadresult); LS.rawget(db, LuaRegistry, "sourcedb"); LS.rawget(info, db, fn); if (!LS.istable(info)) { - LS.result(); return ""; } LS.rawget(code, info, "code"); @@ -211,16 +206,13 @@ eng::string SourceDB::get(const eng::string &fn) { } else { cloadresult = LS.ckstring(loadresult); } - eng::ostringstream oss; - oss << seqno << ":" << ccode << ":" << cloadresult; - LS.result(); - return oss.str(); + return util::ss(seqno, ":", ccode, ":", cloadresult); } void SourceDB::update(const util::LuaSourceVec &source) { lua_State *L = lua_state_; LuaVar sourcedb, info; - LuaOldStack LS(L, sourcedb, info); + LuaExtStack LS(L, sourcedb, info); // Get and clear the source database. LS.rawget(sourcedb, LuaRegistry, "sourcedb"); @@ -233,7 +225,7 @@ void SourceDB::update(const util::LuaSourceVec &source) { for (int i = 0; i < int(source.size()); i++) { const eng::string &file = source[i].first; const eng::string &code = source[i].second; - std::cerr << "Compiling " << file << std::endl; + util::dprint("Compiling ", file); LS.newtable(info); LS.rawset(info, "name", file); LS.rawset(info, "code", code); @@ -242,7 +234,6 @@ void SourceDB::update(const util::LuaSourceVec &source) { calculate_loadresult(LS, info, file, code); LS.rawset(sourcedb, file, info); } - LS.result(); } // Delete everything from the global environment. @@ -270,7 +261,7 @@ static void source_clear_globals(lua_State *L) { // static void source_load_cfunctions(lua_State *L) { LuaVar classobj; - LuaOldStack LS(L, classobj); + LuaExtStack LS(L, classobj); for (auto r = LuaFunctionReg::All; r != nullptr; r=r->next()) { lua_CFunction func = r->get_func(); if ((func != nullptr) && (!r->get_sandbox())) { @@ -286,14 +277,13 @@ static void source_load_cfunctions(lua_State *L) { } } } - LS.result(); } // Load all the 'LuaConstant' constants into the lua state. // static void source_load_cconstants(lua_State *L) { LuaVar classobj, value; - LuaOldStack LS(L, classobj, value); + LuaExtStack LS(L, classobj, value); for (auto r = LuaConstantReg::All; r != nullptr; r=r->next()) { if (r->get_tokenvalue().empty()) { LS.set(value, r->get_numbervalue()); @@ -311,14 +301,13 @@ static void source_load_cconstants(lua_State *L) { LS.rawset(classobj, funcname, value); } } - LS.result(); } // Run all the closures from the source database. // static eng::string source_load_lfunctions(lua_State *L) { LuaVar sourcedb, key, info, seq, closure, err; - LuaOldStack LS(L, sourcedb, key, info, seq, closure, err); + LuaExtStack LS(L, sourcedb, key, info, seq, closure, err); // Get the source database. LS.rawget(sourcedb, LuaRegistry, "sourcedb"); @@ -355,27 +344,24 @@ static eng::string source_load_lfunctions(lua_State *L) { errss << msg << std::endl; } } - LS.result(); return errss.str(); } eng::string SourceDB::rebuild() { lua_State *L = lua_state_; - LuaVar mathclass, httpclass, jsonnull; - LuaOldStack LS(L, mathclass, httpclass, jsonnull); + LuaExtStack LS(L); source_clear_globals(L); source_load_cfunctions(L); source_load_cconstants(L); eng::string errs = source_load_lfunctions(L); - LS.result(); return errs; } void SourceDB::run_unittests() { lua_State *L = lua_state_; LuaVar unittests, name, func, err, globtab; - LuaOldStack LS(L, unittests, name, func, err, globtab); + LuaExtStack LS(L, unittests, name, func, err, globtab); LS.getglobaltable(globtab); LS.rawget(unittests, globtab, "unittests"); @@ -407,13 +393,12 @@ void SourceDB::run_unittests() { if (any) { exit(1); } - LS.result(); } void SourceDB::init(lua_State *L) { lua_state_ = L; LuaVar globtab, persist, unpersist, classname, classtab, funcname, funcp, rawfunc, nullstring; - LuaOldStack LS(L, globtab, persist, unpersist, classname, classtab, funcname, funcp, rawfunc, nullstring); + LuaExtStack LS(L, globtab, persist, unpersist, classname, classtab, funcname, funcp, rawfunc, nullstring); LS.getglobaltable(globtab); LS.rawset(LuaRegistry, "sourcedb", LuaNewTable); @@ -467,61 +452,78 @@ void SourceDB::deserialize_source(util::LuaSourceVec *sv, StreamBuffer *sb) { } } -// This function should not touch the dlmalloc heap. +// Register lua builtins. +// +// To find the lua builtins, we use this approach: we create a new lua state +// (the 'prototype', we call it), and we call luaL_openlibs on it. The +// prototype should now contain all the builtins. +// +// Then, we iterate over our function registry, looking for LuaDefineBuiltin +// records. These records don't have a function pointer yet. For each such +// record, we look into the prototype, and look up the function in the global +// environment. If it's not found, we print an error. If we find it, we extract +// the C function pointer from it. Then, we remove the function from the +// prototype, to indicate that we already processed that function. +// +// At the end, we scan the prototype to make sure all functions have been +// removed. If not, we know our function registry is missing something and we +// print out an error. +// void SourceDB::register_lua_builtins() { lua_State *L = LuaCoreStack::newstate(nullptr); luaL_openlibs(L); - LuaVar globals, lclassname, lfuncname, classtab, func; - LuaOldStack LS(L, globals, lclassname, lfuncname, classtab, func); - LS.getglobaltable(globals); + { + LuaVar globals, lclassname, lfuncname, classtab, func; + LuaExtStack LS(L, globals, lclassname, lfuncname, classtab, func); + LS.getglobaltable(globals); - // Iterate over the function registry, copying function pointers from - // the prototype lua state into the registry, then remove the closure - // from the prototype. - for (auto reg = LuaFunctionReg::All; reg != nullptr; reg=reg->next()) { - std::string_view funcname; - std::string_view classname; - get_reg_name(reg->get_name(), classname, funcname); - if (classname.empty()) { - LS.getglobaltable(classtab); - } else { - LS.rawget(classtab, globals, classname); - } - lua_CFunction builtin = nullptr; - if (LS.istable(classtab)) { - LS.rawget(func, classtab, funcname); - if (LS.iscfunction(func)) { - builtin = lua_tocfunction(L, func.index()); - LS.rawset(classtab, funcname, LuaNil); - } - } - if (reg->get_func() == nullptr) { - if (builtin == nullptr) { - if (!reg->get_sandbox()) { - std::cerr << "No such builtin function: " << classname << " " << funcname << std::endl; - } + // Iterate over the function registry, copying function pointers from + // the prototype lua state into the registry, then remove the closure + // from the prototype. + for (auto reg = LuaFunctionReg::All; reg != nullptr; reg=reg->next()) { + std::string_view funcname; + std::string_view classname; + get_reg_name(reg->get_name(), classname, funcname); + if (classname.empty()) { + LS.getglobaltable(classtab); } else { - reg->set_func(builtin); + LS.rawget(classtab, globals, classname); + } + lua_CFunction builtin = nullptr; + if (LS.istable(classtab)) { + LS.rawget(func, classtab, funcname); + if (LS.iscfunction(func)) { + builtin = lua_tocfunction(L, func.index()); + LS.rawset(classtab, funcname, LuaNil); + } + } + if (reg->get_func() == nullptr) { + if (builtin == nullptr) { + if (!reg->get_sandbox()) { + std::cerr << "No such builtin function: " << classname << " " << funcname << std::endl; + } + } else { + reg->set_func(builtin); + } } } - } - // Iterate over the prototype. All cfunctions should have been removed. - LS.set(lclassname, LuaNil); - while (LS.next(globals, lclassname, classtab)) { - if (LS.isstring(lclassname)) { - if (LS.istable(classtab)) { - LS.set(lfuncname, LuaNil); - while (LS.next(classtab, lfuncname, func)) { - if (LS.iscfunction(func)) { - std::cerr << "Failed to declare builtin: " << LS.ckstring(lclassname) << "." - << LS.ckstring(lfuncname) << std::endl; + // Iterate over the prototype. All cfunctions should have been removed. + LS.set(lclassname, LuaNil); + while (LS.next(globals, lclassname, classtab)) { + if (LS.isstring(lclassname)) { + if (LS.istable(classtab)) { + LS.set(lfuncname, LuaNil); + while (LS.next(classtab, lfuncname, func)) { + if (LS.iscfunction(func)) { + std::cerr << "Failed to declare builtin: " << LS.ckstring(lclassname) << "." + << LS.ckstring(lfuncname) << std::endl; + } } } } } } - lua_close(L); } @@ -529,7 +531,7 @@ void SourceDB::register_lua_builtins() { eng::string SourceDB::function_docs(const LuaCoreStack &LS0, LuaSlot fn) { lua_State *L = LS0.state(); LuaVar sourcedb, fname, finfo, code; - LuaOldStack LS(L, sourcedb, fname, finfo, code); + LuaExtStack LS(L, sourcedb, fname, finfo, code); if (LS.iscfunction(fn)) { lua_CFunction cfn = lua_tocfunction(L, fn.index()); @@ -606,7 +608,7 @@ eng::string SourceDB::function_docs(const LuaCoreStack &LS0, LuaSlot fn) { // These should go away eventually. They're for debugging. LuaDefine(coroutine_setnextid, "thread,id", "set the next id of a thread (debugging only)") { LuaArg co, lid; - LuaOldStack LS(L, co, lid); + LuaDefStack LS(L, co, lid); lua_State *CO = LS.ckthread(co); lua_Number id = LS.ckinteger(lid); lua_setnextid(CO, id); @@ -616,7 +618,7 @@ LuaDefine(coroutine_setnextid, "thread,id", "set the next id of a thread (debugg LuaDefine(coroutine_getnextid, "thread", "get the next id of a thread (debugging only)") { LuaArg co; LuaRet lid; - LuaOldStack LS(L, co, lid); + LuaDefStack LS(L, co, lid); lua_State *CO = LS.ckthread(co); LS.set(lid, lua_getnextid(CO)); return LS.result(); diff --git a/luprex/cpp/core/source.hpp b/luprex/cpp/core/source.hpp index 055551d0..bb86aca7 100644 --- a/luprex/cpp/core/source.hpp +++ b/luprex/cpp/core/source.hpp @@ -177,9 +177,11 @@ public: eng::string get(const eng::string &fn); // Add builtins to the global function registry. + // static void register_lua_builtins(); // Get function documentation. + // static eng::string function_docs(const LuaCoreStack &LS, LuaSlot slot); // Serialize and unserialize a source vector. diff --git a/luprex/cpp/core/util.hpp b/luprex/cpp/core/util.hpp index 17a2db65..55ffd654 100644 --- a/luprex/cpp/core/util.hpp +++ b/luprex/cpp/core/util.hpp @@ -361,14 +361,14 @@ public: // send_to_stream: send all arguments to the specified stream. inline void send_to_stream(std::ostream &os) {} -template +template inline void send_to_stream(std::ostream &os, const ARG &arg, const REST & ... rest) { os << arg; send_to_stream(os, rest...); } // ss: convert all arguments to a string by sending them to a stringstream. -template +template inline eng::string ss(const ARGS & ... args) { eng::ostringstream oss; send_to_stream(oss, args...); @@ -390,7 +390,7 @@ void dprintview(std::string_view view); void dprintf(const char *format, ...); void hook_dprint(void (*func)(const char *oneline, size_t size)); -template +template inline void dprint(const ARGS & ... args) { util::ostringstream oss; send_to_stream(oss, args...);