aboutsummaryrefslogtreecommitdiff
path: root/lparser.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-11-07 14:42:05 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-11-07 14:42:05 -0200
commit7f6f70853c8a2730fca2e95d5968ad52cf470bda (patch)
tree948147a9cf6a5c5eb34232e7547c310eb06eadea /lparser.c
parentb8fed93215a23a3f443c5b0126f0de1725771b44 (diff)
downloadlua-7f6f70853c8a2730fca2e95d5968ad52cf470bda.tar.gz
lua-7f6f70853c8a2730fca2e95d5968ad52cf470bda.tar.bz2
lua-7f6f70853c8a2730fca2e95d5968ad52cf470bda.zip
To-be-closed variable in 'for' loop separated from the state
The variable to be closed in a generic 'for' loop now is the 4th value produced in the loop initialization, instead of being the loop state (the 2nd value produced). That allows a loop to use a state with a '__toclose' metamethod but do not close it. (As an example, 'f:lines()' might use the file 'f' as a state for the loop, but it should not close the file when the loop ends.)
Diffstat (limited to 'lparser.c')
-rw-r--r--lparser.c25
1 files changed, 14 insertions, 11 deletions
diff --git a/lparser.c b/lparser.c
index e4f11cb6..afc5aeab 100644
--- a/lparser.c
+++ b/lparser.c
@@ -165,6 +165,9 @@ static int registerlocalvar (LexState *ls, TString *varname) {
165} 165}
166 166
167 167
168/*
169** Create a new local variable with the given 'name'.
170*/
168static void new_localvar (LexState *ls, TString *name) { 171static void new_localvar (LexState *ls, TString *name) {
169 FuncState *fs = ls->fs; 172 FuncState *fs = ls->fs;
170 Dyndata *dyd = ls->dyd; 173 Dyndata *dyd = ls->dyd;
@@ -176,13 +179,8 @@ static void new_localvar (LexState *ls, TString *name) {
176 dyd->actvar.arr[dyd->actvar.n++].idx = cast(short, reg); 179 dyd->actvar.arr[dyd->actvar.n++].idx = cast(short, reg);
177} 180}
178 181
179
180static void new_localvarliteral_ (LexState *ls, const char *name, size_t sz) {
181 new_localvar(ls, luaX_newstring(ls, name, sz));
182}
183
184#define new_localvarliteral(ls,v) \ 182#define new_localvarliteral(ls,v) \
185 new_localvarliteral_(ls, "" v, (sizeof(v)/sizeof(char))-1) 183 new_localvar(ls, luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char)) - 1));
186 184
187 185
188static LocVar *getlocvar (FuncState *fs, int i) { 186static LocVar *getlocvar (FuncState *fs, int i) {
@@ -192,6 +190,9 @@ static LocVar *getlocvar (FuncState *fs, int i) {
192} 190}
193 191
194 192
193/*
194** Start the scope for the last 'nvars' created variables.
195*/
195static void adjustlocalvars (LexState *ls, int nvars) { 196static void adjustlocalvars (LexState *ls, int nvars) {
196 FuncState *fs = ls->fs; 197 FuncState *fs = ls->fs;
197 fs->nactvar = cast_byte(fs->nactvar + nvars); 198 fs->nactvar = cast_byte(fs->nactvar + nvars);
@@ -1357,7 +1358,6 @@ static void forbody (LexState *ls, int base, int line, int nvars, int kind) {
1357 BlockCnt bl; 1358 BlockCnt bl;
1358 FuncState *fs = ls->fs; 1359 FuncState *fs = ls->fs;
1359 int prep, endfor; 1360 int prep, endfor;
1360 adjustlocalvars(ls, 3); /* control variables */
1361 checknext(ls, TK_DO); 1361 checknext(ls, TK_DO);
1362 prep = luaK_codeABx(fs, forprep[kind], base, 0); 1362 prep = luaK_codeABx(fs, forprep[kind], base, 0);
1363 enterblock(fs, &bl, 0); /* scope for declared variables */ 1363 enterblock(fs, &bl, 0); /* scope for declared variables */
@@ -1399,6 +1399,7 @@ static void fornum (LexState *ls, TString *varname, int line) {
1399 luaK_int(fs, fs->freereg, 1); 1399 luaK_int(fs, fs->freereg, 1);
1400 luaK_reserveregs(fs, 1); 1400 luaK_reserveregs(fs, 1);
1401 } 1401 }
1402 adjustlocalvars(ls, 3); /* control variables */
1402 forbody(ls, base, line, 1, basicfor); 1403 forbody(ls, base, line, 1, basicfor);
1403} 1404}
1404 1405
@@ -1407,7 +1408,7 @@ static void forlist (LexState *ls, TString *indexname) {
1407 /* forlist -> NAME {,NAME} IN explist forbody */ 1408 /* forlist -> NAME {,NAME} IN explist forbody */
1408 FuncState *fs = ls->fs; 1409 FuncState *fs = ls->fs;
1409 expdesc e; 1410 expdesc e;
1410 int nvars = 4; /* gen, state, control, plus at least one declared var */ 1411 int nvars = 5; /* gen, state, control, toclose, 'indexname' */
1411 int line; 1412 int line;
1412 int base = fs->freereg; 1413 int base = fs->freereg;
1413 /* create control variables */ 1414 /* create control variables */
@@ -1415,6 +1416,7 @@ static void forlist (LexState *ls, TString *indexname) {
1415 new_localvarliteral(ls, "(for state)"); 1416 new_localvarliteral(ls, "(for state)");
1416 markupval(fs, fs->nactvar); /* state may create an upvalue */ 1417 markupval(fs, fs->nactvar); /* state may create an upvalue */
1417 new_localvarliteral(ls, "(for control)"); 1418 new_localvarliteral(ls, "(for control)");
1419 new_localvarliteral(ls, "(for toclose)");
1418 /* create declared variables */ 1420 /* create declared variables */
1419 new_localvar(ls, indexname); 1421 new_localvar(ls, indexname);
1420 while (testnext(ls, ',')) { 1422 while (testnext(ls, ',')) {
@@ -1423,9 +1425,10 @@ static void forlist (LexState *ls, TString *indexname) {
1423 } 1425 }
1424 checknext(ls, TK_IN); 1426 checknext(ls, TK_IN);
1425 line = ls->linenumber; 1427 line = ls->linenumber;
1426 adjust_assign(ls, 3, explist(ls, &e), &e); 1428 adjust_assign(ls, 4, explist(ls, &e), &e);
1429 adjustlocalvars(ls, 4); /* control variables */
1427 luaK_checkstack(fs, 3); /* extra space to call generator */ 1430 luaK_checkstack(fs, 3); /* extra space to call generator */
1428 forbody(ls, base, line, nvars - 3, 2); 1431 forbody(ls, base, line, nvars - 4, 2);
1429} 1432}
1430 1433
1431 1434
@@ -1575,9 +1578,9 @@ static void tocloselocalstat (LexState *ls) {
1575 new_localvar(ls, str_checkname(ls)); 1578 new_localvar(ls, str_checkname(ls));
1576 checknext(ls, '='); 1579 checknext(ls, '=');
1577 exp1(ls, 0); 1580 exp1(ls, 0);
1578 luaK_codeABC(fs, OP_TBC, fs->nactvar, 0, 0);
1579 markupval(fs, fs->nactvar); 1581 markupval(fs, fs->nactvar);
1580 adjustlocalvars(ls, 1); 1582 adjustlocalvars(ls, 1);
1583 luaK_codeABC(fs, OP_TBC, fs->nactvar - 1, 0, 0);
1581} 1584}
1582 1585
1583 1586