call_object: print message before abort()

This commit is contained in:
Guido van Rossum 1994-08-30 08:01:59 +00:00
parent b078ce10d4
commit e59214ed91
1 changed files with 144 additions and 157 deletions

View File

@ -1,5 +1,5 @@
/*********************************************************** /***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum, Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands. Amsterdam, The Netherlands.
All Rights Reserved All Rights Reserved
@ -40,6 +40,8 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <ctype.h> #include <ctype.h>
extern int suppress_print; /* Declared in pythonrun.c, set in pythonmain.c */
/* Turn this on if your compiler chokes on the big switch: */ /* Turn this on if your compiler chokes on the big switch: */
/* #define CASE_TOO_BIG 1 /**/ /* #define CASE_TOO_BIG 1 /**/
@ -53,9 +55,6 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#define CHECKEXC 1 /* Double-check exception checking */ #define CHECKEXC 1 /* Double-check exception checking */
#endif #endif
/* Global option, may be set by main() */
int killprint;
/* Forward declarations */ /* Forward declarations */
@ -92,18 +91,15 @@ static int cmp_member PROTO((object *, object *));
static object *cmp_outcome PROTO((int, object *, object *)); static object *cmp_outcome PROTO((int, object *, object *));
static int import_from PROTO((object *, object *, object *)); static int import_from PROTO((object *, object *, object *));
static object *build_class PROTO((object *, object *, object *)); static object *build_class PROTO((object *, object *, object *));
static void locals_2_fast PROTO((frameobject *, int));
static void fast_2_locals PROTO((frameobject *));
static int access_statement PROTO((object *, object *, frameobject *)); static int access_statement PROTO((object *, object *, frameobject *));
static int exec_statement PROTO((object *, object *, object *)); static int exec_statement PROTO((object *, object *, object *));
static void mergelocals PROTO(());
/* Pointer to current frame, used to link new frames to */ /* Pointer to current frame, used to link new frames to */
static frameobject *current_frame; static frameobject *current_frame;
#ifdef USE_THREAD #ifdef WITH_THREAD
#include <errno.h> #include <errno.h>
#include "thread.h" #include "thread.h"
@ -128,7 +124,7 @@ init_save_thread()
object * object *
save_thread() save_thread()
{ {
#ifdef USE_THREAD #ifdef WITH_THREAD
if (interpreter_lock) { if (interpreter_lock) {
object *res; object *res;
res = (object *)current_frame; res = (object *)current_frame;
@ -144,7 +140,7 @@ void
restore_thread(x) restore_thread(x)
object *x; object *x;
{ {
#ifdef USE_THREAD #ifdef WITH_THREAD
if (interpreter_lock) { if (interpreter_lock) {
int err; int err;
err = errno; err = errno;
@ -190,11 +186,11 @@ eval_code(co, globals, locals, owner, arg)
register object *t; register object *t;
register frameobject *f; /* Current frame */ register frameobject *f; /* Current frame */
register listobject *fastlocals = NULL; register listobject *fastlocals = NULL;
object *trace = NULL; /* Trace function or NULL */
object *retval; /* Return value iff why == WHY_RETURN */ object *retval; /* Return value iff why == WHY_RETURN */
char *name; /* Name used by some instructions */ char *name; /* Name used by some instructions */
int needmerge = 0; /* Set if need to merge locals back at end */ int needmerge = 0; /* Set if need to merge locals back at end */
int defmode = 0; /* Default access mode for new variables */ int defmode = 0; /* Default access mode for new variables */
int ticker_count = 10; /* Check for intr every Nth instruction */
#ifdef LLTRACE #ifdef LLTRACE
int lltrace; int lltrace;
#endif #endif
@ -276,7 +272,7 @@ eval_code(co, globals, locals, owner, arg)
depends on the situation. The global trace function depends on the situation. The global trace function
(sys.trace) is also called whenever an exception (sys.trace) is also called whenever an exception
is detected. */ is detected. */
if (call_trace(&sys_trace, &trace, f, "call", arg)) { if (call_trace(&sys_trace, &f->f_trace, f, "call", arg)) {
/* Trace function raised an error */ /* Trace function raised an error */
current_frame = f->f_back; current_frame = f->f_back;
DECREF(f); DECREF(f);
@ -294,6 +290,10 @@ eval_code(co, globals, locals, owner, arg)
} }
} }
x = sysget("check_interval");
if (x != NULL && is_intobject(x))
ticker_count = getintvalue(x);
next_instr = GETUSTRINGVALUE(f->f_code->co_code); next_instr = GETUSTRINGVALUE(f->f_code->co_code);
stack_pointer = f->f_valuestack; stack_pointer = f->f_valuestack;
@ -312,17 +312,16 @@ eval_code(co, globals, locals, owner, arg)
/* Do periodic things. /* Do periodic things.
Doing this every time through the loop would add Doing this every time through the loop would add
too much overhead (a function call per instruction). too much overhead (a function call per instruction).
So we do it only every tenth instruction. */ So we do it only every Nth instruction. */
if (--ticker < 0) { if (--ticker < 0) {
ticker = 10; ticker = ticker_count;
if (intrcheck()) { if (sigcheck()) {
err_set(KeyboardInterrupt);
why = WHY_EXCEPTION; why = WHY_EXCEPTION;
goto on_error; goto on_error;
} }
#ifdef USE_THREAD #ifdef WITH_THREAD
if (interpreter_lock) { if (interpreter_lock) {
/* Give another thread a chance */ /* Give another thread a chance */
@ -642,17 +641,15 @@ eval_code(co, globals, locals, owner, arg)
case PRINT_EXPR: case PRINT_EXPR:
v = POP(); v = POP();
/* Print value except if procedure result */ /* Print value except if procedure result */
if (v != None) { /* Before printing, also assign to '_' */
if (v != None &&
(err = setbuiltin("_", v)) == 0 &&
!suppress_print) {
flushline(); flushline();
x = sysget("stdout"); x = sysget("stdout");
softspace(x, 1); softspace(x, 1);
err = writeobject(v, x, 0); err = writeobject(v, x, 0);
flushline(); flushline();
if (killprint) {
err_setstr(RuntimeError,
"printing expression statement");
x = 0;
}
} }
DECREF(v); DECREF(v);
break; break;
@ -692,7 +689,7 @@ eval_code(co, globals, locals, owner, arg)
v = POP(); v = POP();
w = POP(); w = POP();
/* A tuple is equivalent to its first element here */ /* A tuple is equivalent to its first element here */
while (is_tupleobject(w)) { while (is_tupleobject(w) && gettuplesize(w) > 0) {
u = w; u = w;
w = gettupleitem(u, 0); w = gettupleitem(u, 0);
DECREF(u); DECREF(u);
@ -741,6 +738,14 @@ eval_code(co, globals, locals, owner, arg)
PUSH(x); PUSH(x);
break; break;
case SET_FUNC_ARGS:
v = POP(); /* The function */
w = POP(); /* The argument list */
err = setfuncargstuff(v, oparg, w);
PUSH(v);
DECREF(w);
break;
case POP_BLOCK: case POP_BLOCK:
{ {
block *b = pop_block(f); block *b = pop_block(f);
@ -1109,8 +1114,7 @@ eval_code(co, globals, locals, owner, arg)
x = GETCONST(oparg); x = GETCONST(oparg);
if (x == None) if (x == None)
break; break;
if (x == NULL || !is_dictobject(x)) { if (x == NULL || !is_tupleobject(x)) {
fatal("bad RESERVE_FAST");
err_setstr(SystemError, "bad RESERVE_FAST"); err_setstr(SystemError, "bad RESERVE_FAST");
x = NULL; x = NULL;
break; break;
@ -1119,16 +1123,15 @@ eval_code(co, globals, locals, owner, arg)
XDECREF(f->f_localmap); XDECREF(f->f_localmap);
INCREF(x); INCREF(x);
f->f_localmap = x; f->f_localmap = x;
f->f_fastlocals = x = newlistobject( f->f_fastlocals = x = newlistobject(gettuplesize(x));
x->ob_type->tp_as_mapping->mp_length(x));
fastlocals = (listobject *) x; fastlocals = (listobject *) x;
break; break;
case LOAD_FAST: case LOAD_FAST:
x = GETLISTITEM(fastlocals, oparg); x = GETLISTITEM(fastlocals, oparg);
if (x == NULL) { if (x == NULL) {
err_setstr(NameError, err_setval(NameError,
"undefined local variable"); gettupleitem(f->f_localmap, oparg));
break; break;
} }
if (is_accessobject(x)) { if (is_accessobject(x)) {
@ -1156,12 +1159,12 @@ eval_code(co, globals, locals, owner, arg)
case DELETE_FAST: case DELETE_FAST:
x = GETLISTITEM(fastlocals, oparg); x = GETLISTITEM(fastlocals, oparg);
if (x == NULL) { if (x == NULL) {
err_setstr(NameError, err_setval(NameError,
"undefined local variable"); gettupleitem(f->f_localmap, oparg));
break; break;
} }
if (w != NULL && is_accessobject(w)) { if (x != NULL && is_accessobject(x)) {
err = setaccessvalue(w, f->f_locals, err = setaccessvalue(x, f->f_locals,
(object *)NULL); (object *)NULL);
break; break;
} }
@ -1306,10 +1309,10 @@ eval_code(co, globals, locals, owner, arg)
printf("--- Line %d ---\n", oparg); printf("--- Line %d ---\n", oparg);
#endif #endif
f->f_lineno = oparg; f->f_lineno = oparg;
if (trace != NULL) { if (f->f_trace != NULL) {
/* Trace each line of code reached */ /* Trace each line of code reached */
f->f_lasti = INSTR_OFFSET(); f->f_lasti = INSTR_OFFSET();
err = call_trace(&trace, &trace, err = call_trace(&f->f_trace, &f->f_trace,
f, "line", None); f, "line", None);
} }
break; break;
@ -1368,8 +1371,8 @@ eval_code(co, globals, locals, owner, arg)
f->f_lasti -= 2; f->f_lasti -= 2;
tb_here(f); tb_here(f);
if (trace) if (f->f_trace)
call_exc_trace(&trace, &trace, f); call_exc_trace(&f->f_trace, &f->f_trace, f);
if (sys_profile) if (sys_profile)
call_exc_trace(&sys_profile, (object**)0, f); call_exc_trace(&sys_profile, (object**)0, f);
} }
@ -1446,15 +1449,15 @@ eval_code(co, globals, locals, owner, arg)
if (why != WHY_RETURN) if (why != WHY_RETURN)
retval = NULL; retval = NULL;
if (trace) { if (f->f_trace) {
if (why == WHY_RETURN) { if (why == WHY_RETURN) {
if (call_trace(&trace, &trace, f, "return", retval)) { if (call_trace(&f->f_trace, &f->f_trace, f,
"return", retval)) {
XDECREF(retval); XDECREF(retval);
retval = NULL; retval = NULL;
why = WHY_EXCEPTION; why = WHY_EXCEPTION;
} }
} }
XDECREF(trace);
} }
if (sys_profile && why == WHY_RETURN) { if (sys_profile && why == WHY_RETURN) {
@ -1466,9 +1469,6 @@ eval_code(co, globals, locals, owner, arg)
} }
} }
if (fastlocals && (f->ob_refcnt > 1 || f->f_locals->ob_refcnt > 2))
fast_2_locals(f);
/* Restore previous frame and release the current one */ /* Restore previous frame and release the current one */
current_frame = f->f_back; current_frame = f->f_back;
@ -1561,7 +1561,7 @@ call_trace(p_trace, p_newtrace, f, msg, arg)
settupleitem(arglist, 2, arg); settupleitem(arglist, 2, arg);
tracing++; tracing++;
fast_2_locals(f); fast_2_locals(f);
res = call_object(*p_trace, arglist); res = call_object(*p_trace, arglist); /* May clear *p_trace! */
locals_2_fast(f, 1); locals_2_fast(f, 1);
tracing--; tracing--;
cleanup: cleanup:
@ -1569,7 +1569,7 @@ call_trace(p_trace, p_newtrace, f, msg, arg)
if (res == NULL) { if (res == NULL) {
/* The trace proc raised an exception */ /* The trace proc raised an exception */
tb_here(f); tb_here(f);
DECREF(*p_trace); XDECREF(*p_trace);
*p_trace = NULL; *p_trace = NULL;
if (p_newtrace) { if (p_newtrace) {
XDECREF(*p_newtrace); XDECREF(*p_newtrace);
@ -1592,91 +1592,6 @@ call_trace(p_trace, p_newtrace, f, msg, arg)
} }
} }
static void
fast_2_locals(f)
frameobject *f;
{
/* Merge f->f_fastlocals into f->f_locals */
object *locals, *fast, *map;
object *error_type, *error_value;
int pos;
object *key, *value;
if (f == NULL)
return;
locals = f->f_locals;
fast = f->f_fastlocals;
map = f->f_localmap;
if (locals == NULL || fast == NULL || map == NULL)
return;
if (!is_dictobject(locals) || !is_listobject(fast) ||
!is_dictobject(map))
return;
err_get(&error_type, &error_value);
pos = 0;
while (mappinggetnext(map, &pos, &key, &value)) {
int j;
if (!is_intobject(value))
continue;
j = getintvalue(value);
value = getlistitem(fast, j);
if (value == NULL) {
err_clear();
if (dict2remove(locals, key) != 0)
err_clear();
}
else {
if (dict2insert(locals, key, value) != 0)
err_clear();
}
}
err_setval(error_type, error_value);
}
static void
locals_2_fast(f, clear)
frameobject *f;
int clear;
{
/* Merge f->f_locals into f->f_fastlocals */
object *locals, *fast, *map;
object *error_type, *error_value;
int pos;
object *key, *value;
if (f == NULL)
return;
locals = f->f_locals;
fast = f->f_fastlocals;
map = f->f_localmap;
if (locals == NULL || fast == NULL || map == NULL)
return;
if (!is_dictobject(locals) || !is_listobject(fast) ||
!is_dictobject(map))
return;
err_get(&error_type, &error_value);
pos = 0;
while (mappinggetnext(map, &pos, &key, &value)) {
int j;
if (!is_intobject(value))
continue;
j = getintvalue(value);
value = dict2lookup(locals, key);
if (value == NULL)
err_clear();
else
INCREF(value);
if (value != NULL || clear)
if (setlistitem(fast, j, value) != 0)
err_clear();
}
err_setval(error_type, error_value);
}
static void
mergelocals()
{
locals_2_fast(current_frame, 1);
}
object * object *
getlocals() getlocals()
{ {
@ -1704,6 +1619,12 @@ getowner()
return current_frame->f_owner; return current_frame->f_owner;
} }
object *
getframe()
{
return (object *)current_frame;
}
void void
printtraceback(f) printtraceback(f)
object *f; object *f;
@ -1999,10 +1920,31 @@ call_object(func, arg)
object *func; object *func;
object *arg; object *arg;
{ {
if (is_instancemethodobject(func) || is_funcobject(func)) binaryfunc call;
return call_function(func, arg); object *result;
if (call = func->ob_type->tp_call) {
int size = gettuplesize(arg);
if (arg) {
size = gettuplesize(arg);
if (size == 1)
arg = gettupleitem(arg, 0);
else if (size == 0)
arg = NULL;
}
result = (*call)(func, arg);
}
else if (is_instancemethodobject(func) || is_funcobject(func))
result = call_function(func, arg);
else else
return call_builtin(func, arg); result = call_builtin(func, arg);
if (result == NULL && !err_occurred()) {
fprintf(stderr, "null result without error in call_object\n");
abort();
}
return result;
} }
static object * static object *
@ -2025,6 +1967,17 @@ call_builtin(func, arg)
if (is_classobject(func)) { if (is_classobject(func)) {
return newinstanceobject(func, arg); return newinstanceobject(func, arg);
} }
if (is_instanceobject(func)) {
object *res, *call = getattr(func,"__call__");
if (call == NULL) {
err_clear();
err_setstr(AttributeError, "no __call__ method defined");
return NULL;
}
res = call_object(call, arg);
DECREF(call);
return res;
}
err_setstr(TypeError, "call of non-function"); err_setstr(TypeError, "call of non-function");
return NULL; return NULL;
} }
@ -2038,6 +1991,8 @@ call_function(func, arg)
object *newlocals, *newglobals; object *newlocals, *newglobals;
object *class = NULL; object *class = NULL;
object *co, *v; object *co, *v;
object *argdefs;
int argcount;
if (is_instancemethodobject(func)) { if (is_instancemethodobject(func)) {
object *self = instancemethodgetself(func); object *self = instancemethodgetself(func);
@ -2065,7 +2020,6 @@ call_function(func, arg)
} }
} }
else { else {
int argcount;
if (arg == NULL) if (arg == NULL)
argcount = 0; argcount = 0;
else if (is_tupleobject(arg)) else if (is_tupleobject(arg))
@ -2100,6 +2054,39 @@ call_function(func, arg)
} }
} }
argdefs = getfuncargstuff(func, &argcount);
if (argdefs != NULL && arg != NULL && is_tupleobject(arg)) {
int actualcount, j;
/* Process default arguments */
if (argcount & 0x4000)
argcount ^= 0x4000;
actualcount = gettuplesize(arg);
j = gettuplesize(argdefs) - (argcount - actualcount);
if (actualcount < argcount && j >= 0) {
int i;
object *v;
if (newarg == NULL)
INCREF(arg);
newarg = newtupleobject(argcount);
if (newarg == NULL) {
DECREF(arg);
return NULL;
}
for (i = 0; i < actualcount; i++) {
v = gettupleitem(arg, i);
XINCREF(v);
settupleitem(newarg, i, v);
}
for (; i < argcount; i++, j++) {
v = gettupleitem(argdefs, j);
XINCREF(v);
settupleitem(newarg, i, v);
}
DECREF(arg);
arg = newarg;
}
}
co = getfunccode(func); co = getfunccode(func);
if (co == NULL) { if (co == NULL) {
XDECREF(newarg); XDECREF(newarg);
@ -2162,18 +2149,18 @@ loop_subscript(v, w)
object *v, *w; object *v, *w;
{ {
sequence_methods *sq = v->ob_type->tp_as_sequence; sequence_methods *sq = v->ob_type->tp_as_sequence;
int i, n; int i;
if (sq == NULL) { if (sq == NULL) {
err_setstr(TypeError, "loop over non-sequence"); err_setstr(TypeError, "loop over non-sequence");
return NULL; return NULL;
} }
i = getintvalue(w); i = getintvalue(w);
n = (*sq->sq_length)(v); v = (*sq->sq_item)(v, i);
if (n < 0) if (v)
return NULL; /* Exception */ return v;
if (i >= n) if (err_occurred() == IndexError)
return NULL; /* End of loop */ err_clear();
return (*sq->sq_item)(v, i); return NULL;
} }
static int static int
@ -2300,7 +2287,7 @@ static int
cmp_member(v, w) cmp_member(v, w)
object *v, *w; object *v, *w;
{ {
int i, n, cmp; int i, cmp;
object *x; object *x;
sequence_methods *sq; sequence_methods *sq;
/* Special case for char in string */ /* Special case for char in string */
@ -2327,11 +2314,15 @@ cmp_member(v, w)
"'in' or 'not in' needs sequence right argument"); "'in' or 'not in' needs sequence right argument");
return -1; return -1;
} }
n = (*sq->sq_length)(w); for (i = 0; ; i++) {
if (n < 0)
return -1;
for (i = 0; i < n; i++) {
x = (*sq->sq_item)(w, i); x = (*sq->sq_item)(w, i);
if (x == NULL) {
if (err_occurred() == IndexError) {
err_clear();
break;
}
return -1;
}
cmp = cmpobject(v, x); cmp = cmpobject(v, x);
XDECREF(x); XDECREF(x);
if (cmp == 0) if (cmp == 0)
@ -2473,17 +2464,13 @@ access_statement(name, vmode, f)
if (f->f_localmap == NULL) if (f->f_localmap == NULL)
value = dict2lookup(f->f_locals, name); value = dict2lookup(f->f_locals, name);
else { else {
value = dict2lookup(f->f_localmap, name); object *map = f->f_localmap;
if (value == NULL || !is_intobject(value))
value = NULL; value = NULL;
else { for (fastind = gettuplesize(map); --fastind >= 0; ) {
fastind = getintvalue(value); object *fname = gettupleitem(map, fastind);
if (0 <= fastind && if (cmpobject(name, fname) == 0) {
fastind < getlistsize(f->f_fastlocals))
value = getlistitem(f->f_fastlocals, fastind); value = getlistitem(f->f_fastlocals, fastind);
else { break;
value = NULL;
fastind = -1;
} }
} }
} }