11/*
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 $
33** Lua Parser
44** See Copyright Notice in lua.h
55*/
@@ -1313,11 +1313,20 @@ static void repeatstat (LexState *ls, int line) {
13131313}
13141314
13151315
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 ) {
13171323 expdesc e ;
1324+ int res ;
13181325 expr (ls , & e );
1326+ res = luaK_isKint (& e ) && (i == 0 || i == e .u .ival );
13191327 luaK_exp2nextreg (ls -> fs , & e );
13201328 lua_assert (e .k == VNONRELOC );
1329+ return res ;
13211330}
13221331
13231332
@@ -1337,29 +1346,37 @@ static void fixforjump (FuncState *fs, int pc, int dest, int back) {
13371346}
13381347
13391348
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 ) {
13411355 /* forbody -> DO block */
13421356 BlockCnt bl ;
13431357 FuncState * fs = ls -> fs ;
13441358 int prep , endfor ;
13451359 adjustlocalvars (ls , 3 ); /* control variables */
13461360 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 );
13481364 enterblock (fs , & bl , 0 ); /* scope for declared variables */
13491365 adjustlocalvars (ls , nvars );
13501366 luaK_reserveregs (fs , nvars );
13511367 block (ls );
13521368 leaveblock (fs ); /* end of scope for declared variables */
1353- if (isnum ) { /* numeric for? */
1354- fixforjump (fs , prep , luaK_getlabel (fs ), 0 );
1355- endfor = luaK_codeABx (fs , OP_FORLOOP , base , 0 );
1356- }
1357- else { /* generic for */
1369+ if (kind == 2 ) { /* generic for? */
13581370 luaK_patchtohere (fs , prep );
13591371 luaK_codeABC (fs , OP_TFORCALL , base , 0 , nvars );
13601372 luaK_fixline (fs , line );
13611373 endfor = luaK_codeABx (fs , OP_TFORLOOP , base + 2 , 0 );
13621374 }
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+ }
13631380 fixforjump (fs , endfor , prep + 1 , 1 );
13641381 luaK_fixline (fs , line );
13651382}
@@ -1369,21 +1386,25 @@ static void fornum (LexState *ls, TString *varname, int line) {
13691386 /* fornum -> NAME = exp,exp[,exp] forbody */
13701387 FuncState * fs = ls -> fs ;
13711388 int base = fs -> freereg ;
1389+ int basicfor = 1 ; /* true if it is a "basic" 'for' (integer + 1) */
13721390 new_localvarliteral (ls , "(for index)" );
13731391 new_localvarliteral (ls , "(for limit)" );
13741392 new_localvarliteral (ls , "(for step)" );
13751393 new_localvar (ls , varname );
13761394 checknext (ls , '=' );
1377- exp1 (ls ); /* initial value */
1395+ if (!exp1 (ls , 0 )) /* initial value not an integer? */
1396+ basicfor = 0 ; /* not a basic 'for' */
13781397 checknext (ls , ',' );
1379- exp1 (ls ); /* limit */
1380- if (testnext (ls , ',' ))
1381- exp1 (ls ); /* optional step */
1398+ exp1 (ls , 0 ); /* limit */
1399+ if (testnext (ls , ',' )) {
1400+ if (!exp1 (ls , 1 )) /* optional step not 1? */
1401+ basicfor = 0 ; /* not a basic 'for' */
1402+ }
13821403 else { /* default step = 1 */
13831404 luaK_int (fs , fs -> freereg , 1 );
13841405 luaK_reserveregs (fs , 1 );
13851406 }
1386- forbody (ls , base , line , 1 , 1 );
1407+ forbody (ls , base , line , 1 , basicfor );
13871408}
13881409
13891410
@@ -1408,7 +1429,7 @@ static void forlist (LexState *ls, TString *indexname) {
14081429 line = ls -> linenumber ;
14091430 adjust_assign (ls , 3 , explist (ls , & e ), & e );
14101431 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 );
14121433}
14131434
14141435
0 commit comments