From 47c868876a594041462b3d6661fd0e22f89c0c95 Mon Sep 17 00:00:00 2001 From: jyelon Date: Fri, 14 Apr 2023 14:52:44 -0400 Subject: [PATCH 1/8] Add LuaDefineAlias --- luprex/cpp/core/http.cpp | 2 +- luprex/cpp/core/luastack.hpp | 12 ++++---- luprex/cpp/core/pprint.cpp | 22 +++----------- luprex/cpp/core/table.cpp | 58 ++++++++++++++++++++++++++---------- 4 files changed, 53 insertions(+), 41 deletions(-) diff --git a/luprex/cpp/core/http.cpp b/luprex/cpp/core/http.cpp index 2a8ae3d2..7f484250 100644 --- a/luprex/cpp/core/http.cpp +++ b/luprex/cpp/core/http.cpp @@ -683,7 +683,7 @@ void HttpClientRequest::set_params(LuaCoreStack &LS0, LuaSlot tab) { return; } LuaVar key, val; - LuaDefStack LS(LS0.state(), key, val); + LuaExtStack LS(LS0.state(), key, val); LS.set(key, LuaNil); while (LS.next(tab, key, val)) { set_param(LS, key, val); diff --git a/luprex/cpp/core/luastack.hpp b/luprex/cpp/core/luastack.hpp index d00a8f82..53ac2555 100644 --- a/luprex/cpp/core/luastack.hpp +++ b/luprex/cpp/core/luastack.hpp @@ -411,7 +411,7 @@ public: int rawlen(LuaSlot val) const; int nkeys(LuaSlot tab) const; - + int next(LuaSlot tab, LuaSlot key, LuaSlot value) const; // Return true if the classname is legal. @@ -902,13 +902,13 @@ public: #define LuaDefine(name, args, docs) \ int lfn_##name(lua_State *L); \ - LuaFunctionReg reg_##name(#name, args, docs, false, lfn_##name); \ + const char *lfnarg_##name = args; \ + const char *lfndoc_##name = docs; \ + LuaFunctionReg reg_##name(#name, lfnarg_##name, lfndoc_##name, false, lfn_##name); \ int lfn_##name(lua_State *L) -#define LuaSandbox(name, args, docs) \ - int lfn_##name(lua_State *L); \ - LuaFunctionReg reg_##name(#name, args, docs, true, lfn_##name); \ - int lfn_##name(lua_State *L) +#define LuaDefineAlias(name1, name2) \ + LuaFunctionReg reg_##name1(#name1, lfnarg_##name2, lfndoc_##name2, false, lfn_##name2); \ #define LuaDefineBuiltin(name, args, docs) \ LuaFunctionReg reg_##name(#name, args, docs, false, nullptr); diff --git a/luprex/cpp/core/pprint.cpp b/luprex/cpp/core/pprint.cpp index a786d766..e7a838d9 100644 --- a/luprex/cpp/core/pprint.cpp +++ b/luprex/cpp/core/pprint.cpp @@ -320,25 +320,9 @@ LuaDefine(string_print, "obj", "|Concise print the specified object into a string" "|" "|This prints a concise representation of obj into a string. Tables" - "|are not expanded: for that, use string.pprintx. The functions" - "|tostring and string.print are identical." - "|") { - LuaArg val; - LuaRet result; - LuaDefStack LS(L, val, result); - eng::ostringstream oss; - atomic_print(LS, val, false, &oss); - LS.set(result, oss.str()); - return LS.result(); -} - - -LuaDefine(tostring, "obj", - "|Concise print the specified object into a string" + "|are not expanded: for that, use string.pprint or string.pprintx." "|" - "|This prints a concise representation of obj into a string. Tables" - "|are not expanded: for that, use string.pprint. The functions" - "|tostring and string.print are identical." + "|The functions string.print and tostring are identical." "|") { LuaArg val; LuaRet result; @@ -349,6 +333,8 @@ LuaDefine(tostring, "obj", return LS.result(); } +LuaDefineAlias(tostring, string_print); + LuaDefine(string_isidentifier, "str", "return true if the string is a valid lua identifier") { LuaArg str; LuaRet result; diff --git a/luprex/cpp/core/table.cpp b/luprex/cpp/core/table.cpp index d6d7340f..cb5f9d19 100644 --- a/luprex/cpp/core/table.cpp +++ b/luprex/cpp/core/table.cpp @@ -60,7 +60,16 @@ LuaDefine(table_equal, "table1,table2", return LS.result(); } -static int check_isvector(lua_State *L) { +LuaDefine(table_isvector, "table", + "|Return true if the table is a valid vector." + "|" + "|A vector is a table that has keys starting with 1, and no gaps." + "|The empty table also counts as a valid vector. This function" + "|scans the entire vector to verify its validity, so it takes O(N)" + "|time. See also table.isvectorq" + "|" + "|The functions vector.isvector and table.isvector are identical." + "|") { LuaArg table; LuaRet result; LuaVar tmp; @@ -81,27 +90,44 @@ static int check_isvector(lua_State *L) { return LS.result(); } -LuaDefine(table_isvector, "table", - "|Return true if the table is a valid vector." +LuaDefine(table_isvectorq, "table", + "|Return true if the table is probably a valid vector." "|" "|A vector is a table that has keys starting with 1, and no gaps." - "|The empty table also counts as a valid vector." + "|The empty table also counts as a valid vector. This function" + "|does a constant-time heuristic check: it gets the number of keys" + "|in the table, NKEYS. Then it verifies that table[NKEYS] is not" + "|nil and that table[NKEYS+1] is nil. If these things are both" + "|true, the table is very likely a valid vector." "|" - "|This function is identical to vector.isvector" + "|The functions vector.isvectorq and table.isvectorq are identical." "|") { - return check_isvector(L); + LuaArg table; + LuaRet result; + LuaVar tmp; + LuaDefStack LS(L, table, result, tmp); + if (!LS.istable(table)) { + LS.set(result, false); + return LS.result(); + } + int nkeys = LS.nkeys(table); + if (nkeys > 0) { + LS.rawget(tmp, table, nkeys); + if (LS.isnil(tmp)) { + LS.set(result, false); + return LS.result(); + } + LS.rawget(tmp, table, nkeys + 1); + if (!LS.isnil(tmp)) { + LS.set(result, false); + return LS.result(); + } + } + LS.set(result, true); + return LS.result(); } -LuaDefine(vector_isvector, "table", - "|Return true if the table is a valid vector." - "|" - "|A vector is a table that has keys starting with 1, and no gaps." - "|The empty table also counts as a valid vector." - "|" - "|This function is identical to table.isvector" - "|") { - return check_isvector(L); -} +LuaDefineAlias(vector_isvector, table_isvector); LuaDefine(vector_removeall, "vector,value", "|Remove all occurrences of value from vector." From 167dfe909f9b33368d079bc9ae8ab5a585cfc21d Mon Sep 17 00:00:00 2001 From: jyelon Date: Fri, 14 Apr 2023 15:13:59 -0400 Subject: [PATCH 2/8] Removed some more LuaOldStack --- luprex/cpp/core/world-core.cpp | 2 +- luprex/cpp/core/world-testing.cpp | 25 ++++++++----------------- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/luprex/cpp/core/world-core.cpp b/luprex/cpp/core/world-core.cpp index 17a539c4..5ac1350a 100644 --- a/luprex/cpp/core/world-core.cpp +++ b/luprex/cpp/core/world-core.cpp @@ -386,7 +386,7 @@ void World::rebuild_sourcedb() { lthread_prints_.reset(); close_lthread_state(); if (!err.empty() || !prints.empty()) { - util::dprint("Loading Module ", mod,":"); + util::dprint("Loading Module ", mod); if (!err.empty()) util::dprint(err); if (!prints.empty()) util::dprint(prints); } diff --git a/luprex/cpp/core/world-testing.cpp b/luprex/cpp/core/world-testing.cpp index 3587a557..de160842 100644 --- a/luprex/cpp/core/world-testing.cpp +++ b/luprex/cpp/core/world-testing.cpp @@ -51,7 +51,7 @@ eng::string World::tangibles_near_debug_string(int64_t actor, int64_t distance) eng::string World::tangible_pprint(int64_t id) const { lua_State *L = state(); LuaVar tangibles, tan, meta; - LuaOldStack LS(L, tangibles, tan, meta); + LuaExtStack LS(L, tangibles, tan, meta); LS.rawget(tangibles, LuaRegistry, "tangibles"); LS.rawget(tan, tangibles, id); eng::ostringstream oss; @@ -62,14 +62,13 @@ eng::string World::tangible_pprint(int64_t id) const { } else { oss << "{}"; } - LS.result(); return oss.str(); } eng::string World::numbered_tables_debug_string() const { lua_State *L = state(); LuaVar ntmap, tab, tid; - LuaOldStack LS(L, ntmap, tab, tid); + LuaExtStack LS(L, ntmap, tab, tid); eng::vector result; eng::ostringstream oss; @@ -88,7 +87,6 @@ eng::string World::numbered_tables_debug_string() const { result.push_back("unknown"); } } - LS.result(); std::sort(result.begin(), result.end()); for (const eng::string &s : result) { oss << s << ";"; @@ -99,8 +97,8 @@ eng::string World::numbered_tables_debug_string() const { eng::string World::paired_tables_debug_string(lua_State *master) const { lua_State *synch = state(); LuaVar mntmap, sntmap, mtab, stab, mtid, stid; - LuaOldStack MLS(master, mntmap, mtab, mtid); - LuaOldStack SLS(synch, sntmap, stab, stid); + LuaExtStack MLS(master, mntmap, mtab, mtid); + LuaExtStack SLS(synch, sntmap, stab, stid); eng::vector> result; eng::ostringstream oss; @@ -128,8 +126,6 @@ eng::string World::paired_tables_debug_string(lua_State *master) const { result.push_back(std::make_pair(mname, sname)); } } - MLS.result(); - SLS.result(); std::sort(result.begin(), result.end()); for (const auto &pair : result) { oss << pair.first << "=" << pair.second << ";"; @@ -140,7 +136,7 @@ eng::string World::paired_tables_debug_string(lua_State *master) const { void World::tangible_set_string(int64_t id, const eng::string &path, const eng::string &value) { lua_State *L = state(); LuaVar tangibles, tab, subtab; - LuaOldStack LS(L, tangibles, tab, subtab); + LuaExtStack LS(L, tangibles, tab, subtab); // Fetch the lua side of the tangible. LS.rawget(tangibles, LuaRegistry, "tangibles"); @@ -166,14 +162,12 @@ void World::tangible_set_string(int64_t id, const eng::string &path, const eng:: // Set the string value. LS.rawset(tab, finalpart, value); - LS.result(); - assert(stack_is_clear()); } void World::tangible_copy_global(int64_t id, const eng::string &path, const eng::string &global) { lua_State *L = state(); LuaVar tangibles, tab, subtab, globtab, value; - LuaOldStack LS(L, tangibles, tab, subtab, globtab, value); + LuaExtStack LS(L, tangibles, tab, subtab, globtab, value); // Fetch the lua side of the tangible. LS.rawget(tangibles, LuaRegistry, "tangibles"); @@ -201,12 +195,11 @@ void World::tangible_copy_global(int64_t id, const eng::string &path, const eng: LS.getglobaltable(globtab); LS.rawget(value, globtab, global); LS.rawset(tab, finalpart, value); - LS.result(); } void World::tangible_set_class(int64_t id, const eng::string &c) const { LuaVar tangibles, tan, meta, sclass; - LuaOldStack LS(state(), tangibles, tan, meta, sclass); + LuaExtStack LS(state(), tangibles, tan, meta, sclass); LS.rawget(tangibles, LuaRegistry, "tangibles"); LS.rawget(tan, tangibles, id); assert(LS.istable(tan)); @@ -217,7 +210,6 @@ void World::tangible_set_class(int64_t id, const eng::string &c) const { LS.makeclass(sclass, c); } LS.rawset(meta, "__index", sclass); - LS.result(); } void World::set_global_json(const eng::string &gvar, const eng::string &json) { @@ -248,14 +240,13 @@ eng::string World::get_global_json(const eng::string &gvar) { eng::string World::tangible_get_class(int64_t id) const { LuaVar tangibles, tan, meta, sclass; - LuaOldStack LS(state(), tangibles, tan, meta, sclass); + LuaExtStack LS(state(), tangibles, tan, meta, sclass); LS.rawget(tangibles, LuaRegistry, "tangibles"); LS.rawget(tan, tangibles, id); assert(LS.istable(tan)); LS.getmetatable(meta, tan); LS.rawget(sclass, meta, "__index"); eng::string result = LS.classname(sclass); - LS.result(); return result; } From 69f2fb6226a739d9b96a387c75032e2ce3ef5dd7 Mon Sep 17 00:00:00 2001 From: jyelon Date: Fri, 14 Apr 2023 15:33:58 -0400 Subject: [PATCH 3/8] Overhaul tangible_make to get rid of LuaOldStack --- luprex/cpp/core/world-accessor.cpp | 3 +-- luprex/cpp/core/world-core.cpp | 39 +++++++++++------------------- luprex/cpp/core/world-diffxmit.cpp | 4 +-- luprex/cpp/core/world-testing.cpp | 26 ++++++++++---------- luprex/cpp/core/world.hpp | 9 ++++--- 5 files changed, 35 insertions(+), 46 deletions(-) diff --git a/luprex/cpp/core/world-accessor.cpp b/luprex/cpp/core/world-accessor.cpp index d447b2c9..0a9cf46e 100644 --- a/luprex/cpp/core/world-accessor.cpp +++ b/luprex/cpp/core/world-accessor.cpp @@ -167,8 +167,7 @@ LuaDefine(tangible_build, "config", World *w = World::fetch_global_pointer(L); int64_t new_id = w->alloc_id_predictable(); - Tangible *tan = w->tangible_make(L, new_id, "nowhere", true); - lua_replace(L, database.index()); + Tangible *tan = w->tangible_make(LS, database, new_id, "nowhere"); // Update the class of the new tangible. LS.getmetatable(mt, database); diff --git a/luprex/cpp/core/world-core.cpp b/luprex/cpp/core/world-core.cpp index 5ac1350a..403282a6 100644 --- a/luprex/cpp/core/world-core.cpp +++ b/luprex/cpp/core/world-core.cpp @@ -43,7 +43,7 @@ World::World(WorldType wt) { // Prepare to manipulate the lua state. LuaVar world, globtab; - LuaOldStack LS(state(), world, globtab); + LuaExtStack LS(state(), world, globtab); // Put the world pointer into the lua registry. World::store_global_pointer(state(), this); @@ -75,9 +75,6 @@ World::World(WorldType wt) { // Initialize global variable state. assign_seqno_ = 1; - - LS.result(); - assert (stack_is_clear()); } Tangible::Tangible(World *w, int64_t id) : world_(w), anim_queue_(w->world_type_), id_player_pool_(&w->id_global_pool_) { @@ -143,17 +140,10 @@ Tangible *World::tangible_get(const LuaCoreStack &LS, LuaSlot tab, bool allowdel return result; } -Tangible *World::tangible_make(lua_State *L, int64_t id, const eng::string &plane, bool pushdb) { - // Get a state if we don't already have one. - if (L == nullptr) { - L = state(); - assert(!pushdb); - } +Tangible *World::tangible_make(const LuaCoreStack &LS0, LuaSlot database, int64_t id, const eng::string &plane) { assert(id != 0); - LuaVar metatab; - LuaRet database; - LuaOldStack LS(L, database, metatab); + LuaExtStack LS(LS0.state(), metatab); // Create the C++ part of the structure. UniqueTangible &t = tangibles_[id]; @@ -171,21 +161,24 @@ Tangible *World::tangible_make(lua_State *L, int64_t id, const eng::string &plan // Set up the inventory and thread table. LS.rawset(database, "inventory", LuaNewTable); LS.rawset(metatab, "threads", LuaNewTable); - - LS.result(); - if (!pushdb) lua_pop(L, 1); + return t.get(); } +Tangible *World::tangible_make(int64_t id, const eng::string &plane) { + LuaVar database; + LuaExtStack LS(state(), database); + return tangible_make(LS, database, id, plane); +} + void World::tangible_delete(int64_t id) { lua_State *L = state(); LuaVar tangibles, database, metatab; - LuaOldStack LS(L, tangibles, database, metatab); + LuaExtStack LS(L, tangibles, database, metatab); // Fetch the C++ side of the tangible. auto iter = tangibles_.find(id); if (iter == tangibles_.end()) { - LS.result(); return; // Nothing to delete. } @@ -204,7 +197,6 @@ void World::tangible_delete(int64_t id) { // Remove the C++ portion from the tangibles table. tangibles_.erase(iter); - LS.result(); } util::IdVector World::get_near(int64_t player_id, float radius, bool exclude_nowhere, bool omit_player, bool sorted) const { @@ -235,17 +227,14 @@ World::Redirects World::fetch_redirects() { int64_t World::create_login_actor() { assert(stack_is_clear()); int64_t id = id_global_pool_.get_one(); - Tangible *tan = tangible_make(state(), id, "nowhere", true); - LuaArg database; - LuaVar classtab, mt; - LuaOldStack LS(state(), database, classtab, mt); + LuaVar database, classtab, mt; + LuaExtStack LS(state(), database, classtab, mt); + Tangible *tan = tangible_make(LS, database, id, "nowhere"); LS.makeclass(classtab, "login"); LS.getmetatable(mt, database); LS.rawset(mt, "__index", classtab); - LS.result(); tan->configure_id_pool_for_actor(); tan->print_buffer_.clear(); - assert(stack_is_clear()); return tan->id(); } diff --git a/luprex/cpp/core/world-diffxmit.cpp b/luprex/cpp/core/world-diffxmit.cpp index f4d56ebf..2ea2854a 100644 --- a/luprex/cpp/core/world-diffxmit.cpp +++ b/luprex/cpp/core/world-diffxmit.cpp @@ -14,7 +14,7 @@ int64_t World::patch_actor(StreamBuffer *sb, DebugCollector *dbc) { Tangible *s_actor = tangible_get(actor_id); if (s_actor == nullptr) { DebugLine(dbc) << "create new actor " << actor_id; - s_actor = tangible_make(nullptr, actor_id, "", false); + s_actor = tangible_make(actor_id, ""); s_actor->id_player_pool_.deserialize(sb); s_actor->anim_queue_.deserialize(sb); s_actor->print_buffer_.deserialize(sb); @@ -61,7 +61,7 @@ void World::patch_visible(StreamBuffer *sb, DebugCollector *dbc) { for (int i = 0; i < count; i++) { int64_t id = sb->read_int64(); DebugLine(dbc) << "patch_visible create tan " << id; - Tangible *t = tangible_make(state(), id, "", false); + Tangible *t = tangible_make(id, ""); t->anim_queue_.deserialize(sb); t->update_plane_item(); } diff --git a/luprex/cpp/core/world-testing.cpp b/luprex/cpp/core/world-testing.cpp index de160842..91ad2229 100644 --- a/luprex/cpp/core/world-testing.cpp +++ b/luprex/cpp/core/world-testing.cpp @@ -267,8 +267,8 @@ LuaDefine(unittests_world1animdiff, "", "some unit tests") { util::IdVector ids = util::id_vector_create(123, 345); // Create some tangibles, and add some animations. - m->tangible_make(0, 123, "somewhere", false); - m->tangible_make(0, 345, "somewhere", false); + m->tangible_make(123, "somewhere"); + m->tangible_make(345, "somewhere"); m->tangible_walkto(123, 770, 3, 4); m->tangible_walkto(345, 771, 6, 2); LuaAssertStrEq(L, m->tangible_ids_debug_string(), "123,345"); @@ -337,7 +337,7 @@ LuaDefine(unittests_world2pairtab, "", "some unit tests") { // Create a master model containing some general tables, and // some specialty tables (not numberable). - m->tangible_make(0, 123, "somewhere", false); + m->tangible_make(123, "somewhere"); m->tangible_set_string(123, "inventory.TID", "inventory"); m->tangible_set_string(123, "transactions.TID", "transactions"); m->tangible_set_string(123, "skills.TID", "skills"); @@ -348,7 +348,7 @@ LuaDefine(unittests_world2pairtab, "", "some unit tests") { // Now we're going to create a synchronous model that's similar to, but not // exactly the same as that master model. - ss->tangible_make(0, 123, "somewhere", false); + ss->tangible_make(123, "somewhere"); ss->tangible_set_string(123, "inventory.TID", "inventory"); ss->tangible_set_string(123, "skills.TID", "skills"); ss->tangible_set_string(123, "skills.crap.TID", "skills.crap"); @@ -384,12 +384,12 @@ LuaDefine(unittests_world3diffluatab, "", "some unit tests") { StreamBuffer sb; // Initialize all three models so that a tangible exists. - m->tangible_make(0, 123, "somewhere", false); - ss->tangible_make(0, 123, "somewhere", false); - cs->tangible_make(0, 123, "somewhere", false); - m->tangible_make(0, 345, "somewhere", false); - ss->tangible_make(0, 345, "somewhere", false); - cs->tangible_make(0, 345, "somewhere", false); + m->tangible_make(123, "somewhere"); + ss->tangible_make(123, "somewhere"); + cs->tangible_make(123, "somewhere"); + m->tangible_make(345, "somewhere"); + ss->tangible_make(345, "somewhere"); + cs->tangible_make(345, "somewhere"); // Put some data into the master model. m->tangible_set_string(123, "bacon", "crispy"); @@ -438,9 +438,9 @@ LuaDefine(unittests_world4difftanclass, "", "some unit tests") { StreamBuffer sb; // Initialize all three models so that a tangible exists. - m->tangible_make(0, 123, "somewhere", false); - ss->tangible_make(0, 123, "somewhere", false); - cs->tangible_make(0, 123, "somewhere", false); + m->tangible_make(123, "somewhere"); + ss->tangible_make(123, "somewhere"); + cs->tangible_make(123, "somewhere"); // Change the lua class of the tangible. m->tangible_set_class(123, "chicken"); diff --git a/luprex/cpp/core/world.hpp b/luprex/cpp/core/world.hpp index 3980bf40..2726d6c6 100644 --- a/luprex/cpp/core/world.hpp +++ b/luprex/cpp/core/world.hpp @@ -129,11 +129,12 @@ public: // Make a tangible. // - // You must provide a valid previously-unused ID. If pushdb is true, pushes - // the tangible's database onto the lua stack. Otherwise, leaves the lua - // stack untouched. + // You must provide a valid previously-unused ID. Otherwise, leaves the lua + // stack untouched. Returns a pointer to the C++ part of the tangible, and + // optionally stores the Lua part in a stack slot. // - Tangible *tangible_make(lua_State *L, int64_t id, const eng::string &plane, bool pushdb); + Tangible *tangible_make(const LuaCoreStack &LS0, LuaSlot tan, int64_t id, const eng::string &plane); + Tangible *tangible_make(int64_t id, const eng::string &plane); // Get a pointer to the specified tangible. // From 2c2dabc127c2bce085d268d06e739aeba6a99411 Mon Sep 17 00:00:00 2001 From: jyelon Date: Fri, 14 Apr 2023 17:01:59 -0400 Subject: [PATCH 4/8] Fix a bug in the driver, closing channel too soon --- luprex/cpp/drv/driver-common.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/luprex/cpp/drv/driver-common.cpp b/luprex/cpp/drv/driver-common.cpp index 78d81ef9..816d3073 100644 --- a/luprex/cpp/drv/driver-common.cpp +++ b/luprex/cpp/drv/driver-common.cpp @@ -449,8 +449,10 @@ class Driver { } if (chan.nbytes == 0) { if (engw.get_channel_released(&engw, chan.chid)) { - close_channel(chan, ""); - any_released = true; + if (BIO_pending(chan.send_bio) == 0) { + close_channel(chan, ""); + any_released = true; + } } } } From 669a5a50abea7c90836d477a3de905c39932c537 Mon Sep 17 00:00:00 2001 From: jyelon Date: Fri, 14 Apr 2023 17:50:06 -0400 Subject: [PATCH 5/8] Finally phase out LuaOldStack entirely. --- luprex/cpp/core/luastack.hpp | 132 ++------------- luprex/cpp/core/world-core.cpp | 296 +++++++++++++++------------------ 2 files changed, 143 insertions(+), 285 deletions(-) diff --git a/luprex/cpp/core/luastack.hpp b/luprex/cpp/core/luastack.hpp index 53ac2555..f6c2fd70 100644 --- a/luprex/cpp/core/luastack.hpp +++ b/luprex/cpp/core/luastack.hpp @@ -172,7 +172,6 @@ public: } friend class LuaCoreStack; - friend class LuaOldStack; friend class LuaDefStack; friend class LuaExtStack; }; @@ -529,125 +528,15 @@ public: static bool int64_storable(int64_t v) { return (v <= MAXINT) && (v >= -MAXINT); } }; -//////////////////////////////////////////////////////////////////// -// -// LuaOldStack -// -// This class is deprecated, we're phasing it out. This was the first piece of -// code we wrote to allocate stack slots, and it has issues. It is -// still in use in the difference transmitter and the source database, -// and a few other small spots. -// -//////////////////////////////////////////////////////////////////// - -class LuaOldStack : public LuaCoreStack { -private: - int narg_; - int ngap_; - int nvar_; - int nret_; - - int argpos_; - int gappos_; - int varpos_; - int retpos_; - - int rettop_; - int finaltop_; - -private: - - template - void assign_slots(int argp, int varp, int retp, LuaArg &v, SS & ... stackslots) { - v.index_ = argp; - assign_slots(argp + 1, varp, retp, stackslots...); - } - - template - void assign_slots(int argp, int varp, int retp, LuaVar &v, SS & ... stackslots) { - v.index_ = varp; - assign_slots(argp, varp+1, retp, stackslots...); - } - - template - void assign_slots(int argp, int varp, int retp, LuaRet &v, SS & ... stackslots) { - v.index_ = retp; - assign_slots(argp, varp, retp+1, stackslots...); - } - - void assign_slots(int argp, int varp, int retp) {} - - template - void count_slotsx(LuaArg &v, SS & ... stackslots) - { - count_slotsx(stackslots...); - } - template - void count_slotsx(LuaVar &v, SS & ... stackslots) - { - count_slotsx(stackslots...); - } - template - void count_slotsx(LuaRet &v, SS & ... stackslots) - { - count_slotsx(stackslots...); - } - - template - void count_slotsx() { - narg_ = NARG; - nret_ = NRET; - nvar_ = NVAR; - ngap_ = NRET - NVAR - NARG; - if (ngap_ < 0) ngap_ = 0; - - int argtop = lua_gettop(L_); - argpos_ = argtop + 1 - NARG; - gappos_ = argpos_ + NARG; - varpos_ = gappos_ + ngap_; - retpos_ = varpos_ + NVAR; - - rettop_ = retpos_ + NRET - 1; - finaltop_ = argpos_ + NRET - 1; - } - -public: - template - LuaOldStack(lua_State *L, SS & ... stackslots) : LuaCoreStack(L) { - count_slotsx<0, 0, 0>(stackslots...); - if (lua_gettop(L) < narg_) { - luaL_error(L, "not enough arguments to function"); - } - assign_slots(argpos_, varpos_, retpos_, stackslots...); - lua_settop(L_, varpos_ - 1); - for (int i = 0; i < nvar_ + nret_; i++) { - lua_pushnil(L_); - } - } - - int result() { - lua_settop(L_, rettop_); - int i = finaltop_; - for (int j = 0; j < nret_; j++) { - lua_replace(L_, i); - i -= 1; - } - lua_settop(L_, finaltop_); - return nret_; - } - - ~LuaOldStack() {}; -}; - //////////////////////////////////////////////////////////////////// // // LuaDefStack // -// This version of LuaStack is meant to be used at the top level of a LuaDefine. -// It can assign stack slots to LuaArg, LuaRet, and LuaVar locals. It arranges -// for the arguments to be in the LuaArg variables, and it arranges for the -// LuaRet variables to be returned. It also makes sure that the function has -// the correct number of arguments. +// This version of LuaStack should only be used inside a LuaDefine. It can +// assign stack slots to LuaArg, LuaRet, LuaVar, and LuaExtraArgs. It +// arranges for the arguments to be in the LuaArg variables, and it arranges for +// the LuaRet variables to be returned. It also makes sure that the function +// has the correct number of arguments. // // At the end of the LuaDefine function, you're supposed to return LS.result(). // LS.result causes the allocated stack slots to be freed except for the LuaRet @@ -659,11 +548,11 @@ public: // The lua interpreter will clean up after an error or yield. // // Implementation note: LuaDefStack doesn't have a destructor to deallocate -// stack slots. That's deliberate: you shouldn't expect this class to clean -// up its stack frame, because after all, it has to leave return values on -// the stack. It would be deceptive to put a destructor, which then doesn't -// actually clean up anyway. Better to just let it be known that this -// class doesn't clean up its stack frame. +// stack slots. That's deliberate: you shouldn't expect this class to clean up +// its stack frame, because after all, it has to leave return values on the +// stack. It would be deceptive to put a destructor, which then doesn't +// actually clean up anyway. Better to just let it be known that this class +// doesn't clean up its stack frame. // //////////////////////////////////////////////////////////////////// @@ -742,7 +631,6 @@ public: // //////////////////////////////////////////////////////////////////// - class LuaExtStack : public LuaCoreStack { private: int oldtop_; diff --git a/luprex/cpp/core/world-core.cpp b/luprex/cpp/core/world-core.cpp index 403282a6..8c30c5f0 100644 --- a/luprex/cpp/core/world-core.cpp +++ b/luprex/cpp/core/world-core.cpp @@ -248,7 +248,7 @@ eng::string World::probe_lua(int64_t actor_id, const eng::string &lua) { } LuaVar closure; - LuaOldStack LS(L, closure); + LuaExtStack LS(L, closure); // create the compiled closure. int status = luaL_loadbuffer(L, lua.c_str(), lua.size(), "=probe"); @@ -257,7 +257,6 @@ eng::string World::probe_lua(int64_t actor_id, const eng::string &lua) { // The closure is actually an error message. Do nothing. // This should normally not happen: LuaConsole should filter // out syntax errors. - LS.result(); return ""; } @@ -287,10 +286,6 @@ eng::string World::probe_lua(int64_t actor_id, const eng::string &lua) { lthread_prints_.reset(); close_lthread_state(); - - // And we're done. - LS.result(); - assert(stack_is_clear()); return result; } @@ -300,31 +295,27 @@ void World::update_gui(int64_t actor_id, int64_t place_id, Gui *gui) { lua_State *L = state(); LuaVar actor, place, ugui, func, tangibles, mt, index; - LuaOldStack LS(L, actor, place, ugui, func, tangibles, mt, index); + LuaExtStack LS(L, actor, place, ugui, func, tangibles, mt, index); // Get the actor and place. LS.rawget(tangibles, LuaRegistry, "tangibles"); LS.rawget(actor, tangibles, actor_id); LS.rawget(place, tangibles, place_id); if (!LS.istable(actor) || !LS.istable(place)) { - LS.result(); return; } // Get the interface closure. LS.getmetatable(mt, place); if (!LS.istable(mt)) { - LS.result(); return; } LS.rawget(index, mt, "__index"); if (!LS.istable(index)) { - LS.result(); return; } LS.rawget(func, index, "interface"); if (!LS.isfunction(func)) { - LS.result(); return; } @@ -340,13 +331,8 @@ void World::update_gui(int64_t actor_id, int64_t place_id, Gui *gui) { if (!msg.empty()) { gui->clear(0); util::dprint(msg); - LS.result(); return; } - - // And we're done. - LS.result(); - assert(stack_is_clear()); } void World::update_source(const util::LuaSourcePtr &source) { @@ -398,42 +384,41 @@ void World::http_response(const HttpParser &response) { HttpClientRequest request = iter->second; http_requests_.erase(iter); - // Get the place and thread as lua objects. - LuaVar tangibles, place, mt, threads, thinfo, thread; - LuaOldStack LS(state(), tangibles, place, mt, threads, thinfo, thread); - LS.rawget(tangibles, LuaRegistry, "tangibles"); - LS.rawget(place, tangibles, request.place_id()); - if (!LS.istable(place)) { - return; + lua_State *CO; + { + // Get the place and thread as lua objects. + LuaVar tangibles, place, mt, threads, thinfo, thread; + LuaExtStack LS(state(), tangibles, place, mt, threads, thinfo, thread); + LS.rawget(tangibles, LuaRegistry, "tangibles"); + LS.rawget(place, tangibles, request.place_id()); + if (!LS.istable(place)) { + return; + } + LS.getmetatable(mt, place); + if (!LS.istable(mt)) { + return; + } + LS.rawget(threads, mt, "threads"); + if (!LS.istable(threads)) { + return; + } + LS.rawget(thinfo, threads, request.thread_id()); + if (!LS.istable(thinfo)) { + return; + } + LS.rawget(thread, thinfo, "thread"); + if (!LS.isthread(thread)) { + return; + } + CO = LS.ckthread(thread); } - LS.getmetatable(mt, place); - if (!LS.istable(mt)) { - return; - } - LS.rawget(threads, mt, "threads"); - if (!LS.istable(threads)) { - return; - } - LS.rawget(thinfo, threads, request.thread_id()); - if (!LS.istable(thinfo)) { - return; - } - LS.rawget(thread, thinfo, "thread"); - if (!LS.isthread(thread)) { - return; - } - lua_State *CO = LS.ckthread(thread); // Push the response onto the awakening thread. - LuaRet responsetable; - LuaOldStack LSCO(CO, responsetable); + lua_pushnil(CO); + LuaSpecial responsetable(lua_gettop(CO)); + LuaCoreStack LSCO(CO); response.store(LSCO, responsetable); - // Clean up lua stacks. - LSCO.result(); - LS.result(); - assert(stack_is_clear()); - // Awaken the thread, with its new return value. schedule(0, request.thread_id(), request.place_id()); run_scheduled_threads(); @@ -481,14 +466,13 @@ HttpServerResponse World::http_serve(const HttpParser &request) { lua_State *L = state(); LuaVar www, func, reqtab; - LuaOldStack LS(L, www, func, reqtab); + LuaExtStack LS(L, www, func, reqtab); // Get the www class. If there's no such class, // return a 503 Service Unavailable to the client. eng::string err = LS.getclass(www, "www"); if (!err.empty()) { response.fail(503, "class www doesn't exist"); - LS.result(); return response; } @@ -497,7 +481,6 @@ HttpServerResponse World::http_serve(const HttpParser &request) { LS.rawget(func, www, fn); if (!LS.isfunction(func)) { response.fail(404, util::ss("no such function: www.", fn)); - LS.result(); return response; } @@ -517,7 +500,6 @@ HttpServerResponse World::http_serve(const HttpParser &request) { // a 500 Internal Server Error to the client. if (!msg.empty()) { response.fail(500, msg); - LS.result(); return response; } @@ -526,7 +508,6 @@ HttpServerResponse World::http_serve(const HttpParser &request) { int newtop = lua_gettop(L); if ((newtop != oldtop + 1) || (!lua_istable(L, newtop))) { response.fail(500, util::ss("lua function www.", fn, " didn't return a table")); - LS.result(); return response; } @@ -538,7 +519,6 @@ HttpServerResponse World::http_serve(const HttpParser &request) { if (!kperr.empty()) { response.fail(500, kperr); } - LS.result(); return response; } @@ -609,58 +589,55 @@ void World::invoke_lua(int64_t actor_id, int64_t place_id, const eng::string &ac int64_t tid = tplace->id_player_pool_.get_one(); // Set up for lua manipulation. - lua_State *L = state(); - LuaVar func, tangibles, place, mt, thread, thinfo, threads; - LuaOldStack LS(L, func, tangibles, place, mt, thread, thinfo, threads); + { + lua_State *L = state(); + LuaVar func, tangibles, place, mt, thread, thinfo, threads; + LuaExtStack LS(L, func, tangibles, place, mt, thread, thinfo, threads); - // create the compiled closure. - int status = luaL_loadbuffer(L, action.c_str(), action.size(), "=invoke"); - lua_replace(L, func.index()); - if (status != LUA_OK) { - // The closure is actually an error message. Do nothing. - // This should normally not happen: LuaConsole should filter - // out syntax errors. - LS.result(); - return; + // create the compiled closure. + int status = luaL_loadbuffer(L, action.c_str(), action.size(), "=invoke"); + lua_replace(L, func.index()); + if (status != LUA_OK) { + // The closure is actually an error message. Do nothing. + // This should normally not happen: LuaConsole should filter + // out syntax errors. + return; + } + + // Get the place. + LS.rawget(tangibles, LuaRegistry, "tangibles"); + LS.rawget(place, tangibles, place_id); + if (!LS.istable(place)) { + return; + } + + // Get the place's metatable. + LS.getmetatable(mt, place); + if (!LS.istable(mt)) { + return; + } + + // Create a new thread, set up function and parameters. + lua_State *CO = LS.newthread(thread); + lua_pushvalue(L, func.index()); + lua_xmove(L, CO, 1); + + // Create the thread info table. + LS.newtable(thinfo); + LS.rawset(thinfo, "thread", thread); + LS.rawset(thinfo, "actorid", actor_id); + LS.rawset(thinfo, "isnew", true); + LS.rawset(thinfo, "useppool", true); + LS.rawset(thinfo, "print", true); + + // Store the thread into place's thread table. + LS.rawget(threads, mt, "threads"); + if (!LS.istable(threads)) { + return; + } + LS.rawset(threads, tid, thinfo); } - // Get the place. - LS.rawget(tangibles, LuaRegistry, "tangibles"); - LS.rawget(place, tangibles, place_id); - if (!LS.istable(place)) { - LS.result(); - return; - } - - // Get the place's metatable. - LS.getmetatable(mt, place); - if (!LS.istable(mt)) { - LS.result(); - return; - } - - // Create a new thread, set up function and parameters. - lua_State *CO = LS.newthread(thread); - lua_pushvalue(L, func.index()); - lua_xmove(L, CO, 1); - - // Create the thread info table. - LS.newtable(thinfo); - LS.rawset(thinfo, "thread", thread); - LS.rawset(thinfo, "actorid", actor_id); - LS.rawset(thinfo, "isnew", true); - LS.rawset(thinfo, "useppool", true); - LS.rawset(thinfo, "print", true); - - // Store the thread into place's thread table. - LS.rawget(threads, mt, "threads"); - if (!LS.istable(threads)) { - LS.result(); - return; - } - LS.rawset(threads, tid, thinfo); - LS.result(); - schedule(0, tid, place_id); run_scheduled_threads(); assert(stack_is_clear()); @@ -692,67 +669,63 @@ void World::invoke_plan(int64_t actor_id, int64_t place_id, const eng::string &a // pool in this case. int64_t tid = tactor->id_player_pool_.get_one(); - // Set up for Lua manipulation. - lua_State *L = state(); - LuaVar actor, place, func, tangibles, mt, index, thread, threads, thinfo, message, invdata; - LuaOldStack LS(L, actor, place, func, tangibles, mt, index, thread, threads, thinfo, message, invdata); + { + // Set up for Lua manipulation. + lua_State *L = state(); + LuaVar actor, place, func, tangibles, mt, index, thread, threads, thinfo, message, invdata; + LuaExtStack LS(L, actor, place, func, tangibles, mt, index, thread, threads, thinfo, message, invdata); - // Get the actor and place. - LS.rawget(tangibles, LuaRegistry, "tangibles"); - LS.rawget(actor, tangibles, actor_id); - LS.rawget(place, tangibles, place_id); - if (!LS.istable(actor) || !LS.istable(place)) { - LS.result(); - return; - } + // Get the actor and place. + LS.rawget(tangibles, LuaRegistry, "tangibles"); + LS.rawget(actor, tangibles, actor_id); + LS.rawget(place, tangibles, place_id); + if (!LS.istable(actor) || !LS.istable(place)) { + return; + } - // Get the action closure. - LS.getmetatable(mt, place); - if (!LS.istable(mt)) { - LS.result(); - return; - } - LS.rawget(index, mt, "__index"); - if (!LS.istable(index)) { - LS.result(); - return; - } - LS.rawget(func, index, action); - if (!LS.isfunction(func)) { - LS.result(); - return; - } + // Get the action closure. + LS.getmetatable(mt, place); + if (!LS.istable(mt)) { + return; + } + LS.rawget(index, mt, "__index"); + if (!LS.istable(index)) { + return; + } + LS.rawget(func, index, action); + if (!LS.isfunction(func)) { + return; + } - // Convert the InvocationData into a lua table. - LS.newtable(invdata); - for (const auto &p : data) { - LS.rawset(invdata, p.first, p.second); - } + // Convert the InvocationData into a lua table. + LS.newtable(invdata); + for (const auto &p : data) { + LS.rawset(invdata, p.first, p.second); + } - // Create a new thread, set up function and parameters. - lua_State *CO = LS.newthread(thread); - lua_pushvalue(L, func.index()); - lua_pushvalue(L, actor.index()); - lua_pushvalue(L, place.index()); - lua_pushvalue(L, invdata.index()); - lua_xmove(L, CO, 4); + // Create a new thread, set up function and parameters. + lua_State *CO = LS.newthread(thread); + lua_pushvalue(L, func.index()); + lua_pushvalue(L, actor.index()); + lua_pushvalue(L, place.index()); + lua_pushvalue(L, invdata.index()); + lua_xmove(L, CO, 4); - // Create the thread info table. - LS.newtable(thinfo); - LS.rawset(thinfo, "thread", thread); - LS.rawset(thinfo, "actorid", actor_id); - LS.rawset(thinfo, "isnew", true); - LS.rawset(thinfo, "useppool", true); - LS.rawset(thinfo, "print", false); - - // Store the thread into place's thread table. - LS.rawget(threads, mt, "threads"); - if (!LS.istable(threads)) { - LS.result(); - return; + // Create the thread info table. + LS.newtable(thinfo); + LS.rawset(thinfo, "thread", thread); + LS.rawset(thinfo, "actorid", actor_id); + LS.rawset(thinfo, "isnew", true); + LS.rawset(thinfo, "useppool", true); + LS.rawset(thinfo, "print", false); + + // Store the thread into place's thread table. + LS.rawget(threads, mt, "threads"); + if (!LS.istable(threads)) { + return; + } + LS.rawset(threads, tid, thinfo); } - LS.rawset(threads, tid, thinfo); - LS.result(); // Push the thread's ID into the runnable thread queue, // then run the thread queue. @@ -800,7 +773,7 @@ void World::guard_blockable(lua_State *L, const char *fn) { void World::guard_nopredict(lua_State *L, const char *fn) { // Caution: this code must be equivalent to the - // code in LuaOldStack::guard_nopredict. + // code in LuaCoreStack::guard_nopredict. if (lthread_thread_id_ == 0) { return; } @@ -821,7 +794,7 @@ void World::run_scheduled_threads() { assert(stack_is_clear()); lua_State *L = state(); LuaVar tangibles, place, mt, threads, thinfo, actorid, isnew, useppool, thread, print; - LuaOldStack LS(L, tangibles, place, mt, threads, thinfo, actorid, isnew, useppool, thread, print); + LuaExtStack LS(L, tangibles, place, mt, threads, thinfo, actorid, isnew, useppool, thread, print); LS.rawget(tangibles, LuaRegistry, "tangibles"); while (thread_sched_.ready(clock_)) { @@ -871,7 +844,7 @@ void World::run_scheduled_threads() { // Remove from thread table. LS.rawget(print, thinfo, "print"); LS.rawset(threads, sched.thread_id(), LuaNil); - LuaOldStack LSCO(CO); + LuaCoreStack LSCO(CO); if (LS.ckboolean(print)) { for (int i = 1; i <= lua_gettop(CO); i++) { pprint(LSCO, LuaSpecial(i), PrettyPrintOptions(), ostream); @@ -900,9 +873,6 @@ void World::run_scheduled_threads() { } close_lthread_state(); } - - LS.result(); - assert(stack_is_clear()); } int64_t World::alloc_id_predictable() { From 5ece3a71bad177be6eb7b779becc2558d20887c0 Mon Sep 17 00:00:00 2001 From: Josh Yelon Date: Mon, 8 May 2023 13:32:22 -0400 Subject: [PATCH 6/8] Fix an issue related to the use of constexpr in luastack --- luprex/cpp/core/luastack.hpp | 53 +++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/luprex/cpp/core/luastack.hpp b/luprex/cpp/core/luastack.hpp index d00a8f82..f2b25707 100644 --- a/luprex/cpp/core/luastack.hpp +++ b/luprex/cpp/core/luastack.hpp @@ -147,6 +147,7 @@ #include "wrap-set.hpp" #include #include +#include #include "lua.h" #include "lauxlib.h" @@ -297,34 +298,45 @@ protected: int nvar; int nextra; constexpr Counts(int nr, int na, int nv, int ne) : nret(nr), narg(na), nvar(nv), nextra(ne) {} + constexpr Counts(Counts a, Counts b) + : nret(a.nret+b.nret), narg(a.narg+b.narg), nvar(a.nvar+b.nvar), nextra(a.nextra+b.nextra) {} }; - template - constexpr static Counts count_slots(LuaRet &v, SS & ... stackslots) + template + constexpr static Counts count_slots(LuaRet &v, SS && ... stackslots) { - return count_slots(stackslots...); + return Counts(Counts(1, 0, 0, 0), count_slots(stackslots...)); } - template - constexpr static Counts count_slots(LuaArg &v, SS & ... stackslots) + template + constexpr static Counts count_slots(LuaArg &v, SS && ... stackslots) { - return count_slots(stackslots...); + return Counts(Counts(0, 1, 0, 0), count_slots(stackslots...)); } - template - constexpr static Counts count_slots(LuaVar &v, SS & ... stackslots) + template + constexpr static Counts count_slots(LuaVar &v, SS && ... stackslots) { - return count_slots(stackslots...); + return Counts(Counts(0, 0, 1, 0), count_slots(stackslots...)); } - template - constexpr static Counts count_slots(LuaExtraArgs &v, SS & ... stackslots) + template + constexpr static Counts count_slots(LuaExtraArgs &v, SS && ... stackslots) { - return count_slots(stackslots...); + return Counts(Counts(0, 0, 0, 1), count_slots(stackslots...)); } - template constexpr static Counts count_slots() { - return Counts(NRET, NARG, NVAR, NEXTRA); + return Counts(0, 0, 0, 0); } -private: + + template + constexpr static int count_vars(LuaVar &v, SS && ... stackslots) + { + return 1 + count_vars(stackslots...); + } + constexpr static int count_vars() { + return 0; + } + + private: // Push any value on the stack, by type. void push_any_value(LuaNewTableMarker s) const { lua_newtable(L_); } void push_any_value(LuaNilMarker s) const { lua_pushnil(L_); } @@ -698,7 +710,7 @@ private: public: template inline LuaDefStack(lua_State *L, SS & ... stackslots) : LuaCoreStack(L) { - constexpr Counts counts = count_slots<0, 0, 0, 0>(stackslots...); + Counts counts = count_slots(stackslots...); int nargs = lua_gettop(L); if (counts.nextra == 0) { if (nargs != counts.narg) { @@ -757,13 +769,10 @@ private: public: template LuaExtStack(lua_State *L, SS & ... stackslots) : LuaCoreStack(L) { - constexpr Counts counts = count_slots<0, 0, 0, 0>(stackslots...); - static_assert(counts.narg == 0, "LuaExtStack doesn't allow LuaArg parameters"); - static_assert(counts.nret == 0, "LuaExtStack doesn't allow LuaRet parameters"); - static_assert(counts.nextra == 0, "LuaExtStack doesn't allow LuaExtraArgs parameters"); - lua_checkstack(L_, counts.nvar + 20); + int nvars = count_vars(stackslots...); + lua_checkstack(L_, nvars + 20); oldtop_ = lua_gettop(L_); - for (int i = 0; i < counts.nvar; i++) { + for (int i = 0; i < nvars; i++) { lua_pushnil(L_); } assign_slots(oldtop_ + 1, stackslots...); From d70b9f0d1338d096611053f3784496eb918fe074 Mon Sep 17 00:00:00 2001 From: jyelon Date: Mon, 8 May 2023 15:49:47 -0400 Subject: [PATCH 7/8] Reimplement LuaCountArgs with template specialization to make it constexpr --- luprex/cpp/core/luastack.hpp | 91 +++++++++++++++++------------------- 1 file changed, 43 insertions(+), 48 deletions(-) diff --git a/luprex/cpp/core/luastack.hpp b/luprex/cpp/core/luastack.hpp index 1cb3ab44..c64ac676 100644 --- a/luprex/cpp/core/luastack.hpp +++ b/luprex/cpp/core/luastack.hpp @@ -206,6 +206,41 @@ public: friend class LuaDefStack; }; +struct LuaArgCounts { + int nret; + int narg; + int nvar; + int nextra; + constexpr LuaArgCounts(int nr, int na, int nv, int ne) : nret(nr), narg(na), nvar(nv), nextra(ne) {} + constexpr LuaArgCounts operator +(LuaArgCounts b) const { + return LuaArgCounts(nret + b.nret, narg + b.narg, nvar + b.nvar, nextra + b.nextra); + } +}; + + +template +struct LuaCountArgs; +template<> +struct LuaCountArgs<> { + static constexpr LuaArgCounts value = LuaArgCounts(0,0,0,0); +}; +template +struct LuaCountArgs { + static constexpr LuaArgCounts value = LuaArgCounts(1, 0, 0, 0) + LuaCountArgs::value; +}; +template +struct LuaCountArgs { + static constexpr LuaArgCounts value = LuaArgCounts(0, 1, 0, 0) + LuaCountArgs::value; +}; +template +struct LuaCountArgs { + static constexpr LuaArgCounts value = LuaArgCounts(0, 0, 1, 0) + LuaCountArgs::value; +}; +template +struct LuaCountArgs { + static constexpr LuaArgCounts value = LuaArgCounts(0, 0, 0, 1) + LuaCountArgs::value; +}; + class LuaNilMarker {}; extern LuaNilMarker LuaNil; @@ -291,51 +326,8 @@ protected: lua_State *L_; protected: - struct Counts { - int nret; - int narg; - int nvar; - int nextra; - constexpr Counts(int nr, int na, int nv, int ne) : nret(nr), narg(na), nvar(nv), nextra(ne) {} - constexpr Counts(Counts a, Counts b) - : nret(a.nret+b.nret), narg(a.narg+b.narg), nvar(a.nvar+b.nvar), nextra(a.nextra+b.nextra) {} - }; - template - constexpr static Counts count_slots(LuaRet &v, SS && ... stackslots) - { - return Counts(Counts(1, 0, 0, 0), count_slots(stackslots...)); - } - template - constexpr static Counts count_slots(LuaArg &v, SS && ... stackslots) - { - return Counts(Counts(0, 1, 0, 0), count_slots(stackslots...)); - } - template - constexpr static Counts count_slots(LuaVar &v, SS && ... stackslots) - { - return Counts(Counts(0, 0, 1, 0), count_slots(stackslots...)); - } - template - constexpr static Counts count_slots(LuaExtraArgs &v, SS && ... stackslots) - { - return Counts(Counts(0, 0, 0, 1), count_slots(stackslots...)); - } - constexpr static Counts count_slots() { - return Counts(0, 0, 0, 0); - } - - - template - constexpr static int count_vars(LuaVar &v, SS && ... stackslots) - { - return 1 + count_vars(stackslots...); - } - constexpr static int count_vars() { - return 0; - } - - private: +private: // Push any value on the stack, by type. void push_any_value(LuaNewTableMarker s) const { lua_newtable(L_); } void push_any_value(LuaNilMarker s) const { lua_pushnil(L_); } @@ -599,7 +591,7 @@ private: public: template inline LuaDefStack(lua_State *L, SS & ... stackslots) : LuaCoreStack(L) { - Counts counts = count_slots(stackslots...); + constexpr LuaArgCounts counts = LuaCountArgs::value; int nargs = lua_gettop(L); if (counts.nextra == 0) { if (nargs != counts.narg) { @@ -657,10 +649,13 @@ private: public: template LuaExtStack(lua_State *L, SS & ... stackslots) : LuaCoreStack(L) { - int nvars = count_vars(stackslots...); - lua_checkstack(L_, nvars + 20); + constexpr LuaArgCounts counts = LuaCountArgs::value; + static_assert(counts.narg == 0, "LuaExtStack only allows LuaVar, not LuaArg"); + static_assert(counts.nret == 0, "LuaExtStack only allows LuaVar, not LuaRet"); + static_assert(counts.nextra == 0, "LuaExtStack only allows LuaVar, not LuaExtraArgs"); + lua_checkstack(L_, counts.nvar + 20); oldtop_ = lua_gettop(L_); - for (int i = 0; i < nvars; i++) { + for (int i = 0; i < counts.nvar; i++) { lua_pushnil(L_); } assign_slots(oldtop_ + 1, stackslots...); From 66f3cd8464105f576a90e6f6d0c6a91c14ebe196 Mon Sep 17 00:00:00 2001 From: Josh Yelon Date: Mon, 8 May 2023 21:58:26 -0400 Subject: [PATCH 8/8] Use cv2pdb to generate PDB files for visual studio --- luprex/.gitattributes | 2 +- luprex/.gitignore | 1 + luprex/Makefile | 92 +++++++++++++++++++++++++++---------------- luprex/ext/cv2pdb.exe | 3 ++ 4 files changed, 62 insertions(+), 36 deletions(-) create mode 100644 luprex/ext/cv2pdb.exe diff --git a/luprex/.gitattributes b/luprex/.gitattributes index c8c6a2b1..a9b00949 100644 --- a/luprex/.gitattributes +++ b/luprex/.gitattributes @@ -7,7 +7,7 @@ *.a binary *.lib binary *.o binary -*.obj binary +*.exe binary *.bat text eol=crlf *.a filter=lfs diff=lfs merge=lfs -text *.lib filter=lfs diff=lfs merge=lfs -text diff --git a/luprex/.gitignore b/luprex/.gitignore index 273f56b6..28562f3b 100644 --- a/luprex/.gitignore +++ b/luprex/.gitignore @@ -10,6 +10,7 @@ luprex *.o *.dll *.exe +*.pdb *.so *.a diff --git a/luprex/Makefile b/luprex/Makefile index ea27acf4..70e0cdf7 100644 --- a/luprex/Makefile +++ b/luprex/Makefile @@ -5,34 +5,17 @@ ####################################################################### ifneq "" "$(findstring -linux-,$(MAKE_HOST))" - - OS=linux - EXE=luprex - DLL=luprex.so - LIBS=-L./ext/openssl-linux -lssl -lcrypto -ldl - LUAFLAGS=-DLUA_USE_APICHECK -DLUA_USE_POSIX - LINKDLL=-export-dynamic -Wl,--no-allow-shlib-undefined -Wl,-z,defs -shared - OPT=-g -O0 - + OS=linux else ifneq "" "$(findstring cmd.exe,$(COMSPEC))" + OS=mingw +endif - OS=mingw - EXE=luprex.exe - DLL=luprex.dll - LIBS=-L./ext/openssl-mingw -lssl -lcrypto -lws2_32 -lcrypt32 -lcryptui - LUAFLAGS=-DLUA_USE_APICHECK -DLUA_COMPAT_ALL - LINKDLL=-Wl,--no-allow-shlib-undefined -shared - OPT=-g -O0 - -else - - $(error Cannot figure out whether to build the linux or mingw version) - +ifeq "$(OS)" "" + $(error Cannot figure out which OS to build for." endif $(info Building for $(OS)...) - ####################################################################### ## ## List of all OBJ files @@ -110,46 +93,85 @@ OBJ_CORE=\ obj/core/printbuffer.o\ obj/core/serializelua.o\ + OBJ_DRV=\ obj/drv/drvutil.o\ obj/drv/sslutil.o\ obj/drv/driver-$(OS).o\ - ####################################################################### ## -## Make rules +## Make rules for linux ## ####################################################################### + +ifeq "$(OS)" "linux" + +OPT=-g -O0 GPP=g++ -Wall -fvisibility=hidden $(OPT) -std=c++17 -MMD -all: $(EXE) $(DLL) +luprex: $(OBJ_DRV) luprexlib.so + $(GPP) -o $@ $(OBJ_DRV) -L./ext/openssl-linux -lssl -lcrypto -ldl -$(EXE): $(OBJ_DRV) - $(GPP) -o $@ $(OBJ_DRV) $(LIBS) - -$(DLL): $(OBJ_ERIS) $(OBJ_CORE) - $(GPP) $(LINKDLL) -o $@ $^ +luprexlib.so: $(OBJ_ERIS) $(OBJ_CORE) + $(GPP) -export-dynamic -Wl,--no-allow-shlib-undefined -Wl,-z,defs -shared-o $@ $^ obj/eris/%.o: ext/eris-master/src/%.c - $(GPP) -fPIC $(LUAFLAGS) -o $@ -c $< + $(GPP) -fPIC -DLUA_USE_APICHECK -DLUA_USE_POSIX -o $@ -c $< obj/core/%.o: cpp/core/%.cpp $(GPP) -fPIC -I./ext/eris-master/src -I./cpp/wrap -I./cpp/core -o $@ -c $< -obj/core/%.s: cpp/core/%.cpp - $(GPP) -S -fPIC -I./ext/eris-master/src -I./cpp/wrap -I./cpp/core -o $@ -c $< +obj/drv/%.o: cpp/drv/%.cpp + $(GPP) -I./ext -I./src/drv -o $@ -c $< + +endif + + +####################################################################### +## +## Make rules for mingw +## +####################################################################### + +ifeq "$(OS)" "mingw" + +OPT=-g -O0 +GPP=g++ -Wall -fvisibility=hidden $(OPT) -std=c++17 -MMD + +luprex.exe: $(OBJ_DRV) luprexlib.dll + $(GPP) -o $@ $(OBJ_DRV) -L./ext/openssl-mingw -lssl -lcrypto -lws2_32 -lcrypt32 -lcryptui + ext/cv2pdb.exe luprex.exe + +luprexlib.dll: $(OBJ_ERIS) $(OBJ_CORE) + $(GPP) -Wl,--no-allow-shlib-undefined -shared -o $@ $^ + ext/cv2pdb.exe luprexlib.dll + +obj/eris/%.o: ext/eris-master/src/%.c + $(GPP) -fPIC -DLUA_USE_APICHECK -DLUA_COMPAT_ALL -o $@ -c $< + +obj/core/%.o: cpp/core/%.cpp + $(GPP) -fPIC -I./ext/eris-master/src -I./cpp/wrap -I./cpp/core -o $@ -c $< obj/drv/%.o: cpp/drv/%.cpp $(GPP) -I./ext -I./src/drv -o $@ -c $< -clean: - rm -f luprex luprex.exe luprex.so luprex.dll obj/core/*.* obj/drv/*.* obj/eris/*.* +endif +####################################################################### +## +## Make Clean, deliberately OS independent +## +####################################################################### + +clean: + rm -f luprex luprex.exe luprex.so luprexlib.dll *.pdb obj/core/*.* obj/drv/*.* obj/eris/*.* + + ####################################################################### ## ## Automatically generated Make Dependencies diff --git a/luprex/ext/cv2pdb.exe b/luprex/ext/cv2pdb.exe new file mode 100644 index 00000000..12594140 --- /dev/null +++ b/luprex/ext/cv2pdb.exe @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6b1f26a96ad8b6401469ef245eb4070485c4feafe875c77ce9bc505f57388653 +size 368128