diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2009-09-30 12:38:37 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2009-09-30 12:38:37 -0300 |
| commit | 0ac3d07ea64ce4bcb8b935fb80fbb2b72d6b8f43 (patch) | |
| tree | 2463af169272845741337a44f03afd476a600609 /lparser.c | |
| parent | 5938212748636d21d6f4b372481ab3b6dd6c7538 (diff) | |
| download | lua-0ac3d07ea64ce4bcb8b935fb80fbb2b72d6b8f43.tar.gz lua-0ac3d07ea64ce4bcb8b935fb80fbb2b72d6b8f43.tar.bz2 lua-0ac3d07ea64ce4bcb8b935fb80fbb2b72d6b8f43.zip | |
first implementation of lexical environments
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; |
