فهرست منبع

new version of debug system

Roberto Ierusalimschy 25 سال پیش
والد
کامیت
afef009fce
15فایلهای تغییر یافته به همراه201 افزوده شده و 159 حذف شده
  1. 7 12
      lcode.c
  2. 44 30
      ldebug.c
  3. 6 2
      ldo.c
  4. 5 4
      lfunc.c
  5. 2 3
      lfunc.h
  6. 11 4
      lgc.c
  7. 3 2
      lmem.c
  8. 2 2
      lobject.c
  9. 18 6
      lobject.h
  10. 3 5
      lopcodes.h
  11. 37 36
      lparser.c
  12. 1 3
      lparser.h
  13. 2 2
      ltests.c
  14. 4 4
      lundump.c
  15. 56 44
      lvm.c

+ 7 - 12
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 */
 };

+ 44 - 30
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);

+ 6 - 2
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: {

+ 5 - 4
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;

+ 2 - 3
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

+ 11 - 4
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;

+ 3 - 2
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) */

+ 2 - 2
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"
 };
 
 

+ 18 - 6
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;
 

+ 3 - 5
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)

+ 37 - 36
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);

+ 1 - 3
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 */

+ 2 - 2
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"
 };
 
 

+ 4 - 4
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;
 }
 

+ 56 - 44
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;
-
     }
   }
 }