Convert sourcedb to new LuaStack stuff

This commit is contained in:
2023-04-07 15:49:50 -04:00
parent 4f0713c9cb
commit 9d593cc767
3 changed files with 81 additions and 77 deletions

View File

@@ -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 "<nonexistent>";
}
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();

View File

@@ -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.

View File

@@ -361,14 +361,14 @@ public:
// send_to_stream: send all arguments to the specified stream.
inline void send_to_stream(std::ostream &os) {}
template <class ARG, class... REST>
template <typename ARG, typename... REST>
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 <class... ARGS>
template <typename... ARGS>
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 <class... ARGS>
template <typename... ARGS>
inline void dprint(const ARGS & ... args) {
util::ostringstream oss;
send_to_stream(oss, args...);