summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ldump.c3
-rw-r--r--lfunc.c4
-rw-r--r--lobject.h3
-rw-r--r--lparser.c62
-rw-r--r--lparser.h5
-rw-r--r--lundump.c3
-rw-r--r--lvm.c10
7 files changed, 68 insertions, 22 deletions
diff --git a/ldump.c b/ldump.c
index e8337f03..e59c4224 100644
--- a/ldump.c
+++ b/ldump.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldump.c,v 2.10 2008/07/03 14:25:05 roberto Exp roberto $ 2** $Id: ldump.c,v 2.11 2009/09/28 16:32:50 roberto Exp roberto $
3** save precompiled Lua chunks 3** save precompiled Lua chunks
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -145,6 +145,7 @@ static void DumpFunction(const Proto* f, const TString* p, DumpState* D)
145 DumpChar(f->numparams,D); 145 DumpChar(f->numparams,D);
146 DumpChar(f->is_vararg,D); 146 DumpChar(f->is_vararg,D);
147 DumpChar(f->maxstacksize,D); 147 DumpChar(f->maxstacksize,D);
148 DumpChar(f->envreg,D);
148 DumpCode(f,D); 149 DumpCode(f,D);
149 DumpConstants(f,D); 150 DumpConstants(f,D);
150 DumpUpvalues(f,D); 151 DumpUpvalues(f,D);
diff --git a/lfunc.c b/lfunc.c
index c6c63f2e..bca286ad 100644
--- a/lfunc.c
+++ b/lfunc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lfunc.c,v 2.14 2009/04/17 14:40:13 roberto Exp roberto $ 2** $Id: lfunc.c,v 2.15 2009/09/28 16:32:50 roberto Exp roberto $
3** Auxiliary functions to manipulate prototypes and closures 3** Auxiliary functions to manipulate prototypes and closures
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -16,6 +16,7 @@
16#include "lgc.h" 16#include "lgc.h"
17#include "lmem.h" 17#include "lmem.h"
18#include "lobject.h" 18#include "lobject.h"
19#include "lopcodes.h"
19#include "lstate.h" 20#include "lstate.h"
20 21
21 22
@@ -133,6 +134,7 @@ Proto *luaF_newproto (lua_State *L) {
133 f->linedefined = 0; 134 f->linedefined = 0;
134 f->lastlinedefined = 0; 135 f->lastlinedefined = 0;
135 f->source = NULL; 136 f->source = NULL;
137 f->envreg = NO_REG;
136 return f; 138 return f;
137} 139}
138 140
diff --git a/lobject.h b/lobject.h
index 8b93f70a..581a25a0 100644
--- a/lobject.h
+++ b/lobject.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lobject.h,v 2.28 2009/07/15 18:37:19 roberto Exp roberto $ 2** $Id: lobject.h,v 2.29 2009/09/28 16:32:50 roberto Exp roberto $
3** Type definitions for Lua objects 3** Type definitions for Lua objects
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -261,6 +261,7 @@ typedef struct Proto {
261 lu_byte numparams; 261 lu_byte numparams;
262 lu_byte is_vararg; 262 lu_byte is_vararg;
263 lu_byte maxstacksize; 263 lu_byte maxstacksize;
264 lu_byte envreg; /* register in outer function with initial environment */
264} Proto; 265} Proto;
265 266
266 267
diff --git a/lparser.c b/lparser.c
index 935526ce..1ab1cc69 100644
--- a/lparser.c
+++ b/lparser.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lparser.c,v 2.66 2009/09/23 20:14:00 roberto Exp roberto $ 2** $Id: lparser.c,v 2.67 2009/09/28 16:32:50 roberto Exp roberto $
3** Lua Parser 3** Lua Parser
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -227,10 +227,8 @@ static void markupval (FuncState *fs, int level) {
227 227
228 228
229static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { 229static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
230 if (fs == NULL) { /* no more levels? */ 230 if (fs == NULL) /* no more levels? */
231 init_exp(var, VGLOBAL, NO_REG); /* default is global variable */ 231 return VGLOBAL; /* default is global variable */
232 return VGLOBAL;
233 }
234 else { 232 else {
235 int v = searchvar(fs, n); /* look up at current level */ 233 int v = searchvar(fs, n); /* look up at current level */
236 if (v >= 0) { 234 if (v >= 0) {
@@ -253,8 +251,16 @@ static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
253static void singlevar (LexState *ls, expdesc *var) { 251static void singlevar (LexState *ls, expdesc *var) {
254 TString *varname = str_checkname(ls); 252 TString *varname = str_checkname(ls);
255 FuncState *fs = ls->fs; 253 FuncState *fs = ls->fs;
256 if (singlevaraux(fs, varname, var, 1) == VGLOBAL) 254 if (singlevaraux(fs, varname, var, 1) == VGLOBAL) {
257 var->u.s.info = luaK_stringK(fs, varname); /* info points to global name */ 255 if (fs->envreg == NO_REG) /* regular global? */
256 init_exp(var, VGLOBAL, luaK_stringK(fs, varname));
257 else { /* "globals" are in current lexical environment */
258 expdesc key;
259 init_exp(var, VLOCAL, fs->envreg); /* current environment */
260 codestring(ls, &key, varname); /* key is variable name */
261 luaK_indexed(fs, var, &key); /* env[varname] */
262 }
263 }
258} 264}
259 265
260 266
@@ -313,15 +319,17 @@ static void leaveblock (FuncState *fs) {
313} 319}
314 320
315 321
316static void pushclosure (LexState *ls, FuncState *func, expdesc *v) { 322static void pushclosure (LexState *ls, Proto *clp, expdesc *v) {
317 FuncState *fs = ls->fs->prev; 323 FuncState *fs = ls->fs->prev;
318 Proto *f = fs->f; 324 Proto *f = fs->f; /* prototype of function creating new closure */
319 int oldsize = f->sizep; 325 int oldsize = f->sizep;
320 luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *, 326 luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *,
321 MAXARG_Bx, "functions"); 327 MAXARG_Bx, "functions");
322 while (oldsize < f->sizep) f->p[oldsize++] = NULL; 328 while (oldsize < f->sizep) f->p[oldsize++] = NULL;
323 f->p[fs->np++] = func->f; 329 f->p[fs->np++] = clp;
324 luaC_objbarrier(ls->L, f, func->f); 330 /* initial environment for new function is current lexical environment */
331 clp->envreg = fs->envreg;
332 luaC_objbarrier(ls->L, f, clp);
325 init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1)); 333 init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1));
326} 334}
327 335
@@ -342,6 +350,7 @@ static void open_func (LexState *ls, FuncState *fs) {
342 fs->nups = 0; 350 fs->nups = 0;
343 fs->nlocvars = 0; 351 fs->nlocvars = 0;
344 fs->nactvar = 0; 352 fs->nactvar = 0;
353 fs->envreg = NO_REG;
345 fs->bl = NULL; 354 fs->bl = NULL;
346 fs->h = luaH_new(L); 355 fs->h = luaH_new(L);
347 /* anchor table of constants (to avoid being collected) */ 356 /* anchor table of constants (to avoid being collected) */
@@ -589,7 +598,7 @@ static void body (LexState *ls, expdesc *e, int needself, int line) {
589 chunk(ls); 598 chunk(ls);
590 new_fs.f->lastlinedefined = ls->linenumber; 599 new_fs.f->lastlinedefined = ls->linenumber;
591 check_match(ls, TK_END, TK_FUNCTION, line); 600 check_match(ls, TK_END, TK_FUNCTION, line);
592 pushclosure(ls, &new_fs, e); 601 pushclosure(ls, new_fs.f, e);
593 close_func(ls); 602 close_func(ls);
594} 603}
595 604
@@ -1035,11 +1044,12 @@ static void repeatstat (LexState *ls, int line) {
1035 1044
1036static int exp1 (LexState *ls) { 1045static int exp1 (LexState *ls) {
1037 expdesc e; 1046 expdesc e;
1038 int k; 1047 int reg;
1039 expr(ls, &e); 1048 expr(ls, &e);
1040 k = e.k;
1041 luaK_exp2nextreg(ls->fs, &e); 1049 luaK_exp2nextreg(ls->fs, &e);
1042 return k; 1050 lua_assert(e.k == VNONRELOC);
1051 reg = e.u.s.info;
1052 return reg;
1043} 1053}
1044 1054
1045 1055
@@ -1226,6 +1236,24 @@ static void funcstat (LexState *ls, int line) {
1226} 1236}
1227 1237
1228 1238
1239static void instat (LexState *ls, int line) {
1240 /* instat -> IN exp DO block END */
1241 FuncState *fs = ls->fs;
1242 int oldenv = fs->envreg; /* save current environment */
1243 BlockCnt bl;
1244 luaX_next(ls); /* skip IN */
1245 enterblock(fs, &bl, 0); /* scope for environment variable */
1246 new_localvarliteral(ls, "(environment)", 0);
1247 fs->envreg = exp1(ls); /* new environment */
1248 adjustlocalvars(ls, 1);
1249 checknext(ls, TK_DO);
1250 block(ls);
1251 leaveblock(fs);
1252 check_match(ls, TK_END, TK_IN, line);
1253 fs->envreg = oldenv; /* restore outer environment */
1254}
1255
1256
1229static void exprstat (LexState *ls) { 1257static void exprstat (LexState *ls) {
1230 /* stat -> func | assignment */ 1258 /* stat -> func | assignment */
1231 FuncState *fs = ls->fs; 1259 FuncState *fs = ls->fs;
@@ -1290,6 +1318,10 @@ static int statement (LexState *ls) {
1290 check_match(ls, TK_END, TK_DO, line); 1318 check_match(ls, TK_END, TK_DO, line);
1291 return 0; 1319 return 0;
1292 } 1320 }
1321 case TK_IN: {
1322 instat(ls, line);
1323 return 0;
1324 }
1293 case TK_FOR: { /* stat -> forstat */ 1325 case TK_FOR: { /* stat -> forstat */
1294 forstat(ls, line); 1326 forstat(ls, line);
1295 return 0; 1327 return 0;
diff --git a/lparser.h b/lparser.h
index 5e1856e2..850b787d 100644
--- a/lparser.h
+++ b/lparser.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lparser.h,v 1.58 2008/05/08 15:44:51 roberto Exp roberto $ 2** $Id: lparser.h,v 1.59 2009/09/28 16:32:50 roberto Exp roberto $
3** Lua Parser 3** Lua Parser
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -71,7 +71,8 @@ typedef struct FuncState {
71 short nlocvars; /* number of elements in `locvars' */ 71 short nlocvars; /* number of elements in `locvars' */
72 lu_byte nactvar; /* number of active local variables */ 72 lu_byte nactvar; /* number of active local variables */
73 lu_byte nups; /* number of upvalues */ 73 lu_byte nups; /* number of upvalues */
74 vardesc actvar[LUAI_MAXVARS]; /* declared-variable stack */ 74 lu_byte envreg; /* register holding current lexical environment */
75 vardesc actvar[LUAI_MAXVARS]; /* stack of active variables */
75} FuncState; 76} FuncState;
76 77
77 78
diff --git a/lundump.c b/lundump.c
index 4ee11ac6..753f9964 100644
--- a/lundump.c
+++ b/lundump.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lundump.c,v 2.10 2009/04/30 17:42:21 roberto Exp roberto $ 2** $Id: lundump.c,v 2.11 2009/09/28 16:32:50 roberto Exp roberto $
3** load precompiled Lua chunks 3** load precompiled Lua chunks
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -180,6 +180,7 @@ static Proto* LoadFunction(LoadState* S, TString* p)
180 f->numparams=LoadByte(S); 180 f->numparams=LoadByte(S);
181 f->is_vararg=LoadByte(S); 181 f->is_vararg=LoadByte(S);
182 f->maxstacksize=LoadByte(S); 182 f->maxstacksize=LoadByte(S);
183 f->envreg=LoadByte(S);
183 LoadCode(S,f); 184 LoadCode(S,f);
184 LoadConstants(S,f); 185 LoadConstants(S,f);
185 LoadUpvalues(S,f); 186 LoadUpvalues(S,f);
diff --git a/lvm.c b/lvm.c
index 7473d73b..004e112c 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lvm.c,v 2.97 2009/09/23 20:33:05 roberto Exp roberto $ 2** $Id: lvm.c,v 2.98 2009/09/28 16:32:50 roberto Exp roberto $
3** Lua virtual machine 3** Lua virtual machine
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -780,6 +780,14 @@ void luaV_execute (lua_State *L) {
780 int j; 780 int j;
781 ncl->l.p = p; 781 ncl->l.p = p;
782 setclvalue(L, ra, ncl); /* anchor new closure in stack */ 782 setclvalue(L, ra, ncl); /* anchor new closure in stack */
783 if (p->envreg != NO_REG) { /* lexical environment? */
784 StkId env = base + p->envreg;
785 if (!ttistable(env))
786 luaG_runerror(L, "environment is not a table: "
787 "cannot create closure");
788 else
789 ncl->l.env = hvalue(env);
790 }
783 for (j = 0; j < nup; j++) { /* fill in upvalues */ 791 for (j = 0; j < nup; j++) { /* fill in upvalues */
784 if (uv[j].instack) /* upvalue refers to local variable? */ 792 if (uv[j].instack) /* upvalue refers to local variable? */
785 ncl->l.upvals[j] = luaF_findupval(L, base + uv[j].idx); 793 ncl->l.upvals[j] = luaF_findupval(L, base + uv[j].idx);