浏览代码

metatables for all types

Roberto Ierusalimschy 20 年之前
父节点
当前提交
6cf85dcc90
共有 7 个文件被更改,包括 45 次插入14 次删除
  1. 8 5
      lapi.c
  2. 10 1
      lgc.c
  3. 3 1
      lstate.c
  4. 2 1
      lstate.h
  5. 16 1
      lstrlib.c
  6. 4 4
      ltm.c
  7. 2 1
      ltm.h

+ 8 - 5
lapi.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lapi.c,v 2.37 2005/04/04 18:12:51 roberto Exp roberto $
+** $Id: lapi.c,v 2.38 2005/04/05 15:35:15 roberto Exp roberto $
 ** Lua API
 ** Lua API
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -319,7 +319,8 @@ LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) {
   const TValue *o = index2adr(L, idx);
   const TValue *o = index2adr(L, idx);
   if (tonumber(o, &n)) {
   if (tonumber(o, &n)) {
     lua_Integer res;
     lua_Integer res;
-    lua_number2integer(res, nvalue(o));
+    lua_Number num = nvalue(o);
+    lua_number2integer(res, num);
     return res;
     return res;
   }
   }
   else
   else
@@ -587,6 +588,9 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex) {
     case LUA_TUSERDATA:
     case LUA_TUSERDATA:
       mt = uvalue(obj)->metatable;
       mt = uvalue(obj)->metatable;
       break;
       break;
+    default:
+      mt = G(L)->mt[ttype(obj)];
+      break;
   }
   }
   if (mt == NULL)
   if (mt == NULL)
     res = 0;
     res = 0;
@@ -681,7 +685,6 @@ LUA_API void lua_rawseti (lua_State *L, int idx, int n) {
 LUA_API int lua_setmetatable (lua_State *L, int objindex) {
 LUA_API int lua_setmetatable (lua_State *L, int objindex) {
   TValue *obj;
   TValue *obj;
   Table *mt;
   Table *mt;
-  int res = 1;
   lua_lock(L);
   lua_lock(L);
   api_checknelems(L, 1);
   api_checknelems(L, 1);
   obj = index2adr(L, objindex);
   obj = index2adr(L, objindex);
@@ -706,13 +709,13 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) {
       break;
       break;
     }
     }
     default: {
     default: {
-      res = 0;  /* cannot set */
+      G(L)->mt[ttype(obj)] = mt;
       break;
       break;
     }
     }
   }
   }
   L->top--;
   L->top--;
   lua_unlock(L);
   lua_unlock(L);
-  return res;
+  return 1;
 }
 }
 
 
 
 

+ 10 - 1
lgc.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lgc.c,v 2.30 2005/03/16 17:00:21 roberto Exp roberto $
+** $Id: lgc.c,v 2.31 2005/03/22 16:04:29 roberto Exp roberto $
 ** Garbage Collector
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -493,6 +493,13 @@ void luaC_freeall (lua_State *L) {
 }
 }
 
 
 
 
