From 25c557ec6367870c127e879cce8ed8fa21f34398 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Fri, 12 Mar 2010 16:14:06 -0300 Subject: [PATCH] first version of _ENV; no more global variables --- lbaselib.c | 4 ++-- lcode.c | 14 ++------------ ldebug.c | 48 +++++++++++++++++++++++++++--------------------- ldump.c | 3 +-- lfunc.c | 3 +-- lobject.h | 3 +-- lopcodes.c | 6 +----- lopcodes.h | 7 ++----- lparser.c | 47 ++++++++++------------------------------------- lparser.h | 4 +--- lundump.c | 3 +-- lvm.c | 34 +++------------------------------- 12 files changed, 52 insertions(+), 124 deletions(-) diff --git a/lbaselib.c b/lbaselib.c index 0554ba55..a14ce31d 100644 --- a/lbaselib.c +++ b/lbaselib.c @@ -1,5 +1,5 @@ /* -** $Id: lbaselib.c,v 1.234 2009/12/22 15:32:50 roberto Exp roberto $ +** $Id: lbaselib.c,v 1.235 2009/12/28 16:30:31 roberto Exp roberto $ ** Basic library ** See Copyright Notice in lua.h */ @@ -376,7 +376,7 @@ static int luaB_loadin (lua_State *L) { n = luaB_load_aux(L, 2); if (n == 1) { /* success? */ lua_pushvalue(L, 1); /* environment for loaded function */ - lua_setfenv(L, -2); + lua_setupvalue(L, -2, 1); } return n; } diff --git a/lcode.c b/lcode.c index a61ef112..5458d766 100644 --- a/lcode.c +++ b/lcode.c @@ -1,5 +1,5 @@ /* -** $Id: lcode.c,v 2.43 2010/01/11 17:38:30 roberto Exp roberto $ +** $Id: lcode.c,v 2.44 2010/02/26 20:40:29 roberto Exp roberto $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -372,11 +372,6 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) { e->k = VRELOCABLE; break; } - case VGLOBAL: { - e->u.s.info = luaK_codeABxX(fs, OP_GETGLOBAL, 0, e->u.s.info); - e->k = VRELOCABLE; - break; - } case VINDEXED: { freereg(fs, e->u.s.aux); freereg(fs, e->u.s.info); @@ -555,11 +550,6 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { luaK_codeABC(fs, OP_SETUPVAL, e, var->u.s.info, 0); break; } - case VGLOBAL: { - int e = luaK_exp2anyreg(fs, ex); - luaK_codeABxX(fs, OP_SETGLOBAL, e, var->u.s.info); - break; - } case VINDEXED: { int e = luaK_exp2RK(fs, ex); luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e); @@ -584,9 +574,9 @@ void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { luaK_exp2anyreg(fs, e); freeexp(fs, e); func = fs->freereg; - luaK_reserveregs(fs, 2); luaK_codeABC(fs, OP_SELF, func, e->u.s.info, luaK_exp2RK(fs, key)); freeexp(fs, key); + luaK_reserveregs(fs, 2); e->u.s.info = func; e->k = VNONRELOC; } diff --git a/ldebug.c b/ldebug.c index 2e6eb698..898efe53 100644 --- a/ldebug.c +++ b/ldebug.c @@ -1,5 +1,5 @@ /* -** $Id: ldebug.c,v 2.64 2010/02/26 20:40:29 roberto Exp roberto $ +** $Id: ldebug.c,v 2.65 2010/03/05 14:01:29 roberto Exp roberto $ ** Debug Interface ** See Copyright Notice in lua.h */ @@ -260,11 +260,14 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { */ -static const char *kname (Proto *p, int c) { - if (ISK(c) && ttisstring(&p->k[INDEXK(c)])) - return svalue(&p->k[INDEXK(c)]); +static void kname (Proto *p, int c, int reg, const char *what, + const char **name) { + if (c == reg && *what == 'c') + return; /* index is a constant; name already correct */ + else if (ISK(c) && ttisstring(&p->k[INDEXK(c)])) + *name = svalue(&p->k[INDEXK(c)]); else - return "?"; + *name = "?"; } @@ -283,17 +286,6 @@ static const char *getobjname (lua_State *L, CallInfo *ci, int reg, OpCode op = GET_OPCODE(i); int a = GETARG_A(i); switch (op) { - case OP_GETGLOBAL: { - if (reg == a) { - int g = GETARG_Bx(i); - if (g != 0) g--; - else g = GETARG_Ax(p->code[++pc]); - lua_assert(ttisstring(&p->k[g])); - *name = svalue(&p->k[g]); - what = "global"; - } - break; - } case OP_MOVE: { if (reg == a) { int b = GETARG_B(i); /* move from 'b' to 'a' */ @@ -307,8 +299,12 @@ static const char *getobjname (lua_State *L, CallInfo *ci, int reg, case OP_GETTABLE: { if (reg == a) { int k = GETARG_C(i); /* key index */ - *name = kname(p, k); - what = "field"; + int t = GETARG_B(i); + const char *tabname = (op == OP_GETTABLE) + ? luaF_getlocalname(p, t + 1, pc) + : getstr(p->upvalues[t].name); + kname(p, k, a, what, name); + what = (tabname && strcmp(tabname, "_ENV") == 0) ? "global" : "field"; } break; } @@ -321,6 +317,17 @@ static const char *getobjname (lua_State *L, CallInfo *ci, int reg, } break; } + case OP_LOADK: { + if (reg == a) { + int b = GETARG_Bx(i); + b = (b > 0) ? b - 1 : GETARG_Ax(p->code[pc + 1]); + if (ttisstring(&p->k[b])) { + what = "constant"; + *name = svalue(&p->k[b]); + } + } + break; + } case OP_LOADNIL: { int b = GETARG_B(i); /* move from 'b' to 'a' */ if (a <= reg && reg <= b) /* set registers from 'a' to 'b' */ @@ -330,7 +337,7 @@ static const char *getobjname (lua_State *L, CallInfo *ci, int reg, case OP_SELF: { if (reg == a) { int k = GETARG_C(i); /* key index */ - *name = kname(p, k); + kname(p, k, a, what, name); what = "method"; } break; @@ -378,11 +385,10 @@ static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { *name = "for iterator"; return "for iterator"; } - case OP_GETGLOBAL: case OP_SELF: case OP_GETTABUP: case OP_GETTABLE: tm = TM_INDEX; break; - case OP_SETGLOBAL: + case OP_SETTABUP: case OP_SETTABLE: tm = TM_NEWINDEX; break; case OP_EQ: tm = TM_EQ; break; case OP_ADD: tm = TM_ADD; break; diff --git a/ldump.c b/ldump.c index e59c4224..007f2223 100644 --- a/ldump.c +++ b/ldump.c @@ -1,5 +1,5 @@ /* -** $Id: ldump.c,v 2.11 2009/09/28 16:32:50 roberto Exp roberto $ +** $Id: ldump.c,v 2.12 2009/09/30 15:38:37 roberto Exp roberto $ ** save precompiled Lua chunks ** See Copyright Notice in lua.h */ @@ -145,7 +145,6 @@ static void DumpFunction(const Proto* f, const TString* p, DumpState* D) DumpChar(f->numparams,D); DumpChar(f->is_vararg,D); DumpChar(f->maxstacksize,D); - DumpChar(f->envreg,D); DumpCode(f,D); DumpConstants(f,D); DumpUpvalues(f,D); diff --git a/lfunc.c b/lfunc.c index d0be5e6b..f4e30faa 100644 --- a/lfunc.c +++ b/lfunc.c @@ -1,5 +1,5 @@ /* -** $Id: lfunc.c,v 2.18 2009/12/11 13:39:34 roberto Exp roberto $ +** $Id: lfunc.c,v 2.19 2009/12/16 16:42:58 roberto Exp roberto $ ** Auxiliary functions to manipulate prototypes and closures ** See Copyright Notice in lua.h */ @@ -127,7 +127,6 @@ Proto *luaF_newproto (lua_State *L) { f->linedefined = 0; f->lastlinedefined = 0; f->source = NULL; - f->envreg = NO_REG; return f; } diff --git a/lobject.h b/lobject.h index 23f1f539..4d28438f 100644 --- a/lobject.h +++ b/lobject.h @@ -1,5 +1,5 @@ /* -** $Id: lobject.h,v 2.33 2009/11/19 19:06:52 roberto Exp roberto $ +** $Id: lobject.h,v 2.34 2010/01/08 20:00:20 roberto Exp roberto $ ** Type definitions for Lua objects ** See Copyright Notice in lua.h */ @@ -264,7 +264,6 @@ typedef struct Proto { lu_byte numparams; lu_byte is_vararg; lu_byte maxstacksize; - lu_byte envreg; /* register in outer function with initial environment */ } Proto; diff --git a/lopcodes.c b/lopcodes.c index 7a355752..ddd27010 100644 --- a/lopcodes.c +++ b/lopcodes.c @@ -1,5 +1,5 @@ /* -** $Id: lopcodes.c,v 1.41 2009/11/19 19:06:52 roberto Exp roberto $ +** $Id: lopcodes.c,v 1.42 2010/02/26 20:40:29 roberto Exp roberto $ ** See Copyright Notice in lua.h */ @@ -19,10 +19,8 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = { "LOADBOOL", "LOADNIL", "GETUPVAL", - "GETGLOBAL", "GETTABUP", "GETTABLE", - "SETGLOBAL", "SETTABUP", "SETUPVAL", "SETTABLE", @@ -69,10 +67,8 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LOADNIL */ ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */ - ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_GETGLOBAL */ ,opmode(0, 1, OpArgU, OpArgK, iABC) /* OP_GETTABUP */ ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */ - ,opmode(0, 0, OpArgK, OpArgN, iABx) /* OP_SETGLOBAL */ ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABUP */ ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */ ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */ diff --git a/lopcodes.h b/lopcodes.h index b7ba60b7..dc8f37f5 100644 --- a/lopcodes.h +++ b/lopcodes.h @@ -1,5 +1,5 @@ /* -** $Id: lopcodes.h,v 1.133 2009/11/19 19:06:52 roberto Exp roberto $ +** $Id: lopcodes.h,v 1.134 2010/02/26 20:40:29 roberto Exp roberto $ ** Opcodes for Lua virtual machine ** See Copyright Notice in lua.h */ @@ -171,11 +171,9 @@ OP_LOADBOOL,/* A B C R(A) := (Bool)B; if (C) pc++ */ OP_LOADNIL,/* A B R(A) := ... := R(B) := nil */ OP_GETUPVAL,/* A B R(A) := UpValue[B] */ -OP_GETGLOBAL,/* A Bx R(A) := Gbl[Kst(Bx - 1)] */ OP_GETTABUP,/* A B C R(A) := UpValue[B][RK(C)] */ OP_GETTABLE,/* A B C R(A) := R(B)[RK(C)] */ -OP_SETGLOBAL,/* A Bx Gbl[Kst(Bx - 1)] := R(A) */ OP_SETTABUP,/* A B C UpValue[A][RK(B)] := RK(C) */ OP_SETUPVAL,/* A B UpValue[B] := R(A) */ OP_SETTABLE,/* A B C R(A)[RK(B)] := RK(C) */ @@ -245,8 +243,7 @@ OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */ (*) In OP_SETLIST, if (B == 0) then B = `top'; if (C == 0) then next 'instruction' is EXTRAARG(real C). - (*) In OP_LOADK, OP_GETGLOBAL, and OP_SETGLOBAL, if (Bx == 0) then next - 'instruction' is EXTRAARG(real Bx). + (*) In OP_LOADK, if (Bx == 0) then next 'instruction' is EXTRAARG(real Bx). (*) For comparisons, A specifies what condition the test should accept (true or false). diff --git a/lparser.c b/lparser.c index eb61b02c..6ce0bdbf 100644 --- a/lparser.c +++ b/lparser.c @@ -1,5 +1,5 @@ /* -** $Id: lparser.c,v 2.77 2010/03/04 18:12:57 roberto Exp roberto $ +** $Id: lparser.c,v 2.78 2010/03/08 16:55:52 roberto Exp roberto $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -259,7 +259,7 @@ static void markupval (FuncState *fs, int level) { */ static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { if (fs == NULL) /* no more levels? */ - return VGLOBAL; /* default is global variable */ + return VVOID; /* default is global */ else { int v = searchvar(fs, n); /* look up locals at current level */ if (v >= 0) { /* found? */ @@ -271,8 +271,8 @@ static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { else { /* not found as local at current level; try upvalues */ int idx = searchupvalue(fs, n); /* try existing upvalues */ if (idx < 0) { /* not found? */ - if (singlevaraux(fs->prev, n, var, 0) == VGLOBAL) /* try upper levels */ - return VGLOBAL; /* not found; is a global */ + if (singlevaraux(fs->prev, n, var, 0) == VVOID) /* try upper levels */ + return VVOID; /* not found; is a global */ /* else was LOCAL or UPVAL */ idx = newupvalue(fs, n, var); /* will be a new upvalue */ } @@ -286,15 +286,12 @@ static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { static void singlevar (LexState *ls, expdesc *var) { TString *varname = str_checkname(ls); FuncState *fs = ls->fs; - if (singlevaraux(fs, varname, var, 1) == VGLOBAL) { - if (fs->envreg == NO_REG) /* regular global? */ - init_exp(var, VGLOBAL, luaK_stringK(fs, varname)); - else { /* "globals" are in current lexical environment */ - expdesc key; - init_exp(var, VLOCAL, fs->envreg); /* current environment */ - codestring(ls, &key, varname); /* key is variable name */ - luaK_indexed(fs, var, &key); /* env[varname] */ - } + if (singlevaraux(fs, varname, var, 1) == VVOID) { /* global name? */ + expdesc key; + singlevaraux(fs, ls->envn, var, 1); /* get _ENV variable */ + lua_assert(var->k == VLOCAL || var->k == VUPVAL); + codestring(ls, &key, varname); /* key is variable name */ + luaK_indexed(fs, var, &key); /* env[varname] */ } } @@ -363,7 +360,6 @@ static void pushclosure (LexState *ls, Proto *clp, expdesc *v) { while (oldsize < f->sizep) f->p[oldsize++] = NULL; f->p[fs->np++] = clp; /* initial environment for new function is current lexical environment */ - clp->envreg = fs->envreg; luaC_objbarrier(ls->L, f, clp); init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1)); } @@ -386,7 +382,6 @@ static void open_func (LexState *ls, FuncState *fs) { fs->nlocvars = 0; fs->nactvar = 0; fs->firstlocal = ls->varl->nactvar; - fs->envreg = NO_REG; fs->bl = NULL; f = luaF_newproto(L); fs->f = f; @@ -1304,24 +1299,6 @@ static void funcstat (LexState *ls, int line) { } -static void instat (LexState *ls, int line) { - /* instat -> IN exp DO block END */ - FuncState *fs = ls->fs; - int oldenv = fs->envreg; /* save current environment */ - BlockCnt bl; - luaX_next(ls); /* skip IN */ - enterblock(fs, &bl, 0); /* scope for environment variable */ - new_localvarliteral(ls, "(environment)"); - fs->envreg = exp1(ls); /* new environment */ - adjustlocalvars(ls, 1); - checknext(ls, TK_DO); - block(ls); - leaveblock(fs); - check_match(ls, TK_END, TK_IN, line); - fs->envreg = oldenv; /* restore outer environment */ -} - - static void exprstat (LexState *ls) { /* stat -> func | assignment */ FuncState *fs = ls->fs; @@ -1386,10 +1363,6 @@ static int statement (LexState *ls) { check_match(ls, TK_END, TK_DO, line); return 0; } - case TK_IN: { - instat(ls, line); - return 0; - } case TK_FOR: { /* stat -> forstat */ forstat(ls, line); return 0; diff --git a/lparser.h b/lparser.h index d46265dc..2b6e273f 100644 --- a/lparser.h +++ b/lparser.h @@ -1,5 +1,5 @@ /* -** $Id: lparser.h,v 1.61 2009/10/11 20:02:19 roberto Exp roberto $ +** $Id: lparser.h,v 1.62 2010/02/26 20:40:29 roberto Exp roberto $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -25,7 +25,6 @@ typedef enum { VKNUM, /* nval = numerical value */ VLOCAL, /* info = local register */ VUPVAL, /* info = index of upvalue in 'upvalues' */ - VGLOBAL, /* info = index of global name in 'k' */ VINDEXED, /* info = table R/K; aux = index R/K */ VINDEXEDUP, /* info = table upvalue; aux = R/K */ VJMP, /* info = instruction pc */ @@ -81,7 +80,6 @@ typedef struct FuncState { short nlocvars; /* number of elements in `locvars' */ lu_byte nactvar; /* number of active local variables */ lu_byte nups; /* number of upvalues */ - lu_byte envreg; /* register holding current lexical environment */ } FuncState; diff --git a/lundump.c b/lundump.c index 753f9964..119ebdd5 100644 --- a/lundump.c +++ b/lundump.c @@ -1,5 +1,5 @@ /* -** $Id: lundump.c,v 2.11 2009/09/28 16:32:50 roberto Exp roberto $ +** $Id: lundump.c,v 2.12 2009/09/30 15:38:37 roberto Exp roberto $ ** load precompiled Lua chunks ** See Copyright Notice in lua.h */ @@ -180,7 +180,6 @@ static Proto* LoadFunction(LoadState* S, TString* p) f->numparams=LoadByte(S); f->is_vararg=LoadByte(S); f->maxstacksize=LoadByte(S); - f->envreg=LoadByte(S); LoadCode(S,f); LoadConstants(S,f); LoadUpvalues(S,f); diff --git a/lvm.c b/lvm.c index 26ad6dc4..3c0a8276 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.104 2010/02/26 20:40:29 roberto Exp roberto $ +** $Id: lvm.c,v 2.105 2010/02/27 21:16:24 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -355,14 +355,10 @@ void luaV_finishOp (lua_State *L) { StkId base = ci->u.l.base; Instruction inst = *(ci->u.l.savedpc - 1); /* interrupted instruction */ OpCode op = GET_OPCODE(inst); - if (op == OP_EXTRAARG) { /* extra argument? */ - inst = *(ci->u.l.savedpc - 2); /* get its 'main' instruction */ - op = GET_OPCODE(inst); - } switch (op) { /* finish its execution */ case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: case OP_MOD: case OP_POW: case OP_UNM: case OP_LEN: - case OP_GETGLOBAL: case OP_GETTABUP: case OP_GETTABLE: case OP_SELF: { + case OP_GETTABUP: case OP_GETTABLE: case OP_SELF: { setobjs2s(L, base + GETARG_A(inst), --L->top); break; } @@ -403,7 +399,7 @@ void luaV_finishOp (lua_State *L) { L->top = ci->top; /* adjust results */ break; } - case OP_TAILCALL: case OP_SETGLOBAL: case OP_SETTABUP: case OP_SETTABLE: + case OP_TAILCALL: case OP_SETTABUP: case OP_SETTABLE: break; default: lua_assert(0); } @@ -501,14 +497,6 @@ void luaV_execute (lua_State *L) { setobj2s(L, ra, cl->upvals[b]->v); break; } - case OP_GETGLOBAL: { - TValue g; - TValue *rb = KBx(i); - sethvalue(L, &g, cl->env); - lua_assert(ttisstring(rb)); - Protect(luaV_gettable(L, &g, rb, ra)); - break; - } case OP_GETTABUP: { int b = GETARG_B(i); Protect(luaV_gettable(L, cl->upvals[b]->v, RKC(i), ra)); @@ -518,14 +506,6 @@ void luaV_execute (lua_State *L) { Protect(luaV_gettable(L, RB(i), RKC(i), ra)); break; } - case OP_SETGLOBAL: { - TValue g; - TValue *rb = KBx(i); - sethvalue(L, &g, cl->env); - lua_assert(ttisstring(rb)); - Protect(luaV_settable(L, &g, rb, ra)); - break; - } case OP_SETTABUP: { int a = GETARG_A(i); Protect(luaV_settable(L, cl->upvals[a]->v, RKB(i), RKC(i))); @@ -796,14 +776,6 @@ void luaV_execute (lua_State *L) { int j; ncl->l.p = p; setclvalue(L, ra, ncl); /* anchor new closure in stack */ - if (p->envreg != NO_REG) { /* lexical environment? */ - StkId env = base + p->envreg; - if (!ttistable(env)) - luaG_runerror(L, "environment is not a table: " - "cannot create closure"); - else - ncl->l.env = hvalue(env); - } for (j = 0; j < nup; j++) { /* fill in upvalues */ if (uv[j].instack) /* upvalue refers to local variable? */ ncl->l.upvals[j] = luaF_findupval(L, base + uv[j].idx);