lua-users home
lua-l archive

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


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