+static void markmt (global_State *g) {
+  int i;
+  for (i=0; i<NUM_TAGS; i++)
+    if (g->mt[i]) markobject(g, g->mt[i]);
+}
+
+
 /* mark root set */
 /* mark root set */
 static void markroot (lua_State *L) {
 static void markroot (lua_State *L) {
   global_State *g = G(L);
   global_State *g = G(L);
@@ -503,6 +510,7 @@ static void markroot (lua_State *L) {
   /* make global table be traversed before main stack */
   /* make global table be traversed before main stack */
   markvalue(g, gt(g->mainthread));
   markvalue(g, gt(g->mainthread));
   markvalue(g, registry(L));
   markvalue(g, registry(L));
+  markmt(g);
   g->gcstate = GCSpropagate;
   g->gcstate = GCSpropagate;
 }
 }
 
 
@@ -529,6 +537,7 @@ static void atomic (lua_State *L) {
   g->weak = NULL;
   g->weak = NULL;
   lua_assert(!iswhite(obj2gco(g->mainthread)));
   lua_assert(!iswhite(obj2gco(g->mainthread)));
   markobject(g, L);  /* mark running thread */
   markobject(g, L);  /* mark running thread */
+  markmt(g);  /* mark basic metatables (again) */
   propagateall(g);
   propagateall(g);
   /* remark gray again */
   /* remark gray again */
   g->gray = g->grayagain;
   g->gray = g->grayagain;

+ 3 - 1
lstate.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lstate.c,v 2.29 2005/04/05 13:41:29 roberto Exp roberto $
+** $Id: lstate.c,v 2.30 2005/04/05 15:57:59 roberto Exp roberto $
 ** Global State
 ** Global State
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -141,6 +141,7 @@ void luaE_freethread (lua_State *L, lua_State *L1) {
 
 
 
 
 LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
 LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
+  int i;
   lua_State *L;
   lua_State *L;
   global_State *g;
   global_State *g;
   void *l = (*f)(ud, NULL, 0, state_size(LG));
   void *l = (*f)(ud, NULL, 0, state_size(LG));
@@ -177,6 +178,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
   g->gcpause = LUAI_GCPAUSE;
   g->gcpause = LUAI_GCPAUSE;
   g->gcstepmul = LUAI_GCMUL;
   g->gcstepmul = LUAI_GCMUL;
   g->gcdept = 0;
   g->gcdept = 0;
+  for (i=0; i<NUM_TAGS; i++) g->mt[i] = NULL;
   if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) {
   if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) {
     /* memory allocation error: free partial state */
     /* memory allocation error: free partial state */
     close_state(L);
     close_state(L);

+ 2 - 1
lstate.h

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lstate.h,v 2.19 2005/04/05 13:41:29 roberto Exp roberto $
+** $Id: lstate.h,v 2.20 2005/04/25 19:24:10 roberto Exp roberto $
 ** Global State
 ** Global State
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -89,6 +89,7 @@ typedef struct global_State {
   TValue _registry;
   TValue _registry;
   struct lua_State *mainthread;
   struct lua_State *mainthread;
   UpVal uvhead;  /* head of double-linked list of all open upvalues */
   UpVal uvhead;  /* head of double-linked list of all open upvalues */
+  struct Table *mt[NUM_TAGS];  /* metatables for basic types */
   TString *tmname[TM_N];  /* array with tag-method names */
   TString *tmname[TM_N];  /* array with tag-method names */
 } global_State;
 } global_State;
 
 

+ 16 - 1
lstrlib.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lstrlib.c,v 1.110 2005/03/08 20:10:05 roberto Exp roberto $
+** $Id: lstrlib.c,v 1.111 2005/03/22 16:54:29 roberto Exp roberto $
 ** Standard library for string operations and pattern-matching
 ** Standard library for string operations and pattern-matching
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -772,11 +772,26 @@ static const luaL_reg strlib[] = {
 };
 };
 
 
 
 
+static void createmetatable (lua_State *L) {
+  lua_newtable(L);  /* create metatable for strings */
+  lua_pushliteral(L, "");  /* dummy string */
+  lua_pushvalue(L, -2);
+  lua_setmetatable(L, -2);  /* set string metatable */
+  lua_pop(L, 1);  /* pop dummy string */
+  lua_pushvalue(L, -2);  /* string library... */
+  lua_setfield(L, -2, "__index");  /* ...is the __index metamethod */
+  lua_getfield(L, -2, "len");
+  lua_setfield(L, -2, "__siz");
+  lua_pop(L, 1);  /* pop metatable */
+}
+
+
 /*
 /*
 ** Open string library
 ** Open string library
 */
 */
 LUALIB_API int luaopen_string (lua_State *L) {
 LUALIB_API int luaopen_string (lua_State *L) {
   luaL_openlib(L, LUA_STRLIBNAME, strlib, 0);
   luaL_openlib(L, LUA_STRLIBNAME, strlib, 0);
+  createmetatable(L);
   return 1;
   return 1;
 }
 }
 
 

+ 4 - 4
ltm.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: ltm.c,v 2.3 2004/04/30 20:13:38 roberto Exp roberto $
+** $Id: ltm.c,v 2.4 2005/03/08 18:00:16 roberto Exp roberto $
 ** Tag methods
 ** Tag methods
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -32,7 +32,7 @@ void luaT_init (lua_State *L) {
     "__index", "__newindex",
     "__index", "__newindex",
     "__gc", "__mode", "__eq",
     "__gc", "__mode", "__eq",
     "__add", "__sub", "__mul", "__div", "__mod",
     "__add", "__sub", "__mul", "__div", "__mod",
-    "__pow", "__unm", "__lt", "__le",
+    "__pow", "__unm", "__siz", "__lt", "__le",
     "__concat", "__call"
     "__concat", "__call"
   };
   };
   int i;
   int i;
@@ -68,8 +68,8 @@ const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) {
       mt = uvalue(o)->metatable;
       mt = uvalue(o)->metatable;
       break;
       break;
     default:
     default:
-      mt = NULL;
+      mt = G(L)->mt[ttype(o)];
   }
   }
-  return (mt ?  luaH_getstr(mt, G(L)->tmname[event]) : &luaO_nilobject);
+  return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : &luaO_nilobject);
 }
 }
 
 

+ 2 - 1
ltm.h

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: ltm.h,v 2.2 2005/03/08 18:00:16 roberto Exp roberto $
+** $Id: ltm.h,v 2.3 2005/04/25 19:24:10 roberto Exp roberto $
 ** Tag methods
 ** Tag methods
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -28,6 +28,7 @@ typedef enum {
   TM_MOD,
   TM_MOD,
   TM_POW,
   TM_POW,
   TM_UNM,
   TM_UNM,
+  TM_SIZ,
   TM_LT,
   TM_LT,
   TM_LE,
   TM_LE,
   TM_CONCAT,
   TM_CONCAT,