Browse Source

new API for registry and C upvalues + new implementation for references

Roberto Ierusalimschy 24 năm trước cách đây
mục cha
commit
1e81da51ba
10 tập tin đã thay đổi với 111 bổ sung123 xóa
  1. 56 64
      lapi.c
  2. 9 16
      lbaselib.c
  3. 6 10
      ldblib.c
  4. 7 6
      ldo.c
  5. 2 3
      lgc.c
  6. 2 5
      lstate.c
  7. 2 3
      lstate.h
  8. 11 10
      ltests.c
  9. 2 2
      lua.c
  10. 14 4
      lua.h

+ 56 - 64
lapi.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lapi.c,v 1.152 2001/09/07 17:39:10 roberto Exp $
+** $Id: lapi.c,v 1.154 2001/10/11 21:40:56 roberto Exp $
 ** Lua API
 ** See Copyright Notice in lua.h
 */
@@ -40,15 +40,28 @@ const l_char lua_ident[] =
 
 
 
+static TObject *negindex (lua_State *L, int index) {
+  if (index > LUA_REGISTRYINDEX) {
+    api_check(L, index != 0 && -index <= L->top - L->ci->base);
+    return L->top+index;
+  } else if (index == LUA_REGISTRYINDEX)  /* pseudo-indices */
+      return &G(L)->registry;
+  else {
+    TObject *func = (L->ci->base - 1);
+    index = LUA_REGISTRYINDEX - index;
+    api_check(L, iscfunction(func) && index <= clvalue(func)->c.nupvalues);
+    return &clvalue(func)->c.upvalue[index-1];
+  }
+}
+
+
 TObject *luaA_index (lua_State *L, int index) {
   if (index > 0) {
     api_check(L, index <= L->top - L->ci->base);
     return L->ci->base+index-1;
   }
-  else {
-    api_check(L, index != 0 && -index <= L->top - L->ci->base);
-    return L->top+index;
-  }
+  else
+    return negindex(L, index);
 }
 
 
@@ -59,10 +72,8 @@ static TObject *luaA_indexAcceptable (lua_State *L, int index) {
     if (o >= L->top) return NULL;
     else return o;
   }
-  else {
-    api_check(L, index != 0 && -index <= L->top - L->ci->base);
-    return L->top+index;
-  }
+  else
+    return negindex(L, index);
 }
 
 
@@ -378,24 +389,6 @@ LUA_API void lua_getglobals (lua_State *L) {
 }
 
 
-LUA_API int lua_getref (lua_State *L, int ref) {
-  int status;
-  lua_lock(L);
-  if (ref == LUA_REFNIL) {
-    setnilvalue(L->top);
-    status = 1;
-  }
-  else {
-    setobj(L->top, luaH_getnum(G(L)->weakregistry, ref));
-    status = (ttype(L->top) != LUA_TNIL);
-  }
-  if (status)
-    api_incr_top(L);
-  lua_unlock(L);
-  return status;
-}
-
-
 LUA_API void lua_newtable (lua_State *L) {
   lua_lock(L);
   sethvalue(L->top, luaH_new(L, 0));
@@ -404,22 +397,6 @@ LUA_API void lua_newtable (lua_State *L) {
 }
 
 
-LUA_API void  lua_getregistry (lua_State *L) {
-  lua_lock(L);
-  sethvalue(L->top, G(L)->registry);
-  api_incr_top(L);
-  lua_unlock(L);
-}
-
-
-LUA_API void  lua_getweakregistry (lua_State *L) {
-  lua_lock(L);
-  sethvalue(L->top, G(L)->weakregistry);
-  api_incr_top(L);
-  lua_unlock(L);
-}
-
-
 
 /*
 ** set functions (stack -> Lua)
@@ -483,26 +460,25 @@ LUA_API void lua_setglobals (lua_State *L) {
 
 LUA_API int lua_ref (lua_State *L,  int lock) {
   int ref;
+  if (lock == 0) lua_error(L, l_s("unlocked references are obsolete"));
   if (lua_isnil(L, -1)) {
     lua_pop(L, 1);
-    ref = LUA_REFNIL;
+    return LUA_REFNIL;
   }
-  else {
-    lua_getweakregistry(L);
-    ref = lua_getn(L, -1) + 1;
-    lua_pushvalue(L, -2);
-    lua_rawseti(L, -2, ref);
-    if (lock) {
-      lua_getregistry(L);
-      lua_pushvalue(L, -3);
-      lua_rawseti(L, -2, ref);
-      lua_pop(L, 1);  /* remove registry */
-    }
+  lua_rawgeti(L, LUA_REGISTRYINDEX, 0);  /* get first free element */
+  ref = lua_tonumber(L, -1);
+  lua_pop(L, 1);  /* remove it from stack */
+  if (ref != 0) {  /* some free element? */
+    lua_rawgeti(L, LUA_REGISTRYINDEX, ref);  /* remove it from list */
+    lua_rawseti(L, LUA_REGISTRYINDEX, 0);
+  }
+  else {  /* no free elements */
+    ref = lua_getn(L, LUA_REGISTRYINDEX) + 1;  /* use next `n' */
     lua_pushliteral(L, l_s("n"));
     lua_pushnumber(L, ref);
-    lua_settable(L, -3);
-    lua_pop(L, 2);
+    lua_settable(L, LUA_REGISTRYINDEX);  /* n = n+1 */
   }
