瀏覽代碼

C functions and userdata also have environments

Roberto Ierusalimschy 20 年之前
父節點
當前提交
7d45a5f48f
共有 17 個文件被更改,包括 206 次插入111 次删除
  1. 53 13
      lapi.c
  2. 7 4
      lbaselib.c
  3. 39 1
      ldblib.c
  4. 2 2
      ldo.c
  5. 5 4
      lfunc.c
  6. 3 3
      lfunc.h
  7. 3 2
      lgc.c
  8. 3 1
      linit.c
  9. 17 17
      liolib.c
  10. 7 5
      loadlib.c
  11. 4 3
      lobject.h
  12. 2 1
      lstate.h
  13. 3 2
      lstring.c
  14. 2 2
      lstring.h
  15. 43 43
      ltests.c
  16. 3 2
      lua.h
  17. 10 6
      lvm.c

+ 53 - 13
lapi.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lapi.c,v 2.25 2005/01/07 19:53:32 roberto Exp roberto $
+** $Id: lapi.c,v 2.26 2005/01/14 14:19:42 roberto Exp roberto $
 ** Lua API
 ** See Copyright Notice in lua.h
 */
@@ -58,6 +58,11 @@ static TValue *index2adr (lua_State *L, int idx) {
   }
   else switch (idx) {  /* pseudo-indices */
     case LUA_REGISTRYINDEX: return registry(L);
+    case LUA_ENVIRONINDEX: {
+      Closure *func = curr_func(L);
+      sethvalue(L, &L->env, func->c.env);
+      return &L->env;
+    }
     case LUA_GLOBALSINDEX: return gt(L);
     default: {
       Closure *func = curr_func(L);
@@ -70,6 +75,16 @@ static TValue *index2adr (lua_State *L, int idx) {
 }
 
 
+static Table *getcurrenv (lua_State *L) {
+  if (L->ci == L->base_ci)  /* no enclosing function? */
+    return hvalue(gt(L));  /* use global table as environment */
+  else {
+    Closure *func = curr_func(L);
+    return func->c.env;
+  }
+}
+
+
 void luaA_pushobject (lua_State *L, const TValue *o) {
   setobj2s(L, L->top, o);
   incr_top(L);
@@ -186,9 +201,17 @@ LUA_API void lua_replace (lua_State *L, int idx) {
   api_checknelems(L, 1);
   o = index2adr(L, idx);
   api_checkvalidindex(L, o);
-  setobj(L, o, L->top - 1);
-  if (idx < LUA_GLOBALSINDEX)  /* function upvalue? */
-    luaC_barrier(L, curr_func(L), L->top - 1);
+  if (idx == LUA_ENVIRONINDEX) {
+    Closure *func = curr_func(L);
+    api_check(L, ttistable(L->top - 1)); 
+    func->c.env = hvalue(L->top - 1);
+    luaC_barrier(L, func, L->top - 1);
+  }
+  else {
+    setobj(L, o, L->top - 1);
+    if (idx < LUA_GLOBALSINDEX)  /* function upvalue? */
+      luaC_barrier(L, curr_func(L), L->top - 1);
+  }
   L->top--;
   lua_unlock(L);
 }
@@ -452,7 +475,7 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
   lua_lock(L);
   luaC_checkGC(L);
   api_checknelems(L, n);
-  cl = luaF_newCclosure(L, n);
+  cl = luaF_newCclosure(L, n, getcurrenv(L));
   cl->c.f = fn;
   L->top -= n;
   while (n--)
@@ -579,7 +602,17 @@ LUA_API void lua_getfenv (lua_State *L, int idx) {
   lua_lock(L);
   o = index2adr(L, idx);
   api_checkvalidindex(L, o);
-  setobj2s(L, L->top, isLfunction(o) ? &clvalue(o)->l.g : gt(L));
+  switch (ttype(o)) {
+    case LUA_TFUNCTION:
+      sethvalue(L, L->top, clvalue(o)->c.env);
+      break;
+    case LUA_TUSERDATA:
+      sethvalue(L, L->top, uvalue(o)->env);
+      break;
+    default:
+      setnilvalue(L->top);
+      break;
+  }
   api_incr_top(L);
   lua_unlock(L);
 }
@@ -682,17 +715,24 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) {
 
 LUA_API int lua_setfenv (lua_State *L, int idx) {
   StkId o;
-  int res = 0;
+  int res = 1;
   lua_lock(L);
   api_checknelems(L, 1);
   o = index2adr(L, idx);
   api_checkvalidindex(L, o);
   api_check(L, ttistable(L->top - 1));
-  if (isLfunction(o)) {
-    res = 1;
-    clvalue(o)->l.g = *(L->top - 1);
-    luaC_objbarrier(L, clvalue(o), hvalue(L->top - 1));
+  switch (ttype(o)) {
+    case LUA_TFUNCTION:
+      clvalue(o)->c.env = hvalue(L->top - 1);
+      break;
+    case LUA_TUSERDATA:
+      uvalue(o)->env = hvalue(L->top - 1);
+      break;
+    default:
+      res = 0;
+      break;
   }
+  luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1));
   L->top--;
   lua_unlock(L);
   return res;
@@ -776,7 +816,7 @@ struct CCallS {  /* data to `f_Ccall' */
 static void f_Ccall (lua_State *L, void *ud) {
   struct CCallS *c = cast(struct CCallS *, ud);
   Closure *cl;
-  cl = luaF_newCclosure(L, 0);
+  cl = luaF_newCclosure(L, 0, getcurrenv(L));
   cl->c.f = c->func;
   setclvalue(L, L->top, cl);  /* push function */
   incr_top(L);
@@ -943,7 +983,7 @@ LUA_API void *lua_newuserdata (lua_State *L, size_t size) {
   Udata *u;
   lua_lock(L);
   luaC_checkGC(L);
-  u = luaS_newudata(L, size);
+  u = luaS_newudata(L, size, getcurrenv(L));
   setuvalue(L, L->top, u);
   api_incr_top(L);
   lua_unlock(L);

+ 7 - 4
lbaselib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lbaselib.c,v 1.165 2005/01/14 14:19:42 roberto Exp roberto $
+** $Id: lbaselib.c,v 1.166 2005/02/14 13:19:44 roberto Exp roberto $
 ** Basic library
 ** See Copyright Notice in lua.h
 */
@@ -131,7 +131,10 @@ static void getfunc (lua_State *L) {
 
 static int luaB_getfenv (lua_State *L) {
   getfunc(L);
-  lua_getfenv(L, -1);
+  if (lua_iscfunction(L, -1))  /* is a C function? */
+    lua_pushvalue(L, LUA_GLOBALSINDEX);  /* return the global env. */
+  else
+    lua_getfenv(L, -1);
   return 1;
 }
 
@@ -144,8 +147,8 @@ static int luaB_setfenv (lua_State *L) {
     lua_replace(L, LUA_GLOBALSINDEX);
     return 0;
   }
-  else if (lua_setfenv(L, -2) == 0)
-    luaL_error(L, "`setfenv' cannot change environment of given function");
+  else if (lua_iscfunction(L, -2) || lua_setfenv(L, -2) == 0)
+    luaL_error(L, "`setfenv' cannot change environment of given object");
   return 1;
 }
 

+ 39 - 1
ldblib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldblib.c,v 1.91 2005/01/10 17:21:10 roberto Exp roberto $
+** $Id: ldblib.c,v 1.92 2005/01/18 17:23:25 roberto Exp roberto $
 ** Interface from Lua to its debug API
 ** See Copyright Notice in lua.h
 */
@@ -19,6 +19,40 @@
 
 
 
+static int getmetatable (lua_State *L) {
+  luaL_checkany(L, 1);
+  if (!lua_getmetatable(L, 1)) {
+    lua_pushnil(L);  /* no metatable */
+  }
+  return 1;
+}
+
+
+static int setmetatable (lua_State *L) {
+  int t = lua_type(L, 2);
+  luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
+                    "nil or table expected");
+  lua_settop(L, 2);
+  lua_pushboolean(L, lua_setmetatable(L, 1));
+  return 1;
+}
+
+
+static int getfenv (lua_State *L) {
+  lua_getfenv(L, 1);
+  return 1;
+}
+
+
+static int setfenv (lua_State *L) {
+  luaL_checktype(L, 2, LUA_TTABLE);
+  lua_settop(L, 2);
+  if (lua_setfenv(L, 1) == 0)
+    luaL_error(L, "`setfenv' cannot change environment of given object");
+  return 1;
+}
+
+
 static void settabss (lua_State *L, const char *i, const char *v) {
   lua_pushstring(L, v);
   lua_setfield(L, -2, i);
@@ -328,6 +362,10 @@ static int errorfb (lua_State *L) {
 
 
 static const luaL_reg dblib[] = {
+  {"getmetatable", getmetatable},
+  {"setmetatable", setmetatable},
+  {"getfenv", getfenv},
+  {"setfenv", setfenv},
   {"getlocal", getlocal},
   {"getinfo", getinfo},
   {"gethook", gethook},

+ 2 - 2
ldo.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.c,v 2.12 2004/12/01 15:52:54 roberto Exp roberto $
+** $Id: ldo.c,v 2.13 2004/12/03 20:35:33 roberto Exp roberto $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
@@ -474,7 +474,7 @@ static void f_parser (lua_State *L, void *ud) {
   luaC_checkGC(L);
   tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z,
                                                              &p->buff, p->name);
-  cl = luaF_newLclosure(L, tf->nups, gt(L));
+  cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L)));
   cl->l.p = tf;
   for (i = 0; i < tf->nups; i++)  /* initialize eventual upvalues */
     cl->l.upvals[i] = luaF_newupval(L);

+ 5 - 4
lfunc.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lfunc.c,v 2.7 2005/01/19 15:54:26 roberto Exp roberto $
+** $Id: lfunc.c,v 2.8 2005/02/10 13:25:02 roberto Exp roberto $
 ** Auxiliary functions to manipulate prototypes and closures
 ** See Copyright Notice in lua.h
 */
@@ -20,20 +20,21 @@
 
 
 
-Closure *luaF_newCclosure (lua_State *L, int nelems) {
+Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e) {
   Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems)));
   luaC_link(L, obj2gco(c), LUA_TFUNCTION);
   c->c.isC = 1;
+  c->c.env = e;
   c->c.nupvalues = cast(lu_byte, nelems);
   return c;
 }
 
 
-Closure *luaF_newLclosure (lua_State *L, int nelems, TValue *e) {
+Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e) {
   Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems)));
   luaC_link(L, obj2gco(c), LUA_TFUNCTION);
   c->l.isC = 0;
-  c->l.g = *e;
+  c->l.env = e;
   c->l.nupvalues = cast(lu_byte, nelems);
   while (nelems--) c->l.upvals[nelems] = NULL;
   return c;

+ 3 - 3
lfunc.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lfunc.h,v 2.1 2003/12/10 12:13:36 roberto Exp $
+** $Id: lfunc.h,v 2.2 2005/01/18 17:18:09 roberto Exp roberto $
 ** Auxiliary functions to manipulate prototypes and closures
 ** See Copyright Notice in lua.h
 */
@@ -19,8 +19,8 @@
 
 
 Proto *luaF_newproto (lua_State *L);
-Closure *luaF_newCclosure (lua_State *L, int nelems);
-Closure *luaF_newLclosure (lua_State *L, int nelems, TValue *e);
+Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e);
+Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e);
 UpVal *luaF_newupval (lua_State *L);
 UpVal *luaF_findupval (lua_State *L, StkId level);
 void luaF_close (lua_State *L, StkId level);

+ 3 - 2
lgc.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.c,v 2.24 2005/02/11 20:03:35 roberto Exp roberto $
+** $Id: lgc.c,v 2.25 2005/02/14 13:19:50 roberto Exp roberto $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
@@ -79,6 +79,7 @@ static void reallymarkobject (global_State *g, GCObject *o) {
       Table *mt = gco2u(o)->metatable;
       gray2black(o);  /* udata are never gray */
       if (mt) markobject(g, mt);
+      markobject(g, gco2u(o)->env);
       return;
     }
     case LUA_TUPVAL: {
@@ -223,6 +224,7 @@ static void traverseproto (global_State *g, Proto *f) {
 
 
 static void traverseclosure (global_State *g, Closure *cl) {
+  markobject(g, cl->c.env);
   if (cl->c.isC) {
     int i;
     for (i=0; i<cl->c.nupvalues; i++)  /* mark its upvalues */
@@ -231,7 +233,6 @@ static void traverseclosure (global_State *g, Closure *cl) {
   else {
     int i;
     lua_assert(cl->l.nupvalues == cl->l.p->nups);
-    markobject(g, hvalue(&cl->l.g));
     markobject(g, cl->l.p);
     for (i=0; i<cl->l.nupvalues; i++)  /* mark its upvalues */
       markobject(g, cl->l.upvals[i]);

+ 3 - 1
linit.c

@@ -1,5 +1,5 @@
 /*
-** $Id: linit.c,v 1.7 2004/07/09 14:29:29 roberto Exp roberto $
+** $Id: linit.c,v 1.8 2004/07/09 15:47:48 roberto Exp roberto $
 ** Initialization of libraries for lua.c
 ** See Copyright Notice in lua.h
 */
@@ -32,6 +32,8 @@ LUALIB_API int luaopen_stdlibs (lua_State *L) {
   for (; lib->func; lib++) {
     lib->func(L);  /* open library */
     lua_settop(L, 0);  /* discard any results */
+    lua_pushvalue(L, LUA_GLOBALSINDEX);
+    lua_replace(L, LUA_ENVIRONINDEX);  /* restore environment */
   }
  return 0;
 }

+ 17 - 17
liolib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: liolib.c,v 2.56 2004/08/09 14:35:59 roberto Exp roberto $
+** $Id: liolib.c,v 2.57 2004/08/13 19:52:13 roberto Exp roberto $
 ** Standard I/O (and system) library
 ** See Copyright Notice in lua.h
 */
@@ -105,8 +105,8 @@ static int aux_close (lua_State *L) {
 
 
 static int io_close (lua_State *L) {
-  if (lua_isnone(L, 1) && lua_type(L, lua_upvalueindex(1)) == LUA_TTABLE)
-    lua_rawgeti(L, lua_upvalueindex(1), IO_OUTPUT);
+  if (lua_isnone(L, 1))
+    lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT);
   return pushresult(L, aux_close(L), NULL);
 }
 
@@ -147,7 +147,7 @@ static int io_tmpfile (lua_State *L) {
 
 static FILE *getiofile (lua_State *L, int findex) {
   FILE *f;
-  lua_rawgeti(L, lua_upvalueindex(1), findex);
+  lua_rawgeti(L, LUA_ENVIRONINDEX, findex);
   lua_assert(luaL_checkudata(L, -1, LUA_FILEHANDLE));
   f = *(FILE **)lua_touserdata(L, -1);
   if (f == NULL)
@@ -170,10 +170,10 @@ static int g_iofile (lua_State *L, int f, const char *mode) {
       lua_pushvalue(L, 1);
     }
     lua_assert(luaL_checkudata(L, -1, LUA_FILEHANDLE));
-    lua_rawseti(L, lua_upvalueindex(1), f);
+    lua_rawseti(L, LUA_ENVIRONINDEX, f);
   }
   /* return current value */
-  lua_rawgeti(L, lua_upvalueindex(1), f);
+  lua_rawgeti(L, LUA_ENVIRONINDEX, f);
   return 1;
 }
 
@@ -192,10 +192,9 @@ static int io_readline (lua_State *L);
 
 
 static void aux_lines (lua_State *L, int idx, int close) {
-  lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE);
   lua_pushvalue(L, idx);
   lua_pushboolean(L, close);  /* close/not close file when finished */
-  lua_pushcclosure(L, io_readline, 3);
+  lua_pushcclosure(L, io_readline, 2);
 }
 
 
@@ -209,7 +208,7 @@ static int f_lines (lua_State *L) {
 static int io_lines (lua_State *L) {
   if (lua_isnoneornil(L, 1)) {  /* no arguments? */
     /* will iterate over default input */
-    lua_rawgeti(L, lua_upvalueindex(1), IO_INPUT);
+    lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT);
     return f_lines(L);
   }
   else {
@@ -349,7 +348,7 @@ static int f_read (lua_State *L) {
 
 
 static int io_readline (lua_State *L) {
-  FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(2));
+  FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(1));
   int sucess;
   if (f == NULL)  /* file is already closed? */
     luaL_error(L, "file is already closed");
@@ -358,9 +357,9 @@ static int io_readline (lua_State *L) {
     luaL_error(L, "%s", strerror(errno));
   if (sucess) return 1;
   else {  /* EOF */
-    if (lua_toboolean(L, lua_upvalueindex(3))) {  /* generator created file? */
+    if (lua_toboolean(L, lua_upvalueindex(2))) {  /* generator created file? */
       lua_settop(L, 0);
-      lua_pushvalue(L, lua_upvalueindex(2));
+      lua_pushvalue(L, lua_upvalueindex(1));
       aux_close(L);  /* close it */
     }
     return 0;
@@ -489,12 +488,13 @@ LUALIB_API int luaopen_io (lua_State *L) {
   createmeta(L);
   createupval(L);
   lua_pushvalue(L, -1);
-  luaL_openlib(L, LUA_IOLIBNAME, iolib, 1);
+  lua_replace(L, LUA_ENVIRONINDEX);
+  luaL_openlib(L, LUA_IOLIBNAME, iolib, 0);
   /* put predefined file handles into `io' table */
-  lua_rawgeti(L, -2, IO_INPUT);  /* get current input from metatable */
-  lua_setfield(L, -2, "stdin");  /* io.stdin = metatable[IO_INPUT] */
-  lua_rawgeti(L, -2, IO_OUTPUT);  /* get current output from metatable */
-  lua_setfield(L, -2, "stdout");  /* io.stdout = metatable[IO_OUTPUT] */
+  lua_rawgeti(L, -2, IO_INPUT);  /* get current input from upval */
+  lua_setfield(L, -2, "stdin");  /* io.stdin = upval[IO_INPUT] */
+  lua_rawgeti(L, -2, IO_OUTPUT);  /* get current output from upval */
+  lua_setfield(L, -2, "stdout");  /* io.stdout = upval[IO_OUTPUT] */
   *newfile(L) = stderr;
   lua_setfield(L, -2, "stderr");  /* io.stderr = newfile(stderr) */
   return 1;

+ 7 - 5
loadlib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: loadlib.c,v 1.15 2004/12/29 18:56:34 roberto Exp roberto $
+** $Id: loadlib.c,v 1.16 2005/01/14 14:17:18 roberto Exp roberto $
 ** Dynamic library loader for Lua
 ** See Copyright Notice in lua.h
 *
@@ -302,7 +302,7 @@ static int loader_Lua (lua_State *L) {
   path = lua_tostring(L, -1);
   if (!path) {
     lua_pop(L, 1);
-    luaL_getfield(L, LUA_REGISTRYINDEX, "_PACKAGE.path");
+    lua_getfield(L, LUA_ENVIRONINDEX, "path");
     path = lua_tostring(L, -1);
   }
   if (path == NULL)
@@ -320,7 +320,7 @@ static int loader_C (lua_State *L) {
   const char *fname = luaL_gsub(L, name, ".", LUA_DIRSEP);
   const char *path;
   const char *funcname;
-  luaL_getfield(L, LUA_REGISTRYINDEX, "_PACKAGE.cpath");
+  lua_getfield(L, LUA_ENVIRONINDEX, "cpath");
   path = lua_tostring(L, -1);
   if (path == NULL)
     luaL_error(L, "`package.cpath' must be a string");
@@ -335,7 +335,7 @@ static int loader_C (lua_State *L) {
 
 
 static int loader_preload (lua_State *L) {
-  luaL_getfield(L, LUA_REGISTRYINDEX, "_PACKAGE.preload");
+  lua_getfield(L, LUA_ENVIRONINDEX, "preload");
   if (!lua_istable(L, -1))
     luaL_error(L, "`package.preload' must be a table");
   lua_getfield(L, -1, luaL_checkstring(L, 1));
@@ -355,7 +355,7 @@ static int ll_require (lua_State *L) {
   lua_pushboolean(L, 1);
   lua_setfield(L, 2, name);  /* _LOADED[name] = true */
   /* iterate over available loaders */
-  luaL_getfield(L, LUA_REGISTRYINDEX, "_PACKAGE.loaders");
+  lua_getfield(L, LUA_ENVIRONINDEX, "loaders");
   if (!lua_istable(L, -1))
     luaL_error(L, "`package.loaders' must be a table");
   for (i=1;; i++) {
@@ -457,6 +457,8 @@ LUALIB_API int luaopen_loadlib (lua_State *L) {
   lua_setglobal(L, "package");
   lua_pushvalue(L, -1);
   lua_setfield(L, LUA_REGISTRYINDEX, "_PACKAGE");
+  lua_pushvalue(L, -1);
+  lua_replace(L, LUA_ENVIRONINDEX);
   /* create `loaders' table */
   lua_newtable(L);
   /* fill it with pre-defined loaders */

+ 4 - 3
lobject.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lobject.h,v 2.9 2005/01/05 18:20:51 roberto Exp $
+** $Id: lobject.h,v 2.10 2005/01/18 17:18:09 roberto Exp roberto $
 ** Type definitions for Lua objects
 ** See Copyright Notice in lua.h
 */
@@ -218,6 +218,7 @@ typedef union Udata {
   struct {
     CommonHeader;
     struct Table *metatable;
+    struct Table *env;
     size_t len;
   } uv;
 } Udata;
@@ -286,7 +287,8 @@ typedef struct UpVal {
 */
 
 #define ClosureHeader \
-	CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist
+	CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist; \
+	struct Table *env
 
 typedef struct CClosure {
   ClosureHeader;
@@ -298,7 +300,6 @@ typedef struct CClosure {
 typedef struct LClosure {
   ClosureHeader;
   struct Proto *p;
-  TValue g;  /* global table for this closure */
   UpVal *upvals[1];
 } LClosure;
 

+ 2 - 1
lstate.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.h,v 2.13 2005/01/18 17:18:09 roberto Exp roberto $
+** $Id: lstate.h,v 2.14 2005/02/11 20:03:35 roberto Exp roberto $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -116,6 +116,7 @@ struct lua_State {
   int hookcount;
   lua_Hook hook;
   TValue _gt;  /* table of globals */
+  TValue env;  /* temporary place for environments */
   GCObject *openupval;  /* list of open upvalues in this stack */
   GCObject *gclist;
   struct lua_longjmp *errorJmp;  /* current error recover point */

+ 3 - 2
lstring.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lstring.c,v 2.5 2004/11/24 19:16:03 roberto Exp $
+** $Id: lstring.c,v 2.6 2005/01/18 17:18:09 roberto Exp roberto $
 ** String table (keeps all strings handled by Lua)
 ** See Copyright Notice in lua.h
 */
@@ -93,7 +93,7 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
 }
 
 
-Udata *luaS_newudata (lua_State *L, size_t s) {
+Udata *luaS_newudata (lua_State *L, size_t s, Table *e) {
   Udata *u;
   if (s > MAX_SIZET - sizeof(Udata))
     luaM_toobig(L);
@@ -102,6 +102,7 @@ Udata *luaS_newudata (lua_State *L, size_t s) {
   u->uv.tt = LUA_TUSERDATA;
   u->uv.len = s;
   u->uv.metatable = NULL;
+  u->uv.env = e;
   /* chain it on udata list (after main thread) */
   u->uv.next = G(L)->mainthread->next;
   G(L)->mainthread->next = obj2gco(u);

+ 2 - 2
lstring.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lstring.h,v 1.39 2004/08/24 20:12:06 roberto Exp roberto $
+** $Id: lstring.h,v 1.40 2004/11/19 15:52:40 roberto Exp roberto $
 ** String table (keep all strings handled by Lua)
 ** See Copyright Notice in lua.h
 */
@@ -24,7 +24,7 @@
 #define luaS_fix(s)	setbit((s)->tsv.marked, FIXEDBIT)
 
 void luaS_resize (lua_State *L, int newsize);
-Udata *luaS_newudata (lua_State *L, size_t s);
+Udata *luaS_newudata (lua_State *L, size_t s, Table *e);
 TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
 
 

+ 43 - 43
ltests.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltests.c,v 2.17 2005/01/14 14:19:42 roberto Exp $
+** $Id: ltests.c,v 2.19 2005/01/19 15:54:26 roberto Exp roberto $
 ** Internal Module for Debugging of the Lua Implementation
 ** See Copyright Notice in lua.h
 */
@@ -249,6 +249,7 @@ static void checkproto (global_State *g, Proto *f) {
 
 static void checkclosure (global_State *g, Closure *cl) {
   GCObject *clgc = obj2gco(cl);
+  checkobjref(g, clgc, cl->l.env);
   if (cl->c.isC) {
     int i;
     for (i=0; i<cl->c.nupvalues; i++)
@@ -257,7 +258,6 @@ static void checkclosure (global_State *g, Closure *cl) {
   else {
     int i;
     lua_assert(cl->l.nupvalues == cl->l.p->nups);
-    checkobjref(g, clgc, hvalue(&cl->l.g));
     checkobjref(g, clgc, cl->l.p);
     for (i=0; i<cl->l.nupvalues; i++) {
       if (cl->l.upvals[i]) {
@@ -622,20 +622,6 @@ static int unref (lua_State *L) {
   return 0;
 }
 
-static int metatable (lua_State *L) {
-  luaL_checkany(L, 1);
-  if (lua_isnone(L, 2)) {
-    if (lua_getmetatable(L, 1) == 0)
-      lua_pushnil(L);
-  }
-  else {
-    lua_settop(L, 2);
-    luaL_checktype(L, 2, LUA_TTABLE);
-    lua_setmetatable(L, 1);
-  }
-  return 1;
-}
-
 
 static int upvalue (lua_State *L) {
   int n = luaL_checkint(L, 2);
@@ -814,10 +800,22 @@ static const char *getname_aux (char *buff, const char **pc) {
 }
 
 
+static int getindex_aux (lua_State *L, const char **pc) {
+  skip(pc);
+  switch (*(*pc)++) {
+    case 'R': return LUA_REGISTRYINDEX;
+    case 'G': return LUA_GLOBALSINDEX;
+    case 'E': return LUA_ENVIRONINDEX;
+    case 'U': return lua_upvalueindex(getnum_aux(L, pc));
+    default: (*pc)--; return getnum_aux(L, pc);
+  }
+}
+
 #define EQ(s1)	(strcmp(s1, inst) == 0)
 
 #define getnum	(getnum_aux(L, &pc))
 #define getname	(getname_aux(buff, &pc))
+#define getindex (getindex_aux(L, &pc))
 
 
 static int testC (lua_State *L) {
@@ -836,44 +834,44 @@ static int testC (lua_State *L) {
     const char *inst = getname;
     if EQ("") return 0;
     else if EQ("isnumber") {
-      lua_pushinteger(L1, lua_isnumber(L1, getnum));
+      lua_pushinteger(L1, lua_isnumber(L1, getindex));
     }
     else if EQ("isstring") {
-      lua_pushinteger(L1, lua_isstring(L1, getnum));
+      lua_pushinteger(L1, lua_isstring(L1, getindex));
     }
     else if EQ("istable") {
-      lua_pushinteger(L1, lua_istable(L1, getnum));
+      lua_pushinteger(L1, lua_istable(L1, getindex));
     }
     else if EQ("iscfunction") {
-      lua_pushinteger(L1, lua_iscfunction(L1, getnum));
+      lua_pushinteger(L1, lua_iscfunction(L1, getindex));
     }
     else if EQ("isfunction") {
-      lua_pushinteger(L1, lua_isfunction(L1, getnum));
+      lua_pushinteger(L1, lua_isfunction(L1, getindex));
     }
     else if EQ("isuserdata") {
-      lua_pushinteger(L1, lua_isuserdata(L1, getnum));
+      lua_pushinteger(L1, lua_isuserdata(L1, getindex));
     }
     else if EQ("isudataval") {
-      lua_pushinteger(L1, lua_islightuserdata(L1, getnum));
+      lua_pushinteger(L1, lua_islightuserdata(L1, getindex));
     }
     else if EQ("isnil") {
-      lua_pushinteger(L1, lua_isnil(L1, getnum));
+      lua_pushinteger(L1, lua_isnil(L1, getindex));
     }
     else if EQ("isnull") {
-      lua_pushinteger(L1, lua_isnone(L1, getnum));
+      lua_pushinteger(L1, lua_isnone(L1, getindex));
     }
     else if EQ("tonumber") {
-      lua_pushnumber(L1, lua_tonumber(L1, getnum));
+      lua_pushnumber(L1, lua_tonumber(L1, getindex));
     }
     else if EQ("tostring") {
-      const char *s = lua_tostring(L1, getnum);
+      const char *s = lua_tostring(L1, getindex);
       lua_pushstring(L1, s);
     }
     else if EQ("objsize") {
-      lua_pushinteger(L1, lua_objsize(L1, getnum));
+      lua_pushinteger(L1, lua_objsize(L1, getindex));
     }
     else if EQ("tocfunction") {
-      lua_pushcfunction(L1, lua_tocfunction(L1, getnum));
+      lua_pushcfunction(L1, lua_tocfunction(L1, getindex));
     }
     else if EQ("return") {
       return getnum;
@@ -899,11 +897,14 @@ static int testC (lua_State *L) {
     else if EQ("pushbool") {
       lua_pushboolean(L1, getnum);
     }
+    else if EQ("newuserdata") {
+      lua_newuserdata(L1, getnum);
+    }
     else if EQ("tobool") {
-      lua_pushinteger(L1, lua_toboolean(L1, getnum));
+      lua_pushinteger(L1, lua_toboolean(L1, getindex));
     }
     else if EQ("pushvalue") {
-      lua_pushvalue(L1, getnum);
+      lua_pushvalue(L1, getindex);
     }
     else if EQ("pushcclosure") {
       lua_pushcclosure(L1, testC, getnum);
@@ -915,13 +916,13 @@ static int testC (lua_State *L) {
       lua_insert(L1, getnum);
     }
     else if EQ("replace") {
-      lua_replace(L1, getnum);
+      lua_replace(L1, getindex);
     }
     else if EQ("gettable") {
-      lua_gettable(L1, getnum);
+      lua_gettable(L1, getindex);
     }
     else if EQ("settable") {
-      lua_settable(L1, getnum);
+      lua_settable(L1, getindex);
     }
     else if EQ("next") {
       lua_next(L1, -2);
@@ -930,12 +931,12 @@ static int testC (lua_State *L) {
       lua_concat(L1, getnum);
     }
     else if EQ("lessthan") {
-      int a = getnum;
-      lua_pushboolean(L1, lua_lessthan(L1, a, getnum));
+      int a = getindex;
+      lua_pushboolean(L1, lua_lessthan(L1, a, getindex));
     }
     else if EQ("equal") {
-      int a = getnum;
-      lua_pushboolean(L1, lua_equal(L1, a, getnum));
+      int a = getindex;
+      lua_pushboolean(L1, lua_equal(L1, a, getindex));
     }
     else if EQ("rawcall") {
       int narg = getnum;
@@ -956,21 +957,21 @@ static int testC (lua_State *L) {
       luaL_loadfile(L1, luaL_checkstring(L1, getnum));
     }
     else if EQ("setmetatable") {
-      lua_setmetatable(L1, getnum);
+      lua_setmetatable(L1, getindex);
     }
     else if EQ("getmetatable") {
-      if (lua_getmetatable(L1, getnum) == 0)
+      if (lua_getmetatable(L1, getindex) == 0)
         lua_pushnil(L1);
     }
     else if EQ("type") {
       lua_pushstring(L1, luaL_typename(L1, getnum));
     }
     else if EQ("getn") {
-      int i = getnum;
+      int i = getindex;
       lua_pushinteger(L1, luaL_getn(L1, i));
     }
     else if EQ("setn") {
-      int i = getnum;
+      int i = getindex;
       int n = cast(int, lua_tonumber(L1, -1));
       luaL_setn(L1, i, n);
       lua_pop(L1, 1);
@@ -1095,7 +1096,6 @@ static const struct luaL_reg tests_funcs[] = {
   {"unref", unref},
   {"d2s", d2s},
   {"s2d", s2d},
-  {"metatable", metatable},
   {"upvalue", upvalue},
   {"newuserdata", newuserdata},
   {"pushuserdata", pushuserdata},

+ 3 - 2
lua.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lua.h,v 1.200 2005/01/14 14:19:42 roberto Exp roberto $
+** $Id: lua.h,v 1.201 2005/01/17 23:50:55 roberto Exp roberto $
 ** Lua - An Extensible Extension Language
 ** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil
 ** http://www.lua.org	mailto:[email protected]
@@ -34,7 +34,8 @@
 ** pseudo-indices
 */
 #define LUA_REGISTRYINDEX	(-10000)
-#define LUA_GLOBALSINDEX	(-10001)
+#define LUA_ENVIRONINDEX	(-10001)
+#define LUA_GLOBALSINDEX	(-10002)
 #define lua_upvalueindex(i)	(LUA_GLOBALSINDEX-(i))
 
 

+ 10 - 6
lvm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.c,v 2.22 2005/01/10 18:17:39 roberto Exp roberto $
+** $Id: lvm.c,v 2.23 2005/01/10 18:33:37 roberto Exp roberto $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -428,9 +428,11 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
         continue;
       }
       case OP_GETGLOBAL: {
+        TValue g;
         TValue *rb = KBx(i);
-        lua_assert(ttisstring(rb) && ttistable(&cl->g));
-        base = luaV_gettable(L, &cl->g, rb, ra, pc);  /***/
+        sethvalue(L, &g, cl->env);
+        lua_assert(ttisstring(rb));
+        base = luaV_gettable(L, &g, rb, ra, pc);  /***/
         continue;
       }
       case OP_GETTABLE: {
@@ -438,8 +440,10 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
         continue;
       }
       case OP_SETGLOBAL: {
-        lua_assert(ttisstring(KBx(i)) && ttistable(&cl->g));
-        base = luaV_settable(L, &cl->g, KBx(i), ra, pc);  /***/
+        TValue g;
+        sethvalue(L, &g, cl->env);
+        lua_assert(ttisstring(KBx(i)));
+        base = luaV_settable(L, &g, KBx(i), ra, pc);  /***/
         continue;
       }
       case OP_SETUPVAL: {
@@ -740,7 +744,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
         int nup, j;
         p = cl->p->p[GETARG_Bx(i)];
         nup = p->nups;
-        ncl = luaF_newLclosure(L, nup, &cl->g);
+        ncl = luaF_newLclosure(L, nup, cl->env);
         ncl->l.p = p;
         for (j=0; j<nup; j++, pc++) {
           if (GET_OPCODE(*pc) == OP_GETUPVAL)