lua-users home
lua-l archive

default LUA_TTABLE metatable, like for strings

[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

AltStyle によって変換されたページ (->オリジナル) /