From 7b65328c8e89ecc999e47d00288bfa4cf6692cdc Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Tue, 9 Apr 2002 16:47:44 -0300 Subject: [PATCH] new semantics for `generic for' (with state) --- ldebug.c | 5 ++--- lopcodes.c | 4 +++- lopcodes.h | 7 ++++--- lparser.c | 24 +++++++++++++----------- lvm.c | 26 +++++++++++++------------- 5 files changed, 35 insertions(+), 31 deletions(-) diff --git a/ldebug.c b/ldebug.c index e69afafd..eb282db7 100644 --- a/ldebug.c +++ b/ldebug.c @@ -1,5 +1,5 @@ /* -** $Id: ldebug.c,v 1.105 2002/03/25 17:47:14 roberto Exp roberto $ +** $Id: ldebug.c,v 1.106 2002/04/04 17:21:31 roberto Exp roberto $ ** Debug Interface ** See Copyright Notice in lua.h */ @@ -347,8 +347,7 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) { break; } case OP_TFORLOOP: { - checkreg(pt, a+c); - checkreg(pt, a+2); /* at least 2 for table generators */ + checkreg(pt, a+2+c); check(pc+2 < pt->sizecode); /* check skip */ break; } diff --git a/lopcodes.c b/lopcodes.c index c156f533..bbe66717 100644 --- a/lopcodes.c +++ b/lopcodes.c @@ -1,5 +1,5 @@ /* -** $Id: lopcodes.c,v 1.13 2002/03/21 20:32:22 roberto Exp roberto $ +** $Id: lopcodes.c,v 1.14 2002/03/25 17:47:14 roberto Exp roberto $ ** extracted automatically from lopcodes.h by mkprint.lua ** DO NOT EDIT ** See Copyright Notice in lua.h @@ -49,6 +49,7 @@ const char *const luaP_opnames[] = { "RETURN", "FORLOOP", "TFORLOOP", + "OP_TFORPREP", "SETLIST", "SETLISTO", "CLOSE", @@ -98,6 +99,7 @@ const lu_byte luaP_opmodes[NUM_OPCODES] = { ,opmode(0,0,0,0, 0,0,iABC) /* OP_RETURN */ ,opmode(0,0,0,0, 0,0,iAsBc) /* OP_FORLOOP */ ,opmode(0,0,0,0, 0,0,iABC) /* OP_TFORLOOP */ + ,opmode(0,0,0,0, 0,0,iABC) /* OP_TFORPREP */ ,opmode(0,0,0,0, 0,0,iABc) /* OP_SETLIST */ ,opmode(0,0,0,0, 0,0,iABc) /* OP_SETLISTO */ ,opmode(0,0,0,0, 0,0,iABC) /* OP_CLOSE */ diff --git a/lopcodes.h b/lopcodes.h index 566fc84f..15e1f09d 100644 --- a/lopcodes.h +++ b/lopcodes.h @@ -1,5 +1,5 @@ /* -** $Id: lopcodes.h,v 1.92 2002/03/21 20:32:22 roberto Exp roberto $ +** $Id: lopcodes.h,v 1.93 2002/03/25 17:47:14 roberto Exp roberto $ ** Opcodes for Lua virtual machine ** See Copyright Notice in lua.h */ @@ -173,8 +173,9 @@ OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see (3)) */ OP_FORLOOP,/* A sBc R(A)+=R(A+2); if R(A) upval = 0; bl->previous = fs->bl; fs->bl = bl; + lua_assert(fs->freereg == fs->nactloc); } @@ -1028,24 +1029,25 @@ static void fornum (LexState *ls, TString *varname, int line) { static void forlist (LexState *ls, TString *indexname) { - /* forlist -> NAME {,NAME} IN exp1 DO body */ + /* forlist -> NAME {,NAME} IN explist1 DO body */ FuncState *fs = ls->fs; + expdesc e; int nvars = 0; int prep; int base = fs->freereg; - new_localvarstr(ls, "(for generator)", 0); - new_localvar(ls, indexname, ++nvars); + new_localvarstr(ls, "(for generator)", nvars++); + new_localvarstr(ls, "(for state)", nvars++); + new_localvar(ls, indexname, nvars++); while (optional(ls, ',')) { - new_localvar(ls, str_checkname(ls), ++nvars); + new_localvar(ls, str_checkname(ls), nvars++); next(ls); } check(ls, TK_IN); - exp1(ls); /* table */ - luaK_checkstack(fs, 2); /* at least two slots, to traverse tables */ - luaK_reserveregs(fs, nvars); /* registers for vars */ - luaK_codeABC(fs, OP_LOADNIL, base+1, base+nvars, 0); - adjustlocalvars(ls, nvars+1); /* scope for control variables */ - luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars); + adjust_assign(ls, 3, explist1(ls, &e), &e); + luaK_reserveregs(fs, nvars - 3); /* registers for other variables */ + luaK_codeABC(fs, OP_TFORPREP, base, 0, 0); + luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars - 3); + adjustlocalvars(ls, nvars); /* scope for all variables */ prep = luaK_jump(fs); check(ls, TK_DO); block(ls); diff --git a/lvm.c b/lvm.c index 7f358cca..bb1b9852 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 1.222 2002/03/22 16:54:31 roberto Exp roberto $ +** $Id: lvm.c,v 1.223 2002/03/25 17:47:14 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -549,21 +549,21 @@ StkId luaV_execute (lua_State *L) { break; } case OP_TFORLOOP: { + setobj(ra+4, ra+2); + setobj(ra+3, ra+1); + setobj(ra+2, ra); + L->top = ra+5; + luaD_call(L, ra+2, GETARG_C(i) + 1); + L->top = L->ci->top; + if (ttype(ra+2) != LUA_TNIL) pc++; /* skip jump (keep looping) */ + break; + } + case OP_TFORPREP: { if (ttype(ra) == LUA_TTABLE) { - Table *t = hvalue(ra); - if (luaH_next(L, t, ra+1)) - pc++; /* skip jump (keep looping) */ - } - else if (ttype(ra) == LUA_TFUNCTION) { setobj(ra+1, ra); - L->top = ra+2; /* no arguments */ - luaD_call(L, ra+1, GETARG_C(i)); - L->top = L->ci->top; - if (ttype(ra+1) != LUA_TNIL) - pc++; /* skip jump (keep looping) */ + setsvalue(ra, luaS_new(L, "next")); + luaV_gettable(L, gt(L), ra, ra); } - else - luaD_error(L, "`for' generator must be a table or function"); break; } case OP_SETLIST: