diff --git a/lcode.c b/lcode.c index 086b527f..5caa6515 100644 --- a/lcode.c +++ b/lcode.c @@ -1,5 +1,5 @@ /* -** $Id: lcode.c,v 1.91 2002/03/08 19:10:32 roberto Exp roberto $ +** $Id: lcode.c,v 1.92 2002/03/21 20:31:43 roberto Exp roberto $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -737,31 +737,16 @@ void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { } -static void codelineinfo (FuncState *fs) { - Proto *f = fs->f; - LexState *ls = fs->ls; - if (ls->lastline > fs->lastline) { - if (ls->lastline > fs->lastline+1) { - luaM_growvector(fs->L, f->lineinfo, fs->nlineinfo, f->sizelineinfo, int, - MAX_INT, "line info overflow"); - f->lineinfo[fs->nlineinfo++] = -(ls->lastline - (fs->lastline+1)); - } - luaM_growvector(fs->L, f->lineinfo, fs->nlineinfo, f->sizelineinfo, int, - MAX_INT, "line info overflow"); - f->lineinfo[fs->nlineinfo++] = fs->pc; - fs->lastline = ls->lastline; - } -} - - static int luaK_code (FuncState *fs, Instruction i) { - Proto *f; - codelineinfo(fs); - f = fs->f; + Proto *f = fs->f; + int oldsize = f->sizecode; /* put new instruction in code array */ luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction, MAX_INT, "code size overflow"); f->code[fs->pc] = i; + if (f->sizecode != oldsize) + luaM_reallocvector(fs->L, f->lineinfo, oldsize, f->sizecode, int); + f->lineinfo[fs->pc] = fs->ls->lastline; return fs->pc++; } diff --git a/ldebug.c b/ldebug.c index 34b3eec5..323a5f7c 100644 --- a/ldebug.c +++ b/ldebug.c @@ -1,5 +1,5 @@ /* -** $Id: ldebug.c,v 1.103 2002/03/19 12:45:25 roberto Exp roberto $ +** $Id: ldebug.c,v 1.104 2002/03/22 16:54:31 roberto Exp roberto $ ** Debug Interface ** See Copyright Notice in lua.h */ @@ -34,6 +34,24 @@ static int isLmark (CallInfo *ci) { } +static int currentpc (lua_State *L, CallInfo *ci) { + if (ci->pc == NULL) return -1; /* function is not an active Lua function */ + if (ci == L->ci || ci->pc != (ci+1)->pc) /* no other function using `pc'? */ + return (*ci->pc - ci_func(ci)->l.p->code) - 1; + else /* function's pc is saved */ + return (ci->savedpc - ci_func(ci)->l.p->code) - 1; +} + + +static int currentline (lua_State *L, CallInfo *ci) { + int pc = currentpc(L, ci); + if (pc < 0) + return -1; /* only active lua functions have current-line information */ + else + return ci_func(ci)->l.p->lineinfo[pc]; +} + + LUA_API lua_Hook lua_setcallhook (lua_State *L, lua_Hook func) { lua_Hook oldhook; lua_lock(L); @@ -45,10 +63,13 @@ LUA_API lua_Hook lua_setcallhook (lua_State *L, lua_Hook func) { LUA_API lua_Hook lua_setlinehook (lua_State *L, lua_Hook func) { + CallInfo *ci; lua_Hook oldhook; lua_lock(L); oldhook = L->linehook; L->linehook = func; + for (ci = L->base_ci; ci <= L->ci; ci++) + ci->lastpc = currentpc(L, ci); lua_unlock(L); return oldhook; } @@ -67,57 +88,6 @@ LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { } -int luaG_getline (int *lineinfo, int pc, int refline, int *prefi) { - int refi; - if (lineinfo == NULL) return -1; /* no line info */ - refi = prefi ? *prefi : 0; - if (lineinfo[refi] < 0) - refline += -lineinfo[refi++]; - lua_assert(lineinfo[refi] >= 0); - while (lineinfo[refi] > pc) { - refline--; - refi--; - if (lineinfo[refi] < 0) - refline -= -lineinfo[refi--]; - lua_assert(lineinfo[refi] >= 0); - } - for (;;) { - int nextline = refline + 1; - int nextref = refi + 1; - if (lineinfo[nextref] < 0) - nextline += -lineinfo[nextref++]; - lua_assert(lineinfo[nextref] >= 0); - if (lineinfo[nextref] > pc) - break; - refline = nextline; - refi = nextref; - } - if (prefi) *prefi = refi; - return refline; -} - - -static int currentpc (lua_State *L, CallInfo *ci) { - lua_assert(isLmark(ci)); - if (ci->pc == NULL) return 0; /* function is not active */ - if (ci == L->ci || ci->pc != (ci+1)->pc) /* no other function using `pc'? */ - return (*ci->pc - ci_func(ci)->l.p->code) - 1; - else /* function's pc is saved */ - return (ci->savedpc - ci_func(ci)->l.p->code) - 1; -} - - -static int currentline (lua_State *L, CallInfo *ci) { - if (!isLmark(ci)) - return -1; /* only active lua functions have current-line information */ - else { - int *lineinfo = ci_func(ci)->l.p->lineinfo; - return luaG_getline(lineinfo, currentpc(L, ci), 1, NULL); - } -} - - - static Proto *getluaproto (CallInfo *ci) { return (isLmark(ci) ? ci_func(ci)->l.p : NULL); } @@ -272,19 +242,8 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { #define checkreg(pt,reg) check((reg) < (pt)->maxstacksize) -static int checklineinfo (const Proto *pt) { - int *lineinfo = pt->lineinfo; - if (lineinfo == NULL) return 1; - check(pt->sizelineinfo >= 2 && lineinfo[pt->sizelineinfo-1] == MAX_INT); - lua_assert(luaG_getline(lineinfo, pt->sizecode-1, 1, NULL) < MAX_INT); - if (*lineinfo < 0) lineinfo++; - check(*lineinfo == 0); - return 1; -} - static int precheck (const Proto *pt) { - check(checklineinfo(pt)); check(pt->maxstacksize <= MAXSTACK); lua_assert(pt->numparams+pt->is_vararg <= pt->maxstacksize); check(GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN); diff --git a/ldebug.h b/ldebug.h index 18afa5ab..36b866df 100644 --- a/ldebug.h +++ b/ldebug.h @@ -1,5 +1,5 @@ /* -** $Id: ldebug.h,v 1.16 2001/11/28 20:13:13 roberto Exp roberto $ +** $Id: ldebug.h,v 1.17 2002/03/19 12:45:25 roberto Exp roberto $ ** Auxiliary functions from Debug Interface module ** See Copyright Notice in lua.h */ @@ -15,7 +15,6 @@ void luaG_typeerror (lua_State *L, const TObject *o, const char *opname); void luaG_concaterror (lua_State *L, StkId p1, StkId p2); void luaG_aritherror (lua_State *L, StkId p1, const TObject *p2); -int luaG_getline (int *lineinfo, int pc, int refline, int *refi); void luaG_ordererror (lua_State *L, const TObject *p1, const TObject *p2); int luaG_checkcode (const Proto *pt); diff --git a/ldo.c b/ldo.c index b9efd24a..37dac3b5 100644 --- a/ldo.c +++ b/ldo.c @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 1.164 2002/03/15 17:17:16 roberto Exp roberto $ +** $Id: ldo.c,v 1.165 2002/03/20 12:52:32 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -122,13 +122,13 @@ static void dohook (lua_State *L, lua_Debug *ar, lua_Hook hook) { } -void luaD_lineHook (lua_State *L, int line, lua_Hook linehook) { +void luaD_lineHook (lua_State *L, int line) { if (L->allowhooks) { lua_Debug ar; ar.event = "line"; ar.i_ci = L->ci - L->base_ci; ar.currentline = line; - dohook(L, &ar, linehook); + dohook(L, &ar, L->linehook); } } @@ -221,7 +221,6 @@ StkId luaD_precall (lua_State *L, StkId func) { if (p->is_vararg) /* varargs? */ adjust_varargs(L, p->numparams); luaD_checkstack(L, p->maxstacksize); - ci->line = 0; ci->top = ci->base + p->maxstacksize; while (L->top < ci->top) setnilvalue(L->top++); @@ -250,7 +249,7 @@ void luaD_poscall (lua_State *L, int wanted, StkId firstResult) { luaD_callHook(L, L->callhook, "return"); firstResult = restorestack(L, fr); } - res = L->ci->base - 1; /* func == final position of 1st result */ + res = L->ci->base - 1; /* res == final position of 1st result */ L->ci--; /* move results to correct place */ while (wanted != 0 && firstResult < L->top) { diff --git a/ldo.h b/ldo.h index e25d9c09..2eb5f43b 100644 --- a/ldo.h +++ b/ldo.h @@ -1,5 +1,5 @@ /* -** $Id: ldo.h,v 1.40 2002/01/30 17:27:53 roberto Exp roberto $ +** $Id: ldo.h,v 1.41 2002/03/20 12:52:32 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -27,7 +27,7 @@ #define restorestack(L,n) ((TObject *)((char *)L->stack + (n))) -void luaD_lineHook (lua_State *L, int line, lua_Hook linehook); +void luaD_lineHook (lua_State *L, int line); StkId luaD_precall (lua_State *L, StkId func); void luaD_call (lua_State *L, StkId func, int nResults); void luaD_poscall (lua_State *L, int wanted, StkId firstResult); diff --git a/lfunc.c b/lfunc.c index 2b79b8de..205f39b6 100644 --- a/lfunc.c +++ b/lfunc.c @@ -1,5 +1,5 @@ /* -** $Id: lfunc.c,v 1.53 2001/12/21 17:31:35 roberto Exp roberto $ +** $Id: lfunc.c,v 1.54 2002/03/05 12:42:47 roberto Exp roberto $ ** Auxiliary functions to manipulate prototypes and closures ** See Copyright Notice in lua.h */ @@ -87,7 +87,6 @@ Proto *luaF_newproto (lua_State *L) { f->marked = 0; f->lineinfo = NULL; f->sizelocvars = 0; - f->sizelineinfo = 0; f->locvars = NULL; f->lineDefined = 0; f->source = NULL; @@ -99,10 +98,10 @@ Proto *luaF_newproto (lua_State *L) { void luaF_freeproto (lua_State *L, Proto *f) { luaM_freearray(L, f->code, f->sizecode, Instruction); + luaM_freearray(L, f->lineinfo, f->sizecode, int); luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar); luaM_freearray(L, f->k, f->sizek, TObject); luaM_freearray(L, f->p, f->sizep, Proto *); - luaM_freearray(L, f->lineinfo, f->sizelineinfo, int); luaM_freelem(L, f); } diff --git a/lobject.h b/lobject.h index 746b7751..dca2531a 100644 --- a/lobject.h +++ b/lobject.h @@ -1,5 +1,5 @@ /* -** $Id: lobject.h,v 1.126 2002/03/11 12:45:00 roberto Exp roberto $ +** $Id: lobject.h,v 1.127 2002/03/18 18:16:16 roberto Exp roberto $ ** Type definitions for Lua objects ** See Copyright Notice in lua.h */ @@ -129,7 +129,6 @@ typedef struct Proto { int sizek; /* size of `k' */ int sizecode; int sizep; /* size of `p' */ - int sizelineinfo; /* size of `lineinfo' */ int sizelocvars; int lineDefined; lu_byte nupvalues; diff --git a/lopcodes.c b/lopcodes.c index 8d13a09f..c156f533 100644 --- a/lopcodes.c +++ b/lopcodes.c @@ -1,5 +1,5 @@ /* -** $Id: lopcodes.c,v 1.12 2002/03/08 19:10:32 roberto Exp roberto $ +** $Id: lopcodes.c,v 1.13 2002/03/21 20:32:22 roberto Exp roberto $ ** extracted automatically from lopcodes.h by mkprint.lua ** DO NOT EDIT ** See Copyright Notice in lua.h @@ -59,11 +59,11 @@ const char *const luaP_opnames[] = { #define opmode(t,x,b,c,sa,k,m) (((t)<nk = 0; fs->h = luaH_new(ls->L, 0, 0); fs->np = 0; - fs->nlineinfo = 0; fs->nlocvars = 0; fs->nactloc = 0; fs->nactvar = 0; - fs->lastline = 0; fs->defaultglob = NO_REG; /* default is free globals */ fs->bl = NULL; f->code = NULL; @@ -402,6 +400,7 @@ static void close_func (LexState *ls) { G(L)->roottable = fs->h->next; luaH_free(L, fs->h); luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); + luaM_reallocvector(L, f->lineinfo, f->sizecode, fs->pc, int); f->sizecode = fs->pc; luaM_reallocvector(L, f->k, f->sizek, fs->nk, TObject); f->sizek = fs->nk; @@ -409,9 +408,6 @@ static void close_func (LexState *ls) { f->sizep = fs->np; luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); f->sizelocvars = fs->nlocvars; - luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->nlineinfo+1, int); - f->lineinfo[fs->nlineinfo++] = MAX_INT; /* end flag */ - f->sizelineinfo = fs->nlineinfo; lua_assert(luaG_checkcode(f)); lua_assert(fs->bl == NULL); ls->fs = fs->prev; @@ -999,10 +995,10 @@ static int exp1 (LexState *ls) { } -static void fornum (LexState *ls, TString *varname) { +static void fornum (LexState *ls, TString *varname, int line) { /* fornum -> NAME = exp1,exp1[,exp1] DO body */ FuncState *fs = ls->fs; - int prep; + int prep, endfor; int base = fs->freereg; new_localvar(ls, varname, 0); new_localvarstr(ls, "(for limit)", 1); @@ -1024,7 +1020,9 @@ static void fornum (LexState *ls, TString *varname) { check(ls, TK_DO); block(ls); luaK_patchtohere(fs, prep-1); - luaK_patchlist(fs, luaK_codeAsBc(fs, OP_FORLOOP, base, NO_JUMP), prep); + endfor = luaK_codeAsBc(fs, OP_FORLOOP, base, NO_JUMP); + luaK_patchlist(fs, endfor, prep); + fs->f->lineinfo[endfor] = line; /* pretend that `OP_FOR' starts the loop */ } @@ -1065,7 +1063,7 @@ static void forstat (LexState *ls, int line) { varname = str_checkname(ls); /* first variable name */ next(ls); /* skip var name */ switch (ls->t.token) { - case '=': fornum(ls, varname); break; + case '=': fornum(ls, varname, line); break; case ',': case TK_IN: forlist(ls, varname); break; default: luaK_error(ls, "`=' or `in' expected"); } diff --git a/lparser.h b/lparser.h index 44f1759e..b0adda79 100644 --- a/lparser.h +++ b/lparser.h @@ -1,5 +1,5 @@ /* -** $Id: lparser.h,v 1.39 2002/02/08 22:42:41 roberto Exp roberto $ +** $Id: lparser.h,v 1.40 2002/03/14 18:01:52 roberto Exp roberto $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -68,11 +68,9 @@ typedef struct FuncState { int defaultglob; /* where to look for non-declared globals */ int nk; /* number of elements in `k' */ int np; /* number of elements in `p' */ - int nlineinfo; /* number of elements in `lineinfo' */ int nlocvars; /* number of elements in `locvars' */ int nactloc; /* number of active local variables */ int nactvar; /* number of elements in array `actvar' */ - int lastline; /* line where last `lineinfo' was generated */ expdesc upvalues[MAXUPVALUES]; /* upvalues */ vardesc actvar[MAXVARS]; /* declared-variable stack */ } FuncState; diff --git a/lstate.h b/lstate.h index af56ee40..ee91e853 100644 --- a/lstate.h +++ b/lstate.h @@ -1,5 +1,5 @@ /* -** $Id: lstate.h,v 1.78 2002/03/07 18:11:51 roberto Exp roberto $ +** $Id: lstate.h,v 1.79 2002/03/11 12:45:00 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -91,16 +91,12 @@ typedef struct CallInfo { StkId top; /* top for this function (when it's a Lua function) */ const Instruction **pc; /* points to `pc' variable in `luaV_execute' */ StkId *pb; /* points to `base' variable in `luaV_execute' */ - /* extra information for line tracing */ int lastpc; /* last pc traced */ - int line; /* current line */ - int refi; /* current index in `lineinfo' */ + int yield_results; } CallInfo; #define ci_func(ci) (clvalue((ci)->base - 1)) -#define yield_results refi /* reuse this field */ - /* ** `global state', shared by all threads of this state diff --git a/ltests.c b/ltests.c index 72487ad8..097f7d1b 100644 --- a/ltests.c +++ b/ltests.c @@ -1,5 +1,5 @@ /* -** $Id: ltests.c,v 1.112 2002/03/14 18:01:52 roberto Exp roberto $ +** $Id: ltests.c,v 1.113 2002/03/20 12:54:08 roberto Exp roberto $ ** Internal Module for Debugging of the Lua Implementation ** See Copyright Notice in lua.h */ @@ -144,7 +144,7 @@ static char *buildop (Proto *p, int pc, char *buff) { Instruction i = p->code[pc]; OpCode o = GET_OPCODE(i); const char *name = luaP_opnames[o]; - int line = luaG_getline(p->lineinfo, pc, 1, NULL); + int line = p->lineinfo[pc]; sprintf(buff, "(%4d) %4d - ", line, pc); switch (getOpMode(o)) { case iABC: diff --git a/lundump.c b/lundump.c index 4906a8db..6b2bb759 100644 --- a/lundump.c +++ b/lundump.c @@ -1,5 +1,5 @@ /* -** $Id: lundump.c,v 1.43 2001/07/24 21:57:19 roberto Exp $ +** $Id: lundump.c,v 1.44 2001/11/28 20:13:13 roberto Exp roberto $ ** load pre-compiled Lua chunks ** See Copyright Notice in lua.h */ @@ -133,7 +133,6 @@ static void LoadLines (lua_State* L, Proto* f, ZIO* Z, int swap) int n; n=LoadInt(L,Z,swap); f->lineinfo=luaM_newvector(L,n,int); - f->sizelineinfo=n; LoadVector(L,f->lineinfo,n,sizeof(*f->lineinfo),Z,swap); } diff --git a/lvm.c b/lvm.c index 84a70fd5..7f358cca 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 1.221 2002/03/20 12:52:32 roberto Exp roberto $ +** $Id: lvm.c,v 1.222 2002/03/22 16:54:31 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -62,33 +62,17 @@ int luaV_tostring (lua_State *L, TObject *obj) { } -static void traceexec (lua_State *L, lua_Hook linehook) { +static void traceexec (lua_State *L) { CallInfo *ci = L->ci; int *lineinfo = ci_func(ci)->l.p->lineinfo; int pc = cast(int, *ci->pc - ci_func(ci)->l.p->code) - 1; - int newline; - if (testOpMode(GET_OPCODE(*(*ci->pc - 1)), OpModeNoTrace)) - return; - if (ci->line == -1) return; /* no linehooks for this function */ - else if (ci->line == 0) { /* first linehook? */ - if (pc == 0) { /* function is starting now? */ - ci->line = 1; - ci->refi = 0; - ci->lastpc = pc+1; /* make sure it will call linehook */ - } - else { /* function started without hooks: */ - ci->line = -1; /* keep it that way */ - return; - } - } - newline = luaG_getline(lineinfo, pc, ci->line, &ci->refi); + int newline = lineinfo[pc]; + if (pc == 0) /* tracing may be starting now? */ + ci->lastpc = 0; /* initialize `lastpc' */ /* calls linehook when enters a new line or jumps back (loop) */ - if (newline != ci->line || pc <= ci->lastpc) { - ci->line = newline; - luaD_lineHook(L, newline, linehook); - ci = L->ci; /* previous call may realocate `ci' */ - } - ci->lastpc = pc; + if (pc <= ci->lastpc || newline != lineinfo[ci->lastpc]) + luaD_lineHook(L, newline); + L->ci->lastpc = pc; } @@ -316,21 +300,17 @@ static void powOp (lua_State *L, StkId ra, StkId rb, StkId rc) { #define dojump(pc, i) ((pc) += (i)) -/* -** Executes current Lua function. Parameters are between [base,top). -** Returns n such that the results are between [n,top). -*/ + StkId luaV_execute (lua_State *L) { StkId base; LClosure *cl; TObject *k; const Instruction *pc; - lua_Hook linehook; - reinit: - linehook = L->linehook; + callentry: /* entry point when calling new functions */ L->ci->pc = &pc; - pc = L->ci->savedpc; L->ci->pb = &base; + pc = L->ci->savedpc; + retentry: /* entry point when returning to old functions */ base = L->ci->base; cl = &clvalue(base - 1)->l; k = cl->p->k; @@ -338,13 +318,13 @@ StkId luaV_execute (lua_State *L) { for (;;) { const Instruction i = *pc++; StkId ra; - if (linehook) - traceexec(L, linehook); + if (L->linehook) + traceexec(L); ra = RA(i); lua_assert(L->top <= L->stack + L->stacksize && L->top >= L->ci->base); - lua_assert(L->top == L->ci->top || GET_OPCODE(i) == OP_CALL || - GET_OPCODE(i) == OP_TAILCALL || GET_OPCODE(i) == OP_RETURN || - GET_OPCODE(i) == OP_SETLISTO); + lua_assert(L->top == L->ci->top || + GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL || + GET_OPCODE(i) == OP_RETURN || GET_OPCODE(i) == OP_SETLISTO); switch (GET_OPCODE(i)) { case OP_MOVE: { setobj(ra, RB(i)); @@ -453,7 +433,6 @@ StkId luaV_execute (lua_State *L) { break; } case OP_JMP: { - linehook = L->linehook; dojump(pc, GETARG_sBc(i)); break; } @@ -511,7 +490,7 @@ StkId luaV_execute (lua_State *L) { } else { /* it is a Lua function: `call' it */ (L->ci-1)->savedpc = pc; - goto reinit; + goto callentry; } break; } @@ -521,7 +500,7 @@ StkId luaV_execute (lua_State *L) { if (b != 0) L->top = ra+b; /* else previous instruction set top */ luaD_poscall(L, LUA_MULTRET, ra); /* move down function and args. */ ra = luaD_precall(L, base-1); - if (ra == NULL) goto reinit; /* it is a Lua function */ + if (ra == NULL) goto callentry; /* it is a Lua function */ else if (ra > L->top) return NULL; /* yield??? */ else goto ret; } @@ -540,14 +519,12 @@ StkId luaV_execute (lua_State *L) { else { /* yes: continue its execution */ int nresults; lua_assert(ttype(ci->base-1) == LUA_TFUNCTION); - base = ci->base; /* restore previous values */ - cl = &clvalue(base - 1)->l; - k = cl->p->k; pc = ci->savedpc; lua_assert(GET_OPCODE(*(pc-1)) == OP_CALL); nresults = GETARG_C(*(pc-1)) - 1; luaD_poscall(L, nresults, ra); if (nresults >= 0) L->top = L->ci->top; + goto retentry; } break; } @@ -556,7 +533,6 @@ StkId luaV_execute (lua_State *L) { int j = GETARG_sBc(i); const TObject *plimit = ra+1; const TObject *pstep = ra+2; - dojump(pc, j); /* jump back before tests (for error messages) */ if (ttype(ra) != LUA_TNUMBER) luaD_error(L, "`for' initial value must be a number"); if (!tonumber(plimit, ra+1)) @@ -567,11 +543,9 @@ StkId luaV_execute (lua_State *L) { index = nvalue(ra) + step; /* increment index */ limit = nvalue(plimit); if (step > 0 ? index <= limit : index >= limit) { + dojump(pc, j); /* jump back */ chgnvalue(ra, index); /* update index */ - linehook = L->linehook; } - else - dojump(pc, -j); /* undo jump */ break; } case OP_TFORLOOP: {