Quellcode durchsuchen

tag system replaced by event tables

Roberto Ierusalimschy vor 24 Jahren
Ursprung
Commit
592a309177
24 geänderte Dateien mit 412 neuen und 706 gelöschten Zeilen
  1. 59 91
      lapi.c
  2. 6 13
      lauxlib.c
  3. 2 4
      lauxlib.h
  4. 40 98
      lbaselib.c
  5. 6 23
      ldebug.c
  6. 12 9
      ldo.c
  7. 1 3
      lfunc.c
  8. 61 60
      lgc.c
  9. 2 2
      lgc.h
  10. 43 15
      liolib.c
  11. 2 3
      lmathlib.c
  12. 5 17
      lobject.h
  13. 11 10
      lstate.c
  14. 24 10
      lstate.h
  15. 5 3
      lstring.c
  16. 2 2
      lstrlib.c
  17. 4 15
      ltable.c
  18. 1 2
      ltable.h
  19. 23 38
      ltests.c
  20. 24 141
      ltm.c
  21. 8 41
      ltm.h
  22. 12 24
      lua.h
  23. 58 79
      lvm.c
  24. 1 3
      lvm.h

+ 59 - 91
lapi.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lapi.c,v 1.160 2001/11/16 16:29:51 roberto Exp $
+** $Id: lapi.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $
 ** Lua API
 ** See Copyright Notice in lua.h
 */
