3rd arg for raise; INCOMPLETE keyword parameter passing (currently f(kw=value) is seen as f('kw', value))

This commit is contained in:
Guido van Rossum 1995-07-07 22:53:21 +00:00
parent 7faeab3103
commit f10570b9eb
2 changed files with 229 additions and 52 deletions

View File

@ -775,43 +775,88 @@ eval_code(co, globals, locals, owner, arg)
case BREAK_LOOP: case BREAK_LOOP:
why = WHY_BREAK; why = WHY_BREAK;
break; break;
case RAISE_EXCEPTION: case RAISE_EXCEPTION:
v = POP(); oparg = 2;
w = POP(); /* Fallthrough */
case RAISE_VARARGS:
u = v = w = NULL;
switch (oparg) {
case 3:
u = POP(); /* traceback */
if (u == None) {
DECREF(u);
u = NULL;
}
else if (strcmp(u->ob_type->tp_name,
"traceback") != 0) {
/* XXX traceback.h needs to define
is_traceback() */
err_setstr(TypeError,
"raise 3rd arg must be traceback or None");
goto raise_error;
}
/* Fallthrough */
case 2:
v = POP(); /* value */
/* Fallthrough */
case 1:
w = POP(); /* exc */
break;
default:
err_setstr(SystemError,
"bad RAISE_VARARGS oparg");
goto raise_error;
}
if (v == NULL) {
v = None;
INCREF(v);
}
/* A tuple is equivalent to its first element here */ /* A tuple is equivalent to its first element here */
while (is_tupleobject(w) && gettuplesize(w) > 0) { while (is_tupleobject(w) && gettuplesize(w) > 0) {
u = w; object *t = w;
w = GETTUPLEITEM(u, 0); w = GETTUPLEITEM(t, 0);
INCREF(w); INCREF(w);
DECREF(u); DECREF(t);
} }
if (is_stringobject(w)) { if (is_stringobject(w)) {
err_setval(w, v); ;
} else if (is_classobject(w)) { } else if (is_classobject(w)) {
if (!is_instanceobject(v) if (!is_instanceobject(v)
|| !issubclass((object*)((instanceobject*)v)->in_class, || !issubclass((object*)((instanceobject*)v)->in_class,
w)) w)) {
err_setstr(TypeError, err_setstr(TypeError,
"a class exception must have a value that is an instance of the class"); "a class exception must have a value that is an instance of the class");
else goto raise_error;
err_setval(w,v); }
} else if (is_instanceobject(w)) { } else if (is_instanceobject(w)) {
if (v != None) if (v != None) {
err_setstr(TypeError, err_setstr(TypeError,
"an instance exception may not have a separate value"); "an instance exception may not have a separate value");
goto raise_error;
}
else { else {
DECREF(v); DECREF(v);
v = w; v = w;
w = (object*) ((instanceobject*)w)->in_class; w = (object*) ((instanceobject*)w)->in_class;
INCREF(w); INCREF(w);
err_setval(w, v);
} }
} else }
else {
err_setstr(TypeError, err_setstr(TypeError,
"exceptions must be strings, classes, or instances"); "exceptions must be strings, classes, or instances");
DECREF(v); goto raise_error;
DECREF(w); }
err_restore(w, v, u);
if (u == NULL)
why = WHY_EXCEPTION;
else
why = WHY_RERAISE;
break;
raise_error:
XDECREF(v);
XDECREF(w);
XDECREF(u);
why = WHY_EXCEPTION; why = WHY_EXCEPTION;
break; break;
@ -876,11 +921,8 @@ eval_code(co, globals, locals, owner, arg)
} }
else if (is_stringobject(v) || is_classobject(v)) { else if (is_stringobject(v) || is_classobject(v)) {
w = POP(); w = POP();
err_setval(v, w); u = POP();
DECREF(w); err_restore(v, w, u);
w = POP();
tb_store(w);
DECREF(w);
why = WHY_RERAISE; why = WHY_RERAISE;
} }
else if (v != None) { else if (v != None) {
@ -1000,6 +1042,7 @@ eval_code(co, globals, locals, owner, arg)
err_setstr(TypeError, err_setstr(TypeError,
"bad argument list"); "bad argument list");
why = WHY_EXCEPTION; why = WHY_EXCEPTION;
DECREF(v);
break; break;
} }
n = gettuplesize(v); n = gettuplesize(v);
@ -1308,8 +1351,7 @@ eval_code(co, globals, locals, owner, arg)
} }
x = call_object(x, w); x = call_object(x, w);
DECREF(w); DECREF(w);
if (x) PUSH(x);
PUSH(x);
break; break;
case IMPORT_FROM: case IMPORT_FROM:
@ -1402,6 +1444,85 @@ eval_code(co, globals, locals, owner, arg)
f, "line", None); f, "line", None);
} }
break; break;
case CALL_FUNCTION:
{
/* XXX To do:
- fill in default arguments here
- proper handling of keyword parameters
- change eval_code interface to take an
array of arguments instead of a tuple
*/
int na = oparg & 0xff;
int nk = (oparg>>8) & 0xff;
int n = na + 2*nk;
object **pfunc = stack_pointer - n - 1;
object *func = *pfunc;
object *self = NULL;
object *class = NULL;
object *args;
f->f_lasti = INSTR_OFFSET() - 3; /* For tracing */
INCREF(func);
if (is_instancemethodobject(func)) {
self = instancemethodgetself(func);
if (self != NULL) {
class = instancemethodgetclass(func);
DECREF(func);
func = instancemethodgetfunc(func);
INCREF(func);
INCREF(self);
DECREF(*pfunc);
*pfunc = self;
na++;
n++;
}
}
args = newtupleobject(n);
if (args == NULL)
x = NULL;
else {
while (--n >= 0) {
w = POP();
SETTUPLEITEM(args, n, w);
}
if (self == NULL)
POP();
if (is_funcobject(func)) {
int argcount;
object *argdefs =
getfuncargstuff(func, &argcount);
if (argdefs == NULL) { /* Fast path */
object *co, *loc, *glob;
co = getfunccode(func);
loc = newdictobject();
if (loc == NULL) {
x = NULL;
DECREF(func);
break;
}
glob = getfuncglobals(func);
INCREF(glob);
x = eval_code(
(codeobject *)co,
glob,
loc,
class,
args);
DECREF(glob);
DECREF(loc);
DECREF(args);
DECREF(func);
PUSH(x);
break;
}
}
x = call_object(func, args);
DECREF(args);
PUSH(x);
}
DECREF(func);
break;
}
default: default:
fprintf(stderr, fprintf(stderr,
@ -1613,7 +1734,7 @@ call_trace(p_trace, p_newtrace, f, msg, arg)
char *msg; char *msg;
object *arg; object *arg;
{ {
object *arglist, *what; object *args, *what;
object *res = NULL; object *res = NULL;
static int tracing = 0; static int tracing = 0;
@ -1626,26 +1747,26 @@ call_trace(p_trace, p_newtrace, f, msg, arg)
return 0; return 0;
} }
arglist = newtupleobject(3); args = newtupleobject(3);
if (arglist == NULL) if (args == NULL)
goto cleanup; goto cleanup;
what = newstringobject(msg); what = newstringobject(msg);
if (what == NULL) if (what == NULL)
goto cleanup; goto cleanup;
INCREF(f); INCREF(f);
SETTUPLEITEM(arglist, 0, (object *)f); SETTUPLEITEM(args, 0, (object *)f);
SETTUPLEITEM(arglist, 1, what); SETTUPLEITEM(args, 1, what);
if (arg == NULL) if (arg == NULL)
arg = None; arg = None;
INCREF(arg); INCREF(arg);
SETTUPLEITEM(arglist, 2, arg); SETTUPLEITEM(args, 2, arg);
tracing++; tracing++;
fast_2_locals(f); fast_2_locals(f);
res = call_object(*p_trace, arglist); /* May clear *p_trace! */ res = call_object(*p_trace, args); /* May clear *p_trace! */
locals_2_fast(f, 1); locals_2_fast(f, 1);
tracing--; tracing--;
cleanup: cleanup:
XDECREF(arglist); XDECREF(args);
if (res == NULL) { if (res == NULL) {
/* The trace proc raised an exception */ /* The trace proc raised an exception */
tb_here(f); tb_here(f);

View File

@ -782,19 +782,72 @@ com_apply_subscript(c, n)
} }
} }
static int
com_argument(c, n, inkeywords)
struct compiling *c;
node *n; /* argument */
int inkeywords;
{
node *m;
REQ(n, argument); /* [test '='] test; really [ keyword '='] keyword */
if (NCH(n) == 1) {
if (inkeywords) {
err_setstr(SyntaxError,
"non-keyword arg after keyword arg");
c->c_errors++;
}
else {
com_node(c, CHILD(n, 0));
}
return 0;
}
m = n;
do {
m = CHILD(m, 0);
} while (NCH(m) == 1);
if (TYPE(m) != NAME) {
err_setstr(SyntaxError, "keyword can't be an expression");
c->c_errors++;
}
else {
object *v = newstringobject(STR(m));
if (v == NULL)
c->c_errors++;
else {
com_addoparg(c, LOAD_CONST, com_addconst(c, v));
DECREF(v);
}
}
com_node(c, CHILD(n, 2));
return 1;
}
static void static void
com_call_function(c, n) com_call_function(c, n)
struct compiling *c; struct compiling *c;
node *n; /* EITHER testlist OR ')' */ node *n; /* EITHER arglist OR ')' */
{ {
if (TYPE(n) == RPAR) { if (TYPE(n) == RPAR) {
com_addoparg(c, BUILD_TUPLE, 0); com_addoparg(c, CALL_FUNCTION, 0);
com_addbyte(c, BINARY_CALL);
} }
else { else {
REQ(n, testlist); int inkeywords, i, na, nk;
com_list(c, n, 1); REQ(n, arglist);
com_addbyte(c, BINARY_CALL); inkeywords = 0;
na = 0;
nk = 0;
for (i = 0; i < NCH(n); i += 2) {
inkeywords = com_argument(c, CHILD(n, i), inkeywords);
if (!inkeywords)
na++;
else
nk++;
}
if (na > 255 || nk > 255) {
err_setstr(SyntaxError, "more than 255 arguments");
c->c_errors++;
}
com_addoparg(c, CALL_FUNCTION, na | (nk << 8));
} }
} }
@ -1482,13 +1535,18 @@ com_raise_stmt(c, n)
struct compiling *c; struct compiling *c;
node *n; node *n;
{ {
REQ(n, raise_stmt); /* 'raise' test [',' test] */ REQ(n, raise_stmt); /* 'raise' test [',' test [',' test]] */
com_node(c, CHILD(n, 1)); com_node(c, CHILD(n, 1));
if (NCH(n) > 3) if (NCH(n) > 3)
com_node(c, CHILD(n, 3)); com_node(c, CHILD(n, 3));
else else
com_addoparg(c, LOAD_CONST, com_addconst(c, None)); com_addoparg(c, LOAD_CONST, com_addconst(c, None));
com_addbyte(c, RAISE_EXCEPTION); if (NCH(n) > 5) {
com_node(c, CHILD(n, 5));
com_addoparg(c, RAISE_VARARGS, 3);
}
else
com_addbyte(c, RAISE_EXCEPTION);
} }
static void static void
@ -1980,19 +2038,16 @@ com_argdefs(c, n, argcount_return)
if (TYPE(n) != varargslist) if (TYPE(n) != varargslist)
return -1; return -1;
/* varargslist: /* varargslist:
(fpdef ['=' test] ',')* '*' NAME | (fpdef ['=' test] ',')* '*' NAME ....... |
fpdef ['=' test] (',' fpdef ['=' test])* [','] */ fpdef ['=' test] (',' fpdef ['=' test])* [','] */
nch = NCH(n); nch = NCH(n);
if (nch >= 2 && TYPE(CHILD(n, nch-2)) == STAR) {
star = 1;
nch -= 2;
}
else
star = 0;
nargs = 0; nargs = 0;
ndefs = 0; ndefs = 0;
star = 0;
for (i = 0; i < nch; i++) { for (i = 0; i < nch; i++) {
int t; int t;
if (TYPE(CHILD(n, i)) == STAR)
break;
nargs++; nargs++;
i++; i++;
if (i >= nch) if (i >= nch)
@ -2285,17 +2340,18 @@ com_arglist(c, n)
int nch, op, nargs, i, t; int nch, op, nargs, i, t;
REQ(n, varargslist); REQ(n, varargslist);
/* varargslist: /* varargslist:
(fpdef ['=' test] ',')* '*' NAME | (fpdef ['=' test] ',')* '*' NAME ..... |
fpdef ['=' test] (',' fpdef ['=' test])* [','] */ fpdef ['=' test] (',' fpdef ['=' test])* [','] */
nch = NCH(n); nch = NCH(n);
if (nch >= 2 && TYPE(CHILD(n, nch-2)) == STAR) { op = UNPACK_ARG;
op = UNPACK_VARARG;
nch -= 2;
}
else
op = UNPACK_ARG;
nargs = 0; nargs = 0;
for (i = 0; i < nch; i++) { for (i = 0; i < nch; i++) {
if (TYPE(CHILD(n, i)) == STAR) {
nch = i;
if (TYPE(CHILD(n, i+1)) != STAR)
op = UNPACK_VARARG;
break;
}
nargs++; nargs++;
i++; i++;
if (i >= nch) if (i >= nch)