From be8445d7e4b6122620c428877b51a27d464253d5 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Wed, 10 Jul 2019 14:58:31 -0300 Subject: [PATCH] Details In the generic for loop, it is simpler for OP_TFORLOOP to use the same 'ra' as OP_TFORCALL. Moreover, the internal names of the loop temporaries "(for ...)" don't need to leak internal details (even because the numerical for loop doesn't have a fixed role for each of its temporaries). --- lparser.c | 13 ++++++------- lvm.c | 5 ++--- testes/files.lua | 8 +++++--- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/lparser.c b/lparser.c index c4626ba1..7f282bf9 100644 --- a/lparser.c +++ b/lparser.c @@ -1527,7 +1527,6 @@ static void forbody (LexState *ls, int base, int line, int nvars, int isgen) { if (isgen) { /* generic for? */ luaK_codeABC(fs, OP_TFORCALL, base, 0, nvars); luaK_fixline(fs, line); - base += 2; /* base for 'OP_TFORLOOP' (skips function and state) */ } endfor = luaK_codeABx(fs, forloop[isgen], base, 0); fixforjump(fs, endfor, prep + 1, 1); @@ -1539,9 +1538,9 @@ static void fornum (LexState *ls, TString *varname, int line) { /* fornum -> NAME = exp,exp[,exp] forbody */ FuncState *fs = ls->fs; int base = fs->freereg; - new_localvarliteral(ls, "(for index)"); - new_localvarliteral(ls, "(for limit)"); - new_localvarliteral(ls, "(for step)"); + new_localvarliteral(ls, "(for state)"); + new_localvarliteral(ls, "(for state)"); + new_localvarliteral(ls, "(for state)"); new_localvar(ls, varname); checknext(ls, '='); exp1(ls); /* initial value */ @@ -1566,10 +1565,10 @@ static void forlist (LexState *ls, TString *indexname) { int line; int base = fs->freereg; /* create control variables */ - new_localvarliteral(ls, "(for generator)"); new_localvarliteral(ls, "(for state)"); - new_localvarliteral(ls, "(for control)"); - new_localvarliteral(ls, "(for toclose)"); + new_localvarliteral(ls, "(for state)"); + new_localvarliteral(ls, "(for state)"); + new_localvarliteral(ls, "(for state)"); /* create declared variables */ new_localvar(ls, indexname); while (testnext(ls, ',')) { diff --git a/lvm.c b/lvm.c index b05a887d..a52f186f 100644 --- a/lvm.c +++ b/lvm.c @@ -1746,14 +1746,13 @@ void luaV_execute (lua_State *L, CallInfo *ci) { Protect(luaD_call(L, ra + 4, GETARG_C(i))); /* do the call */ updatestack(ci); /* stack may have changed */ i = *(pc++); /* go to next instruction */ - ra += 2; /* adjust for next instruction */ lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i)); goto l_tforloop; } vmcase(OP_TFORLOOP) { l_tforloop: - if (!ttisnil(s2v(ra + 2))) { /* continue loop? */ - setobjs2s(L, ra, ra + 2); /* save control variable */ + if (!ttisnil(s2v(ra + 4))) { /* continue loop? */ + setobjs2s(L, ra + 2, ra + 4); /* save control variable */ pc -= GETARG_Bx(i); /* jump back */ } vmbreak; diff --git a/testes/files.lua b/testes/files.lua index 54931c14..c8f23d18 100644 --- a/testes/files.lua +++ b/testes/files.lua @@ -427,10 +427,12 @@ do -- testing closing file in line iteration -- get the to-be-closed variable from a loop local function gettoclose (lv) lv = lv + 1 - for i = 1, math.maxinteger do + local stvar = 0 -- to-be-closed is 4th state variable in the loop + for i = 1, 1000 do local n, v = debug.getlocal(lv, i) - if n == "(for toclose)" then - return v + if n == "(for state)" then + stvar = stvar + 1 + if stvar == 4 then return v end end end end