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.