From d388c165ef79cb9c668e28fa92242ffbc0430e54 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Mon, 18 Dec 2017 15:53:50 -0200 Subject: new opcodes 'FORLOOP1'/'FORPREP1' for "basic for" (integer variable with increment of 1) --- lparser.c | 51 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 15 deletions(-) (limited to 'lparser.c') diff --git a/lparser.c b/lparser.c index 8f25eec3..6317a788 100644 --- a/lparser.c +++ b/lparser.c @@ -1,5 +1,5 @@ /* -** $Id: lparser.c,v 2.172 2017/12/15 13:07:10 roberto Exp roberto $ +** $Id: lparser.c,v 2.173 2017/12/18 12:33:54 roberto Exp roberto $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -1313,11 +1313,20 @@ static void repeatstat (LexState *ls, int line) { } -static void exp1 (LexState *ls) { +/* +** Read an expression and generate code to put its results in next +** stack slot. Return true if expression is a constant integer and, +** if 'i' is not-zero, its value is equal to 'i'. +** +*/ +static int exp1 (LexState *ls, int i) { expdesc e; + int res; expr(ls, &e); + res = luaK_isKint(&e) && (i == 0 || i == e.u.ival); luaK_exp2nextreg(ls->fs, &e); lua_assert(e.k == VNONRELOC); + return res; } @@ -1337,29 +1346,37 @@ static void fixforjump (FuncState *fs, int pc, int dest, int back) { } -static void forbody (LexState *ls, int base, int line, int nvars, int isnum) { +/* +** Generate code for a 'for' loop. 'kind' can be zero (a common for +** loop), one (a basic for loop, with integer values and increment of +** 1), or two (a generic for loop). +*/ +static void forbody (LexState *ls, int base, int line, int nvars, int kind) { /* forbody -> DO block */ BlockCnt bl; FuncState *fs = ls->fs; int prep, endfor; adjustlocalvars(ls, 3); /* control variables */ checknext(ls, TK_DO); - prep = isnum ? luaK_codeABx(fs, OP_FORPREP, base, 0) : luaK_jump(fs); + prep = (kind == 0) ? luaK_codeABx(fs, OP_FORPREP, base, 0) + : (kind == 1) ? luaK_codeABx(fs, OP_FORPREP1, base, 0) + : luaK_jump(fs); enterblock(fs, &bl, 0); /* scope for declared variables */ adjustlocalvars(ls, nvars); luaK_reserveregs(fs, nvars); block(ls); leaveblock(fs); /* end of scope for declared variables */ - if (isnum) { /* numeric for? */ - fixforjump(fs, prep, luaK_getlabel(fs), 0); - endfor = luaK_codeABx(fs, OP_FORLOOP, base, 0); - } - else { /* generic for */ + if (kind == 2) { /* generic for? */ luaK_patchtohere(fs, prep); luaK_codeABC(fs, OP_TFORCALL, base, 0, nvars); luaK_fixline(fs, line); endfor = luaK_codeABx(fs, OP_TFORLOOP, base + 2, 0); } + else { + fixforjump(fs, prep, luaK_getlabel(fs), 0); + endfor = (kind == 0) ? luaK_codeABx(fs, OP_FORLOOP, base, 0) + : luaK_codeABx(fs, OP_FORLOOP1, base, 0); + } fixforjump(fs, endfor, prep + 1, 1); luaK_fixline(fs, line); } @@ -1369,21 +1386,25 @@ static void fornum (LexState *ls, TString *varname, int line) { /* fornum -> NAME = exp,exp[,exp] forbody */ FuncState *fs = ls->fs; int base = fs->freereg; + int basicfor = 1; /* true if it is a "basic" 'for' (integer + 1) */ new_localvarliteral(ls, "(for index)"); new_localvarliteral(ls, "(for limit)"); new_localvarliteral(ls, "(for step)"); new_localvar(ls, varname); checknext(ls, '='); - exp1(ls); /* initial value */ + if (!exp1(ls, 0)) /* initial value not an integer? */ + basicfor = 0; /* not a basic 'for' */ checknext(ls, ','); - exp1(ls); /* limit */ - if (testnext(ls, ',')) - exp1(ls); /* optional step */ + exp1(ls, 0); /* limit */ + if (testnext(ls, ',')) { + if (!exp1(ls, 1)) /* optional step not 1? */ + basicfor = 0; /* not a basic 'for' */ + } else { /* default step = 1 */ luaK_int(fs, fs->freereg, 1); luaK_reserveregs(fs, 1); } - forbody(ls, base, line, 1, 1); + forbody(ls, base, line, 1, basicfor); } @@ -1408,7 +1429,7 @@ static void forlist (LexState *ls, TString *indexname) { line = ls->linenumber; adjust_assign(ls, 3, explist(ls, &e), &e); luaK_checkstack(fs, 3); /* extra space to call generator */ - forbody(ls, base, line, nvars - 3, 0); + forbody(ls, base, line, nvars - 3, 2); } -- cgit v1.2.3-55-g6feb