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 | |
| parent | 5938212748636d21d6f4b372481ab3b6dd6c7538 (diff) | |
| download | lua-0ac3d07ea64ce4bcb8b935fb80fbb2b72d6b8f43.tar.gz lua-0ac3d07ea64ce4bcb8b935fb80fbb2b72d6b8f43.tar.bz2 lua-0ac3d07ea64ce4bcb8b935fb80fbb2b72d6b8f43.zip | |
first implementation of lexical environments
| -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); |
