diff options
-rw-r--r-- | ldump.c | 3 | ||||
-rw-r--r-- | lfunc.c | 4 | ||||
-rw-r--r-- | lobject.h | 3 | ||||
-rw-r--r-- | lparser.c | 62 | ||||
-rw-r--r-- | lparser.h | 5 | ||||
-rw-r--r-- | lundump.c | 3 | ||||
-rw-r--r-- | lvm.c | 10 |
7 files changed, 68 insertions, 22 deletions
@@ -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); |
@@ -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 | ||
@@ -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 | ||
@@ -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 | ||
229 | static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { | 229 | static 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) { | |||
253 | static void singlevar (LexState *ls, expdesc *var) { | 251 | static 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 | ||
316 | static void pushclosure (LexState *ls, FuncState *func, expdesc *v) { | 322 | static 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 | ||
1036 | static int exp1 (LexState *ls) { | 1045 | static 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 | ||
1239 | static 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 | |||
1229 | static void exprstat (LexState *ls) { | 1257 | static 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; |
@@ -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 | ||
@@ -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); |
@@ -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); |