diff --git a/lcode.c b/lcode.c index 50ed11e6..98ad5078 100644 --- a/lcode.c +++ b/lcode.c @@ -1,5 +1,5 @@ /* -** $Id: lcode.c,v 1.37 2000/06/21 17:05:49 roberto Exp roberto $ +** $Id: lcode.c,v 1.38 2000/06/21 18:13:56 roberto Exp roberto $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -283,7 +283,6 @@ static void luaK_testgo (FuncState *fs, expdesc *v, int invert, OpCode jump) { prevpos = fs->pc-1; previous = &fs->f->code[prevpos]; LUA_ASSERT(L, *previous==previous_instruction(fs), "no jump allowed here"); - LUA_ASSERT(L, GET_OPCODE(*previous) != OP_SETLINE, "no setline allowed here"); if (!ISJUMP(GET_OPCODE(*previous))) prevpos = luaK_code1(fs, jump, NO_JUMP); else { /* last instruction is already a jump */ @@ -316,7 +315,6 @@ void luaK_tostack (LexState *ls, expdesc *v, int onlyone) { FuncState *fs = ls->fs; if (!discharge(fs, v)) { /* `v' is an expression? */ OpCode previous = GET_OPCODE(fs->f->code[fs->pc-1]); - LUA_ASSERT(L, previous != OP_SETLINE, "bad place to set line"); if (!ISJUMP(previous) && v->u.l.f == NO_JUMP && v->u.l.t == NO_JUMP) { /* expression has no jumps */ if (onlyone) @@ -623,17 +621,15 @@ int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2) { case iS: i = CREATE_S(o, arg1); break; case iAB: i = CREATE_AB(o, arg1, arg2); break; } - /* check space for new instruction plus eventual SETLINE */ - luaM_growvector(fs->L, fs->f->code, fs->pc, 2, Instruction, - "code size overflow", MAX_INT); - /* check the need for SETLINE */ - if (fs->debug && fs->ls->lastline != fs->lastsetline) { + if (fs->f->debug) { LexState *ls = fs->ls; luaX_checklimit(ls, ls->lastline, MAXARG_U, "lines in a chunk"); - fs->f->code[fs->pc++] = CREATE_U(OP_SETLINE, ls->lastline); - fs->lastsetline = ls->lastline; + luaM_growvector(fs->L, fs->f->lines, fs->pc, 1, int, "??", MAXARG_U); + fs->f->lines[fs->pc] = ls->lastline; } /* put new instruction in code array */ + luaM_growvector(fs->L, fs->f->code, fs->pc, 1, Instruction, + "code size overflow", MAX_INT); fs->f->code[fs->pc] = i; return fs->pc++; } @@ -688,6 +684,5 @@ const struct OpProperties luaK_opproperties[NUM_OPCODES] = { {iS, -3}, /* OP_FORLOOP */ {iS, 3}, /* OP_LFORPREP */ {iS, -4}, /* OP_LFORLOOP */ - {iAB, VD}, /* OP_CLOSURE */ - {iU, 0} /* OP_SETLINE */ + {iAB, VD} /* OP_CLOSURE */ }; diff --git a/ldebug.c b/ldebug.c index 6d26029b..c816200d 100644 --- a/ldebug.c +++ b/ldebug.c @@ -1,5 +1,5 @@ /* -** $Id: ldebug.c,v 1.22 2000/06/08 17:48:31 roberto Exp roberto $ +** $Id: ldebug.c,v 1.23 2000/06/12 13:52:05 roberto Exp roberto $ ** Debug Interface ** See Copyright Notice in lua.h */ @@ -23,22 +23,21 @@ #include "luadebug.h" -static const lua_Type normtype[] = { /* ORDER LUA_T */ - TAG_USERDATA, TAG_NUMBER, TAG_STRING, TAG_TABLE, - TAG_LCLOSURE, TAG_CCLOSURE, TAG_NIL, - TAG_LCLOSURE, TAG_CCLOSURE /* TAG_LMARK, TAG_CMARK */ -}; - static void setnormalized (TObject *d, const TObject *s) { - d->value = s->value; - d->ttype = normtype[ttype(s)]; -} - - - -static int hasdebuginfo (lua_State *L, StkId f) { - return (f+1 < L->top && (f+1)->ttype == TAG_LINE); + switch (s->ttype) { + case TAG_CMARK: { + clvalue(d) = clvalue(s); + ttype(d) = TAG_CCLOSURE; + break; + } + case TAG_LMARK: { + clvalue(d) = infovalue(s)->func; + ttype(d) = TAG_LCLOSURE; + break; + } + default: *d = *s; + } } @@ -88,22 +87,35 @@ int lua_getstack (lua_State *L, int level, lua_Debug *ar) { static int lua_nups (StkId f) { switch (ttype(f)) { - case TAG_LCLOSURE: case TAG_CCLOSURE: - case TAG_LMARK: case TAG_CMARK: + case TAG_LCLOSURE: case TAG_CCLOSURE: case TAG_CMARK: return clvalue(f)->nupvalues; + case TAG_LMARK: + return infovalue(f)->func->nupvalues; default: return 0; } } -static int lua_currentline (lua_State *L, StkId f) { - return hasdebuginfo(L, f) ? (f+1)->value.i : -1; +static int lua_currentline (StkId f) { + if (ttype(f) != TAG_LMARK) + return -1; /* only active lua functions have current-line information */ + else { + CallInfo *ci = infovalue(f); + int *lines = ci->func->f.l->lines; + if (!lines) return -1; /* no static debug information */ + else return lines[ci->pc]; + } +} + + +static int lua_currentpc (StkId f) { + return infovalue(f)->pc; } static Proto *getluaproto (StkId f) { - return (ttype(f) == TAG_LMARK) ? clvalue(f)->f.l : NULL; + return (ttype(f) == TAG_LMARK) ? infovalue(f)->func->f.l : NULL; } @@ -111,12 +123,9 @@ int lua_getlocal (lua_State *L, const lua_Debug *ar, lua_Localvar *v) { StkId f = ar->_func; Proto *fp = getluaproto(f); if (!fp) return 0; /* `f' is not a Lua function? */ - v->name = luaF_getlocalname(fp, v->index, lua_currentline(L, f)); + v->name = luaF_getlocalname(fp, v->index, lua_currentpc(f)); if (!v->name) return 0; - /* if `name', there must be a TAG_LINE */ - /* therefore, f+2 points to function base */ - LUA_ASSERT(L, ttype(f+1) == TAG_LINE, ""); - v->value = luaA_putluaObject(L, (f+2)+(v->index-1)); + v->value = luaA_putluaObject(L, (f+1)+(v->index-1)); return 1; } @@ -124,22 +133,27 @@ int lua_getlocal (lua_State *L, const lua_Debug *ar, lua_Localvar *v) { int lua_setlocal (lua_State *L, const lua_Debug *ar, lua_Localvar *v) { StkId f = ar->_func; Proto *fp = getluaproto(f); + UNUSED(L); if (!fp) return 0; /* `f' is not a Lua function? */ - v->name = luaF_getlocalname(fp, v->index, lua_currentline(L, f)); + v->name = luaF_getlocalname(fp, v->index, lua_currentpc(f)); if (!v->name || v->name[0] == '*') return 0; /* `*' starts private locals */ - LUA_ASSERT(L, ttype(f+1) == TAG_LINE, ""); - *((f+2)+(v->index-1)) = *v->value; + *((f+1)+(v->index-1)) = *v->value; return 1; } static void lua_funcinfo (lua_Debug *ar, StkId func) { switch (ttype(func)) { - case TAG_LCLOSURE: case TAG_LMARK: + case TAG_LCLOSURE: ar->source = clvalue(func)->f.l->source->str; ar->linedefined = clvalue(func)->f.l->lineDefined; ar->what = "Lua"; break; + case TAG_LMARK: + ar->source = infovalue(func)->func->f.l->source->str; + ar->linedefined = infovalue(func)->func->f.l->lineDefined; + ar->what = "Lua"; + break; case TAG_CCLOSURE: case TAG_CMARK: ar->source = "(C)"; ar->linedefined = -1; @@ -191,7 +205,7 @@ int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { lua_funcinfo(ar, func); break; case 'l': - ar->currentline = lua_currentline(L, func); + ar->currentline = lua_currentline(func); break; case 'u': ar->nups = lua_nups(func); diff --git a/ldo.c b/ldo.c index 6f04c374..8fe2ca38 100644 --- a/ldo.c +++ b/ldo.c @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 1.78 2000/06/12 13:52:05 roberto Exp roberto $ +** $Id: ldo.c,v 1.79 2000/06/16 17:16:34 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -185,10 +185,14 @@ void luaD_call (lua_State *L, StkId func, int nResults) { retry: /* for `function' tag method */ switch (ttype(func)) { case TAG_LCLOSURE: { + CallInfo ci; + ci.func = clvalue(func); + ci.pc = 0; ttype(func) = TAG_LMARK; + infovalue(func) = &ci; if (callhook) luaD_callHook(L, func, callhook, "call"); - firstResult = luaV_execute(L, clvalue(func), func+1); + firstResult = luaV_execute(L, ci.func, func+1); break; } case TAG_CCLOSURE: { diff --git a/lfunc.c b/lfunc.c index 39753bdc..cabe717f 100644 --- a/lfunc.c +++ b/lfunc.c @@ -1,5 +1,5 @@ /* -** $Id: lfunc.c,v 1.23 2000/05/30 19:00:31 roberto Exp roberto $ +** $Id: lfunc.c,v 1.24 2000/06/12 13:52:05 roberto Exp roberto $ ** Auxiliary functions to manipulate prototypes and closures ** See Copyright Notice in lua.h */ @@ -35,6 +35,7 @@ Closure *luaF_newclosure (lua_State *L, int nelems) { Proto *luaF_newproto (lua_State *L) { Proto *f = luaM_new(L, Proto); f->code = NULL; + f->lines = NULL; f->lineDefined = 0; f->source = NULL; f->kstr = NULL; @@ -59,6 +60,7 @@ void luaF_freeproto (lua_State *L, Proto *f) { luaM_free(L, f->kstr); luaM_free(L, f->knum); luaM_free(L, f->kproto); + luaM_free(L, f->lines); luaM_free(L, f); } @@ -73,14 +75,13 @@ void luaF_freeclosure (lua_State *L, Closure *c) { ** Look for n-th local variable at line `line' in function `func'. ** Returns NULL if not found. */ -const char *luaF_getlocalname (const Proto *func, - int local_number, int line) { +const char *luaF_getlocalname (const Proto *func, int local_number, int pc) { int count = 0; const char *varname = NULL; LocVar *lv = func->locvars; if (lv == NULL) return NULL; - for (; lv->line != -1 && lv->line < line; lv++) { + for (; lv->pc != -1 && lv->pc <= pc; lv++) { if (lv->varname) { /* register */ if (++count == local_number) varname = lv->varname->str; diff --git a/lfunc.h b/lfunc.h index a0dc7817..1182e3fa 100644 --- a/lfunc.h +++ b/lfunc.h @@ -1,5 +1,5 @@ /* -** $Id: lfunc.h,v 1.10 1999/12/27 17:33:22 roberto Exp roberto $ +** $Id: lfunc.h,v 1.11 2000/03/10 18:37:44 roberto Exp roberto $ ** Auxiliary functions to manipulate prototypes and closures ** See Copyright Notice in lua.h */ @@ -17,8 +17,7 @@ Closure *luaF_newclosure (lua_State *L, int nelems); void luaF_freeproto (lua_State *L, Proto *f); void luaF_freeclosure (lua_State *L, Closure *c); -const char *luaF_getlocalname (const Proto *func, - int local_number, int line); +const char *luaF_getlocalname (const Proto *func, int local_number, int pc); #endif diff --git a/lgc.c b/lgc.c index bc0494f0..3bcfd1b7 100644 --- a/lgc.c +++ b/lgc.c @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 1.56 2000/06/08 17:48:31 roberto Exp roberto $ +** $Id: lgc.c,v 1.57 2000/06/12 13:52:05 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -41,7 +41,7 @@ static void protomark (lua_State *L, Proto *f) { protomark(L, f->kproto[i]); if (f->locvars) { /* is there debug information? */ LocVar *lv; - for (lv=f->locvars; lv->line != -1; lv++) /* mark local-variable names */ + for (lv=f->locvars; lv->pc != -1; lv++) /* mark local-variable names */ if (lv->varname) strmark(L, lv->varname); } } @@ -99,9 +99,16 @@ static int markobject (lua_State *L, TObject *o) { case TAG_TABLE: tablemark(L, hvalue(o)); break; - case TAG_LCLOSURE: case TAG_LMARK: + case TAG_LCLOSURE: protomark(L, clvalue(o)->f.l); - /* go trhough */ + closuremark(L, clvalue(o)); + break; + case TAG_LMARK: { + Closure *cl = infovalue(o)->func; + protomark(L, cl->f.l); + closuremark(L, cl); + break; + } case TAG_CCLOSURE: case TAG_CMARK: closuremark(L, clvalue(o)); break; diff --git a/lmem.c b/lmem.c index b60285a6..f41d92d5 100644 --- a/lmem.c +++ b/lmem.c @@ -1,5 +1,5 @@ /* -** $Id: lmem.c,v 1.32 2000/05/31 16:53:30 roberto Exp roberto $ +** $Id: lmem.c,v 1.33 2000/06/12 13:52:05 roberto Exp roberto $ ** Interface to Memory Manager ** See Copyright Notice in lua.h */ @@ -47,7 +47,8 @@ /* ensures maximum alignment for HEADER */ -#define HEADER (sizeof(union { double d; char *s; long l; })) +union L_U { double d; char *s; long l; }; +#define HEADER (sizeof(union L_U)) #define MARKSIZE 16 #define MARK 0x55 /* 01010101 (a nice pattern) */ diff --git a/lobject.c b/lobject.c index d500fd1c..7d26a981 100644 --- a/lobject.c +++ b/lobject.c @@ -1,5 +1,5 @@ /* -** $Id: lobject.c,v 1.40 2000/06/08 17:48:31 roberto Exp roberto $ +** $Id: lobject.c,v 1.41 2000/06/12 13:52:05 roberto Exp roberto $ ** Some generic functions over Lua objects ** See Copyright Notice in lua.h */ @@ -16,7 +16,7 @@ const char *const luaO_typenames[] = { /* ORDER LUA_T */ "userdata", "number", "string", "table", "function", "function", "nil", - "function", "function", "line" + "function", "function" }; diff --git a/lobject.h b/lobject.h index 0395afa3..2a61d138 100644 --- a/lobject.h +++ b/lobject.h @@ -1,5 +1,5 @@ /* -** $Id: lobject.h,v 1.66 2000/05/30 19:00:31 roberto Exp roberto $ +** $Id: lobject.h,v 1.67 2000/06/08 18:27:13 roberto Exp roberto $ ** Type definitions for Lua objects ** See Copyright Notice in lua.h */ @@ -46,9 +46,8 @@ typedef enum { TAG_NIL, /* last "pre-defined" tag */ TAG_LMARK, /* mark for Lua closures */ - TAG_CMARK, /* mark for C closures */ + TAG_CMARK /* mark for C closures */ - TAG_LINE } lua_Type; /* tags for values visible from Lua == first user-created tag */ @@ -63,10 +62,10 @@ typedef enum { typedef union { struct TString *ts; /* TAG_STRING, TAG_USERDATA */ - struct Closure *cl; /* TAG_[CL]CLOSURE, TAG_[CL]MARK */ + struct Closure *cl; /* TAG_[CL]CLOSURE, TAG_CMARK */ struct Hash *a; /* TAG_TABLE */ + struct CallInfo *i; /* TAG_LMARK */ Number n; /* TAG_NUMBER */ - int i; /* TAG_LINE */ } Value; @@ -76,6 +75,7 @@ typedef union { #define tsvalue(o) ((o)->value.ts) #define clvalue(o) ((o)->value.cl) #define hvalue(o) ((o)->value.a) +#define infovalue(o) ((o)->value.i) #define svalue(o) (tsvalue(o)->str) @@ -119,8 +119,10 @@ typedef struct Proto { struct Proto **kproto; /* functions defined inside the function */ int nkproto; /* size of `kproto' */ Instruction *code; /* ends with opcode ENDCODE */ + int *lines; /* source line that generated each opcode */ int lineDefined; TString *source; + int debug; /* flag for debug information */ int numparams; int is_vararg; int maxstacksize; @@ -130,7 +132,7 @@ typedef struct Proto { typedef struct LocVar { TString *varname; /* NULL signals end of scope */ - int line; + int pc; } LocVar; @@ -165,6 +167,16 @@ typedef struct Hash { } Hash; +/* +** informations about a call (for debugging) +*/ +typedef struct CallInfo { + int pc; /* current pc of called function */ + int line; /* current line */ + struct Closure *func; /* function being called */ +} CallInfo; + + extern const char *const luaO_typenames[]; extern const TObject luaO_nilobject; diff --git a/lopcodes.h b/lopcodes.h index f98f562b..e5067493 100644 --- a/lopcodes.h +++ b/lopcodes.h @@ -1,5 +1,5 @@ /* -** $Id: lopcodes.h,v 1.63 2000/06/05 14:56:18 roberto Exp roberto $ +** $Id: lopcodes.h,v 1.64 2000/06/21 17:05:49 roberto Exp roberto $ ** Opcodes for Lua virtual machine ** See Copyright Notice in lua.h */ @@ -146,13 +146,11 @@ OP_FORLOOP,/* J */ OP_LFORPREP,/* J */ OP_LFORLOOP,/* J */ -OP_CLOSURE,/* A B v_b-v_1 closure(KPROTO[a], v_1-v_b) */ - -OP_SETLINE/* U - - LINE=u */ +OP_CLOSURE/* A B v_b-v_1 closure(KPROTO[a], v_1-v_b) */ } OpCode; -#define NUM_OPCODES ((int)OP_SETLINE+1) +#define NUM_OPCODES ((int)OP_CLOSURE+1) #define ISJUMP(o) (OP_JMPNE <= (o) && (o) <= OP_JMP) diff --git a/lparser.c b/lparser.c index e920af3e..725ff0ed 100644 --- a/lparser.c +++ b/lparser.c @@ -1,5 +1,5 @@ /* -** $Id: lparser.c,v 1.97 2000/06/19 18:26:23 roberto Exp roberto $ +** $Id: lparser.c,v 1.98 2000/06/21 18:13:56 roberto Exp roberto $ ** LL(1) Parser and code generator for Lua ** See Copyright Notice in lua.h */ @@ -152,19 +152,19 @@ static int checkname (LexState *ls) { } -static void luaI_registerlocalvar (LexState *ls, TString *varname, int line) { +static void luaI_registerlocalvar (LexState *ls, TString *varname, int pc) { FuncState *fs = ls->fs; - if (fs->debug) { + if (fs->f->debug) { Proto *f = fs->f; luaM_growvector(ls->L, f->locvars, fs->nvars, 1, LocVar, "", MAX_INT); f->locvars[fs->nvars].varname = varname; - f->locvars[fs->nvars].line = line; + f->locvars[fs->nvars].pc = pc; fs->nvars++; } } -static void store_localvar (LexState *ls, TString *name, int n) { +static void new_localvar (LexState *ls, TString *name, int n) { FuncState *fs = ls->fs; luaX_checklimit(ls, fs->nlocalvar+n+1, MAXLOCALS, "local variables"); fs->localvar[fs->nlocalvar+n] = name; @@ -172,27 +172,27 @@ static void store_localvar (LexState *ls, TString *name, int n) { static void adjustlocalvars (LexState *ls, int nvars) { - int line = ls->fs->lastsetline; FuncState *fs = ls->fs; int i; + /* `pc' is first opcode where variable is already active */ for (i=fs->nlocalvar; inlocalvar+nvars; i++) - luaI_registerlocalvar(ls, fs->localvar[i], line); + luaI_registerlocalvar(ls, fs->localvar[i], fs->pc); fs->nlocalvar += nvars; } static void removelocalvars (LexState *ls, int nvars) { - int line = ls->fs->lastsetline; + FuncState *fs = ls->fs; int i; + /* `pc' is first opcode where variable is already dead */ for (i=0;ifs->nlocalvar -= nvars; + luaI_registerlocalvar(ls, NULL, fs->pc); + fs->nlocalvar -= nvars; } -static void add_localvar (LexState *ls, const char *name) { - store_localvar(ls, luaS_newfixed(ls->L, name), 0); - adjustlocalvars(ls, 1); +static void new_localvarstr (LexState *ls, const char *name, int n) { + new_localvar(ls, luaS_newfixed(ls->L, name), n); } @@ -277,8 +277,10 @@ static void code_params (LexState *ls, int nparams, int dots) { luaX_checklimit(ls, fs->nlocalvar, MAXPARAMS, "parameters"); fs->f->numparams = fs->nlocalvar; /* `self' could be there already */ fs->f->is_vararg = dots; - if (dots) - add_localvar(ls, "arg"); + if (dots) { + new_localvarstr(ls, "arg", 0); + adjustlocalvars(ls, 1); + } luaK_deltastack(fs, fs->nlocalvar); /* count parameters in the stack */ } @@ -320,7 +322,6 @@ static void open_func (LexState *ls, FuncState *fs) { fs->stacklevel = 0; fs->nlocalvar = 0; fs->nupvalues = 0; - fs->lastsetline = 0; fs->bl = NULL; fs->f = f; f->source = ls->source; @@ -358,7 +359,7 @@ Proto *luaY_parser (lua_State *L, ZIO *z) { luaX_setinput(L, &lexstate, z, luaS_new(L, zname(z))); open_func(&lexstate, &funcstate); next(&lexstate); /* read first token */ - funcstate.debug = L->debug; /* previous `next' may scan a pragma */ + funcstate.f->debug = L->debug; /* previous `next' may scan a pragma */ chunk(&lexstate); check_condition(&lexstate, (lexstate.t.token == TK_EOS), " expected"); close_func(&lexstate); @@ -821,22 +822,23 @@ static void repeatstat (LexState *ls, int line) { } -static void forbody (LexState *ls, OpCode prepfor, OpCode loopfor) { +static void forbody (LexState *ls, int nvar, OpCode prepfor, OpCode loopfor) { /* forbody -> DO block END */ FuncState *fs = ls->fs; int prep = luaK_code1(fs, prepfor, NO_JUMP); int blockinit = luaK_getlabel(fs); check(ls, TK_DO); + adjustlocalvars(ls, nvar); /* scope for control variables */ block(ls); luaK_patchlist(fs, prep, luaK_getlabel(fs)); luaK_patchlist(fs, luaK_code1(fs, loopfor, NO_JUMP), blockinit); + removelocalvars(ls, nvar); } static void fornum (LexState *ls, TString *varname) { /* fornum -> NAME = exp1,exp1[,exp1] forbody */ FuncState *fs = ls->fs; - store_localvar(ls, varname, 0); check(ls, '='); exp1(ls); /* initial value */ check(ls, ','); @@ -845,11 +847,10 @@ static void fornum (LexState *ls, TString *varname) { exp1(ls); /* optional step */ else luaK_code1(fs, OP_PUSHINT, 1); /* default step */ - adjustlocalvars(ls, 1); /* scope for control variables */ - add_localvar(ls, "*limit*"); - add_localvar(ls, "*count*"); - forbody(ls, OP_FORPREP, OP_FORLOOP); - removelocalvars(ls, 3); + new_localvar(ls, varname, 0); + new_localvarstr(ls, "*limit*", 1); + new_localvarstr(ls, "*step*", 2); + forbody(ls, 3, OP_FORPREP, OP_FORLOOP); } @@ -864,13 +865,11 @@ static void forlist (LexState *ls, TString *indexname) { "`in' expected"); next(ls); /* skip `in' */ exp1(ls); /* table */ - add_localvar(ls, "*table*"); - add_localvar(ls, "*counter*"); - store_localvar(ls, indexname, 0); - store_localvar(ls, valname, 1); - adjustlocalvars(ls, 2); /* scope for control variable */ - forbody(ls, OP_LFORPREP, OP_LFORLOOP); - removelocalvars(ls, 4); + new_localvarstr(ls, "*table*", 0); + new_localvarstr(ls, "*counter*", 1); + new_localvar(ls, indexname, 2); + new_localvar(ls, valname, 3); + forbody(ls, 4, OP_LFORPREP, OP_LFORLOOP); } @@ -931,7 +930,7 @@ static void localstat (LexState *ls) { int nexps; do { next(ls); /* skip LOCAL or ',' */ - store_localvar(ls, str_checkname(ls), nvars++); + new_localvar(ls, str_checkname(ls), nvars++); } while (ls->t.token == ','); if (optional(ls, '=')) nexps = explist1(ls); @@ -1072,7 +1071,7 @@ static void parlist (LexState *ls) { do { switch (ls->t.token) { case TK_DOTS: next(ls); dots = 1; break; - case TK_NAME: store_localvar(ls, str_checkname(ls), nparams++); break; + case TK_NAME: new_localvar(ls, str_checkname(ls), nparams++); break; default: luaK_error(ls, " or `...' expected"); } } while (!dots && optional(ls, ',')); @@ -1086,10 +1085,12 @@ static void body (LexState *ls, int needself, int line) { FuncState new_fs; open_func(ls, &new_fs); new_fs.f->lineDefined = line; - new_fs.debug = ls->L->debug; + new_fs.f->debug = ls->L->debug; check(ls, '('); - if (needself) - add_localvar(ls, "self"); + if (needself) { + new_localvarstr(ls, "self", 0); + adjustlocalvars(ls, 1); + } parlist(ls); check(ls, ')'); chunk(ls); diff --git a/lparser.h b/lparser.h index 2fb8e000..2432c08e 100644 --- a/lparser.h +++ b/lparser.h @@ -1,5 +1,5 @@ /* -** $Id: lparser.h,v 1.17 2000/05/25 18:26:42 roberto Exp roberto $ +** $Id: lparser.h,v 1.18 2000/06/21 18:13:56 roberto Exp roberto $ ** LL(1) Parser and code generator for Lua ** See Copyright Notice in lua.h */ @@ -48,8 +48,6 @@ typedef struct FuncState { int nlocalvar; /* number of active local variables */ int nupvalues; /* number of upvalues */ int nvars; /* number of entries in f->locvars */ - int lastsetline; /* line where last SETLINE was issued */ - int debug; /* flag to generate debug information */ struct Breaklabel *bl; /* chain of breakable blocks */ expdesc upvalues[MAXUPVALUES]; /* upvalues */ TString *localvar[MAXLOCALS]; /* store local variable names */ diff --git a/ltests.c b/ltests.c index dd247b5b..7e7c980b 100644 --- a/ltests.c +++ b/ltests.c @@ -1,5 +1,5 @@ /* -** $Id: ltests.c,v 1.25 2000/06/12 13:52:05 roberto Exp roberto $ +** $Id: ltests.c,v 1.26 2000/06/21 17:05:49 roberto Exp roberto $ ** Internal Module for Debugging of the Lua Implementation ** See Copyright Notice in lua.h */ @@ -58,7 +58,7 @@ static const char *const instrname[NUM_OPCODES] = { "ADD", "ADDI", "SUB", "MULT", "DIV", "POW", "CONCAT", "MINUS", "NOT", "JMPNE", "JMPEQ", "JMPLT", "JMPLE", "JMPGT", "JMPGE", "JMPT", "JMPF", "JMPONT", "JMPONF", "JMP", "PUSHNILJMP", "FORPREP", "FORLOOP", "LFORPREP", - "LFORLOOP", "CLOSURE", "SETLINE" + "LFORLOOP", "CLOSURE" }; diff --git a/lundump.c b/lundump.c index 97ceccaf..36c89704 100644 --- a/lundump.c +++ b/lundump.c @@ -1,5 +1,5 @@ /* -** $Id: lundump.c,v 1.21 2000/05/08 19:32:53 roberto Exp roberto $ +** $Id: lundump.c,v 1.22 2000/06/12 13:52:05 roberto Exp roberto $ ** load bytecodes from files ** See Copyright Notice in lua.h */ @@ -93,7 +93,7 @@ static TString* LoadString (lua_State* L, ZIO* Z) static void SwapCode (lua_State* L, Instruction* code, int size, ZIO* Z) { unsigned char* p; - int c; + unsigned char c; if (sizeof(Instruction)==4) while (size--) { @@ -138,10 +138,10 @@ static void LoadLocals (lua_State* L, Proto* tf, ZIO* Z) tf->locvars=luaM_newvector(L,n+1,LocVar); for (i=0; ilocvars[i].line=LoadInt(L,Z,"too many lines"); + tf->locvars[i].pc=LoadInt(L,Z,"too many lines"); tf->locvars[i].varname=LoadString(L,Z); } - tf->locvars[i].line=-1; /* flag end of vector */ + tf->locvars[i].pc=-1; /* flag end of vector */ tf->locvars[i].varname=NULL; } diff --git a/lvm.c b/lvm.c index 1a21a116..77faadfa 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 1.115 2000/06/12 13:52:05 roberto Exp roberto $ +** $Id: lvm.c,v 1.116 2000/06/19 18:04:41 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -67,6 +67,23 @@ int luaV_tostring (lua_State *L, TObject *obj) { /* LUA_NUMBER */ } +static void traceexec (lua_State *L, StkId base, int pc) { + CallInfo *ci = infovalue(base-1); + int oldpc = ci->pc; + pc--; /* pc has been already incremented */ + ci->pc = pc; + if (L->linehook && ci->func->f.l->debug) { + int *lines = ci->func->f.l->lines; + LUA_ASSERT(L, lines, "must have debug information"); + /* calls linehook when jumps back (a loop) or enters a new line */ + if (pc <= oldpc || lines[pc] != ci->line) { + ci->line = lines[pc]; + luaD_lineHook(L, base-2, lines[pc]); + } + } +} + + static Closure *luaV_closure (lua_State *L, lua_Type t, int nelems) { Closure *c = luaF_newclosure(L, nelems); L->top -= nelems; @@ -226,13 +243,6 @@ static void call_arith (lua_State *L, StkId top, IMS event) { } -static void addK (lua_State *L, StkId top, int k) { - ttype(top) = TAG_NUMBER; - nvalue(top) = (Number)k; - call_arith(L, top+1, IM_ADD); -} - - static int luaV_strcomp (const TString *ls, const TString *rs) { const char *l = ls->str; size_t ll = ls->u.s.len; @@ -338,6 +348,7 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) { StkId top; /* keep top local, for performance */ const Instruction *pc = tf->code; TString **kstr = tf->kstr; + int debug = tf->debug; luaD_checkstack(L, tf->maxstacksize+EXTRA_STACK); if (tf->is_vararg) { /* varargs? */ adjust_varargs(L, base, tf->numparams); @@ -346,8 +357,13 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) { else luaD_adjusttop(L, base, tf->numparams); top = L->top; + /* main loop of interpreter */ for (;;) { Instruction i = *pc++; + if (debug) { + L->top = top; + traceexec(L, base, pc - tf->code); + } switch (GET_OPCODE(i)) { case OP_END: @@ -499,8 +515,11 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) { break; case OP_ADDI: - if (tonumber(top-1)) - addK(L, top, GETARG_S(i)); + if (tonumber(top-1)) { + ttype(top) = TAG_NUMBER; + nvalue(top) = (Number)GETARG_S(i); + call_arith(L, top+1, IM_ADD); + } else nvalue(top-1) += (Number)GETARG_S(i); break; @@ -622,35 +641,44 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) { lua_error(L, "`for' limit must be a number"); if (tonumber(top-3)) lua_error(L, "`for' initial value must be a number"); - /* number of steps */ - nvalue(top-2) = (nvalue(top-2)-nvalue(top-3))/nvalue(top-1); - nvalue(top-3) -= nvalue(top-1); /* to be undone by first FORLOOP */ - pc += GETARG_S(i); + if (nvalue(top-1) > 0 ? + nvalue(top-3) > nvalue(top-2) : + nvalue(top-3) < nvalue(top-2)) { /* `empty' loop? */ + top -= 3; /* remove control variables */ + pc += GETARG_S(i)+1; /* jump to loop end */ + } break; case OP_FORLOOP: { LUA_ASSERT(L, ttype(top-1) == TAG_NUMBER, "invalid step"); - LUA_ASSERT(L, ttype(top-2) == TAG_NUMBER, "invalid count"); - if (nvalue(top-2) < 0) + LUA_ASSERT(L, ttype(top-2) == TAG_NUMBER, "invalid limit"); + if (ttype(top-3) != TAG_NUMBER) + lua_error(L, "`for' index must be a number"); + nvalue(top-3) += nvalue(top-1); /* increment index */ + if (nvalue(top-1) > 0 ? + nvalue(top-3) > nvalue(top-2) : + nvalue(top-3) < nvalue(top-2)) top -= 3; /* end loop: remove control variables */ - else { - nvalue(top-2)--; /* decrement count */ - if (ttype(top-3) != TAG_NUMBER) - lua_error(L, "`for' index must be a number"); - nvalue(top-3) += nvalue(top-1); /* increment index */ - pc += GETARG_S(i); - } + else + pc += GETARG_S(i); /* repeat loop */ break; } case OP_LFORPREP: { if (ttype(top-1) != TAG_TABLE) lua_error(L, "`for' table must be a table"); - top += 3; /* counter + index,value */ - ttype(top-3) = TAG_NUMBER; - nvalue(top-3) = 0.0; /* counter */ - ttype(top-2) = ttype(top-1) = TAG_NIL; - pc += GETARG_S(i); + top++; /* counter */ + L->top = top; + ttype(top-1) = TAG_NUMBER; + nvalue(top-1) = (Number)luaA_next(L, hvalue(top-2), 0); /* counter */ + if (nvalue(top-1) == 0) { /* `empty' loop? */ + top -= 2; /* remove table and counter */ + pc += GETARG_S(i)+1; /* jump to loop end */ + } + else { + top += 2; /* index,value */ + LUA_ASSERT(L, top==L->top, "bad top"); + } break; } @@ -678,22 +706,6 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) { luaC_checkGC(L); break; - case OP_SETLINE: - if ((base-1)->ttype != TAG_LINE) { - /* open space for LINE value */ - int n = top-base; - while (n--) base[n+1] = base[n]; - base++; - top++; - (base-1)->ttype = TAG_LINE; - } - (base-1)->value.i = GETARG_U(i); - if (L->linehook) { - L->top = top; - luaD_lineHook(L, base-2, GETARG_U(i)); - } - break; - } } }