diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-12-18 15:53:50 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-12-18 15:53:50 -0200 |
commit | d388c165ef79cb9c668e28fa92242ffbc0430e54 (patch) | |
tree | c10d2aee1d049d9c430ac9bebe810e9e733a8acb /lparser.c | |
parent | ab07005568a399f2e97996677472d9e6e69c9f4f (diff) | |
download | lua-d388c165ef79cb9c668e28fa92242ffbc0430e54.tar.gz lua-d388c165ef79cb9c668e28fa92242ffbc0430e54.tar.bz2 lua-d388c165ef79cb9c668e28fa92242ffbc0430e54.zip |
new opcodes 'FORLOOP1'/'FORPREP1' for "basic for" (integer variable
with increment of 1)
Diffstat (limited to 'lparser.c')
-rw-r--r-- | lparser.c | 51 |
1 files changed, 36 insertions, 15 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.c,v 2.172 2017/12/15 13:07:10 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 2.173 2017/12/18 12:33:54 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 | */ |
@@ -1313,11 +1313,20 @@ static void repeatstat (LexState *ls, int line) { | |||
1313 | } | 1313 | } |
1314 | 1314 | ||
1315 | 1315 | ||
1316 | static void exp1 (LexState *ls) { | 1316 | /* |
1317 | ** Read an expression and generate code to put its results in next | ||
1318 | ** stack slot. Return true if expression is a constant integer and, | ||
1319 | ** if 'i' is not-zero, its value is equal to 'i'. | ||
1320 | ** | ||
1321 | */ | ||
1322 | static int exp1 (LexState *ls, int i) { | ||
1317 | expdesc e; | 1323 | expdesc e; |
1324 | int res; | ||
1318 | expr(ls, &e); | 1325 | expr(ls, &e); |
1326 | res = luaK_isKint(&e) && (i == 0 || i == e.u.ival); | ||
1319 | luaK_exp2nextreg(ls->fs, &e); | 1327 | luaK_exp2nextreg(ls->fs, &e); |
1320 | lua_assert(e.k == VNONRELOC); | 1328 | lua_assert(e.k == VNONRELOC); |
1329 | return res; | ||
1321 | } | 1330 | } |
1322 | 1331 | ||
1323 | 1332 | ||
@@ -1337,29 +1346,37 @@ static void fixforjump (FuncState *fs, int pc, int dest, int back) { | |||
1337 | } | 1346 | } |
1338 | 1347 | ||
1339 | 1348 | ||
1340 | static void forbody (LexState *ls, int base, int line, int nvars, int isnum) { | 1349 | /* |
1350 | ** Generate code for a 'for' loop. 'kind' can be zero (a common for | ||
1351 | ** loop), one (a basic for loop, with integer values and increment of | ||
1352 | ** 1), or two (a generic for loop). | ||
1353 | */ | ||
1354 | static void forbody (LexState *ls, int base, int line, int nvars, int kind) { | ||
1341 | /* forbody -> DO block */ | 1355 | /* forbody -> DO block */ |
1342 | BlockCnt bl; | 1356 | BlockCnt bl; |
1343 | FuncState *fs = ls->fs; | 1357 | FuncState *fs = ls->fs; |
1344 | int prep, endfor; | 1358 | int prep, endfor; |
1345 | adjustlocalvars(ls, 3); /* control variables */ | 1359 | adjustlocalvars(ls, 3); /* control variables */ |
1346 | checknext(ls, TK_DO); | 1360 | checknext(ls, TK_DO); |
1347 | prep = isnum ? luaK_codeABx(fs, OP_FORPREP, base, 0) : luaK_jump(fs); | 1361 | prep = (kind == 0) ? luaK_codeABx(fs, OP_FORPREP, base, 0) |
1362 | : (kind == 1) ? luaK_codeABx(fs, OP_FORPREP1, base, 0) | ||
1363 | : luaK_jump(fs); | ||
1348 | enterblock(fs, &bl, 0); /* scope for declared variables */ | 1364 | enterblock(fs, &bl, 0); /* scope for declared variables */ |
1349 | adjustlocalvars(ls, nvars); | 1365 | adjustlocalvars(ls, nvars); |
1350 | luaK_reserveregs(fs, nvars); | 1366 | luaK_reserveregs(fs, nvars); |
1351 | block(ls); | 1367 | block(ls); |
1352 | leaveblock(fs); /* end of scope for declared variables */ | 1368 | leaveblock(fs); /* end of scope for declared variables */ |
1353 | if (isnum) { /* numeric for? */ | 1369 | if (kind == 2) { /* generic for? */ |
1354 | fixforjump(fs, prep, luaK_getlabel(fs), 0); | ||
1355 | endfor = luaK_codeABx(fs, OP_FORLOOP, base, 0); | ||
1356 | } | ||
1357 | else { /* generic for */ | ||
1358 | luaK_patchtohere(fs, prep); | 1370 | luaK_patchtohere(fs, prep); |
1359 | luaK_codeABC(fs, OP_TFORCALL, base, 0, nvars); | 1371 | luaK_codeABC(fs, OP_TFORCALL, base, 0, nvars); |
1360 | luaK_fixline(fs, line); | 1372 | luaK_fixline(fs, line); |
1361 | endfor = luaK_codeABx(fs, OP_TFORLOOP, base + 2, 0); | 1373 | endfor = luaK_codeABx(fs, OP_TFORLOOP, base + 2, 0); |
1362 | } | 1374 | } |
1375 | else { | ||
1376 | fixforjump(fs, prep, luaK_getlabel(fs), 0); | ||
1377 | endfor = (kind == 0) ? luaK_codeABx(fs, OP_FORLOOP, base, 0) | ||
1378 | : luaK_codeABx(fs, OP_FORLOOP1, base, 0); | ||
1379 | } | ||
1363 | fixforjump(fs, endfor, prep + 1, 1); | 1380 | fixforjump(fs, endfor, prep + 1, 1); |
1364 | luaK_fixline(fs, line); | 1381 | luaK_fixline(fs, line); |
1365 | } | 1382 | } |
@@ -1369,21 +1386,25 @@ static void fornum (LexState *ls, TString *varname, int line) { | |||
1369 | /* fornum -> NAME = exp,exp[,exp] forbody */ | 1386 | /* fornum -> NAME = exp,exp[,exp] forbody */ |
1370 | FuncState *fs = ls->fs; | 1387 | FuncState *fs = ls->fs; |
1371 | int base = fs->freereg; | 1388 | int base = fs->freereg; |
1389 | int basicfor = 1; /* true if it is a "basic" 'for' (integer + 1) */ | ||
1372 | new_localvarliteral(ls, "(for index)"); | 1390 | new_localvarliteral(ls, "(for index)"); |
1373 | new_localvarliteral(ls, "(for limit)"); | 1391 | new_localvarliteral(ls, "(for limit)"); |
1374 | new_localvarliteral(ls, "(for step)"); | 1392 | new_localvarliteral(ls, "(for step)"); |
1375 | new_localvar(ls, varname); | 1393 | new_localvar(ls, varname); |
1376 | checknext(ls, '='); | 1394 | checknext(ls, '='); |
1377 | exp1(ls); /* initial value */ | 1395 | if (!exp1(ls, 0)) /* initial value not an integer? */ |
1396 | basicfor = 0; /* not a basic 'for' */ | ||
1378 | checknext(ls, ','); | 1397 | checknext(ls, ','); |
1379 | exp1(ls); /* limit */ | 1398 | exp1(ls, 0); /* limit */ |
1380 | if (testnext(ls, ',')) | 1399 | if (testnext(ls, ',')) { |
1381 | exp1(ls); /* optional step */ | 1400 | if (!exp1(ls, 1)) /* optional step not 1? */ |
1401 | basicfor = 0; /* not a basic 'for' */ | ||
1402 | } | ||
1382 | else { /* default step = 1 */ | 1403 | else { /* default step = 1 */ |
1383 | luaK_int(fs, fs->freereg, 1); | 1404 | luaK_int(fs, fs->freereg, 1); |
1384 | luaK_reserveregs(fs, 1); | 1405 | luaK_reserveregs(fs, 1); |
1385 | } | 1406 | } |
1386 | forbody(ls, base, line, 1, 1); | 1407 | forbody(ls, base, line, 1, basicfor); |
1387 | } | 1408 | } |
1388 | 1409 | ||
1389 | 1410 | ||
@@ -1408,7 +1429,7 @@ static void forlist (LexState *ls, TString *indexname) { | |||
1408 | line = ls->linenumber; | 1429 | line = ls->linenumber; |
1409 | adjust_assign(ls, 3, explist(ls, &e), &e); | 1430 | adjust_assign(ls, 3, explist(ls, &e), &e); |
1410 | luaK_checkstack(fs, 3); /* extra space to call generator */ | 1431 | luaK_checkstack(fs, 3); /* extra space to call generator */ |
1411 | forbody(ls, base, line, nvars - 3, 0); | 1432 | forbody(ls, base, line, nvars - 3, 2); |
1412 | } | 1433 | } |
1413 | 1434 | ||
1414 | 1435 | ||