diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-11-07 14:42:05 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-11-07 14:42:05 -0200 |
commit | 7f6f70853c8a2730fca2e95d5968ad52cf470bda (patch) | |
tree | 948147a9cf6a5c5eb34232e7547c310eb06eadea /lparser.c | |
parent | b8fed93215a23a3f443c5b0126f0de1725771b44 (diff) | |
download | lua-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.c | 25 |
1 files changed, 14 insertions, 11 deletions
@@ -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 | */ | ||
168 | static void new_localvar (LexState *ls, TString *name) { | 171 | static 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 | |||
180 | static 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 | ||
188 | static LocVar *getlocvar (FuncState *fs, int i) { | 186 | static 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 | */ | ||
195 | static void adjustlocalvars (LexState *ls, int nvars) { | 196 | static 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 | ||