commit afef009fcea199bd4eff28ea6e5206b59cda9939
parent b69e712713785394ceefa11ab3e5f9636abea733
Author: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date: Mon, 26 Jun 2000 16:28:09 -0300
new version of debug system
Diffstat:
15 files changed, 201 insertions(+), 159 deletions(-)
diff --git 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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; i<fs->nlocalvar+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;i<nvars;i++)
- luaI_registerlocalvar(ls, NULL, line);
- ls->fs->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), "<eof> 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, "<name> 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
@@ -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
@@ -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
@@ -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; i<n; i++)
{
- tf->locvars[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
@@ -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;
-
}
}
}