better error messages

This commit is contained in:
Roberto Ierusalimschy 2000-06-28 17:21:06 -03:00
parent b622282973
commit 014a09c509
10 changed files with 230 additions and 104 deletions

108
lcode.c
View File

@ -1,5 +1,5 @@
/*
** $Id: lcode.c,v 1.38 2000/06/21 18:13:56 roberto Exp roberto $
** $Id: lcode.c,v 1.39 2000/06/26 19:28:31 roberto Exp roberto $
** Code generator for Lua
** See Copyright Notice in lua.h
*/
@ -423,12 +423,9 @@ int luaK_code1 (FuncState *fs, OpCode o, int arg1) {
}
#define VD 100 /* flag for variable delta */
int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2) {
Instruction i = previous_instruction(fs);
int delta = luaK_opproperties[o].delta;
int delta = luaK_opproperties[o].push - luaK_opproperties[o].pop;
int optm = 0; /* 1 when there is an optimization */
switch (o) {
case OP_CLOSURE: {
@ -621,7 +618,7 @@ 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;
}
if (fs->f->debug) {
if (fs->debug) {
LexState *ls = fs->ls;
luaX_checklimit(ls, ls->lastline, MAXARG_U, "lines in a chunk");
luaM_growvector(fs->L, fs->f->lines, fs->pc, 1, int, "??", MAXARG_U);
@ -636,53 +633,54 @@ int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2) {
const struct OpProperties luaK_opproperties[NUM_OPCODES] = {
{iO, 0}, /* OP_END */
{iU, 0}, /* OP_RETURN */
{iAB, 0}, /* OP_CALL */
{iAB, 0}, /* OP_TAILCALL */
{iU, VD}, /* OP_PUSHNIL */
{iU, VD}, /* OP_POP */
{iS, 1}, /* OP_PUSHINT */
{iU, 1}, /* OP_PUSHSTRING */
{iU, 1}, /* OP_PUSHNUM */
{iU, 1}, /* OP_PUSHNEGNUM */
{iU, 1}, /* OP_PUSHUPVALUE */
{iU, 1}, /* OP_GETLOCAL */
{iU, 1}, /* OP_GETGLOBAL */
{iO, -1}, /* OP_GETTABLE */
{iU, 0}, /* OP_GETDOTTED */
{iU, 0}, /* OP_GETINDEXED */
{iU, 1}, /* OP_PUSHSELF */
{iU, 1}, /* OP_CREATETABLE */
{iU, -1}, /* OP_SETLOCAL */
{iU, -1}, /* OP_SETGLOBAL */
{iAB, VD}, /* OP_SETTABLE */
{iAB, VD}, /* OP_SETLIST */
{iU, VD}, /* OP_SETMAP */
{iO, -1}, /* OP_ADD */
{iS, 0}, /* OP_ADDI */
{iO, -1}, /* OP_SUB */
{iO, -1}, /* OP_MULT */
{iO, -1}, /* OP_DIV */
{iO, -1}, /* OP_POW */
{iU, VD}, /* OP_CONCAT */
{iO, 0}, /* OP_MINUS */
{iO, 0}, /* OP_NOT */
{iS, -2}, /* OP_JMPNE */
{iS, -2}, /* OP_JMPEQ */
{iS, -2}, /* OP_JMPLT */
{iS, -2}, /* OP_JMPLE */
{iS, -2}, /* OP_JMPGT */
{iS, -2}, /* OP_JMPGE */
{iS, -1}, /* OP_JMPT */
{iS, -1}, /* OP_JMPF */
{iS, -1}, /* OP_JMPONT */
{iS, -1}, /* OP_JMPONF */
{iS, 0}, /* OP_JMP */
{iO, 1}, /* OP_PUSHNILJMP */
{iS, 0}, /* OP_FORPREP */
{iS, -3}, /* OP_FORLOOP */
{iS, 3}, /* OP_LFORPREP */
{iS, -4}, /* OP_LFORLOOP */
{iAB, VD} /* OP_CLOSURE */
{iO, 0, 0}, /* OP_END */
{iU, 0, 0}, /* OP_RETURN */
{iAB, 0, 0}, /* OP_CALL */
{iAB, 0, 0}, /* OP_TAILCALL */
{iU, VD, 0}, /* OP_PUSHNIL */
{iU, VD, 0}, /* OP_POP */
{iS, 1, 0}, /* OP_PUSHINT */
{iU, 1, 0}, /* OP_PUSHSTRING */
{iU, 1, 0}, /* OP_PUSHNUM */
{iU, 1, 0}, /* OP_PUSHNEGNUM */
{iU, 1, 0}, /* OP_PUSHUPVALUE */
{iU, 1, 0}, /* OP_GETLOCAL */
{iU, 1, 0}, /* OP_GETGLOBAL */
{iO, 1, 2}, /* OP_GETTABLE */
{iU, 1, 1}, /* OP_GETDOTTED */
{iU, 1, 1}, /* OP_GETINDEXED */
{iU, 2, 1}, /* OP_PUSHSELF */
{iU, 1, 0}, /* OP_CREATETABLE */
{iU, 0, 1}, /* OP_SETLOCAL */
{iU, 0, 1}, /* OP_SETGLOBAL */
{iAB, VD, 0}, /* OP_SETTABLE */
{iAB, VD, 0}, /* OP_SETLIST */
{iU, VD, 0}, /* OP_SETMAP */
{iO, 1, 2}, /* OP_ADD */
{iS, 1, 1}, /* OP_ADDI */
{iO, 1, 2}, /* OP_SUB */
{iO, 1, 2}, /* OP_MULT */
{iO, 1, 2}, /* OP_DIV */
{iO, 1, 2}, /* OP_POW */
{iU, VD, 0}, /* OP_CONCAT */
{iO, 1, 1}, /* OP_MINUS */
{iO, 1, 1}, /* OP_NOT */
{iS, 0, 2}, /* OP_JMPNE */
{iS, 0, 2}, /* OP_JMPEQ */
{iS, 0, 2}, /* OP_JMPLT */
{iS, 0, 2}, /* OP_JMPLE */
{iS, 0, 2}, /* OP_JMPGT */
{iS, 0, 2}, /* OP_JMPGE */
{iS, 0, 1}, /* OP_JMPT */
{iS, 0, 1}, /* OP_JMPF */
{iS, 0, 1}, /* OP_JMPONT */
{iS, 0, 1}, /* OP_JMPONF */
{iS, 0, 0}, /* OP_JMP */
{iO, 1, 0}, /* OP_PUSHNILJMP */
{iS, 0, 0}, /* OP_FORPREP */
{iS, 0, 3}, /* OP_FORLOOP */
{iS, 3, 0}, /* OP_LFORPREP */
{iS, 0, 4}, /* OP_LFORLOOP */
{iAB, VD, 0} /* OP_CLOSURE */
};

View File

@ -1,5 +1,5 @@
/*
** $Id: lcode.h,v 1.13 2000/05/22 18:44:46 roberto Exp roberto $
** $Id: lcode.h,v 1.14 2000/06/16 17:51:40 roberto Exp roberto $
** Code generator for Lua
** See Copyright Notice in lua.h
*/
@ -22,9 +22,12 @@
enum Mode {iO, iU, iS, iAB}; /* instruction format */
#define VD 100 /* flag for variable delta */
extern const struct OpProperties {
char mode;
signed char delta;
unsigned char push;
unsigned char pop;
} luaK_opproperties[];

148
ldebug.c
View File

@ -1,5 +1,5 @@
/*
** $Id: ldebug.c,v 1.23 2000/06/12 13:52:05 roberto Exp roberto $
** $Id: ldebug.c,v 1.24 2000/06/26 19:28:31 roberto Exp roberto $
** Debug Interface
** See Copyright Notice in lua.h
*/
@ -13,10 +13,12 @@
#include "lapi.h"
#include "lauxlib.h"
#include "lcode.h"
#include "ldebug.h"
#include "ldo.h"
#include "lfunc.h"
#include "lobject.h"
#include "lopcodes.h"
#include "lstate.h"
#include "ltable.h"
#include "ltm.h"
@ -97,6 +99,13 @@ static int lua_nups (StkId f) {
}
static int lua_currentpc (StkId f) {
CallInfo *ci = infovalue(f);
LUA_ASSERT(L, ttype(f) == TAG_LMARK, "function has no pc");
return (*ci->pc - 1) - ci->func->f.l->code;
}
static int lua_currentline (StkId f) {
if (ttype(f) != TAG_LMARK)
return -1; /* only active lua functions have current-line information */
@ -104,15 +113,11 @@ static int lua_currentline (StkId f) {
CallInfo *ci = infovalue(f);
int *lines = ci->func->f.l->lines;
if (!lines) return -1; /* no static debug information */
else return lines[ci->pc];
else return lines[lua_currentpc(f)];
}
}
static int lua_currentpc (StkId f) {
return infovalue(f)->pc;
}
static Proto *getluaproto (StkId f) {
return (ttype(f) == TAG_LMARK) ? infovalue(f)->func->f.l : NULL;
@ -225,17 +230,136 @@ int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
}
/*
** {======================================================
** Symbolic Execution
** =======================================================
*/
static void call_index_error (lua_State *L, TObject *o, const char *v) {
luaL_verror(L, "attempt to %.10s a %.10s value", v, lua_type(L, o));
static Instruction luaG_symbexec (const Proto *pt, int lastpc, int stackpos) {
int stack[MAXSTACK]; /* stores last instruction that changes each value */
const Instruction *code = pt->code;
int top = pt->numparams;
int pc = 0;
if (pt->is_vararg) /* varargs? */
top++; /* `arg' */
while (pc < lastpc) {
const Instruction i = code[pc++];
switch (GET_OPCODE(i)) {
case OP_CALL: {
int nresults = GETARG_B(i);
if (nresults == MULT_RET) nresults = 1;
top = GETARG_A(i);
while (nresults--)
stack[top++] = pc-1;
break;
}
case OP_PUSHNIL: {
int n;
for (n=0; n<GETARG_U(i); n++)
stack[top++] = pc-1;
break;
}
case OP_POP: {
top -= GETARG_U(i);
break;
}
case OP_SETTABLE:
case OP_SETLIST: {
top -= GETARG_B(i);
break;
}
case OP_SETMAP: {
top -= 2*GETARG_U(i);
break;
}
case OP_CONCAT: {
top -= GETARG_U(i);
stack[top++] = pc-1;
break;
}
case OP_JMPONT:
case OP_JMPONF: {
int newpc = pc + GETARG_S(i);
if (newpc >= lastpc) {
stack[top-1] = pc-1; /* value generated by or-and */
pc = newpc; /* do the jump */
}
else
top--; /* original code did not jump; condition was false */
break;
}
case OP_PUSHNILJMP: {
break; /* do not `push', to compensate next instruction */
}
case OP_CLOSURE: {
top -= GETARG_B(i);
stack[top++] = pc-1;
break;
}
default: {
int n;
LUA_ASSERT(NULL, luaK_opproperties[GET_OPCODE(i)].push != VD,
"invalid opcode for default");
top -= luaK_opproperties[GET_OPCODE(i)].pop;
for (n=0; n<luaK_opproperties[GET_OPCODE(i)].push; n++)
stack[top++] = pc-1;
}
}
}
return code[stack[stackpos]];
}
void luaG_callerror (lua_State *L, TObject *func) {
call_index_error(L, func, "call");
static const char *getname (lua_State *L, StkId obj, const char **name) {
StkId func = aux_stackedfunction(L, 0, obj);
if (func == NULL || ttype(func) != TAG_LMARK)
return NULL; /* not a Lua function */
else {
Proto *p = infovalue(func)->func->f.l;
int pc = lua_currentpc(func);
int stackpos = obj - (func+1); /* func+1 == function base */
Instruction i = luaG_symbexec(p, pc, stackpos);
switch (GET_OPCODE(i)) {
case OP_GETGLOBAL: {
*name = p->kstr[GETARG_U(i)]->str;
return "global";
}
case OP_GETLOCAL: {
*name = luaF_getlocalname(p, GETARG_U(i)+1, pc);
return (*name) ? "local" : NULL;
}
case OP_PUSHSELF:
case OP_GETDOTTED: {
*name = p->kstr[GETARG_U(i)]->str;
return "field";
}
default:
return NULL; /* no usefull name found */
}
}
}
void luaG_indexerror (lua_State *L, TObject *t) {
call_index_error(L, t, "index");
/* }====================================================== */
static void call_index_error (lua_State *L, StkId o, const char *op,
const char *tp) {
const char *name;
const char *kind = getname(L, o, &name);
if (kind)
luaL_verror(L, "%s `%s' is not a %s", kind, name, tp);
else
luaL_verror(L, "attempt to %.10s a %.10s value", op, lua_type(L, o));
}
void luaG_callerror (lua_State *L, StkId func) {
call_index_error(L, func, "call", "function");
}
void luaG_indexerror (lua_State *L, StkId t) {
call_index_error(L, t, "index", "table");
}

View File

@ -1,5 +1,5 @@
/*
** $Id: $
** $Id: ldebug.h,v 1.1 2000/01/14 17:15:44 roberto Exp roberto $
** Auxiliary functions from Debug Interface module
** See Copyright Notice in lua.h
*/
@ -8,12 +8,12 @@
#define ldebug_h
#include "lobject.h"
#include "lstate.h"
#include "luadebug.h"
void luaG_callerror (lua_State *L, TObject *func);
void luaG_indexerror (lua_State *L, TObject *t);
void luaG_callerror (lua_State *L, StkId func);
void luaG_indexerror (lua_State *L, StkId t);
#endif

8
ldo.c
View File

@ -1,5 +1,5 @@
/*
** $Id: ldo.c,v 1.79 2000/06/16 17:16:34 roberto Exp roberto $
** $Id: ldo.c,v 1.80 2000/06/26 19:28:31 roberto Exp roberto $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/
@ -103,7 +103,7 @@ void luaD_openstack (lua_State *L, StkId pos) {
}
void luaD_lineHook (lua_State *L, StkId func, int line) {
void luaD_lineHook (lua_State *L, StkId func, int line, lua_Hook linehook) {
if (L->allowhooks) {
lua_Debug ar;
struct C_Lua_Stack oldCLS = L->Cstack;
@ -113,7 +113,7 @@ void luaD_lineHook (lua_State *L, StkId func, int line) {
ar.event = "line";
ar.currentline = line;
L->allowhooks = 0; /* cannot call hooks inside a hook */
(*L->linehook)(L, &ar);
(*linehook)(L, &ar);
L->allowhooks = 1;
L->top = old_top;
L->Cstack = oldCLS;
@ -187,7 +187,7 @@ void luaD_call (lua_State *L, StkId func, int nResults) {
case TAG_LCLOSURE: {
CallInfo ci;
ci.func = clvalue(func);
ci.pc = 0;
ci.line = 0;
ttype(func) = TAG_LMARK;
infovalue(func) = &ci;
if (callhook)

4
ldo.h
View File

@ -1,5 +1,5 @@
/*
** $Id: ldo.h,v 1.19 2000/03/29 20:19:20 roberto Exp roberto $
** $Id: ldo.h,v 1.20 2000/04/14 18:12:35 roberto Exp $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/
@ -22,7 +22,7 @@
void luaD_init (lua_State *L, int stacksize);
void luaD_adjusttop (lua_State *L, StkId base, int extra);
void luaD_openstack (lua_State *L, StkId pos);
void luaD_lineHook (lua_State *L, StkId func, int line);
void luaD_lineHook (lua_State *L, StkId func, int line, lua_Hook linehook);
void luaD_call (lua_State *L, StkId func, int nResults);
void luaD_callTM (lua_State *L, const TObject *f, int nParams, int nResults);
int luaD_protectedrun (lua_State *L);

View File

@ -1,5 +1,5 @@
/*
** $Id: lobject.h,v 1.67 2000/06/08 18:27:13 roberto Exp roberto $
** $Id: lobject.h,v 1.68 2000/06/26 19:28:31 roberto Exp roberto $
** Type definitions for Lua objects
** See Copyright Notice in lua.h
*/
@ -122,7 +122,6 @@ typedef struct Proto {
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;
@ -171,9 +170,10 @@ typedef struct 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 */
const Instruction **pc; /* current pc of called function */
int lastpc; /* last pc traced */
int line; /* current line */
} CallInfo;

View File

@ -1,5 +1,5 @@
/*
** $Id: lparser.c,v 1.99 2000/06/26 19:28:31 roberto Exp roberto $
** $Id: lparser.c,v 1.100 2000/06/28 17:06:07 roberto Exp roberto $
** LL(1) Parser and code generator for Lua
** See Copyright Notice in lua.h
*/
@ -154,7 +154,7 @@ static int checkname (LexState *ls) {
static void luaI_registerlocalvar (LexState *ls, TString *varname, int pc) {
FuncState *fs = ls->fs;
if (fs->f->debug) {
if (fs->debug) {
Proto *f = fs->f;
luaM_growvector(ls->L, f->locvars, fs->nvars, 1, LocVar, "", MAX_INT);
f->locvars[fs->nvars].varname = varname;
@ -359,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.f->debug = L->debug; /* previous `next' may scan a pragma */
funcstate.debug = L->debug; /* previous `next' may scan a pragma */
chunk(&lexstate);
check_condition(&lexstate, (lexstate.t.token == TK_EOS), "<eof> expected");
close_func(&lexstate);
@ -1085,7 +1085,7 @@ static void body (LexState *ls, int needself, int line) {
FuncState new_fs;
open_func(ls, &new_fs);
new_fs.f->lineDefined = line;
new_fs.f->debug = ls->L->debug;
new_fs.debug = ls->L->debug;
check(ls, '(');
if (needself) {
new_localvarstr(ls, "self", 0);

View File

@ -1,5 +1,5 @@
/*
** $Id: lparser.h,v 1.18 2000/06/21 18:13:56 roberto Exp roberto $
** $Id: lparser.h,v 1.19 2000/06/26 19:28:31 roberto Exp roberto $
** LL(1) Parser and code generator for Lua
** See Copyright Notice in lua.h
*/
@ -47,6 +47,7 @@ typedef struct FuncState {
int stacklevel; /* number of values on activation register */
int nlocalvar; /* number of active local variables */
int nupvalues; /* number of upvalues */
int debug; /* flag for debug information */
int nvars; /* number of entries in f->locvars */
struct Breaklabel *bl; /* chain of breakable blocks */
expdesc upvalues[MAXUPVALUES]; /* upvalues */

32
lvm.c
View File

@ -1,5 +1,5 @@
/*
** $Id: lvm.c,v 1.117 2000/06/26 19:28:31 roberto Exp roberto $
** $Id: lvm.c,v 1.118 2000/06/27 19:00:36 roberto Exp roberto $
** Lua virtual machine
** See Copyright Notice in lua.h
*/
@ -67,20 +67,19 @@ int luaV_tostring (lua_State *L, TObject *obj) { /* LUA_NUMBER */
}
static void traceexec (lua_State *L, StkId base, int pc, StkId top) {
static void traceexec (lua_State *L, StkId base, StkId top, lua_Hook linehook) {
CallInfo *ci = infovalue(base-1);
int oldpc = ci->pc;
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 (loop) or enters a new line */
if (pc <= oldpc || lines[pc] != ci->line) {
int *lines = ci->func->f.l->lines;
int pc = (*ci->pc - 1) - ci->func->f.l->code;
if (lines) {
/* calls linehook when enters a new line or jumps back (loop) */
if (lines[pc] != ci->line || pc <= ci->lastpc) {
ci->line = lines[pc];
L->top = top;
luaD_lineHook(L, base-2, lines[pc]);
luaD_lineHook(L, base-2, lines[pc], linehook);
}
}
ci->lastpc = pc;
}
@ -113,7 +112,7 @@ void luaV_Lclosure (lua_State *L, Proto *l, int nelems) {
** Receives the table at top-2 and the index at top-1.
*/
void luaV_gettable (lua_State *L, StkId top) {
TObject *table = top-2;
StkId table = top-2;
const TObject *im;
if (ttype(table) != TAG_TABLE) { /* not a table, get gettable TM */
im = luaT_getimbyObj(L, table, IM_GETTABLE);
@ -348,7 +347,8 @@ 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;
lua_Hook linehook = L->linehook;
infovalue(base-1)->pc = &pc;
luaD_checkstack(L, tf->maxstacksize+EXTRA_STACK);
if (tf->is_vararg) { /* varargs? */
adjust_varargs(L, base, tf->numparams);
@ -359,9 +359,9 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) {
top = L->top;
/* main loop of interpreter */
for (;;) {
if (debug)
traceexec(L, base, pc - tf->code, top);
{const Instruction i = *pc++;
const Instruction i = *pc++;
if (linehook)
traceexec(L, base, top, linehook);
switch (GET_OPCODE(i)) {
case OP_END:
@ -705,5 +705,5 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) {
break;
}
}}
}
}