From c02109699e4b35053bc095e73095806804f7c24b Mon Sep 17 00:00:00 2001 From: Josh Yelon Date: Fri, 26 Nov 2021 12:28:59 -0500 Subject: [PATCH] Improvements to the pretty-printer --- luprex/core/cpp/luastack.cpp | 18 +++++++- luprex/core/cpp/luastack.hpp | 5 ++- luprex/core/cpp/pprint.cpp | 68 +++++++++++++++++++----------- luprex/core/cpp/world-accessor.cpp | 6 ++- luprex/core/cpp/world-core.cpp | 18 +------- luprex/core/cpp/world-difftab.cpp | 6 ++- luprex/core/cpp/world.hpp | 6 --- 7 files changed, 75 insertions(+), 52 deletions(-) diff --git a/luprex/core/cpp/luastack.cpp b/luprex/core/cpp/luastack.cpp index 4238ace2..92a1d1ef 100644 --- a/luprex/core/cpp/luastack.cpp +++ b/luprex/core/cpp/luastack.cpp @@ -257,7 +257,7 @@ void LuaStack::makeclass(LuaSlot tab, const std::string &name) const { lua_pop(L_, 1); } -std::string LuaStack::classname(LuaSlot tab) { +std::string LuaStack::classname(LuaSlot tab) const { std::string result; if (istable(tab)) { lua_pushstring(L_, "__class"); @@ -279,6 +279,22 @@ std::string LuaStack::classname(LuaSlot tab) { return result; } +int64_t LuaStack::tanid(LuaSlot tab) const { + int64_t result = 0; + if (istable(tab) && gettabletype(tab) == LUA_TT_TANGIBLE) { + if (lua_getmetatable(L_, tab.index())) { + lua_pushstring(L_, "id"); + lua_rawget(L_, -2); + if (lua_type(L_, -1) == LUA_TNUMBER) { + result = int64_t(lua_tonumber(L_, -1)); + } + lua_pop(L_, 2); + } + } + return result; +} + + void LuaStack::movesortablekey(LuaSlot key, LuaStack &otherstack, LuaSlot otherslot) { int type = lua_type(L_, key); switch (type) { diff --git a/luprex/core/cpp/luastack.hpp b/luprex/core/cpp/luastack.hpp index 551edb3b..214aa2c8 100644 --- a/luprex/core/cpp/luastack.hpp +++ b/luprex/core/cpp/luastack.hpp @@ -390,7 +390,10 @@ public: void makeclass(LuaSlot tab, LuaSlot name) const; void makeclass(LuaSlot tab, const char *name) const; void makeclass(LuaSlot tab, const std::string &name) const; - std::string classname(LuaSlot tab); + std::string classname(LuaSlot tab) const; + + int64_t tanid(LuaSlot tab) const; + // There's no 'isclass' operator, but 'classname' will return empty // string if tab is not a valid class. diff --git a/luprex/core/cpp/pprint.cpp b/luprex/core/cpp/pprint.cpp index d6d5db1c..f4d18915 100644 --- a/luprex/core/cpp/pprint.cpp +++ b/luprex/core/cpp/pprint.cpp @@ -37,9 +37,16 @@ static bool string_quote(LuaStack &LS, LuaSlot val, std::ostream *os) { case LUA_TSTRING: util::quote_string(LS.ckstring(val), os); return true; - case LUA_TNUMBER: - (*os) << LS.ckinteger(val); + case LUA_TNUMBER: { + double value = LS.cknumber(val); + int64_t ivalue = int64_t(value); + if (double(ivalue) == value) { + (*os) << ivalue; + } else { + (*os) << value; + } return true; + } case LUA_TBOOLEAN: (*os) << (LS.ckboolean(val) ? "true" : "false"); return true; @@ -140,29 +147,48 @@ static void pprint_r(Inspector &insp, int level, LuaSlot root) { return; } - // If the table ID is greater than zero, then we've already - // printed it. Just print the table ID. + // Determine the table's ID, allocating an ID if necessary. LS.rawget(idv, insp.ids, root); int id = LS.ckint(idv); - if (id > 0) { - if (lua_nkeys(insp.L, root.index())==0) { - (*insp.stream) << "{}"; - } else { - (*insp.stream) << "
{...}"; + bool new_id = false; + if (id < 0) { + new_id = true; + id = insp.nextid++; + LS.rawset(insp.ids, root, id); + } + + // Print the table's name, if any. + bool is_class = false; + bool is_tangible = false; + std::string cname = LS.classname(root); + if (cname != "") { + is_class = true; + (*insp.stream) << ""; + } else { + int64_t tid = LS.tanid(root); + if (tid > 0) { + is_tangible = true; + (*insp.stream) << ""; + } else if (id > 0) { + (*insp.stream) << "
"; } + } + + // If this is a class, and we're not at the top level, truncate. + if ((is_class || is_tangible) && (level > 0)) { LS.result(); return; } - // Allocate an ID for the table, if necessary. - if (id < 0) { - id = insp.nextid++; - LS.rawset(insp.ids, root, id); - } - - // Print the table ID if greater than zero. - if (id > 0) { - (*insp.stream) << "
"; + // If this is a table we've already printed, truncate it. + if ((id > 0) && (!new_id)) { + if (lua_nkeys(insp.L, root.index())==0) { + (*insp.stream) << "{}"; + } else { + (*insp.stream) << "{...}"; + } + LS.result(); + return; } // State variables. @@ -212,12 +238,6 @@ static void pprint_r(Inspector &insp, int level, LuaSlot root) { needcomma = true; tabify(insp, level + 1); (*insp.stream) << " = "; - - // if isclass(mt) then - // self:puts('') - // end pprint_r(insp, level + 1, val); } diff --git a/luprex/core/cpp/world-accessor.cpp b/luprex/core/cpp/world-accessor.cpp index cab61250..cd80c925 100644 --- a/luprex/core/cpp/world-accessor.cpp +++ b/luprex/core/cpp/world-accessor.cpp @@ -188,7 +188,11 @@ LuaDefine(tangible_id, "c") { LuaArg tanobj; LuaRet id; LuaStack LS(L, tanobj, id); - LS.set(id, World::tangible_id(LS, tanobj)); + int64_t tid = LS.tanid(tanobj); + if (tid == 0) { + luaL_error(L, "Not a tangible"); + } + LS.set(id, tid); return LS.result(); } diff --git a/luprex/core/cpp/world-core.cpp b/luprex/core/cpp/world-core.cpp index d5e7a5c5..ac69bfaf 100644 --- a/luprex/core/cpp/world-core.cpp +++ b/luprex/core/cpp/world-core.cpp @@ -127,7 +127,7 @@ World::TanVector World::tangible_get_all(const IdVector &ids) const { } Tangible *World::tangible_get(const LuaStack &LS, LuaSlot tab) { - int64_t id = tangible_id(LS, tab); + int64_t id = LS.tanid(tab); if (id == 0) { luaL_error(LS.state(), "parameter is not a tangible"); } @@ -138,22 +138,6 @@ Tangible *World::tangible_get(const LuaStack &LS, LuaSlot tab) { return result; } -int64_t World::tangible_id(const LuaStack &LS, LuaSlot tab) { - int64_t id = 0; - if (LS.istable(tab) && LS.gettabletype(tab) == LUA_TT_TANGIBLE) { - lua_State *L = LS.state(); - if (lua_getmetatable(L, tab.index())) { - lua_pushstring(L, "id"); - lua_rawget(L, -2); - if (lua_type(L, -1) == LUA_TNUMBER) { - id = lua_tointeger(L, -1); - } - lua_pop(L, 2); - } - } - return id; -} - Tangible *World::tangible_make(lua_State *L, int64_t id, const std::string &plane, bool pushdb) { // Get a state if we don't already have one. if (L == nullptr) { diff --git a/luprex/core/cpp/world-difftab.cpp b/luprex/core/cpp/world-difftab.cpp index 6eca2f18..2734ab0f 100644 --- a/luprex/core/cpp/world-difftab.cpp +++ b/luprex/core/cpp/world-difftab.cpp @@ -70,11 +70,13 @@ static bool equivalent_values(LuaStack &MLS, LuaSlot mval, LuaSlot mtnmap, } case LUA_TT_CLASS: { if (SLS.xtype(sval) != LUA_TT_CLASS) return false; + // What if it's an ill-formed class? return MLS.classname(mval) == SLS.classname(sval); } case LUA_TT_TANGIBLE: { if (SLS.xtype(sval) != LUA_TT_TANGIBLE) return false; - return World::tangible_id(MLS, mval) == World::tangible_id(SLS, sval); + // What if it's an ill-formed tangible? + return MLS.tanid(mval) == SLS.tanid(sval); } case LUA_TT_GLOBALENV: { return (SLS.xtype(sval) == LUA_TT_GLOBALENV); @@ -120,7 +122,7 @@ static void transmit_value(LuaStack &MLS, LuaSlot mval, LuaSlot mtnmap, StreamBu } case LUA_TT_TANGIBLE: { sb->write_uint8(LUA_TT_TANGIBLE); - sb->write_int64(World::tangible_id(MLS, mval)); + sb->write_int64(MLS.tanid(mval)); return; } case LUA_TT_GLOBALENV: { diff --git a/luprex/core/cpp/world.hpp b/luprex/core/cpp/world.hpp index 41d56f65..ce31f4f7 100644 --- a/luprex/core/cpp/world.hpp +++ b/luprex/core/cpp/world.hpp @@ -130,12 +130,6 @@ public: // Tangible *tangible_make(lua_State *L, int64_t id, const std::string &plane, bool pushdb); - // Get the tangible ID of the specified LUA tangible database. - // - // Return zero if the item is not a tangible database. - // - static int64_t tangible_id(const LuaStack &LS, LuaSlot slot); - // Get a pointer to the specified tangible. // // If there's no such tangible, returns nullptr.