diff options
Diffstat (limited to 'lparser.c')
-rw-r--r-- | lparser.c | 62 |
1 files changed, 47 insertions, 15 deletions
@@ -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; |