diff --git a/ldebug.c b/ldebug.c index 468c2358..d42b161a 100644 --- a/ldebug.c +++ b/ldebug.c @@ -1,5 +1,5 @@ /* -** $Id: ldebug.c,v 1.150 2003/03/19 21:24:04 roberto Exp roberto $ +** $Id: ldebug.c,v 1.151 2003/04/28 13:31:06 roberto Exp roberto $ ** Debug Interface ** See Copyright Notice in lua.h */ @@ -374,10 +374,11 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) { break; } case OP_TFORLOOP: - checkreg(pt, a+c+5); + checkreg(pt, a+5); if (reg >= a) last = pc; /* affect all registers above base */ /* go through */ case OP_FORLOOP: + case OP_FORPREP: checkreg(pt, a+2); /* go through */ case OP_JMP: { diff --git a/lopcodes.c b/lopcodes.c index 16950461..b10e5bd1 100644 --- a/lopcodes.c +++ b/lopcodes.c @@ -1,5 +1,5 @@ /* -** $Id: lopcodes.c,v 1.21 2002/08/20 20:03:05 roberto Exp roberto $ +** $Id: lopcodes.c,v 1.22 2002/12/04 17:38:31 roberto Exp roberto $ ** extracted automatically from lopcodes.h by mkprint.lua ** DO NOT EDIT ** See Copyright Notice in lua.h @@ -46,6 +46,7 @@ const char *const luaP_opnames[] = { "TAILCALL", "RETURN", "FORLOOP", + "FORPREP", "TFORLOOP", "TFORPREP", "SETLIST", @@ -92,6 +93,7 @@ const lu_byte luaP_opmodes[NUM_OPCODES] = { ,opmode(0, 0, 0, 0, 0, 0, iABC) /* OP_TAILCALL */ ,opmode(0, 0, 0, 0, 0, 0, iABC) /* OP_RETURN */ ,opmode(0, 0, 0, 0, 0, 0, iAsBx) /* OP_FORLOOP */ + ,opmode(0, 0, 0, 0, 0, 0, iAsBx) /* OP_FORPREP */ ,opmode(1, 0, 0, 0, 0, 0, iABC) /* OP_TFORLOOP */ ,opmode(0, 0, 0, 0, 0, 0, iAsBx) /* OP_TFORPREP */ ,opmode(0, 0, 0, 0, 0, 0, iABx) /* OP_SETLIST */ diff --git a/lopcodes.h b/lopcodes.h index 5386bb21..259b5f5d 100644 --- a/lopcodes.h +++ b/lopcodes.h @@ -1,5 +1,5 @@ /* -** $Id: lopcodes.h,v 1.101 2002/08/20 20:03:05 roberto Exp roberto $ +** $Id: lopcodes.h,v 1.102 2002/08/21 18:56:09 roberto Exp roberto $ ** Opcodes for Lua virtual machine ** See Copyright Notice in lua.h */ @@ -172,6 +172,7 @@ OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ OP_FORLOOP,/* A sBx R(A)+=R(A+2); if R(A) DO block */ BlockCnt bl; FuncState *fs = ls->fs; int prep, endfor; - adjustlocalvars(ls, nvars); /* scope for all variables */ + adjustlocalvars(ls, 3); /* control variables */ check(ls, TK_DO); - enterblock(fs, &bl, 1); /* loop block */ - prep = luaK_getlabel(fs); + prep = luaK_codeAsBx(fs, (isnum ? OP_FORPREP : OP_TFORPREP), base, NO_JUMP); + enterblock(fs, &bl, 0); /* scope for declared variables */ + adjustlocalvars(ls, nvars); + luaK_reserveregs(fs, nvars); block(ls); - luaK_patchtohere(fs, prep-1); + leaveblock(fs); /* end of scope for declared variables */ + luaK_patchtohere(fs, prep); endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) : - luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars - 3); + luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars); luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */ - luaK_patchlist(fs, (isnum) ? endfor : luaK_jump(fs), prep); - leaveblock(fs); + luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1); } static void fornum (LexState *ls, TString *varname, int line) { - /* fornum -> NAME = exp1,exp1[,exp1] DO body */ + /* fornum -> NAME = exp1,exp1[,exp1] forbody */ FuncState *fs = ls->fs; int base = fs->freereg; - new_localvar(ls, varname, 0); + new_localvarstr(ls, "(for index)", 0); new_localvarstr(ls, "(for limit)", 1); new_localvarstr(ls, "(for step)", 2); + new_localvar(ls, varname, 3); check(ls, '='); exp1(ls); /* initial value */ check(ls, ','); @@ -1061,39 +1065,39 @@ static void fornum (LexState *ls, TString *varname, int line) { luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1)); luaK_reserveregs(fs, 1); } - luaK_codeABC(fs, OP_SUB, fs->freereg - 3, fs->freereg - 3, fs->freereg - 1); - luaK_jump(fs); - forbody(ls, base, line, 3, 1); + forbody(ls, base, line, 1, 1); } static void forlist (LexState *ls, TString *indexname) { - /* forlist -> NAME {,NAME} IN explist1 DO body */ + /* forlist -> NAME {,NAME} IN explist1 forbody */ FuncState *fs = ls->fs; expdesc e; int nvars = 0; int line; int base = fs->freereg; + /* create control variables */ new_localvarstr(ls, "(for generator)", nvars++); new_localvarstr(ls, "(for state)", nvars++); + new_localvarstr(ls, "(for control)", nvars++); + /* create declared variables */ new_localvar(ls, indexname, nvars++); while (testnext(ls, ',')) new_localvar(ls, str_checkname(ls), nvars++); check(ls, TK_IN); line = ls->linenumber; - adjust_assign(ls, nvars, explist1(ls, &e), &e); + adjust_assign(ls, 3, explist1(ls, &e), &e); luaK_checkstack(fs, 3); /* extra space to call generator */ - luaK_codeAsBx(fs, OP_TFORPREP, base, NO_JUMP); - forbody(ls, base, line, nvars, 0); + forbody(ls, base, line, nvars - 3, 0); } static void forstat (LexState *ls, int line) { - /* forstat -> fornum | forlist */ + /* forstat -> FOR (fornum | forlist) END */ FuncState *fs = ls->fs; TString *varname; BlockCnt bl; - enterblock(fs, &bl, 0); /* block to control variable scope */ + enterblock(fs, &bl, 1); /* scope for loop and control variables */ next(ls); /* skip `for' */ varname = str_checkname(ls); /* first variable name */ switch (ls->t.token) { @@ -1102,7 +1106,7 @@ static void forstat (LexState *ls, int line) { default: luaX_syntaxerror(ls, "`=' or `in' expected"); } check_match(ls, TK_END, TK_FOR, line); - leaveblock(fs); + leaveblock(fs); /* loop scope (`break' jumps to this point) */ } diff --git a/lvm.c b/lvm.c index a3fa1ae7..f5348881 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 1.284 2003/04/03 13:35:34 roberto Exp roberto $ +** $Id: lvm.c,v 1.285 2003/05/05 18:39:57 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -639,43 +639,45 @@ StkId luaV_execute (lua_State *L) { } } case OP_FORLOOP: { - lua_Number step, idx, limit; - const TObject *plimit = ra+1; - const TObject *pstep = ra+2; - if (!ttisnumber(ra)) - luaG_runerror(L, "`for' initial value must be a number"); - if (!tonumber(plimit, ra+1)) - luaG_runerror(L, "`for' limit must be a number"); - if (!tonumber(pstep, ra+2)) - luaG_runerror(L, "`for' step must be a number"); - step = nvalue(pstep); - idx = nvalue(ra) + step; /* increment index */ - limit = nvalue(plimit); + lua_Number step = nvalue(ra+2); + lua_Number idx = nvalue(ra) + step; /* increment index */ + lua_Number limit = nvalue(ra+1); if (step > 0 ? idx <= limit : idx >= limit) { dojump(pc, GETARG_sBx(i)); /* jump back */ - chgnvalue(ra, idx); /* update index */ + setnvalue(ra, idx); /* update internal index... */ + setnvalue(ra+3, idx); /* ...and external index */ } break; } + case OP_FORPREP: { + const TObject *init = ra; + const TObject *plimit = ra+1; + const TObject *pstep = ra+2; + if (!tonumber(init, ra)) + luaG_runerror(L, "`for' initial value must be a number"); + else if (!tonumber(plimit, ra+1)) + luaG_runerror(L, "`for' limit must be a number"); + else if (!tonumber(pstep, ra+2)) + luaG_runerror(L, "`for' step must be a number"); + setnvalue(ra, nvalue(ra) - nvalue(pstep)); + dojump(pc, GETARG_sBx(i)); + break; + } case OP_TFORLOOP: { - int nvar = GETARG_C(i) + 1; - StkId cb = ra + nvar + 2; /* call base */ - setobjs2s(cb, ra); - setobjs2s(cb+1, ra+1); + StkId cb = ra + 3; /* call base */ setobjs2s(cb+2, ra+2); + setobjs2s(cb+1, ra+1); + setobjs2s(cb, ra); L->top = cb+3; /* func. + 2 args (state and index) */ - luaD_call(L, cb, nvar); + luaD_call(L, cb, GETARG_C(i)); L->top = L->ci->top; - ra = XRA(i) + 2; /* final position of first result */ - cb = ra + nvar; - do { /* move results to proper positions */ - nvar--; - setobjs2s(ra+nvar, cb+nvar); - } while (nvar > 0); - if (ttisnil(ra)) /* break loop? */ + cb = XRA(i) + 3; /* previous call may change the stack */ + if (ttisnil(cb)) /* break loop? */ pc++; /* skip jump (break loop) */ - else + else { + setobjs2s(cb-1, cb); /* save control variable */ dojump(pc, GETARG_sBx(*pc) + 1); /* jump back */ + } break; } case OP_TFORPREP: { /* for compatibility only */