diff --git a/lapi.c b/lapi.c index f82b00dc..b08fa6ad 100644 --- a/lapi.c +++ b/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); diff --git a/lbaselib.c b/lbaselib.c index ae3ad956..7acbba4b 100644 --- a/lbaselib.c +++ b/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; } diff --git a/ldblib.c b/ldblib.c index 919b2766..1686339a 100644 --- a/ldblib.c +++ b/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}, diff --git a/ldo.c b/ldo.c index 3dcb5ba9..a96cc388 100644 --- a/ldo.c +++ b/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); diff --git a/lfunc.c b/lfunc.c index d69f75dd..9631f5dc 100644 --- a/lfunc.c +++ b/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; diff --git a/lfunc.h b/lfunc.h index fb542716..a69b5327 100644 --- a/lfunc.h +++ b/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); diff --git a/lgc.c b/lgc.c index 127260c9..da03498a 100644 --- a/lgc.c +++ b/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; ic.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; il.nupvalues; i++) /* mark its upvalues */ markobject(g, cl->l.upvals[i]); diff --git a/linit.c b/linit.c index a50b894e..da414468 100644 --- a/linit.c +++ b/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; } diff --git a/liolib.c b/liolib.c index 4663dd78..87cc77e8 100644 --- a/liolib.c +++ b/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; diff --git a/loadlib.c b/loadlib.c index 2c1d87f2..1fe4fc38 100644 --- a/loadlib.c +++ b/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 */ diff --git a/lobject.h b/lobject.h index 0c781ef3..ab0ddee7 100644 --- a/lobject.h +++ b/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; diff --git a/lstate.h b/lstate.h index 2ba5a91d..995733d9 100644 --- a/lstate.h +++ b/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 */ diff --git a/lstring.c b/lstring.c index 0c82220e..768d064f 100644 --- a/lstring.c +++ b/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); diff --git a/lstring.h b/lstring.h index ec2972a1..1d2d752e 100644 --- a/lstring.h +++ b/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); diff --git a/ltests.c b/ltests.c index 8686fa73..620b6a41 100644 --- a/ltests.c +++ b/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; ic.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; il.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}, diff --git a/lua.h b/lua.h index b3d7e83e..ac02d433 100644 --- a/lua.h +++ b/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:info@lua.org @@ -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)) diff --git a/lvm.c b/lvm.c index 9592a11a..9ab8aa38 100644 --- a/lvm.c +++ b/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