lua-users home
lua-l archive

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


Why was the simple syntax addition for table constructors not augmented to use a ":" operator between table constructors, where "table1:table2" means attaching table2 as a metatable of table1? (I suggested using ":" for that purpose, but you may design another notation if you think it conflicts with other syntax, e.g. using "~" or ":=" or simply "=").
We should not even need to call setmetatable() with simple constructors.
Then what we do in LuaC is another problem. But probably a Lua state may also have an API to set a default metatable (defined as some "global" in the Lua state context), even if we can override this context by using "table1:null" with the same notation in Lua to explicitly remove this default.

Le dim. 17 mars 2019 à 16:03, temp 213 qwe <temp213@gorodok.net> a écrit :
Proposal:
While table metatable is not set, make it "t->metatable =
G(L)->mt[LUA_TTABLE]" by default, instead of "t->metatable =
NULL".
Access from Lua could be provided by special string e.g.
getmetatable("table")
And creation of this default metatable in tablelib init, like
for strings, additionally __index could also be set to
tablelib.


@ltable.c, line 421:
Table *luaH_new (lua_State *L) {
   GCObject *o = luaC_newobj(L, LUA_TTABLE, sizeof(Table));
   Table *t = gco2t(o);
-  t->metatable = NULL;
+  t->metatable = G(L)->mt[LUA_TTABLE];
   t->flags = cast_byte(~0);
   t->array = NULL;
   t->sizearray = 0;
   setnodevector(L, t, 0);
   return t;
}

@lapi.c,, line 697:
LUA_API int lua_getmetatable (lua_State *L, int objindex) {
   const TValue *obj;
   Table *mt;
   int res = 0;
   lua_lock(L);
   obj = index2addr(L, objindex);
   switch (ttnov(obj)) {
     case LUA_TTABLE:
       mt = hvalue(obj)->metatable;
       break;
     case LUA_TUSERDATA:
       mt = uvalue(obj)->metatable;
       break;
+    case LUA_TSTRING: {
+      if (0 == strcmp(lua_tostring(L, objindex), "table"))
+        mt = G(L)->mt[LUA_TTABLE];
+      else
+        mt = G(L)->mt[LUA_TSTRING];
+      break;
+    }
     default:
       mt = G(L)->mt[ttnov(obj)];
       break;
   }
   if (mt != NULL) {
     sethvalue(L, L->top, mt);
     api_incr_top(L);
     res = 1;
   }
   lua_unlock(L);
   return res;
}

@lapi.c, line 846:
LUA_API int lua_setmetatable (lua_State *L, int objindex) {
   TValue *obj;
   Table *mt;
   lua_lock(L);
   api_checknelems(L, 1);
   obj = index2addr(L, objindex);
   if (ttisnil(L->top - 1))
     mt = NULL;
   else {
     api_check(L, ttistable(L->top - 1), "table expected");
     mt = hvalue(L->top - 1);
   }
   switch (ttnov(obj)) {
     case LUA_TTABLE: {
       hvalue(obj)->metatable = mt;
       if (mt) {
         luaC_objbarrier(L, gcvalue(obj), mt);
         luaC_checkfinalizer(L, gcvalue(obj), mt);
       }
       break;
     }
     case LUA_TUSERDATA: {
       uvalue(obj)->metatable = mt;
       if (mt) {
         luaC_objbarrier(L, uvalue(obj), mt);
         luaC_checkfinalizer(L, gcvalue(obj), mt);
       }
       break;
     }
+    case LUA_TSTRING: {
+      if (0 == strcmp(lua_tostring(L, objindex), "table"))
+        G(L)->mt[LUA_TTABLE] = mt;
+      else
+        G(L)->mt[LUA_TSTRING] = mt;
+      break;
+    }
     default: {
       G(L)->mt[ttnov(obj)] = mt;
       break;
     }
   }
   L->top--;
   lua_unlock(L);
   return 1;
}

@ltablib.c, line 440:
+static void createmetatable (lua_State *L) {
+  lua_createtable(L, 0, 1);  /* table to be metatable for
tables */
+  lua_pushliteral(L, "table");  /* 'table' string */
+  lua_pushvalue(L, -2);  /* copy table */
+  lua_setmetatable(L, -2);  /* set table as metatable for
tables */
+  lua_pop(L, 1);  /* pop 'table' string */
+  lua_pushvalue(L, -2);  /* get table library */
+  lua_setfield(L, -2, "__index");  /* metatable.__index =
table */
+  lua_pop(L, 1);  /* pop metatable */
+}

LUAMOD_API int luaopen_table (lua_State *L) {
   luaL_newlib(L, tab_funcs);
+  createmetatable(L);
#if defined(LUA_COMPAT_UNPACK)
   /* _G.unpack = table.unpack */
   lua_getfield(L, -1, "unpack");
   lua_setglobal(L, "unpack");
#endif
   return 1;
}

regards,
Pavel