+  lua_rawseti(L, LUA_REGISTRYINDEX, ref);
   return ref;
 }
 
@@ -661,13 +637,10 @@ LUA_API void lua_error (lua_State *L, const l_char *s) {
 
 LUA_API void lua_unref (lua_State *L, int ref) {
   if (ref >= 0) {
-    lua_getregistry(L);
-    lua_pushnil(L);
-    lua_rawseti(L, -2, ref);
-    lua_getweakregistry(L);
-    lua_pushnil(L);
-    lua_rawseti(L, -2, ref);
-    lua_pop(L, 2);  /* remove both registries */
+    lua_rawgeti(L, LUA_REGISTRYINDEX, 0);
+    lua_pushnumber(L, ref);
+    lua_rawseti(L, LUA_REGISTRYINDEX, 0);
+    lua_rawseti(L, LUA_REGISTRYINDEX, ref);
   }
 }
 
@@ -787,3 +760,22 @@ LUA_API void  lua_setweakmode (lua_State *L, int mode) {
   lua_unlock(L);
 }
 
+
+
+LUA_API void lua_pushupvalues (lua_State *L) {
+  TObject *func;
+  int n, i;
+  lua_lock(L);
+  func = (L->ci->base - 1);
+  api_check(L, iscfunction(func));
+  n = clvalue(func)->c.nupvalues;
+  if (LUA_MINSTACK+n > lua_stackspace(L))
+    luaD_error(L, l_s("stack overflow"));
+  for (i=0; i<n; i++) {
+    setobj(L->top, &clvalue(func)->c.upvalue[i]);
+    L->top++;
+  }
+  lua_unlock(L);
+}
+
+

+ 9 - 16
lbaselib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lbaselib.c,v 1.41 2001/08/31 19:46:07 roberto Exp $
+** $Id: lbaselib.c,v 1.43 2001/10/11 21:41:21 roberto Exp $
 ** Basic library
 ** See Copyright Notice in lua.h
 */
@@ -363,18 +363,8 @@ static int luaB_require (lua_State *L) {
     lua_pushvalue(L, -1);  /* duplicate to leave a copy on stack */
     lua_setglobal(L, LUA_PATH);
   }
-  lua_getregistry(L);
-  lua_pushliteral(L, LUA_PATH);
-  lua_gettable(L, 3);  /* get book-keeping table */
-  if (lua_isnil(L, 4)) {  /* no book-keeping table? */
-    lua_pop(L, 1);  /* pop the `nil' */
-    lua_newtable(L);  /* create book-keeping table */
-    lua_pushliteral(L, LUA_PATH);
-    lua_pushvalue(L, -2);  /* duplicate table to leave a copy on stack */
-    lua_settable(L, 3);  /* store book-keeping table in registry */
-  }
-  lua_pushvalue(L, 1);
-  lua_gettable(L, 4);  /* check package's name in book-keeping table */
+  lua_pushvalue(L, 1);  /* check package's name in book-keeping table */
+  lua_gettable(L, lua_upvalueindex(1));
   if (!lua_isnil(L, -1))  /* is it there? */
     return 0;  /* package is already loaded */
   else {  /* must load it */
@@ -385,7 +375,7 @@ static int luaB_require (lua_State *L) {
       lua_pushvalue(L, 1);  /* package name */
       lua_concat(L, 2);  /* concat directory with package name */
       res = lua_dofile(L, lua_tostring(L, -1));  /* try to load it */
-      lua_settop(L, 4);  /* pop string and eventual results from dofile */
+      lua_settop(L, 2);  /* pop string and eventual results from dofile */
       if (res == 0) break;  /* ok; file done */
       else if (res != LUA_ERRFILE)
         lua_error(L, NULL);  /* error running package; propagate it */
@@ -397,7 +387,7 @@ static int luaB_require (lua_State *L) {
   }
   lua_pushvalue(L, 1);
   lua_pushnumber(L, 1);
-  lua_settable(L, 4);  /* mark it as loaded */
+  lua_settable(L, lua_upvalueindex(1));  /* mark it as loaded */
   return 0;
 }
 
@@ -713,7 +703,6 @@ static const luaL_reg base_funcs[] = {
   {l_s("rawgettable"), luaB_rawget},  /* for compatibility 3.2 */
   {l_s("rawsettable"), luaB_rawset},  /* for compatibility 3.2 */
   {l_s("rawtype"), luaB_rawtype},
-  {l_s("require"), luaB_require},
   {l_s("setglobal"), luaB_setglobal},
   {l_s("settag"), luaB_settype},  /* for compatibility 4.0 */
   {l_s("settype"), luaB_settype},
@@ -737,6 +726,10 @@ LUALIB_API int lua_baselibopen (lua_State *L) {
   luaL_openl(L, base_funcs);
   lua_pushliteral(L, l_s(LUA_VERSION));
   lua_setglobal(L, l_s("_VERSION"));
+  /* `require' needs an empty table as upvalue */
+  lua_newtable(L);
+  lua_pushcclosure(L, luaB_require, 1);
+  lua_setglobal(L, l_s("require"));
   return 0;
 }
 

+ 6 - 10
ldblib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldblib.c,v 1.37 2001/06/06 18:00:19 roberto Exp $
+** $Id: ldblib.c,v 1.38 2001/08/31 19:46:07 roberto Exp $
 ** Interface from Lua to its debug API
 ** See Copyright Notice in lua.h
 */
@@ -116,16 +116,14 @@ static int setlocal (lua_State *L) {
 
 
 static void hookf (lua_State *L, const l_char *key) {
-  lua_getregistry(L);
   lua_pushstring(L, key);
-  lua_gettable(L, -2);
+  lua_gettable(L, LUA_REGISTRYINDEX);
   if (lua_isfunction(L, -1)) {
-    lua_pushvalue(L, -3);  /* original argument (below table and function) */
+    lua_pushvalue(L, -2);  /* original argument (below function) */
     lua_rawcall(L, 1, 0);
   }
   else
     lua_pop(L, 1);  /* pop result from gettable */
-  lua_pop(L, 1);  /* pop table */
 }
 
 
@@ -150,13 +148,11 @@ static void sethook (lua_State *L, const l_char *key, lua_Hook hook,
     (*sethookf)(L, hook);
   else
     luaL_argerror(L, 1, l_s("function expected"));
-  lua_getregistry(L);
   lua_pushstring(L, key);
-  lua_pushvalue(L, -1);  /* dup key */
-  lua_gettable(L, -3);   /* get old value */
-  lua_pushvalue(L, -2);  /* key (again) */
+  lua_gettable(L, LUA_REGISTRYINDEX);   /* get old value */
+  lua_pushstring(L, key);
   lua_pushvalue(L, 1);
-  lua_settable(L, -5);  /* set new value */
+  lua_settable(L, LUA_REGISTRYINDEX);  /* set new value */
 }
 
 

+ 7 - 6
ldo.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.c,v 1.141 2001/09/25 17:05:49 roberto Exp $
+** $Id: ldo.c,v 1.142 2001/10/02 16:45:03 roberto Exp $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
@@ -44,7 +44,8 @@ void luaD_init (lua_State *L, int stacksize) {
   stacksize += EXTRA_STACK;
   L->stack = luaM_newvector(L, stacksize, TObject);
   L->stacksize = stacksize;
-  L->basefunc.base = L->top = L->stack;
+  setnilvalue(L->stack);  /* the `initial' function */
+  L->top = L->basefunc.base = L->stack + 1;
   restore_stack_limit(L);
 }
 
@@ -119,12 +120,12 @@ static void luaD_callHook (lua_State *L, lua_Hook callhook,
 
 
 static StkId callCclosure (lua_State *L, const struct CClosure *cl) {
-  int nup = cl->nupvalues;  /* number of upvalues */
   int n;
-  luaD_checkstack(L, nup+LUA_MINSTACK);  /* ensure minimum stack size */
-  for (n=0; n<nup; n++)  /* copy upvalues as extra arguments */
-    setobj(L->top++, &cl->upvalue[n]);
+  luaD_checkstack(L, LUA_MINSTACK);  /* ensure minimum stack size */
   lua_unlock(L);
+#if LUA_COMPATUPVALUES
+  lua_pushupvalues(L);
+#endif
   n = (*cl->f)(L);  /* do the actual call */
   lua_lock(L);
   return L->top - n;  /* return index of first result */

+ 2 - 3
lgc.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.c,v 1.111 2001/09/07 17:39:10 roberto Exp $
+** $Id: lgc.c,v 1.112 2001/10/02 16:45:03 roberto Exp $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
@@ -171,8 +171,7 @@ static void markall (lua_State *L) {
   marktagmethods(G(L), &st);  /* mark tag methods */
   markstacks(L, &st); /* mark all stacks */
   marktable(&st, G(L)->type2tag);
-  marktable(&st, G(L)->registry);
-  marktable(&st, G(L)->weakregistry);
+  markobject(&st, &G(L)->registry);
   while (st.tmark) {  /* mark tables */
     Hash *h = st.tmark;  /* get first table from list */
     st.tmark = h->mark;  /* remove it from list */

+ 2 - 5
lstate.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.c,v 1.66 2001/07/17 17:54:46 roberto Exp $
+** $Id: lstate.c,v 1.68 2001/09/07 17:39:10 roberto Exp $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -66,10 +66,7 @@ static void f_luaopen (lua_State *L, void *ud) {
     luaD_init(L, so->stacksize);  /* init stack */
     L->gt = luaH_new(L, 10);  /* table of globals */
     G(L)->type2tag = luaH_new(L, 10);
-    G(L)->registry = luaH_new(L, 0);
-    G(L)->weakregistry = luaH_new(L, 0);
-    /* make weakregistry weak */
-    G(L)->weakregistry->weakmode = LUA_WEAK_KEY | LUA_WEAK_VALUE;
+    sethvalue(&G(L)->registry, luaH_new(L, 0));
     luaS_resize(L, MINPOWER2);
     luaX_init(L);
     luaT_init(L);

+ 2 - 3
lstate.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.h,v 1.59 2001/09/07 17:39:10 roberto Exp $
+** $Id: lstate.h,v 1.60 2001/10/02 16:43:29 roberto Exp $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -58,8 +58,7 @@ typedef struct global_State {
   size_t Mbuffsize;  /* size of Mbuffer */
   stringtable strt;  /* hash table for strings */
   Hash *type2tag;  /* hash table from type names to tags */
-  Hash *registry;  /* (strong) registry table */
-  Hash *weakregistry;  /* weakregistry table */
+  TObject registry;  /* registry table */
   struct TM *TMtable;  /* table for tag methods */
   int sizeTM;  /* size of TMtable */
   int ntag;  /* number of tags in TMtable */

+ 11 - 10
ltests.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltests.c,v 1.91 2001/09/07 17:39:10 roberto Exp $
+** $Id: ltests.c,v 1.92 2001/10/02 16:45:03 roberto Exp $
 ** Internal Module for Debugging of the Lua Implementation
 ** See Copyright Notice in lua.h
 */
@@ -317,21 +317,16 @@ static int tref (lua_State *L) {
   int level = lua_gettop(L);
   luaL_checkany(L, 1);
   lua_pushvalue(L, 1);
-  lua_pushnumber(L, lua_ref(L, luaL_opt_int(L, 2, 1)));
+  lua_pushnumber(L, lua_ref(L, 1));
   assert(lua_gettop(L) == level+1);  /* +1 for result */
   return 1;
 }
 
 static int getref (lua_State *L) {
   int level = lua_gettop(L);
-  if (lua_getref(L, luaL_check_int(L, 1))) {
-    assert(lua_gettop(L) == level+1);
-    return 1;
-  }
-  else {
-    assert(lua_gettop(L) == level);
-    return 0;
-  }
+  lua_getref(L, luaL_check_int(L, 1));
+  assert(lua_gettop(L) == level+1);
+  return 1;
 }
 
 static int unref (lua_State *L) {
@@ -570,6 +565,12 @@ static int testC (lua_State *L) {
     else if EQ(l_s("pushvalue")) {
       lua_pushvalue(L, getnum);
     }
+    else if EQ(l_s("pushcclosure")) {
+      lua_pushcclosure(L, testC, getnum);
+    }
+    else if EQ(l_s("pushupvalues")) {
+      lua_pushupvalues(L);
+    }
     else if EQ(l_s("remove")) {
       lua_remove(L, getnum);
     }

+ 2 - 2
lua.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lua.c,v 1.69 2001/08/30 20:54:02 roberto Exp $
+** $Id: lua.c,v 1.70 2001/09/25 17:06:34 roberto Exp $
 ** Lua stand-alone interpreter
 ** See Copyright Notice in lua.h
 */
@@ -141,7 +141,7 @@ static void getargs (l_char *argv[]) {
 
 
 static int l_getargs (lua_State *l) {
-  l_char **argv = (l_char **)lua_touserdata(l, -1);
+  l_char **argv = (l_char **)lua_touserdata(l, lua_upvalueindex(1));
   getargs(argv);
   return 1;
 }

+ 14 - 4
lua.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lua.h,v 1.103 2001/08/31 19:46:07 roberto Exp $
+** $Id: lua.h,v 1.104 2001/10/11 21:41:21 roberto Exp $
 ** Lua - An Extensible Extension Language
 ** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil
 ** e-mail: [email protected]
@@ -35,6 +35,13 @@
 #define LUA_MULTRET	(-1)
 
 
+/* pseudo-index for registry */
+#define LUA_REGISTRYINDEX	(-10000)
+
+/* pseudo-indices for upvalues */
+#define lua_upvalueindex(i)	(LUA_REGISTRYINDEX-(i))
+
+
 /* error codes for `lua_do*' and the like */
 #define LUA_ERRRUN	1
 #define LUA_ERRFILE	2
@@ -160,9 +167,7 @@ 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_getglobals (lua_State *L);
 LUA_API void  lua_gettagmethod (lua_State *L, int tag, const lua_char *event);
-LUA_API int   lua_getref (lua_State *L, int ref);
 LUA_API void  lua_newtable (lua_State *L);
-LUA_API void  lua_getregistry (lua_State *L);
 LUA_API void  lua_getweakregistry (lua_State *L);
 
 
@@ -246,14 +251,19 @@ LUA_API int   lua_getweakmode (lua_State *L, int index);
 #define lua_pushliteral(L, s)	lua_pushlstring(L, s, \
                                                 (sizeof(s)/sizeof(lua_char))-1)
 
+#define lua_getregistry(L)	lua_pushvalue(L, LUA_REGISTRYINDEX);
+
+#define lua_getref(L,ref)	lua_rawgeti(L, LUA_REGISTRYINDEX, ref)
 
 
 /*
-** compatibility macros
+** 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);
+
 #endif