浏览代码

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

Roberto Ierusalimschy 24 年之前
父节点
当前提交
1e81da51ba
共有 10 个文件被更改,包括 111 次插入123 次删除
  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