@@ -45,8 +45,8 @@ static TObject *negindex (lua_State *L, int index) {
     return L->top+index;
   }
   else switch (index) {  /* pseudo-indices */
-    case LUA_REGISTRYINDEX: return &G(L)->registry;
-    case LUA_GLOBALSINDEX: return &L->gt;
+    case LUA_REGISTRYINDEX: return registry(L);
+    case LUA_GLOBALSINDEX: return gt(L);
     default: {
       TObject *func = (L->ci->base - 1);
       index = LUA_GLOBALSINDEX - index;
@@ -149,20 +149,15 @@ LUA_API void lua_pushvalue (lua_State *L, int index) {
 */
 
 
-LUA_API int lua_rawtag (lua_State *L, int index) {
+LUA_API int lua_type (lua_State *L, int index) {
   StkId o = luaA_indexAcceptable(L, index);
   return (o == NULL) ? LUA_TNONE : ttype(o);
 }
 
 
-LUA_API const char *lua_type (lua_State *L, int index) {
-  StkId o;
-  const char *type;
-  lua_lock(L);
-  o = luaA_indexAcceptable(L, index);
-  type = (o == NULL) ? "no value" : luaT_typename(G(L), o);
-  lua_unlock(L);
-  return type;
+LUA_API const char *lua_typename (lua_State *L, int t) {
+  UNUSED(L);
+  return (t == LUA_TNONE) ? "no value" : luaT_typenames[t];
 }
 
 
@@ -180,22 +175,11 @@ LUA_API int lua_isnumber (lua_State *L, int index) {
 
 
 LUA_API int lua_isstring (lua_State *L, int index) {
-  int t = lua_rawtag(L, index);
+  int t = lua_type(L, index);
   return (t == LUA_TSTRING || t == LUA_TNUMBER);
 }
 
 
-LUA_API int lua_tag (lua_State *L, int index) {
-  StkId o;
-  int i;
-  lua_lock(L);  /* other thread could be changing the tag */
-  o = luaA_indexAcceptable(L, index);
-  i = (o == NULL) ? LUA_NOTAG : luaT_tag(o);
-  lua_unlock(L);
-  return i;
-}
-
-
 LUA_API int lua_equal (lua_State *L, int index1, int index2) {
   StkId o1 = luaA_indexAcceptable(L, index1);
   StkId o2 = luaA_indexAcceptable(L, index2);
@@ -346,8 +330,10 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
 
 
 LUA_API void lua_getglobal (lua_State *L, const char *name) {
+  TObject o;
   lua_lock(L);
-  luaV_getglobal(L, luaS_new(L, name), L->top);
+  setsvalue(&o, luaS_new(L, name));
+  luaV_gettable(L, gt(L), &o, L->top);
   api_incr_top(L);
   lua_unlock(L);
 }
@@ -391,6 +377,29 @@ LUA_API void lua_newtable (lua_State *L) {
 }
 
 
+LUA_API void lua_geteventtable (lua_State *L, int objindex) {
+  StkId obj;
+  Table *et;
+  lua_lock(L);
+  obj = luaA_indexAcceptable(L, objindex);
+  switch (ttype(obj)) {
+    case LUA_TTABLE:
+      et = hvalue(obj)->eventtable;
+      break;
+    case LUA_TUSERDATA:
+      et = uvalue(obj)->uv.eventtable;
+      break;
+    default:
+      et = hvalue(defaultet(L));
+  }
+  if (et == hvalue(defaultet(L)))
+    setnilvalue(L->top);
+  else
+    sethvalue(L->top, et);
+  api_incr_top(L);
+  lua_unlock(L);
+}
+
 
 /*
 ** set functions (stack -> Lua)
@@ -398,9 +407,11 @@ LUA_API void lua_newtable (lua_State *L) {
 
 
 LUA_API void lua_setglobal (lua_State *L, const char *name) {
+  TObject o;
   lua_lock(L);
   api_checknelems(L, 1);
-  luaV_setglobal(L, luaS_new(L, name), L->top - 1);
+  setsvalue(&o, luaS_new(L, name));
+  luaV_settable(L, gt(L), &o, L->top - 1);
   L->top--;  /* remove element from the top */
   lua_unlock(L);
 }
@@ -447,11 +458,32 @@ LUA_API void lua_setglobals (lua_State *L) {
   api_checknelems(L, 1);
   newtable = --L->top;
   api_check(L, ttype(newtable) == LUA_TTABLE);
-  setobj(&L->gt, newtable);
+  setobj(gt(L), newtable);
   lua_unlock(L);
 }
 
 
+LUA_API void lua_seteventtable (lua_State *L, int objindex) {
+  StkId obj, et;
+  lua_lock(L);
+  api_checknelems(L, 1);
+  obj = luaA_indexAcceptable(L, objindex);
+  et = --L->top;
+  api_check(L, ttype(et) == LUA_TTABLE);
+  switch (ttype(obj)) {
+    case LUA_TTABLE:
+      hvalue(obj)->eventtable = hvalue(et);
+      break;
+    case LUA_TUSERDATA:
+      uvalue(obj)->uv.eventtable = hvalue(et);
+      break;
+    default:
+      luaO_verror(L, "cannot change the event table of a %.20s",
+                  luaT_typenames[ttype(obj)]);
+  }
+  lua_unlock(L);
+}
+
 
 /*
 ** `do' functions (run Lua code)
@@ -533,70 +565,6 @@ LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold) {
 ** miscellaneous functions
 */
 
-LUA_API int lua_newtype (lua_State *L, const char *name, int basictype) {
-  int tag;
-  lua_lock(L);
-  if (basictype != LUA_TNONE &&
-      basictype != LUA_TTABLE &&
-      basictype != LUA_TUSERDATA)
-    luaO_verror(L, "invalid basic type (%d) for new type", basictype);
-  tag = luaT_newtag(L, name, basictype);
-  if (tag == LUA_TNONE)
-    luaO_verror(L, "type name '%.30s' already exists", name);
-  lua_unlock(L);
-  return tag;
-}
-
-
-LUA_API int lua_name2tag (lua_State *L, const char *name) {
-  int tag;
-  const TObject *v;
-  lua_lock(L);
-  v = luaH_getstr(G(L)->type2tag, luaS_new(L, name));
-  if (ttype(v) == LUA_TNIL)
-    tag = LUA_TNONE;
-  else {
-    lua_assert(ttype(v) == LUA_TNUMBER);
-    tag = cast(int, nvalue(v));
-  }
-  lua_unlock(L);
-  return tag;
-}
-
-
-LUA_API const char *lua_tag2name (lua_State *L, int tag) {
-  const char *s;
-  lua_lock(L);
-  s = (tag == LUA_TNONE) ? "no value" : typenamebytag(G(L), tag);
-  lua_unlock(L);
-  return s;
-}
-
-
-LUA_API void lua_settag (lua_State *L, int tag) {
-  int basictype;
-  lua_lock(L);
-  api_checknelems(L, 1);
-  if (tag < 0 || tag >= G(L)->ntag)
-    luaO_verror(L, "%d is not a valid tag", tag);
-  basictype = G(L)->TMtable[tag].basictype;
-  if (basictype != LUA_TNONE && basictype != ttype(L->top-1))
-    luaO_verror(L, "tag %d can only be used for type '%.20s'", tag,
-                typenamebytag(G(L), basictype));
-  switch (ttype(L->top-1)) {
-    case LUA_TTABLE:
-      hvalue(L->top-1)->htag = tag;
-      break;
-    case LUA_TUSERDATA:
-      uvalue(L->top-1)->uv.tag = tag;
-      break;
-    default:
-      luaO_verror(L, "cannot change the tag of a %.20s",
-                  luaT_typename(G(L), L->top-1));
-  }
-  lua_unlock(L);
-}
-
 
 LUA_API void lua_error (lua_State *L, const char *s) {
   lua_lock(L);

+ 6 - 13
lauxlib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lauxlib.c,v 1.53 2001/10/31 19:40:14 roberto Exp $
+** $Id: lauxlib.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $
 ** Auxiliary functions for building Lua libraries
 ** See Copyright Notice in lua.h
 */
@@ -43,7 +43,8 @@ LUALIB_API void luaL_argerror (lua_State *L, int narg, const char *extramsg) {
 
 LUALIB_API void luaL_typerror (lua_State *L, int narg, const char *tname) {
   char buff[80];
-  sprintf(buff, "%.25s expected, got %.25s", tname, lua_type(L,narg));
+  sprintf(buff, "%.25s expected, got %.25s", tname,
+                                             lua_typename(L, lua_type(L,narg)));
   luaL_argerror(L, narg, buff);
 }
 
@@ -59,26 +60,18 @@ LUALIB_API void luaL_check_stack (lua_State *L, int space, const char *mes) {
 }
 
 
-LUALIB_API void luaL_check_rawtype(lua_State *L, int narg, int t) {
-  if (lua_rawtag(L, narg) != t)
+LUALIB_API void luaL_check_type(lua_State *L, int narg, int t) {
+  if (lua_type(L, narg) != t)
     tag_error(L, narg, t);
 }
 
 
 LUALIB_API void luaL_check_any (lua_State *L, int narg) {
-  if (lua_rawtag(L, narg) == LUA_TNONE)
+  if (lua_type(L, narg) == LUA_TNONE)
     luaL_argerror(L, narg, "value expected");
 }
 
 
-LUALIB_API void *luaL_check_userdata (lua_State *L, int narg,
-                                      const char *name) {
-  if (strcmp(lua_type(L, narg), name) != 0)
-    luaL_typerror(L, narg, name);
-  return lua_touserdata(L, narg);
-}
-
-
 LUALIB_API const char *luaL_check_lstr (lua_State *L, int narg, size_t *len) {
   const char *s = lua_tostring(L, narg);
   if (!s) tag_error(L, narg, LUA_TSTRING);

+ 2 - 4
lauxlib.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lauxlib.h,v 1.38 2001/10/31 19:40:14 roberto Exp $
+** $Id: lauxlib.h,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $
 ** Auxiliary functions for building Lua libraries
 ** See Copyright Notice in lua.h
 */
@@ -38,10 +38,8 @@ LUALIB_API lua_Number luaL_check_number (lua_State *L, int numArg);
 LUALIB_API lua_Number luaL_opt_number (lua_State *L, int nArg, lua_Number def);
 
 LUALIB_API void luaL_check_stack (lua_State *L, int space, const char *msg);
-LUALIB_API void luaL_check_rawtype (lua_State *L, int narg, int t);
+LUALIB_API void luaL_check_type (lua_State *L, int narg, int t);
 LUALIB_API void luaL_check_any (lua_State *L, int narg);
-LUALIB_API void *luaL_check_userdata (lua_State *L, int narg,
-                                      const char *name);
 
 LUALIB_API void luaL_verror (lua_State *L, const char *fmt, ...);
 LUALIB_API int luaL_findstring (const char *name, 

+ 40 - 98
lbaselib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lbaselib.c,v 1.45 2001/10/26 17:33:30 roberto Exp $
+** $Id: lbaselib.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $
 ** Basic library
 ** See Copyright Notice in lua.h
 */
@@ -41,7 +41,7 @@ static int luaB__ALERT (lua_State *L) {
 ** The library `liolib' redefines _ERRORMESSAGE for better error information.
 */
 static int luaB__ERRORMESSAGE (lua_State *L) {
-  luaL_check_rawtype(L, 1, LUA_TSTRING);
+  luaL_check_type(L, 1, LUA_TSTRING);
   lua_getglobal(L, LUA_ALERT);
   if (lua_isfunction(L, -1)) {  /* avoid error loop if _ALERT is not defined */
     lua_Debug ar;
@@ -136,41 +136,22 @@ static int luaB_getglobal (lua_State *L) {
 }
 
 
-/* auxiliary function to get `tags' */
-static int gettag (lua_State *L, int narg) {
-  switch (lua_rawtag(L, narg)) {
-    case LUA_TNUMBER:
-      return (int)(lua_tonumber(L, narg));
-    case LUA_TSTRING: {
-      const char *name = lua_tostring(L, narg);
-      int tag = lua_name2tag(L, name);
-      if (tag == LUA_TNONE)
-        luaL_verror(L, "'%.30s' is not a valid type name", name);
-      return tag;
-    }
-    default:
-      luaL_argerror(L, narg, "tag or type name expected");
-      return 0;  /* to avoid warnings */
+static int luaB_eventtable (lua_State *L) {
+  luaL_check_type(L, 1, LUA_TTABLE);
+  if (lua_isnull(L, 2))
+    lua_geteventtable(L, 1);
+  else {
+    lua_settop(L, 2);
+    luaL_check_type(L, 2, LUA_TTABLE);
+    lua_seteventtable(L, 1);
   }
-}
-
-
-static int luaB_tag (lua_State *L) {
-  luaL_check_any(L, 1);
-  lua_pushnumber(L, lua_tag(L, 1));
   return 1;
 }
 
-static int luaB_settype (lua_State *L) {
-  luaL_check_rawtype(L, 1, LUA_TTABLE);
-  lua_pushvalue(L, 1);  /* push table */
-  lua_settag(L, gettag(L, 2));
-  return 1;  /* return table */
-}
 
 static int luaB_weakmode (lua_State *L) {
   const char *mode = luaL_check_string(L, 2);
-  luaL_check_rawtype(L, 1, LUA_TTABLE);
+  luaL_check_type(L, 1, LUA_TTABLE);
   if (*mode == '?') {
     char buff[3];
     char *s = buff;
@@ -191,17 +172,11 @@ static int luaB_weakmode (lua_State *L) {
   }
 }
 
-static int luaB_newtype (lua_State *L) {
-  const char *name = luaL_opt_string(L, 1, NULL);
-  lua_pushnumber(L, lua_newtype(L, name, LUA_TTABLE));
-  return 1;
-}
-
 
 static int luaB_globals (lua_State *L) {
   lua_getglobals(L);  /* value to be returned */
   if (!lua_isnull(L, 1)) {
-    luaL_check_rawtype(L, 1, LUA_TTABLE);
+    luaL_check_type(L, 1, LUA_TTABLE);
     lua_pushvalue(L, 1);  /* new table of globals */
     lua_setglobals(L);
   }
@@ -209,43 +184,20 @@ static int luaB_globals (lua_State *L) {
 }
 
 static int luaB_rawget (lua_State *L) {
-  luaL_check_rawtype(L, 1, LUA_TTABLE);
+  luaL_check_type(L, 1, LUA_TTABLE);
   luaL_check_any(L, 2);
   lua_rawget(L, -2);
   return 1;
 }
 
 static int luaB_rawset (lua_State *L) {
-  luaL_check_rawtype(L, 1, LUA_TTABLE);
+  luaL_check_type(L, 1, LUA_TTABLE);
   luaL_check_any(L, 2);
   luaL_check_any(L, 3);
   lua_rawset(L, -3);
   return 1;
 }
 
-static int luaB_settagmethod (lua_State *L) {
-  int tag = gettag(L, 1);
-  const char *event = luaL_check_string(L, 2);
-  luaL_arg_check(L, lua_isfunction(L, 3) || lua_isnil(L, 3), 3,
-                 "function or nil expected");
-  if (strcmp(event, "gc") == 0)
-    lua_error(L, "cannot set `gc' tag method from Lua");
-  lua_gettagmethod(L, tag, event);
-  lua_pushvalue(L, 3);
-  lua_settagmethod(L, tag, event);
-  return 1;
-}
-
-
-static int luaB_gettagmethod (lua_State *L) {
-  int tag = gettag(L, 1);
-  const char *event = luaL_check_string(L, 2);
-  if (strcmp(event, "gc") == 0)
-    lua_error(L, "cannot get `gc' tag method from Lua");
-  lua_gettagmethod(L, tag, event);
-  return 1;
-}
-
 
 static int luaB_gcinfo (lua_State *L) {
   lua_pushnumber(L, lua_getgccount(L));
@@ -262,20 +214,20 @@ static int luaB_collectgarbage (lua_State *L) {
 
 static int luaB_type (lua_State *L) {
   luaL_check_any(L, 1);
-  lua_pushstring(L, lua_type(L, 1));
-  return 1;
-}
-
-
-static int luaB_rawtype (lua_State *L) {
-  luaL_check_any(L, 1);
-  lua_pushstring(L, lua_tag2name(L, lua_rawtag(L, 1)));
+  if (lua_isnull(L, 2))
+    lua_pushstring(L, lua_typename(L, lua_type(L, 1)));
+  else {
+    if (strcmp(lua_typename(L, lua_type(L, 1)), luaL_check_string(L, 2)) == 0)
+      lua_pushnumber(L, 1);
+    else
+      lua_pushnil(L);
+  }
   return 1;
 }
 
 
 static int luaB_next (lua_State *L) {
-  luaL_check_rawtype(L, 1, LUA_TTABLE);
+  luaL_check_type(L, 1, LUA_TTABLE);
   lua_settop(L, 2);  /* create a 2nd argument if there isn't one */
   if (lua_next(L, 1))
     return 2;
@@ -393,7 +345,7 @@ static int luaB_require (lua_State *L) {
 
 static int aux_unpack (lua_State *L, int arg) {
   int n, i;
-  luaL_check_rawtype(L, arg, LUA_TTABLE);
+  luaL_check_type(L, arg, LUA_TTABLE);
   n = lua_getn(L, arg);
   luaL_check_stack(L, n, "table too big to unpack");
   for (i=1; i<=n; i++)  /* push arg[1...n] */
@@ -443,7 +395,7 @@ static int luaB_call (lua_State *L) {
 
 static int luaB_tostring (lua_State *L) {
   char buff[64];
-  switch (lua_rawtag(L, 1)) {
+  switch (lua_type(L, 1)) {
     case LUA_TNUMBER:
       lua_pushstring(L, lua_tostring(L, 1));
       return 1;
@@ -451,16 +403,15 @@ static int luaB_tostring (lua_State *L) {
       lua_pushvalue(L, 1);
       return 1;
     case LUA_TTABLE:
-      sprintf(buff, "%.40s: %p", lua_type(L, 1), lua_topointer(L, 1));
+      sprintf(buff, "%.40s: %p", lua_typename(L, lua_type(L, 1)), lua_topointer(L, 1));
       break;
     case LUA_TFUNCTION:
       sprintf(buff, "function: %p", lua_topointer(L, 1));
       break;
     case LUA_TUSERDATA: {
-      const char *t = lua_type(L, 1);
+      const char *t = lua_typename(L, lua_type(L, 1));
       if (strcmp(t, "userdata") == 0)
-        sprintf(buff, "userdata(%d): %p", lua_tag(L, 1),
-                lua_touserdata(L, 1));
+        sprintf(buff, "userdata: %p", lua_touserdata(L, 1));
       else
         sprintf(buff, "%.40s: %p", t, lua_touserdata(L, 1));
       break;
@@ -478,8 +429,8 @@ static int luaB_tostring (lua_State *L) {
 
 static int luaB_foreachi (lua_State *L) {
   int n, i;
-  luaL_check_rawtype(L, 1, LUA_TTABLE);
-  luaL_check_rawtype(L, 2, LUA_TFUNCTION);
+  luaL_check_type(L, 1, LUA_TTABLE);
+  luaL_check_type(L, 2, LUA_TFUNCTION);
   n = lua_getn(L, 1);
   for (i=1; i<=n; i++) {
     lua_pushvalue(L, 2);  /* function */
@@ -495,8 +446,8 @@ static int luaB_foreachi (lua_State *L) {
 
 
 static int luaB_foreach (lua_State *L) {
-  luaL_check_rawtype(L, 1, LUA_TTABLE);
-  luaL_check_rawtype(L, 2, LUA_TFUNCTION);
+  luaL_check_type(L, 1, LUA_TTABLE);
+  luaL_check_type(L, 2, LUA_TFUNCTION);
   lua_pushnil(L);  /* first index */
   for (;;) {
     if (lua_next(L, 1) == 0)
@@ -523,7 +474,7 @@ static int luaB_assert (lua_State *L) {
 
 
 static int luaB_getn (lua_State *L) {
-  luaL_check_rawtype(L, 1, LUA_TTABLE);
+  luaL_check_type(L, 1, LUA_TTABLE);
   lua_pushnumber(L, lua_getn(L, 1));
   return 1;
 }
@@ -532,7 +483,7 @@ static int luaB_getn (lua_State *L) {
 static int luaB_tinsert (lua_State *L) {
   int v = lua_gettop(L);  /* number of arguments */
   int n, pos;
-  luaL_check_rawtype(L, 1, LUA_TTABLE);
+  luaL_check_type(L, 1, LUA_TTABLE);
   n = lua_getn(L, 1);
   if (v == 2)  /* called with only 2 arguments */
     pos = n+1;
@@ -553,7 +504,7 @@ static int luaB_tinsert (lua_State *L) {
 
 static int luaB_tremove (lua_State *L) {
   int pos, n;
-  luaL_check_rawtype(L, 1, LUA_TTABLE);
+  luaL_check_type(L, 1, LUA_TTABLE);
   n = lua_getn(L, 1);
   pos = luaL_opt_int(L, 2, n);
   if (n <= 0) return 0;  /* table is `empty' */
@@ -665,10 +616,10 @@ static void auxsort (lua_State *L, int l, int u) {
 
 static int luaB_sort (lua_State *L) {
   int n;
-  luaL_check_rawtype(L, 1, LUA_TTABLE);
+  luaL_check_type(L, 1, LUA_TTABLE);
   n = lua_getn(L, 1);
   if (!lua_isnull(L, 2))  /* is there a 2nd argument? */
-    luaL_check_rawtype(L, 2, LUA_TFUNCTION);
+    luaL_check_type(L, 2, LUA_TFUNCTION);
   lua_settop(L, 2);  /* make sure there is two arguments */
   auxsort(L, 1, n);
   return 0;
@@ -686,28 +637,19 @@ static const luaL_reg base_funcs[] = {
   {"dofile", luaB_dofile},
   {"dostring", luaB_dostring},
   {"error", luaB_error},
+  {"eventtable", luaB_eventtable},
   {"foreach", luaB_foreach},
   {"foreachi", luaB_foreachi},
   {"gcinfo", luaB_gcinfo},
-  {"getglobal", luaB_getglobal},
-  {"gettagmethod", luaB_gettagmethod},
+  {"getglobal", luaB_getglobal},  /* compatibility with 4.0 */
   {"globals", luaB_globals},
   {"loadfile", luaB_loadfile},
   {"loadstring", luaB_loadstring},
-  {"newtype", luaB_newtype},
-  {"newtag", luaB_newtype},  /* for compatibility 4.0 */
   {"next", luaB_next},
   {"print", luaB_print},
   {"rawget", luaB_rawget},
   {"rawset", luaB_rawset},
-  {"rawgettable", luaB_rawget},  /* for compatibility 3.2 */
-  {"rawsettable", luaB_rawset},  /* for compatibility 3.2 */
-  {"rawtype", luaB_rawtype},
-  {"setglobal", luaB_setglobal},
-  {"settag", luaB_settype},  /* for compatibility 4.0 */
-  {"settype", luaB_settype},
-  {"settagmethod", luaB_settagmethod},
-  {"tag", luaB_tag},
+  {"setglobal", luaB_setglobal},  /* compatibility with 4.0 */
   {"tonumber", luaB_tonumber},
   {"tostring", luaB_tostring},
   {"type", luaB_type},

+ 6 - 23
ldebug.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldebug.c,v 1.92 2001/10/31 19:58:11 roberto Exp $
+** $Id: ldebug.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $
 ** Debug Interface
 ** See Copyright Notice in lua.h
 */
@@ -205,22 +205,8 @@ static void funcinfo (lua_State *L, lua_Debug *ar, StkId func) {
 }
 
 
-static const char *travtagmethods (global_State *G, const TObject *o) {
-  if (ttype(o) == LUA_TFUNCTION) {
-    int e;
-    for (e=0; e<TM_N; e++) {
-      int t;
-      for (t=0; t<G->ntag; t++)
-        if (clvalue(o) == luaT_gettm(G, t, e))
-          return luaT_eventname[e];
-    }
-  }
-  return NULL;
-}
-
-
 static const char *travglobals (lua_State *L, const TObject *o) {
-  Table *g = hvalue(&L->gt);
+  Table *g = hvalue(gt(L));
   int i = sizenode(g);
   while (i--) {
     Node *n = node(g, i);
@@ -235,10 +221,7 @@ static void getname (lua_State *L, const TObject *f, lua_Debug *ar) {
   /* try to find a name for given function */
   if ((ar->name = travglobals(L, f)) != NULL)
     ar->namewhat = "global";
-  /* not found: try tag methods */
-  else if ((ar->name = travtagmethods(G(L), f)) != NULL)
-    ar->namewhat = "tag-method";
-  else ar->namewhat = "";  /* not found at all */
+  else ar->namewhat = "";  /* not found */
 }
 
 
@@ -531,7 +514,7 @@ static const char *getfuncname (lua_State *L, CallInfo *ci,
 void luaG_typeerror (lua_State *L, StkId o, const char *op) {
   const char *name;
   const char *kind = getobjname(L, o, &name);
-  const char *t = luaT_typename(G(L), o);
+  const char *t = luaT_typenames[ttype(o)];
   if (kind)
     luaO_verror(L, "attempt to %.30s %.20s `%.40s' (a %.10s value)",
                 op, kind, name, t);
@@ -556,8 +539,8 @@ void luaG_aritherror (lua_State *L, StkId p1, TObject *p2) {
 
 
 void luaG_ordererror (lua_State *L, const TObject *p1, const TObject *p2) {
-  const char *t1 = luaT_typename(G(L), p1);
-  const char *t2 = luaT_typename(G(L), p2);
+  const char *t1 = luaT_typenames[ttype(p1)];
+  const char *t2 = luaT_typenames[ttype(p2)];
   if (t1[2] == t2[2])
     luaO_verror(L, "attempt to compare two %.10s values", t1);
   else

+ 12 - 9
ldo.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.c,v 1.144 2001/11/27 20:56:47 roberto Exp $
+** $Id: ldo.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
@@ -43,8 +43,7 @@ void luaD_init (lua_State *L, int stacksize) {
   stacksize += EXTRA_STACK;
   L->stack = luaM_newvector(L, stacksize, TObject);
   L->stacksize = stacksize;
-  setnilvalue(L->stack);  /* the `initial' function */
-  L->top = L->basefunc.base = L->stack + 1;
+  L->top = L->basefunc.base = L->stack + RESERVED_STACK_PREFIX;
   restore_stack_limit(L);
 }
 
@@ -143,12 +142,13 @@ void luaD_call (lua_State *L, StkId func) {
   CallInfo ci;
   if (ttype(func) != LUA_TFUNCTION) {
     /* `func' is not a function; check the `function' tag method */
-    Closure *tm = luaT_gettmbyObj(G(L), func, TM_FUNCTION);
-    if (tm == NULL)
+    const TObject *tm = luaT_gettmbyobj(L, func, TM_CALL);
+    if (tm == NULL || ttype(tm) != LUA_TFUNCTION)
       luaG_typeerror(L, func, "call");
     luaD_openstack(L, func);
-    setclvalue(func, tm);  /* tag method is the new function to be called */
+    setobj(func, tm);  /* tag method is the new function to be called */
   }
+  lua_assert(ttype(func) == LUA_TFUNCTION);
   ci.prev = L->ci;  /* chain new callinfo */
   L->ci = &ci;
   ci.base = func+1;
@@ -300,9 +300,12 @@ struct lua_longjmp {
 
 
 static void message (lua_State *L, const char *s) {
-  StkId top = L->top;
-  luaV_getglobal(L, luaS_newliteral(L, LUA_ERRORMESSAGE), top);
-  if (ttype(top) == LUA_TFUNCTION) {
+  TObject o, m;
+  setsvalue(&o, luaS_newliteral(L, LUA_ERRORMESSAGE));
+  luaV_gettable(L, gt(L), &o, &m);
+  if (ttype(&m) == LUA_TFUNCTION) {
+    StkId top = L->top;
+    setobj(top, &m);
     incr_top;
     setsvalue(top+1, luaS_new(L, s));
     incr_top;

+ 1 - 3
lfunc.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lfunc.c,v 1.49 2001/11/06 21:41:53 roberto Exp $
+** $Id: lfunc.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $
 ** Auxiliary functions to manipulate prototypes and closures
 ** See Copyright Notice in lua.h
 */
@@ -54,7 +54,6 @@ UpVal *luaF_findupval (lua_State *L, StkId level) {
   }
   p = luaM_new(L, UpVal);  /* not found: create a new one */
   p->v = level;  /* current value lives in the stack */
-  p->mark = 1;  /* won't participate in GC while open */
   p->next = *pp;  /* chain it in the proper position */
   *pp = p;
   return p;
@@ -68,7 +67,6 @@ void luaF_close (lua_State *L, StkId level) {
     p->v = &p->value;  /* now current value lives here */
     L->openupval = p->next;  /* remove from `open' list */
     p->next = G(L)->rootupval;  /* chain in `closed' list */
-    p->mark = 0;  /* now it can be collected */
     G(L)->rootupval = p;
   }
 }

+ 61 - 60
lgc.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.c,v 1.116 2001/11/06 21:41:53 roberto Exp $
+** $Id: lgc.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
@@ -30,6 +30,15 @@ typedef struct GCState {
 #define strmark(s)    {if ((s)->tsv.marked == 0) (s)->tsv.marked = 1;}
 
 
+/* mark tricks for userdata */
+#define isudmarked(u)	(u->uv.len & 1)
+#define markud(u)	(u->uv.len |= 1)
+#define unmarkud(u)	(u->uv.len--)
+
+
+/* mark tricks for upvalues (assume that open upvalues are always marked) */
+#define isupvalmarked(uv)	((uv)->v != &(uv)->value)
+
 
 static void markobject (GCState *st, TObject *o);
 
@@ -66,9 +75,9 @@ static void markclosure (GCState *st, Closure *cl) {
       protomark(cl->l.p);
       for (i=0; i<cl->l.nupvalues; i++) {  /* mark its upvalues */
         UpVal *u = cl->l.upvals[i];
-        if (!u->mark) {
-          u->mark = 1;
-          markobject(st, u->v);
+        if (!isupvalmarked(u)) {
+          markobject(st, &u->value);
+          u->v = NULL;  /* mark it! */
         }
       }
     }
@@ -90,8 +99,8 @@ static void markobject (GCState *st, TObject *o) {
       strmark(tsvalue(o));
       break;
     case LUA_TUSERDATA:
-      if (!ismarkedudata(uvalue(o)))
-        switchudatamark(uvalue(o));
+      if (!isudmarked(uvalue(o)))
+        markud(uvalue(o));
       break;
     case LUA_TFUNCTION:
       markclosure(st, clvalue(o));
@@ -112,7 +121,6 @@ static void markstacks (lua_State *L, GCState *st) {
   lua_State *L1 = L;
   do {  /* for each thread */
     StkId o, lim;
-    markobject(st, &L1->gt);  /* mark table of globals */
     for (o=L1->stack; o<L1->top; o++)
       markobject(st, o);
     lim = (L1->stack_last - L1->ci->base > MAXSTACK) ? L1->ci->base+MAXSTACK
@@ -124,17 +132,10 @@ static void markstacks (lua_State *L, GCState *st) {
 }
 
 
-static void marktagmethods (global_State *G, GCState *st) {
-  int t;
-  for (t=0; t<G->ntag; t++) {
-    struct TM *tm = &G->TMtable[t];
-    int e;
-    if (tm->name) strmark(tm->name);
-    for (e=0; e<TM_N; e++) {
-      Closure *cl = tm->method[e];
-      if (cl) markclosure(st, cl);
-    }
-  }
+static void markudet (lua_State *L, GCState *st) {
+  Udata *u;
+  for (u = G(L)->rootudata; u; u = u->uv.next)
+    marktable(st, u->uv.eventtable);
 }
 
 
@@ -152,6 +153,7 @@ static void traversetable (GCState *st, Table *h) {
     h->mark = st->toclear;  /* put in the appropriate list */
     st->toclear = h;
   }
+  marktable(st, h->eventtable);
   if (!(mode & LUA_WEAK_VALUE)) {
     i = sizearray(h);
     while (i--)
@@ -172,11 +174,9 @@ static void traversetable (GCState *st, Table *h) {
 
 
 static void markall (lua_State *L, GCState *st) {
-  marktagmethods(G(L), st);  /* mark tag methods */
   markstacks(L, st); /* mark all stacks */
-  marktable(st, G(L)->type2tag);
-  markobject(st, &G(L)->registry);
-  while (st->tmark) {  /* mark tables */
+  markudet(L, st);  /* mark userdata's event tables */
+  while (st->tmark) {  /* traverse marked tables */
     Table *h = st->tmark;  /* get first table from list */
     st->tmark = h->mark;  /* remove it from list */
     traversetable(st, h);
@@ -189,7 +189,7 @@ static int hasmark (const TObject *o) {
     case LUA_TSTRING:
       return tsvalue(o)->tsv.marked;
     case LUA_TUSERDATA:
-      return ismarkedudata(uvalue(o));
+      return isudmarked(uvalue(o));
     case LUA_TTABLE:
       return ismarked(hvalue(o));
     case LUA_TFUNCTION:
@@ -261,8 +261,9 @@ static void collectupval (lua_State *L) {
   UpVal **v = &G(L)->rootupval;
   UpVal *curr;
   while ((curr = *v) != NULL) {
-    if (curr->mark) {
-      curr->mark = 0;
+    if (isupvalmarked(curr)) {
+      lua_assert(curr->v == NULL);
+      curr->v = &curr->value;  /* unmark */
       v = &curr->next;  /* next */
     }
     else {
@@ -289,26 +290,27 @@ static void collecttable (lua_State *L) {
 }
 
 
-static void collectudata (lua_State *L, int keep) {
+static Udata *collectudata (lua_State *L, int keep) {
   Udata **p = &G(L)->rootudata;
   Udata *curr;
+  Udata *collected = NULL;
   while ((curr = *p) != NULL) {
-    if (ismarkedudata(curr)) {
-      switchudatamark(curr);  /* unmark */
+    if (isudmarked(curr)) {
+      unmarkud(curr);
       p = &curr->uv.next;
     }
     else {  /* collect */
-      int tag = curr->uv.tag;
+      const TObject *tm = fasttm(L, curr->uv.eventtable, TM_GC);
       *p = curr->uv.next;
-      if (keep ||  /* must keep all of them (to close state)? */
-          luaT_gettm(G(L), tag, TM_GC)) {  /* or is there a GC tag method? */
-        curr->uv.next = G(L)->TMtable[tag].collected;  /* chain udata ... */
-        G(L)->TMtable[tag].collected = curr;  /* ... to call its TM later */
+      if (keep || tm != NULL) {
+        curr->uv.next = collected;
+        collected = curr;
       }
-      else  /* no tag method; delete udata */
+      else  /* no gc action; delete udata */
         luaM_free(L, curr, sizeudata(curr->uv.len));
     }
   }
+  return collected;
 }
 
 
@@ -347,14 +349,14 @@ static void checkMbuffer (lua_State *L) {
 }
 
 
-static void callgcTM (lua_State *L, const TObject *obj) {
-  Closure *tm = luaT_gettmbyObj(G(L), obj, TM_GC);
-  if (tm != NULL) {
+static void callgcTM (lua_State *L, Udata *udata) {
+  const TObject *tm = fasttm(L, udata->uv.eventtable, TM_GC);
+  if (tm != NULL && ttype(tm) == LUA_TFUNCTION) {
     int oldah = L->allowhooks;
     StkId top = L->top;
     L->allowhooks = 0;  /* stop debug hooks during GC tag methods */
-    setclvalue(top, tm);
-    setobj(top+1, obj);
+    setobj(top, tm);
+    setuvalue(top+1, udata);
     L->top += 2;
     luaD_call(L, top);
     L->top = top;  /* restore top */
@@ -363,53 +365,52 @@ static void callgcTM (lua_State *L, const TObject *obj) {
 }
 
 
-static void callgcTMudata (lua_State *L) {
-  int tag;
+static void callgcTMudata (lua_State *L, Udata *c) {
   luaD_checkstack(L, 3);
-  for (tag=G(L)->ntag-1; tag>=0; tag--) {  /* for each tag (in reverse order) */
-    Udata *udata;
-    while ((udata = G(L)->TMtable[tag].collected) != NULL) {
-      G(L)->TMtable[tag].collected = udata->uv.next;  /* remove it from list */
-      udata->uv.next = G(L)->rootudata;  /* resurect it */
-      G(L)->rootudata = udata;
-      setuvalue(L->top, udata);
-      L->top++;  /* keep it in stack to avoid being (recursively) collected */
-      callgcTM(L, L->top-1);
-      uvalue(L->top-1)->uv.tag = 0;  /* default tag (udata is `finalized') */
-      L->top--;
-    }
+  L->top++;  /* reserve space to keep udata while runs its gc method */
+  while (c != NULL) {
+    Udata *udata = c;
+    c = udata->uv.next;  /* remove udata from list */
+    udata->uv.next = G(L)->rootudata;  /* resurect it */
+    G(L)->rootudata = udata;
+    setuvalue(L->top - 1, udata);
+    callgcTM(L, udata);
+    /* mark udata as finalized (default event table) */
+    uvalue(L->top-1)->uv.eventtable = hvalue(defaultet(L));
   }
+  L->top--;
 }
 
 
 void luaC_callallgcTM (lua_State *L) {
   if (G(L)->rootudata) {  /* avoid problems with incomplete states */
-    collectudata(L, 1);  /* collect all udata into tag lists */
-    callgcTMudata(L);  /* call their GC tag methods */
+    Udata *c = collectudata(L, 1);  /* collect all udata */
+    callgcTMudata(L, c);  /* call their GC tag methods */
   }
 }
 
 
-void luaC_collect (lua_State *L, int all) {
-  collectudata(L, 0);
+Udata *luaC_collect (lua_State *L, int all) {
+  Udata *c = collectudata(L, 0);
   collectstrings(L, all);
   collecttable(L);
   collectproto(L);
   collectupval(L);
   collectclosures(L);
+  return c;
 }
 
 
 void luaC_collectgarbage (lua_State *L) {
+  Udata *c;
   GCState st;
   st.tmark = NULL;
   st.toclear = NULL;
   markall(L, &st);
   cleartables(st.toclear);
-  luaC_collect(L, 0);
+  c = luaC_collect(L, 0);
   checkMbuffer(L);
   G(L)->GCthreshold = 2*G(L)->nblocks;  /* new threshold */
-  callgcTMudata(L);
-  callgcTM(L, &luaO_nilobject);
+  callgcTMudata(L, c);
 }
 

+ 2 - 2
lgc.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.h,v 1.11 2001/06/12 18:43:13 roberto Exp roberto $
+** $Id: lgc.h,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
@@ -16,7 +16,7 @@
 
 
 void luaC_callallgcTM (lua_State *L);
-void luaC_collect (lua_State *L, int all);
+Udata *luaC_collect (lua_State *L, int all);
 void luaC_collectgarbage (lua_State *L);
 
 

+ 43 - 15
liolib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: liolib.c,v 1.124 2001/10/26 17:33:30 roberto Exp $
+** $Id: liolib.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $
 ** Standard I/O (and system) library
 ** See Copyright Notice in lua.h
 */
@@ -61,6 +61,7 @@ static int pushresult (lua_State *L, int i) {
 }
 
 
+
 /*
 ** {======================================================
 ** FILE Operations
@@ -68,14 +69,30 @@ static int pushresult (lua_State *L, int i) {
 */
 
 
-#define checkfile(L,f)	(strcmp(lua_type(L,(f)), FILEHANDLE) == 0)
+
+static int checkfile (lua_State *L, int findex, const char *tname) {
+  int res;
+  lua_geteventtable(L, findex);
+  lua_pushstring(L, tname);
+  lua_gettable(L, LUA_REGISTRYINDEX);
+  res = lua_equal(L, -1, -2);
+  lua_pop(L, 2);
+  return res;
+}
+
+
+/* temporary?? should be in auxlib... */
+static void *luaL_check_userdata (lua_State *L, int findex, const char *tn) {
+  luaL_arg_check(L, checkfile(L, findex, tn), findex, "bad file");
+  return lua_touserdata(L, findex);
+}
 
 
 static FILE *getopthandle (lua_State *L, int inout) {
   FILE *p = (FILE *)(lua_touserdata(L, 1));
   if (p != NULL) {  /* is it a userdata ? */
-    if (!checkfile(L, 1)) {  /* not a valid file handle? */
-      if (strcmp(lua_type(L, 1), CLOSEDFILEHANDLE) == 0)
+    if (!checkfile(L, 1, FILEHANDLE)) {  /* not a valid file handle? */
+      if (checkfile(L, 1, CLOSEDFILEHANDLE))
         luaL_argerror(L, 1, "file is closed");
       else
         luaL_argerror(L, 1, "(invalid value)");
@@ -84,7 +101,7 @@ static FILE *getopthandle (lua_State *L, int inout) {
   }
   else {  /* try global value */
     lua_getglobal(L, filenames[inout]);
-    if (!checkfile(L,-1))
+    if (!checkfile(L, -1, FILEHANDLE))
       luaL_verror(L, "global variable `%.10s' is not a valid file handle",
                   filenames[inout]);
     p = (FILE *)(lua_touserdata(L, -1));
@@ -95,7 +112,9 @@ static FILE *getopthandle (lua_State *L, int inout) {
 
 static void newfile (lua_State *L, FILE *f) {
   lua_newuserdatabox(L, f);
-  lua_settag(L, lua_name2tag(L, FILEHANDLE));
+  lua_pushliteral(L, FILEHANDLE);
+  lua_gettable(L, LUA_REGISTRYINDEX);
+  lua_seteventtable(L, -2);
 }
 
 
@@ -130,7 +149,9 @@ static int io_close (lua_State *L) {
   int status = 1;
   if (f != stdin && f != stdout && f != stderr) {
     lua_settop(L, 1);  /* make sure file is on top */
-    lua_settag(L, lua_name2tag(L, CLOSEDFILEHANDLE));
+    lua_pushliteral(L, CLOSEDFILEHANDLE);
+    lua_gettable(L, LUA_REGISTRYINDEX);
+    lua_seteventtable(L, 1);
     status = (CLOSEFILE(L, f) == 0);
   }
   return pushresult(L, status);
@@ -301,7 +322,7 @@ static int io_read (lua_State *L) {
     luaL_check_stack(L, nargs+LUA_MINSTACK, "too many arguments");
     success = 1;
     for (n = 1; n<=nargs && success; n++) {
-      if (lua_rawtag(L, n) == LUA_TNUMBER) {
+      if (lua_type(L, n) == LUA_TNUMBER) {
         size_t l = (size_t)lua_tonumber(L, n);
         success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);
       }
@@ -353,7 +374,7 @@ static int io_write (lua_State *L) {
   int arg;
   int status = 1;
   for (arg=1; arg<=nargs; arg++) {
-    if (lua_rawtag(L, arg) == LUA_TNUMBER) {
+    if (lua_type(L, arg) == LUA_TNUMBER) {
       /* optimization: could be done exactly as for strings */
       status = status &&
           fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
@@ -514,7 +535,7 @@ static int io_time (lua_State *L) {
   else {
     time_t t;
     struct tm ts;
-    luaL_check_rawtype(L, 1, LUA_TTABLE);
+    luaL_check_type(L, 1, LUA_TTABLE);
     lua_settop(L, 1);  /* make sure table is at the top */
     ts.tm_sec = getfield(L, "sec", 0);
     ts.tm_min = getfield(L, "min", 0);
@@ -677,8 +698,18 @@ static const luaL_reg iolib[] = {
 
 
 LUALIB_API int lua_iolibopen (lua_State *L) {
-  int iotag = lua_newtype(L, FILEHANDLE, LUA_TUSERDATA);
-  lua_newtype(L, CLOSEDFILEHANDLE, LUA_TUSERDATA);
+  lua_pushliteral(L, FILEHANDLE);
+  lua_newtable(L);  /* event table for FILEHANDLE */
+  /* close files when collected */
+  lua_pushliteral(L, "gc");
+  lua_pushcfunction(L, file_collect);
+  lua_settable(L, -3);
+  /* put new eventtable into registry */
+  lua_settable(L, LUA_REGISTRYINDEX);  /* registry.FILEHANDLE = eventtable */
+  lua_pushliteral(L, CLOSEDFILEHANDLE);
+  /* event table for CLOSEDFILEHANDLE */
+  lua_newtable(L);
+  lua_settable(L, LUA_REGISTRYINDEX);
   luaL_openl(L, iolib);
   /* predefined file handles */
   newfilewithname(L, stdin, basicfiles[INFILE]);
@@ -686,9 +717,6 @@ LUALIB_API int lua_iolibopen (lua_State *L) {
   newfilewithname(L, stderr, "_STDERR");
   resetfile(L, INFILE);
   resetfile(L, OUTFILE);
-  /* close files when collected */
-  lua_pushcfunction(L, file_collect);
-  lua_settagmethod(L, iotag, "gc");
   return 0;
 }
 

+ 2 - 3
lmathlib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lmathlib.c,v 1.38 2001/03/26 14:31:49 roberto Exp $
+** $Id: lmathlib.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $
 ** Standard mathematical library
 ** See Copyright Notice in lua.h
 */
@@ -220,6 +220,7 @@ static const luaL_reg mathlib[] = {
 {"log10", math_log10},
 {"exp",   math_exp},
 {"deg",   math_deg},
+{"pow",   math_pow},
 {"rad",   math_rad},
 {"random",     math_random},
 {"randomseed", math_randomseed}
@@ -230,8 +231,6 @@ static const luaL_reg mathlib[] = {
 */
 LUALIB_API int lua_mathlibopen (lua_State *L) {
   luaL_openl(L, mathlib);
-  lua_pushcfunction(L, math_pow);
-  lua_settagmethod(L, LUA_TNUMBER, "pow");
   lua_pushnumber(L, PI);
   lua_setglobal(L, "PI");
   return 0;

+ 5 - 17
lobject.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lobject.h,v 1.116 2001/11/06 21:41:53 roberto Exp $
+** $Id: lobject.h,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $
 ** Type definitions for Lua objects
 ** See Copyright Notice in lua.h
 */
@@ -31,15 +31,6 @@
 #define NUM_TAGS	6
 
 
-/*
-** extra tags:
-** first is used locally when moving an upvalue from the stack to the heap;
-** second prefixes upvalues in the heap
-*/
-#define LUA_TUPVAL	6
-#define LUA_HEAPUPVAL	7
-
-
 typedef union {
   union TString *ts;
   union Udata *u;
@@ -122,17 +113,14 @@ typedef union TString {
 typedef union Udata {
   union L_Umaxalign dummy;  /* ensures maximum alignment for `local' udata */
   struct {
-    int tag;  /* negative means `marked' (only during GC) */
+    struct Table *eventtable;
     void *value;
-    size_t len;
+    size_t len;  /* least bit reserved for gc mark */
     union Udata *next;  /* chain for list of all udata */
   } uv;
 } Udata;
 
 
-#define switchudatamark(u)	((u)->uv.tag = (-((u)->uv.tag+1)))
-#define ismarkedudata(u)	((u)->uv.tag < 0)
-
 
 
 /*
@@ -175,7 +163,6 @@ typedef struct LocVar {
 
 typedef struct UpVal {
   TObject *v;  /* points to stack or to its own value */
-  int mark;
   struct UpVal *next;
   TObject value;  /* the value (when closed) */
 } UpVal;
@@ -227,12 +214,13 @@ typedef struct Node {
 
 
 typedef struct Table {
+  struct Table *eventtable;
   TObject *array;  /* array part */
   Node *node;
-  int htag;
   int sizearray;  /* size of `array' array */
   lu_byte lsizenode;  /* log2 of size of `node' array */
   lu_byte weakmode;
+  unsigned short flags;  /* 1<<p means tagmethod(p) is not present */ 
   Node *firstfree;  /* this position is free; all positions after it are full */
   struct Table *next;
   struct Table *mark;  /* marked tables (point to itself when not marked) */

+ 11 - 10
lstate.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.c,v 1.72 2001/11/06 21:40:51 roberto Exp $
+** $Id: lstate.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -40,12 +40,14 @@ static void f_luaopen (lua_State *L, void *ud) {
     so->stacksize += LUA_MINSTACK;
   if (so->L != NULL) {  /* shared global state? */
     L->_G = G(so->L);
-    L->gt = so->L->gt;  /* share table of globals */
     so->L->next->previous = L;  /* insert L into linked list */
     L->next = so->L->next;
     so->L->next = L;
     L->previous = so->L;
     luaD_init(L, so->stacksize);  /* init stack */
+    setobj(defaultet(L), defaultet(so->L));  /* share default event table */
+    setobj(gt(L), gt(so->L));  /* share table of globals */
+    setobj(registry(L), registry(so->L));  /* share registry */
   }
   else {  /* create a new global state */
     L->_G = luaM_new(L, global_State);
@@ -59,17 +61,17 @@ static void f_luaopen (lua_State *L, void *ud) {
     G(L)->roottable = NULL;
     G(L)->rootudata = NULL;
     G(L)->rootupval = NULL;
-    G(L)->TMtable = NULL;
-    G(L)->sizeTM = 0;
-    G(L)->ntag = 0;
     G(L)->nblocks = sizeof(lua_State) + sizeof(global_State);
     luaD_init(L, so->stacksize);  /* init stack */
-    sethvalue(&L->gt, luaH_new(L, 0, 4));  /* table of globals */
-    G(L)->type2tag = luaH_new(L, 0, 3);
-    sethvalue(&G(L)->registry, luaH_new(L, 0, 0));
+    /* create default event table with a dummy table, and then close the loop */
+    sethvalue(defaultet(L), NULL);
+    sethvalue(defaultet(L), luaH_new(L, 0, 4));
+    hvalue(defaultet(L))->eventtable = hvalue(defaultet(L));
+    sethvalue(gt(L), luaH_new(L, 0, 4));  /* table of globals */
+    sethvalue(registry(L), luaH_new(L, 0, 0));  /* registry */
     luaS_resize(L, 4);  /* initial size of string table */
-    luaX_init(L);
     luaT_init(L);
+    luaX_init(L);
     G(L)->GCthreshold = 4*G(L)->nblocks;
   }
 }
@@ -122,7 +124,6 @@ static void close_state (lua_State *L, lua_State *OL) {
     lua_assert(G(L)->rootupval == NULL);
     lua_assert(G(L)->roottable == NULL);
     luaS_freeall(L);
-    luaM_freearray(L, G(L)->TMtable, G(L)->sizeTM, struct TM);
     luaM_freearray(L, G(L)->Mbuffer, G(L)->Mbuffsize, char);
     luaM_freelem(NULL, L->_G);
   }

+ 24 - 10
lstate.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.h,v 1.64 2001/11/06 21:40:51 roberto Exp $
+** $Id: lstate.h,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -7,8 +7,10 @@
 #ifndef lstate_h
 #define lstate_h
 
-#include "lobject.h"
 #include "lua.h"
+
+#include "lobject.h"
+#include "ltm.h"
 #include "luadebug.h"
 
 
@@ -40,7 +42,24 @@
 
 
 struct lua_longjmp;  /* defined in ldo.c */
-struct TM;  /* defined in ltm.h */
+
+
+
+/*
+** reserve init of stack to store some global values
+*/
+
+/* default event table (both for tables and udata) */
+#define defaultet(L)	(L->stack)
+
+/* table of globals */
+#define gt(L)	(L->stack + 1)
+
+/* registry */
+#define registry(L)	(L->stack + 2)
+
+#define RESERVED_STACK_PREFIX	3
+
 
 
 typedef struct stringtable {
@@ -57,11 +76,6 @@ typedef struct global_State {
   void *Mbuffer;  /* global buffer */
   size_t Mbuffsize;  /* size of Mbuffer */
   stringtable strt;  /* hash table for strings */
-  Table *type2tag;  /* hash table from type names to tags */
-  TObject registry;  /* registry table */
-  struct TM *TMtable;  /* table for tag methods */
-  int sizeTM;  /* size of TMtable */
-  int ntag;  /* number of tags in TMtable */
   lu_mem GCthreshold;
   lu_mem nblocks;  /* number of `bytes' currently allocated */
   Proto *rootproto;  /* list of all prototypes */
@@ -69,6 +83,7 @@ typedef struct global_State {
   Table *roottable;  /* list of all tables */
   Udata *rootudata;   /* list of all userdata */
   UpVal *rootupval;  /* list of closed up values */
+  TString *tmname[TM_N];  /* array with tag-method names */
 } global_State;
 
 
@@ -80,10 +95,9 @@ struct lua_State {
   StkId top;  /* first free slot in the stack */
   CallInfo *ci;  /* call info for current function */
   StkId stack_last;  /* last free slot in the stack */
-  TObject gt;  /* table for globals */
-  global_State *_G;
   StkId stack;  /* stack base */
   int stacksize;
+  global_State *_G;
   lua_Hook callhook;
   lua_Hook linehook;
   int allowhooks;

+ 5 - 3
lstring.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lstring.c,v 1.67 2001/08/31 19:46:07 roberto Exp $
+** $Id: lstring.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $
 ** String table (keeps all strings handled by Lua)
 ** See Copyright Notice in lua.h
 */
@@ -84,9 +84,11 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
 
 
 Udata *luaS_newudata (lua_State *L, size_t s) {
-  Udata *u = cast(Udata *, luaM_malloc(L, sizeudata(s)));
+  Udata *u;
+  if (s & 1) s++;  /* make sure size is even */
+  u = cast(Udata *, luaM_malloc(L, sizeudata(s)));
   u->uv.len = s;
-  u->uv.tag = 0;
+  u->uv.eventtable = hvalue(defaultet(L));
   u->uv.value = u + 1;
   /* chain it on udata list */
   u->uv.next = G(L)->rootudata;

+ 2 - 2
lstrlib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lstrlib.c,v 1.73 2001/10/26 17:33:30 roberto Exp $
+** $Id: lstrlib.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $
 ** Standard library for string operations and pattern-matching
 ** See Copyright Notice in lua.h
 */
@@ -97,7 +97,7 @@ static int str_concat (lua_State *L) {
   size_t lsep;
   const char *sep = luaL_opt_lstr(L, 2, "", &lsep);
   int n, i;
-  luaL_check_rawtype(L, 1, LUA_TTABLE);
+  luaL_check_type(L, 1, LUA_TTABLE);
   luaL_buffinit(L, &b);
   n = lua_getn(L, 1);
   for (i=1; i<=n; i++) {

+ 4 - 15
ltable.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltable.c,v 1.88 2001/11/16 16:29:51 roberto Exp $
+** $Id: ltable.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $
 ** Lua tables (hash)
 ** See Copyright Notice in lua.h
 */
@@ -258,11 +258,12 @@ static void rehash (lua_State *L, Table *t) {
 
 Table *luaH_new (lua_State *L, int narray, int lnhash) {
   Table *t = luaM_new(L, Table);
-  t->htag = TagDefault;
+  t->eventtable = hvalue(defaultet(L));
   t->next = G(L)->roottable;
   G(L)->roottable = t;
   t->mark = t;
   t->weakmode = 0;
+  t->flags = ~0;
   /* temporary values (kept only if some malloc fails) */
   t->array = NULL;
   t->sizearray = 0;
@@ -419,19 +420,7 @@ void luaH_set (lua_State *L, Table *t, const TObject *key, const TObject *val) {
     if (ttype(key) == LUA_TNIL) luaD_error(L, "table index is nil");
     newkey(L, t, key, val);
   }
-}
-
-
-void luaH_setstr (lua_State *L, Table *t, TString *key, const TObject *val) {
-  const TObject *p = luaH_getstr(t, key);
-  if (p != &luaO_nilobject) {
-    settableval(p, val);
-  }
-  else {
-    TObject k;
-    setsvalue(&k, key);
-    newkey(L, t, &k, val);
-  }
+  t->flags = 0;
 }
 
 

+ 1 - 2
ltable.h

@@ -1,5 +1,5 @@
 /*
-** $Id: ltable.h,v 1.37 2001/10/25 19:14:14 roberto Exp $
+** $Id: ltable.h,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $
 ** Lua tables (hash)
 ** See Copyright Notice in lua.h
 */
@@ -20,7 +20,6 @@
 const TObject *luaH_getnum (Table *t, int key);
 void luaH_setnum (lua_State *L, Table *t, int key, const TObject *val);
 const TObject *luaH_getstr (Table *t, TString *key);
-void luaH_setstr (lua_State *L, Table *t, TString *key, const TObject *val);
 const TObject *luaH_get (Table *t, const TObject *key);
 void luaH_set (lua_State *L, Table *t, const TObject *key, const TObject *val);
 Table *luaH_new (lua_State *L, int narray, int lnhash);

+ 23 - 38
ltests.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltests.c,v 1.96 2001/11/06 21:41:43 roberto Exp $
+** $Id: ltests.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $
 ** Internal Module for Debugging of the Lua Implementation
 ** See Copyright Notice in lua.h
 */
@@ -240,13 +240,13 @@ static int mem_query (lua_State *L) {
 
 static int hash_query (lua_State *L) {
   if (lua_isnull(L, 2)) {
-    luaL_arg_check(L, lua_tag(L, 1) == LUA_TSTRING, 1, "string expected");
+    luaL_arg_check(L, lua_type(L, 1) == LUA_TSTRING, 1, "string expected");
     lua_pushnumber(L, tsvalue(luaA_index(L, 1))->tsv.hash);
   }
   else {
     TObject *o = luaA_index(L, 1);
     Table *t;
-    luaL_check_rawtype(L, 2, LUA_TTABLE);
+    luaL_check_type(L, 2, LUA_TTABLE);
     t = hvalue(luaA_index(L, 2));
     lua_pushnumber(L, luaH_mainposition(t, o) - t->node);
   }
@@ -257,7 +257,7 @@ static int hash_query (lua_State *L) {
 static int table_query (lua_State *L) {
   const Table *t;
   int i = luaL_opt_int(L, 2, -1);
-  luaL_check_rawtype(L, 1, LUA_TTABLE);
+  luaL_check_type(L, 1, LUA_TTABLE);
   t = hvalue(luaA_index(L, 1));
   if (i == -1) {
     lua_pushnumber(L, t->sizearray);
@@ -333,6 +333,18 @@ static int unref (lua_State *L) {
   return 0;
 }
 
+static int eventtable (lua_State *L) {
+  luaL_check_any(L, 1);
+  if (lua_isnull(L, 2))
+    lua_geteventtable(L, 1);
+  else {
+    lua_settop(L, 2);
+    luaL_check_type(L, 2, LUA_TTABLE);
+    lua_seteventtable(L, 1);
+  }
+  return 1;
+}
+
 static int newuserdata (lua_State *L) {
   size_t size = luaL_check_int(L, 1);
   char *p = cast(char *, lua_newuserdata(L, size));
@@ -345,24 +357,13 @@ static int newuserdatabox (lua_State *L) {
   return 1;
 }
 
-static int settag (lua_State *L) {
-  luaL_check_any(L, 1);
-  lua_pushvalue(L, 1);  /* push value */
-  lua_settag(L, luaL_check_int(L, 2));
-  return 1;  /* return value */
-}
 
 static int udataval (lua_State *L) {
-  luaL_check_rawtype(L, 1, LUA_TUSERDATA);
+  luaL_check_type(L, 1, LUA_TUSERDATA);
   lua_pushnumber(L, cast(int, lua_touserdata(L, 1)));
   return 1;
 }
 
-static int newtag (lua_State *L) {
-  lua_pushnumber(L, lua_newtype(L, lua_tostring(L, 1),
-                                   cast(int, lua_tonumber(L, 2))));
-  return 1;
-}
 
 static int doonnewstack (lua_State *L) {
   lua_State *L1 = lua_newthread(L, luaL_check_int(L, 1));
@@ -435,16 +436,6 @@ static int doremote (lua_State *L) {
   }
 }
 
-static int settagmethod (lua_State *L) {
-  int tag = luaL_check_int(L, 1);
-  const char *event = luaL_check_string(L, 2);
-  luaL_check_any(L, 3);
-  lua_gettagmethod(L, tag, event);
-  lua_pushvalue(L, 3);
-  lua_settagmethod(L, tag, event);
-  return 1;
-}
-
 
 static int log2_aux (lua_State *L) {
   lua_pushnumber(L, luaO_log2(luaL_check_int(L, 1)));
@@ -614,18 +605,14 @@ static int testC (lua_State *L) {
     else if EQ("dostring") {
       lua_dostring(L, luaL_check_string(L, getnum));
     }
-    else if EQ("settagmethod") {
-      int tag = getnum;
-      const char *event = getname;
-      lua_settagmethod(L, tag, event);
+    else if EQ("seteventtable") {
+      lua_seteventtable(L, getnum);
     }
-    else if EQ("gettagmethod") {
-      int tag = getnum;
-      const char *event = getname;
-      lua_gettagmethod(L, tag, event);
+    else if EQ("geteventtable") {
+      lua_geteventtable(L, getnum);
     }
     else if EQ("type") {
-      lua_pushstring(L, lua_type(L, getnum));
+      lua_pushstring(L, lua_typename(L, lua_type(L, getnum)));
     }
     else luaL_verror(L, "unknown instruction %.30s", buff);
   }
@@ -651,16 +638,14 @@ static const struct luaL_reg tests_funcs[] = {
   {"unref", unref},
   {"d2s", d2s},
   {"s2d", s2d},
+  {"eventtable", eventtable},
   {"newuserdata", newuserdata},
   {"newuserdatabox", newuserdatabox},
-  {"settag", settag},
   {"udataval", udataval},
-  {"newtag", newtag},
   {"doonnewstack", doonnewstack},
   {"newstate", newstate},
   {"closestate", closestate},
   {"doremote", doremote},
-  {"settagmethod", settagmethod},
   {"log2", log2_aux},
   {"totalmem", mem_query}
 };

+ 24 - 141
ltm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltm.c,v 1.80 2001/10/11 21:41:21 roberto Exp $
+** $Id: ltm.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $
 ** Tag methods
 ** See Copyright Notice in lua.h
 */
@@ -10,8 +10,6 @@
 
 #include "lua.h"
 
-#include "ldo.h"
-#include "lmem.h"
 #include "lobject.h"
 #include "lstate.h"
 #include "lstring.h"
@@ -19,161 +17,46 @@
 #include "ltm.h"
 
 
-const char *const luaT_eventname[] = {  /* ORDER TM */
-  "gettable", "settable", "index", "getglobal",
-  "setglobal", "add", "sub", "mul", "div",
-  "pow", "unm", "lt", "concat", "gc",
-  "function",
-  NULL
-};
-
-
-static int findevent (const char *name) {
-  int i;
-  for (i=0; luaT_eventname[i]; i++)
-    if (strcmp(luaT_eventname[i], name) == 0)
-      return i;
-  return -1;  /* name not found */
-}
-
-
-static int luaI_checkevent (lua_State *L, const char *name) {
-  int e = findevent(name);
-  if (e < 0)
-    luaO_verror(L, "`%.50s' is not a valid event name", name);
-  return e;
-}
 
-
-
-/* events in LUA_TNIL are all allowed, since this is used as a
-*  `placeholder' for default fallbacks
-*/
-/* ORDER LUA_T, ORDER TM */
-static const lu_byte luaT_validevents[NUM_TAGS][TM_N] = {
-  {1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1},  /* LUA_TUSERDATA */
-  {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},  /* LUA_TNIL */
-  {1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1},  /* LUA_TNUMBER */
-  {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},  /* LUA_TSTRING */
-  {0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1},  /* LUA_TTABLE */
-  {1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}   /* LUA_TFUNCTION */
+const char *const luaT_typenames[] = {
+  "userdata", "nil", "number", "string", "table", "function"
 };
 
-static int luaT_validevent (int t, int e) {  /* ORDER LUA_T */
-  return (t >= NUM_TAGS) ?  1 : cast(int, luaT_validevents[t][e]);
-}
-
 
 void luaT_init (lua_State *L) {
-  static const char *const typenames[NUM_TAGS] = {
-    "userdata", "nil", "number", "string",
-    "table", "function"
+  static const char *const luaT_eventname[] = {  /* ORDER TM */
+    "gettable", "settable", "index",
+    "gc",
+    "add", "sub", "mul", "div",
+    "pow", "unm", "lt", "concat",
+    "call"
   };
   int i;
-  for (i=0; i<NUM_TAGS; i++)
-    luaT_newtag(L, typenames[i], i);
-}
-
-
-int luaT_newtag (lua_State *L, const char *name, int basictype) {
-  int tag;
-  int i;
-  TString *ts = NULL;
-  luaM_growvector(L, G(L)->TMtable, G(L)->ntag, G(L)->sizeTM, struct TM,
-                  MAX_INT, "tag table overflow");
-  tag = G(L)->ntag;
-  if (name) {
-    const TObject *v;
-    TObject otag;
-    ts = luaS_new(L, name);
-    v = luaH_getstr(G(L)->type2tag, ts);
-    if (ttype(v) == LUA_TNUMBER) return cast(int, nvalue(v));
-    setnvalue(&otag, tag);
-    luaH_setstr(L, G(L)->type2tag, ts, &otag);
+  for (i=0; i<TM_N; i++) {
+    G(L)->tmname[i] = luaS_new(L, luaT_eventname[i]);
+    G(L)->tmname[i]->tsv.marked = FIXMARK;  /* never collect these names */
   }
-  for (i=0; i<TM_N; i++)
-    luaT_gettm(G(L), tag, i) = NULL;
-  G(L)->TMtable[tag].collected = NULL;
-  G(L)->TMtable[tag].name = ts;
-  G(L)->TMtable[tag].basictype = basictype;
-  G(L)->ntag++;
-  return tag;
-}
-
-
-static void checktag (lua_State *L, int tag) {
-  if (!(0 <= tag && tag < G(L)->ntag))
-    luaO_verror(L, "%d is not a valid tag", tag);
 }
 
 
-int luaT_tag (const TObject *o) {
-  int t = ttype(o);
-  switch (t) {
-    case LUA_TUSERDATA: return uvalue(o)->uv.tag;
-    case LUA_TTABLE:    return hvalue(o)->htag;
-    default:            return t;
+const TObject *luaT_gettm (Table *events, TMS event, TString *ename) {
+  const TObject *tm = luaH_getstr(events, ename);
+  if (ttype(tm) == LUA_TNIL) {  /* no tag method? */
+    events->flags |= (1<<event);  /* cache this fact */
+    return NULL;
   }
+  else return tm;
 }
 
 
-const char *luaT_typename (global_State *G, const TObject *o) {
-  int t = ttype(o);
-  int tag;
-  TString *ts;
-  switch (t) {
-    case LUA_TUSERDATA:
-      tag = uvalue(o)->uv.tag;
-      break;
+const TObject *luaT_gettmbyobj (lua_State *L, const TObject *o, TMS event) {
+  switch (ttype(o)) {
     case LUA_TTABLE:
-      tag = hvalue(o)->htag;
-      break;
-    default:
-      tag = t;
-  }
-  ts = G->TMtable[tag].name;
-  if (ts == NULL)
-    ts = G->TMtable[t].name;
-  return getstr(ts);
-}
-
-
-LUA_API void lua_gettagmethod (lua_State *L, int t, const char *event) {
-  int e;
-  lua_lock(L);
-  e = luaI_checkevent(L, event);
-  checktag(L, t);
-  if (luaT_validevent(t, e) && luaT_gettm(G(L), t, e)) {
-    setclvalue(L->top, luaT_gettm(G(L), t, e));
-  }
-  else
-    setnilvalue(L->top);
-  incr_top;
-  lua_unlock(L);
-}
-
-
-LUA_API void lua_settagmethod (lua_State *L, int t, const char *event) {
-  int e;
-  lua_lock(L);
-  e = luaI_checkevent(L, event);
-  checktag(L, t);
-  if (!luaT_validevent(t, e))
-    luaO_verror(L, "cannot change `%.20s' tag method for type `%.20s'%.20s",
-                luaT_eventname[e], typenamebytag(G(L), t),
-                (t == LUA_TTABLE || t == LUA_TUSERDATA) ?
-                   " with default tag" : "");
-  switch (ttype(L->top - 1)) {
-    case LUA_TNIL:
-      luaT_gettm(G(L), t, e) = NULL;
-      break;
-    case LUA_TFUNCTION:
-      luaT_gettm(G(L), t, e) = clvalue(L->top - 1);
-      break;
+      return fasttm(L, hvalue(o)->eventtable, event);
+    case LUA_TUSERDATA:
+      return fasttm(L, uvalue(o)->uv.eventtable, event);
     default:
-      luaD_error(L, "tag method must be a function (or nil)");
+      return NULL;
   }
-  L->top--;
-  lua_unlock(L);
 }
 

+ 8 - 41
ltm.h

@@ -1,5 +1,5 @@
 /*
-** $Id: ltm.h,v 1.28 2001/10/02 16:43:54 roberto Exp $
+** $Id: ltm.h,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $
 ** Tag methods
 ** See Copyright Notice in lua.h
 */
@@ -9,7 +9,6 @@
 
 
 #include "lobject.h"
-#include "lstate.h"
 
 /*
 * WARNING: if you change the order of this enumeration,
@@ -19,8 +18,7 @@ typedef enum {
   TM_GETTABLE = 0,
   TM_SETTABLE,
   TM_INDEX,
-  TM_GETGLOBAL,
-  TM_SETGLOBAL,
+  TM_GC,
   TM_ADD,
   TM_SUB,
   TM_MUL,
@@ -29,51 +27,20 @@ typedef enum {
   TM_UNM,
   TM_LT,
   TM_CONCAT,
-  TM_GC,
-  TM_FUNCTION,
+  TM_CALL,
   TM_N		/* number of elements in the enum */
 } TMS;
 
 
 
-/*
-** masks for allowable tag methods
-** (see `luaT_validevents')
-*/
-#define HAS_TM_GETGLOBAL(L,t)	((1<<(t)) & ((1<<LUA_TUSERDATA) | \
-                                           (1<<LUA_TTABLE) | \
-                                           (1<<LUA_TNIL)))
-
-#define HAS_TM_SETGLOBAL(L,t)	((1<<(t)) & ((1<<LUA_TUSERDATA) | \
-                                           (1<<LUA_TTABLE) | \
-                                           (1<<LUA_TNIL) | \
-                                           (1<<LUA_TFUNCTION)))
-
-
-
-struct TM {
-  Closure *method[TM_N];
-  Udata *collected;  /* list of garbage-collected udata with this tag */
-  TString *name;  /* type name */
-  int basictype;
-};
-
-
-#define luaT_gettm(G,tag,event) (G->TMtable[tag].method[event])
-#define luaT_gettmbyObj(G,o,e)  (luaT_gettm((G),luaT_tag(o),(e)))
-
-#define typenamebytag(G, t)	getstr(G->TMtable[t].name)
-
-
-#define validtag(G,t) (NUM_TAGS <= (t) && (t) < G->ntag)
-
-extern const char *const luaT_eventname[];
+#define fasttm(l,et,e) \
+  (((et)->flags & (1<<(e))) ? NULL : luaT_gettm(et, e, G(l)->tmname[e]))
 
 
+const TObject *luaT_gettm (Table *events, TMS event, TString *ename);
+const TObject *luaT_gettmbyobj (lua_State *L, const TObject *o, TMS event);
 void luaT_init (lua_State *L);
-int luaT_newtag (lua_State *L, const char *name, int basictype);
-const char *luaT_typename (global_State *G, const TObject *o);
-int luaT_tag (const TObject *o);
 
+extern const char *const luaT_typenames[];
 
 #endif

+ 12 - 24
lua.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lua.h,v 1.107 2001/10/31 19:58:11 roberto Exp $
+** $Id: lua.h,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $
 ** Lua - An Extensible Extension Language
 ** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil
 ** e-mail: [email protected]
@@ -55,15 +55,11 @@ typedef struct lua_State lua_State;
 typedef int (*lua_CFunction) (lua_State *L);
 
 
-/*
-** an invalid `tag'
-*/
-#define LUA_NOTAG	(-1)
 
 /*
-** tags for basic types
+** basic types
 */
-#define LUA_TNONE	LUA_NOTAG
+#define LUA_TNONE	(-1)
 
 #define LUA_TUSERDATA	0
 #define LUA_TNIL	1
@@ -120,12 +116,11 @@ LUA_API int   lua_stackspace (lua_State *L);
 ** access functions (stack -> C)
 */
 
-LUA_API const char *lua_type (lua_State *L, int index);
 LUA_API int             lua_isnumber (lua_State *L, int index);
 LUA_API int             lua_isstring (lua_State *L, int index);
 LUA_API int             lua_iscfunction (lua_State *L, int index);
-LUA_API int             lua_tag (lua_State *L, int index);
-LUA_API int             lua_rawtag (lua_State *L, int index);
+LUA_API int             lua_type (lua_State *L, int index);
+LUA_API const char     *lua_typename (lua_State *L, int type);
 
 LUA_API int            lua_equal (lua_State *L, int index1, int index2);
 LUA_API int            lua_lessthan (lua_State *L, int index1, int index2);
@@ -155,9 +150,9 @@ LUA_API void  lua_getglobal (lua_State *L, const char *name);
 LUA_API void  lua_gettable (lua_State *L, int index);
 LUA_API void  lua_rawget (lua_State *L, int index);
 LUA_API void  lua_rawgeti (lua_State *L, int index, int n);
-LUA_API void  lua_gettagmethod (lua_State *L, int tag, const char *event);
 LUA_API void  lua_newtable (lua_State *L);
 LUA_API void  lua_getweakregistry (lua_State *L);
+LUA_API void  lua_geteventtable (lua_State *L, int objindex);
 
 
 /*
@@ -168,7 +163,7 @@ LUA_API void  lua_settable (lua_State *L, int index);
 LUA_API void  lua_rawset (lua_State *L, int index);
 LUA_API void  lua_rawseti (lua_State *L, int index, int n);
 LUA_API void  lua_setglobals (lua_State *L);
-LUA_API void  lua_settagmethod (lua_State *L, int tag, const char *event);
+LUA_API void  lua_seteventtable (lua_State *L, int objindex);
 
 
 /*
@@ -194,11 +189,6 @@ LUA_API void  lua_setgcthreshold (lua_State *L, int newthreshold);
 /*
 ** miscellaneous functions
 */
-LUA_API int   lua_newtype (lua_State *L, const char *name, int basictype);
-LUA_API void  lua_settag (lua_State *L, int tag);
-
-LUA_API int             lua_name2tag (lua_State *L, const char *name);
-LUA_API const char *lua_tag2name (lua_State *L, int tag);
 
 LUA_API void  lua_error (lua_State *L, const char *s);
 
@@ -228,11 +218,11 @@ LUA_API int   lua_getweakmode (lua_State *L, int index);
 #define lua_register(L,n,f)	(lua_pushcfunction(L, f), lua_setglobal(L, n))
 #define lua_pushcfunction(L,f)	lua_pushcclosure(L, f, 0)
 
-#define lua_isfunction(L,n)	(lua_rawtag(L,n) == LUA_TFUNCTION)
-#define lua_istable(L,n)	(lua_rawtag(L,n) == LUA_TTABLE)
-#define lua_isuserdata(L,n)	(lua_rawtag(L,n) == LUA_TUSERDATA)
-#define lua_isnil(L,n)		(lua_rawtag(L,n) == LUA_TNIL)
-#define lua_isnull(L,n)		(lua_rawtag(L,n) == LUA_TNONE)
+#define lua_isfunction(L,n)	(lua_type(L,n) == LUA_TFUNCTION)
+#define lua_istable(L,n)	(lua_type(L,n) == LUA_TTABLE)
+#define lua_isuserdata(L,n)	(lua_type(L,n) == LUA_TUSERDATA)
+#define lua_isnil(L,n)		(lua_type(L,n) == LUA_TNIL)
+#define lua_isnull(L,n)		(lua_type(L,n) == LUA_TNONE)
 
 #define lua_pushliteral(L, s)	lua_pushlstring(L, "" s, \
                                                 (sizeof(s)/sizeof(char))-1)
@@ -245,8 +235,6 @@ LUA_API int   lua_getweakmode (lua_State *L, int index);
 /*
 ** compatibility macros and functions
 */
-#define lua_newtag(L)	lua_newtype(L, NULL, LUA_TNONE)
-#define lua_typename	lua_tag2name
 
 LUA_API void lua_pushupvalues (lua_State *L);
 

+ 58 - 79
lvm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.c,v 1.198 2001/11/06 21:41:53 roberto Exp $
+** $Id: lvm.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -85,69 +85,66 @@ static void traceexec (lua_State *L, lua_Hook linehook) {
 /* maximum stack used by a call to a tag method (func + args) */
 #define MAXSTACK_TM	4
 
-static StkId callTM (lua_State *L, Closure *f, const char *fmt, ...) {
-  va_list argp;
+static void callTM (lua_State *L, const TObject *f,
+     const TObject *p1, const TObject *p2, const TObject *p3, TObject *result ) {
   StkId base = L->top;
-  lua_assert(strlen(fmt)+1 <= MAXSTACK_TM);
   luaD_checkstack(L, MAXSTACK_TM);
-  va_start(argp, fmt);
-  setclvalue(L->top, f);  /* push function */
-  L->top++;
-  while (*fmt) {
-    if (*fmt++ == 'o') {
-        setobj(L->top, va_arg(argp, TObject *));
-    }
-    else {
-      lua_assert(*(fmt-1) == 's');
-      setsvalue(L->top, va_arg(argp, TString *));
-    }
+  setobj(base, f);  /* push function */
+  setobj(base+1, p1);  /* 1st argument */
+  setobj(base+2, p2);  /* 2nd argument */
+  L->top += 3;
+  if (p3) {
+    setobj(base+3, p3);  /* 3th argument */
     L->top++;
   }
   luaD_call(L, base);
-  va_end(argp);
-  return base;
-}
-
-
-#define setTM(L, base)	(L->top = (base))
-
-static void setTMresult (lua_State *L, TObject *result, StkId base) {
-  if (L->top == base) {  /* are there valid results? */
-    setnilvalue(result);  /* function had no results */
-  }
-  else {
-    setobj(result, base);  /* get first result */
+  if (result) {  /* need a result? */
+    if (L->top == base) {  /* are there valid results? */
+      setnilvalue(result);  /* function had no results */
+    }
+    else {
+      setobj(result, base);  /* get first result */
+    }
   }
   L->top = base;  /* restore top */
 }
 
 
+
 /*
 ** Function to index a table.
 ** Receives the table at `t' and the key at the `key'.
 ** leaves the result at `res'.
 */
 void luaV_gettable (lua_State *L, StkId t, TObject *key, StkId res) {
-  Closure *tm;
+  const TObject *tm;
+  init:
   if (ttype(t) == LUA_TTABLE) {  /* `t' is a table? */
-    int tg = hvalue(t)->htag;
-    if (tg == LUA_TTABLE ||  /* with default tag? */
-       (tm = luaT_gettm(G(L), tg, TM_GETTABLE)) == NULL) {  /* or no TM? */
+    Table *et = hvalue(t)->eventtable;
+    if ((tm = fasttm(L, et, TM_GETTABLE)) == NULL) {  /* no gettable TM? */
       const TObject *h = luaH_get(hvalue(t), key);  /* do a primitive get */
       /* result is no nil or there is no `index' tag method? */
       if (ttype(h) != LUA_TNIL ||  /* no nil? */
-         ((tm=luaT_gettm(G(L), tg, TM_INDEX)) == NULL)) {  /* or no index TM? */
+          (tm = fasttm(L, et, TM_INDEX)) == NULL) {  /* or no index TM? */
         setobj(res, h);  /* default get */
         return;
       }
     }
     /* else will call the tag method */
   } else {  /* not a table; try a `gettable' tag method */
-    tm = luaT_gettmbyObj(G(L), t, TM_GETTABLE);
-    if (tm == NULL)  /* no tag method? */
+    if (ttype(t) != LUA_TUSERDATA ||
+        (tm = fasttm(L, uvalue(t)->uv.eventtable, TM_GETTABLE)) == NULL) {
       luaG_typeerror(L, t, "index");
+      return;  /* to avoid warnings */
+    }
+  }
+  lua_assert(tm != NULL);
+  if (ttype(tm) == LUA_TFUNCTION)
+    callTM(L, tm, t, key, NULL, res);
+  else {
+    t = tm;
+    goto init;  /* return luaV_gettable(L, tm, key, res); */
   }
-  setTMresult(L, res, callTM(L, tm, "oo", t, key));
 }
 
 
@@ -156,63 +153,44 @@ void luaV_gettable (lua_State *L, StkId t, TObject *key, StkId res) {
 ** Receives table at `t', key at `key' and value at `val'.
 */
 void luaV_settable (lua_State *L, StkId t, TObject *key, StkId val) {
-  Closure *tm;
+  const TObject *tm;
+  init:
   if (ttype(t) == LUA_TTABLE) {  /* `t' is a table? */
-    int tg = hvalue(t)->htag;
-    if (hvalue(t)->htag == LUA_TTABLE ||  /* with default tag? */
-        (tm = luaT_gettm(G(L), tg, TM_SETTABLE)) == NULL) { /* or no TM? */
+    Table *et = hvalue(t)->eventtable;
+    if ((tm = fasttm(L, et, TM_SETTABLE)) == NULL) {  /* no TM? */
       luaH_set(L, hvalue(t), key, val);  /* do a primitive set */
       return;
     }
     /* else will call the tag method */
   } else {  /* not a table; try a `settable' tag method */
-    tm = luaT_gettmbyObj(G(L), t, TM_SETTABLE);
-    if (tm == NULL)  /* no tag method? */
+    if (ttype(t) != LUA_TUSERDATA ||
+        (tm = fasttm(L, uvalue(t)->uv.eventtable, TM_SETTABLE)) == NULL) {
       luaG_typeerror(L, t, "index");
+      return;  /* to avoid warnings */
+    }
   }
-  setTM(L, callTM(L, tm, "ooo", t, key, val));
-}
-
-
-void luaV_getglobal (lua_State *L, TString *name, StkId res) {
-  const TObject *value = luaH_getstr(hvalue(&L->gt), name);
-  Closure *tm;
-  if (!HAS_TM_GETGLOBAL(L, ttype(value)) ||  /* is there a tag method? */
-      (tm = luaT_gettmbyObj(G(L), value, TM_GETGLOBAL)) == NULL) {
-    setobj(res, value);  /* default behavior */
-  }
-  else
-    setTMresult(L, res, callTM(L, tm, "so", name, value));
-}
-
-
-void luaV_setglobal (lua_State *L, TString *name, StkId val) {
-  const TObject *oldvalue = luaH_getstr(hvalue(&L->gt), name);
-  Closure *tm;
-  if (!HAS_TM_SETGLOBAL(L, ttype(oldvalue)) ||  /* no tag methods? */
-     (tm = luaT_gettmbyObj(G(L), oldvalue, TM_SETGLOBAL)) == NULL) {
-    if (oldvalue == &luaO_nilobject)
-      luaH_setstr(L, hvalue(&L->gt), name, val);  /* raw set */
-    else
-      settableval(oldvalue, val);  /* warning: tricky optimization! */
+  lua_assert(tm != NULL);
+  if (ttype(tm) == LUA_TFUNCTION)
+    callTM(L, tm, t, key, val, NULL);
+  else {
+    t = tm;
+    goto init;  /* luaV_settable(L, tm, key, val); */
   }
-  else
-    setTM(L, callTM(L, tm, "soo", name, oldvalue, val));
 }
 
 
 static int call_binTM (lua_State *L, const TObject *p1, const TObject *p2,
                        TObject *res, TMS event) {
-  Closure *tm = luaT_gettmbyObj(G(L), p1, event);  /* try first operand */
+  const TObject *tm = luaT_gettmbyobj(L, p1, event);  /* try first operand */
   if (tm == NULL) {
-    tm = luaT_gettmbyObj(G(L), p2, event);  /* try second operand */
+    tm = luaT_gettmbyobj(L, p2, event);  /* try second operand */
     if (tm == NULL) {
-      tm = luaT_gettm(G(L), 0, event);  /* try a `global' method */
-      if (tm == NULL)
-        return 0;  /* no tag method */
+      tm = fasttm(L, hvalue(gt(L)), event);
+      if (tm == NULL) return 0;  /* no tag method */
     }
   }
-  setTMresult(L, res, callTM(L, tm, "oo", p1, p2));
+  if (ttype(tm) != LUA_TFUNCTION) return 0;
+    callTM(L, tm, p1, p2, NULL, res);
   return 1;
 }
 
@@ -295,12 +273,13 @@ void luaV_strconc (lua_State *L, int total, StkId top) {
 static void luaV_pack (lua_State *L, StkId firstelem) {
   int i;
   Table *htab = luaH_new(L, 0, 0);
-  TObject n;
+  TObject n, nname;
   for (i=0; firstelem+i<L->top; i++)
     luaH_setnum(L, htab, i+1, firstelem+i);
   /* store counter in field `n' */
   setnvalue(&n, i);
-  luaH_setstr(L, htab, luaS_newliteral(L, "n"), &n);
+  setsvalue(&nname, luaS_newliteral(L, "n"));
+  luaH_set(L, htab, &nname, &n);
   L->top = firstelem;  /* remove elements from the stack */
   sethvalue(L->top, htab);
   incr_top;
@@ -395,7 +374,7 @@ StkId luaV_execute (lua_State *L, const LClosure *cl, StkId base) {
       }
       case OP_GETGLOBAL: {
         lua_assert(ttype(KBc(i)) == LUA_TSTRING);
-        luaV_getglobal(L, tsvalue(KBc(i)), ra);
+        luaV_gettable(L, gt(L), KBc(i), ra);
         break;
       }
       case OP_GETTABLE: {
@@ -404,7 +383,7 @@ StkId luaV_execute (lua_State *L, const LClosure *cl, StkId base) {
       }
       case OP_SETGLOBAL: {
         lua_assert(ttype(KBc(i)) == LUA_TSTRING);
-        luaV_setglobal(L, tsvalue(KBc(i)), ra);
+        luaV_settable(L, gt(L), KBc(i), ra);
         break;
       }
       case OP_SETUPVAL: {

+ 1 - 3
lvm.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.h,v 1.31 2001/09/07 17:39:10 roberto Exp $
+** $Id: lvm.h,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -20,8 +20,6 @@ const TObject *luaV_tonumber (const TObject *obj, TObject *n);
 int luaV_tostring (lua_State *L, TObject *obj);
 void luaV_gettable (lua_State *L, StkId t, TObject *key, StkId res);
 void luaV_settable (lua_State *L, StkId t, TObject *key, StkId val);
-void luaV_getglobal (lua_State *L, TString *s, StkId res);
-void luaV_setglobal (lua_State *L, TString *s, StkId val);
 StkId luaV_execute (lua_State *L, const LClosure *cl, StkId base);
 int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r);
 void luaV_strconc (lua_State *L, int total, StkId top);