mirror of
https://github.com/lua/lua
synced 2024-11-22 21:01:26 +03:00
new opcodes 'FORLOOP1'/'FORPREP1' for "basic for" (integer variable
with increment of 1)
This commit is contained in:
parent
ab07005568
commit
d388c165ef
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lopcodes.c,v 1.72 2017/12/04 17:41:30 roberto Exp roberto $
|
** $Id: lopcodes.c,v 1.73 2017/12/13 18:32:09 roberto Exp roberto $
|
||||||
** Opcodes for Lua virtual machine
|
** Opcodes for Lua virtual machine
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@ -82,6 +82,8 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = {
|
|||||||
"RETURN",
|
"RETURN",
|
||||||
"RETURN0",
|
"RETURN0",
|
||||||
"RETURN1",
|
"RETURN1",
|
||||||
|
"FORLOOP1",
|
||||||
|
"FORPREP1",
|
||||||
"FORLOOP",
|
"FORLOOP",
|
||||||
"FORPREP",
|
"FORPREP",
|
||||||
"TFORCALL",
|
"TFORCALL",
|
||||||
@ -160,6 +162,8 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
|
|||||||
,opmode(0, 0, iABC) /* OP_RETURN */
|
,opmode(0, 0, iABC) /* OP_RETURN */
|
||||||
,opmode(0, 0, iABC) /* OP_RETURN0 */
|
,opmode(0, 0, iABC) /* OP_RETURN0 */
|
||||||
,opmode(0, 0, iABC) /* OP_RETURN1 */
|
,opmode(0, 0, iABC) /* OP_RETURN1 */
|
||||||
|
,opmode(0, 1, iABx) /* OP_FORLOOP1 */
|
||||||
|
,opmode(0, 1, iABx) /* OP_FORPREP1 */
|
||||||
,opmode(0, 1, iABx) /* OP_FORLOOP */
|
,opmode(0, 1, iABx) /* OP_FORLOOP */
|
||||||
,opmode(0, 1, iABx) /* OP_FORPREP */
|
,opmode(0, 1, iABx) /* OP_FORPREP */
|
||||||
,opmode(0, 0, iABC) /* OP_TFORCALL */
|
,opmode(0, 0, iABC) /* OP_TFORCALL */
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lopcodes.h,v 1.178 2017/12/15 18:35:22 roberto Exp roberto $
|
** $Id: lopcodes.h,v 1.179 2017/12/15 18:53:48 roberto Exp roberto $
|
||||||
** Opcodes for Lua virtual machine
|
** Opcodes for Lua virtual machine
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@ -267,6 +267,10 @@ OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */
|
|||||||
OP_RETURN0,/* return */
|
OP_RETURN0,/* return */
|
||||||
OP_RETURN1,/* A return R(A) */
|
OP_RETURN1,/* A return R(A) */
|
||||||
|
|
||||||
|
OP_FORLOOP1,/* A Bx R(A)++;
|
||||||
|
if R(A) <= R(A+1) then { pc-=Bx; R(A+3)=R(A) } */
|
||||||
|
OP_FORPREP1,/* A Bx R(A)--; pc+=Bx */
|
||||||
|
|
||||||
OP_FORLOOP,/* A Bx R(A)+=R(A+2);
|
OP_FORLOOP,/* A Bx R(A)+=R(A+2);
|
||||||
if R(A) <?= R(A+1) then { pc-=Bx; R(A+3)=R(A) } */
|
if R(A) <?= R(A+1) then { pc-=Bx; R(A+3)=R(A) } */
|
||||||
OP_FORPREP,/* A Bx R(A)-=R(A+2); pc+=Bx */
|
OP_FORPREP,/* A Bx R(A)-=R(A+2); pc+=Bx */
|
||||||
|
51
lparser.c
51
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
|
** Lua Parser
|
||||||
** See Copyright Notice in lua.h
|
** 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;
|
expdesc e;
|
||||||
|
int res;
|
||||||
expr(ls, &e);
|
expr(ls, &e);
|
||||||
|
res = luaK_isKint(&e) && (i == 0 || i == e.u.ival);
|
||||||
luaK_exp2nextreg(ls->fs, &e);
|
luaK_exp2nextreg(ls->fs, &e);
|
||||||
lua_assert(e.k == VNONRELOC);
|
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 */
|
/* forbody -> DO block */
|
||||||
BlockCnt bl;
|
BlockCnt bl;
|
||||||
FuncState *fs = ls->fs;
|
FuncState *fs = ls->fs;
|
||||||
int prep, endfor;
|
int prep, endfor;
|
||||||
adjustlocalvars(ls, 3); /* control variables */
|
adjustlocalvars(ls, 3); /* control variables */
|
||||||
checknext(ls, TK_DO);
|
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 */
|
enterblock(fs, &bl, 0); /* scope for declared variables */
|
||||||
adjustlocalvars(ls, nvars);
|
adjustlocalvars(ls, nvars);
|
||||||
luaK_reserveregs(fs, nvars);
|
luaK_reserveregs(fs, nvars);
|
||||||
block(ls);
|
block(ls);
|
||||||
leaveblock(fs); /* end of scope for declared variables */
|
leaveblock(fs); /* end of scope for declared variables */
|
||||||
if (isnum) { /* numeric for? */
|
if (kind == 2) { /* generic for? */
|
||||||
fixforjump(fs, prep, luaK_getlabel(fs), 0);
|
|
||||||
endfor = luaK_codeABx(fs, OP_FORLOOP, base, 0);
|
|
||||||
}
|
|
||||||
else { /* generic for */
|
|
||||||
luaK_patchtohere(fs, prep);
|
luaK_patchtohere(fs, prep);
|
||||||
luaK_codeABC(fs, OP_TFORCALL, base, 0, nvars);
|
luaK_codeABC(fs, OP_TFORCALL, base, 0, nvars);
|
||||||
luaK_fixline(fs, line);
|
luaK_fixline(fs, line);
|
||||||
endfor = luaK_codeABx(fs, OP_TFORLOOP, base + 2, 0);
|
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);
|
fixforjump(fs, endfor, prep + 1, 1);
|
||||||
luaK_fixline(fs, line);
|
luaK_fixline(fs, line);
|
||||||
}
|
}
|
||||||
@ -1369,21 +1386,25 @@ static void fornum (LexState *ls, TString *varname, int line) {
|
|||||||
/* fornum -> NAME = exp,exp[,exp] forbody */
|
/* fornum -> NAME = exp,exp[,exp] forbody */
|
||||||
FuncState *fs = ls->fs;
|
FuncState *fs = ls->fs;
|
||||||
int base = fs->freereg;
|
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 index)");
|
||||||
new_localvarliteral(ls, "(for limit)");
|
new_localvarliteral(ls, "(for limit)");
|
||||||
new_localvarliteral(ls, "(for step)");
|
new_localvarliteral(ls, "(for step)");
|
||||||
new_localvar(ls, varname);
|
new_localvar(ls, varname);
|
||||||
checknext(ls, '=');
|
checknext(ls, '=');
|
||||||
exp1(ls); /* initial value */
|
if (!exp1(ls, 0)) /* initial value not an integer? */
|
||||||
|
basicfor = 0; /* not a basic 'for' */
|
||||||
checknext(ls, ',');
|
checknext(ls, ',');
|
||||||
exp1(ls); /* limit */
|
exp1(ls, 0); /* limit */
|
||||||
if (testnext(ls, ','))
|
if (testnext(ls, ',')) {
|
||||||
exp1(ls); /* optional step */
|
if (!exp1(ls, 1)) /* optional step not 1? */
|
||||||
|
basicfor = 0; /* not a basic 'for' */
|
||||||
|
}
|
||||||
else { /* default step = 1 */
|
else { /* default step = 1 */
|
||||||
luaK_int(fs, fs->freereg, 1);
|
luaK_int(fs, fs->freereg, 1);
|
||||||
luaK_reserveregs(fs, 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;
|
line = ls->linenumber;
|
||||||
adjust_assign(ls, 3, explist(ls, &e), &e);
|
adjust_assign(ls, 3, explist(ls, &e), &e);
|
||||||
luaK_checkstack(fs, 3); /* extra space to call generator */
|
luaK_checkstack(fs, 3); /* extra space to call generator */
|
||||||
forbody(ls, base, line, nvars - 3, 0);
|
forbody(ls, base, line, nvars - 3, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
28
lvm.c
28
lvm.c
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lvm.c,v 2.324 2017/12/04 17:41:30 roberto Exp roberto $
|
** $Id: lvm.c,v 2.326 2017/12/18 17:49:31 roberto Exp $
|
||||||
** Lua virtual machine
|
** Lua virtual machine
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@ -1564,6 +1564,32 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
vmcase(OP_FORLOOP1) {
|
||||||
|
lua_Integer idx = intop(+, ivalue(vra), 1); /* increment index */
|
||||||
|
lua_Integer limit = ivalue(s2v(ra + 1));
|
||||||
|
if (idx <= limit) {
|
||||||
|
pc -= GETARG_Bx(i); /* jump back */
|
||||||
|
chgivalue(vra, idx); /* update internal index... */
|
||||||
|
setivalue(s2v(ra + 3), idx); /* ...and external index */
|
||||||
|
}
|
||||||
|
updatetrap(ci);
|
||||||
|
vmbreak;
|
||||||
|
}
|
||||||
|
vmcase(OP_FORPREP1) {
|
||||||
|
TValue *init = vra;
|
||||||
|
TValue *plimit = s2v(ra + 1);
|
||||||
|
lua_Integer ilimit, initv;
|
||||||
|
int stopnow;
|
||||||
|
if (!forlimit(plimit, &ilimit, 1, &stopnow)) {
|
||||||
|
savepc(L); /* for the error message */
|
||||||
|
luaG_runerror(L, "'for' limit must be a number");
|
||||||
|
}
|
||||||
|
initv = (stopnow ? 0 : ivalue(init));
|
||||||
|
setivalue(plimit, ilimit);
|
||||||
|
setivalue(init, intop(-, initv, 1));
|
||||||
|
pc += GETARG_Bx(i);
|
||||||
|
vmbreak;
|
||||||
|
}
|
||||||
vmcase(OP_FORLOOP) {
|
vmcase(OP_FORLOOP) {
|
||||||
if (ttisinteger(vra)) { /* integer loop? */
|
if (ttisinteger(vra)) { /* integer loop? */
|
||||||
lua_Integer step = ivalue(s2v(ra + 2));
|
lua_Integer step = ivalue(s2v(ra + 2));
|
||||||
|
Loading…
Reference in New Issue
Block a user