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 | |
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)
-rw-r--r-- | lopcodes.c | 6 | ||||
-rw-r--r-- | lopcodes.h | 6 | ||||
-rw-r--r-- | lparser.c | 51 | ||||
-rw-r--r-- | lvm.c | 28 |
4 files changed, 73 insertions, 18 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lopcodes.c,v 1.72 2017/12/04 17:41:30 roberto Exp roberto $ | 2 | ** $Id: lopcodes.c,v 1.73 2017/12/13 18:32:09 roberto Exp roberto $ |
3 | ** Opcodes for Lua virtual machine | 3 | ** Opcodes for Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -82,6 +82,8 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = { | |||
82 | "RETURN", | 82 | "RETURN", |
83 | "RETURN0", | 83 | "RETURN0", |
84 | "RETURN1", | 84 | "RETURN1", |
85 | "FORLOOP1", | ||
86 | "FORPREP1", | ||
85 | "FORLOOP", | 87 | "FORLOOP", |
86 | "FORPREP", | 88 | "FORPREP", |
87 | "TFORCALL", | 89 | "TFORCALL", |
@@ -160,6 +162,8 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { | |||
160 | ,opmode(0, 0, iABC) /* OP_RETURN */ | 162 | ,opmode(0, 0, iABC) /* OP_RETURN */ |
161 | ,opmode(0, 0, iABC) /* OP_RETURN0 */ | 163 | ,opmode(0, 0, iABC) /* OP_RETURN0 */ |
162 | ,opmode(0, 0, iABC) /* OP_RETURN1 */ | 164 | ,opmode(0, 0, iABC) /* OP_RETURN1 */ |
165 | ,opmode(0, 1, iABx) /* OP_FORLOOP1 */ | ||
166 | ,opmode(0, 1, iABx) /* OP_FORPREP1 */ | ||
163 | ,opmode(0, 1, iABx) /* OP_FORLOOP */ | 167 | ,opmode(0, 1, iABx) /* OP_FORLOOP */ |
164 | ,opmode(0, 1, iABx) /* OP_FORPREP */ | 168 | ,opmode(0, 1, iABx) /* OP_FORPREP */ |
165 | ,opmode(0, 0, iABC) /* OP_TFORCALL */ | 169 | ,opmode(0, 0, iABC) /* OP_TFORCALL */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lopcodes.h,v 1.178 2017/12/15 18:35:22 roberto Exp roberto $ | 2 | ** $Id: lopcodes.h,v 1.179 2017/12/15 18:53:48 roberto Exp roberto $ |
3 | ** Opcodes for Lua virtual machine | 3 | ** Opcodes for Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -267,6 +267,10 @@ OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ | |||
267 | OP_RETURN0,/* return */ | 267 | OP_RETURN0,/* return */ |
268 | OP_RETURN1,/* A return R(A) */ | 268 | OP_RETURN1,/* A return R(A) */ |
269 | 269 | ||
270 | OP_FORLOOP1,/* A Bx R(A)++; | ||
271 | if R(A) <= R(A+1) then { pc-=Bx; R(A+3)=R(A) } */ | ||
272 | OP_FORPREP1,/* A Bx R(A)--; pc+=Bx */ | ||
273 | |||
270 | OP_FORLOOP,/* A Bx R(A)+=R(A+2); | 274 | OP_FORLOOP,/* A Bx R(A)+=R(A+2); |
271 | if R(A) <?= R(A+1) then { pc-=Bx; R(A+3)=R(A) } */ | 275 | if R(A) <?= R(A+1) then { pc-=Bx; R(A+3)=R(A) } */ |
272 | OP_FORPREP,/* A Bx R(A)-=R(A+2); pc+=Bx */ | 276 | OP_FORPREP,/* A Bx R(A)-=R(A+2); pc+=Bx */ |
@@ -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 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 2.324 2017/12/04 17:41:30 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.326 2017/12/18 17:49:31 roberto Exp $ |
3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -1564,6 +1564,32 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1564 | } | 1564 | } |
1565 | return; | 1565 | return; |
1566 | } | 1566 | } |
1567 | vmcase(OP_FORLOOP1) { | ||
1568 | lua_Integer idx = intop(+, ivalue(vra), 1); /* increment index */ | ||
1569 | lua_Integer limit = ivalue(s2v(ra + 1)); | ||
1570 | if (idx <= limit) { | ||
1571 | pc -= GETARG_Bx(i); /* jump back */ | ||
1572 | chgivalue(vra, idx); /* update internal index... */ | ||
1573 | setivalue(s2v(ra + 3), idx); /* ...and external index */ | ||
1574 | } | ||
1575 | updatetrap(ci); | ||
1576 | vmbreak; | ||
1577 | } | ||
1578 | vmcase(OP_FORPREP1) { | ||
1579 | TValue *init = vra; | ||
1580 | TValue *plimit = s2v(ra + 1); | ||
1581 | lua_Integer ilimit, initv; | ||
1582 | int stopnow; | ||
1583 | if (!forlimit(plimit, &ilimit, 1, &stopnow)) { | ||
1584 | savepc(L); /* for the error message */ | ||
1585 | luaG_runerror(L, "'for' limit must be a number"); | ||
1586 | } | ||
1587 | initv = (stopnow ? 0 : ivalue(init)); | ||
1588 | setivalue(plimit, ilimit); | ||
1589 | setivalue(init, intop(-, initv, 1)); | ||
1590 | pc += GETARG_Bx(i); | ||
1591 | vmbreak; | ||
1592 | } | ||
1567 | vmcase(OP_FORLOOP) { | 1593 | vmcase(OP_FORLOOP) { |
1568 | if (ttisinteger(vra)) { /* integer loop? */ | 1594 | if (ttisinteger(vra)) { /* integer loop? */ |
1569 | lua_Integer step = ivalue(s2v(ra + 2)); | 1595 | lua_Integer step = ivalue(s2v(ra + 2)); |