lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Greetings Lua-l!

A while ago I was having a look at the Lua source code and found that in
certain parts, a `__name` value in the metatable is used for providing
custom type names to objects.

I've held the opinion for years now that there should be a way to change
what type is reported for an object by the `type` function, so I took
the opportunity that most of this is already implemented and wrote a
quick patch that adds this behavior, along with a `rawtype` function
that essentially works as the `type` function normally does.

I posted the patch on github for easier reading, but I'm also appending
it at the bottom of the mail:
https://gist.github.com/DarkWiiPlayer/bb0d153827990b4781f4f743d2bc7a3a

I will admit that I didn't spend much time considering the performance
impact of such a change, but I imagine for most Lua code it would make
almost no difference.

While it would be a breaking change, the only code that would be
affected is where the `__name` field is already being used for something
else, which I doubt would be in too many places.

As an alternative proposal: if changing the behavior of `type` is
considered a bad idea, I'd love to at least see some other function that
behaves like this, although I'm unsure about what it could be called.
`type` really is the best name in my opinion, with `name` (in reference
to the `__name` field name) being the next best option I can think of.
`class` might also be easy to remember for non-programmers, but
misleading to people with a programming background. The only other thing
I can think of is `typename`, which is probably the easiest to remember
(Does what `type` does, except when `__name` exists).

Greetings and happy holidays!

—————

diff --unified -r lua-5.4.0/src/lapi.c lua-5.4.0-rawtype/src/lapi.c
--- lua-5.4.0/src/lapi.c    2020-06-18 16:25:53.000000000 +0200
+++ lua-5.4.0-rawtype/src/lapi.c    2020-11-27 09:31:30.787330086 +0100
@@ -267,6 +267,13 @@
 }
 
 
+LUA_API const char *lua_objtypename (lua_State *L, int t) {
+  api_check(L, LUA_TNONE <= t && t < LUA_NUMTYPES, "invalid type");
+  const TValue *o = index2value(L, t);
+  return luaT_objtypename(L, o);
+}
+
+
 LUA_API int lua_iscfunction (lua_State *L, int idx) {
   const TValue *o = index2value(L, idx);
   return (ttislcf(o) || (ttisCclosure(o)));
diff --unified -r lua-5.4.0/src/lbaselib.c lua-5.4.0-rawtype/src/lbaselib.c
--- lua-5.4.0/src/lbaselib.c    2020-06-18 16:25:53.000000000 +0200
+++ lua-5.4.0-rawtype/src/lbaselib.c    2020-11-27 09:38:19.813573132 +0100
@@ -240,7 +240,7 @@
 }
 
 
-static int luaB_type (lua_State *L) {
+static int luaB_rawtype (lua_State *L) {
   int t = lua_type(L, 1);
   luaL_argcheck(L, t != LUA_TNONE, 1, "value expected");
   lua_pushstring(L, lua_typename(L, t));
@@ -248,6 +248,16 @@
 }
 
 
+static int luaB_type (lua_State *L) {
+  int t = lua_type(L, 1);
+  luaL_argcheck(L, t != LUA_TNONE, 1, "value expected");
+  //lua_pushstring(L, lua_typename(L, t));
+  const char *s = lua_objtypename(L, -1);
+  lua_pushstring(L, s);
+  return 1;
+}
+
+
 static int luaB_next (lua_State *L) {
   luaL_checktype(L, 1, LUA_TTABLE);
   lua_settop(L, 2);  /* create a 2nd argument if there isn't one */
@@ -504,6 +514,7 @@
   {"tonumber", luaB_tonumber},
   {"tostring", luaB_tostring},
   {"type", luaB_type},
+  {"rawtype", luaB_rawtype},
   {"xpcall", luaB_xpcall},
   /* placeholders */
   {LUA_GNAME, NULL},
diff --unified -r lua-5.4.0/src/lua.h lua-5.4.0-rawtype/src/lua.h
--- lua-5.4.0/src/lua.h    2020-06-18 16:25:54.000000000 +0200
+++ lua-5.4.0-rawtype/src/lua.h    2020-11-27 09:33:22.347601208 +0100
@@ -186,6 +186,7 @@
 LUA_API int             (lua_isuserdata) (lua_State *L, int idx);
 LUA_API int             (lua_type) (lua_State *L, int idx);
 LUA_API const char     *(lua_typename) (lua_State *L, int tp);
+LUA_API const char     *(lua_objtypename) (lua_State *L, int tp);
 
 LUA_API lua_Number      (lua_tonumberx) (lua_State *L, int idx, int
*isnum);
 LUA_API lua_Integer     (lua_tointegerx) (lua_State *L, int idx, int
*isnum);