mirror of https://github.com/python/cpython
3rd arg for raise; INCOMPLETE keyword parameter passing (currently f(kw=value) is seen as f('kw', value))
This commit is contained in:
parent
7faeab3103
commit
f10570b9eb
181
Python/ceval.c
181
Python/ceval.c
|
@ -775,43 +775,88 @@ eval_code(co, globals, locals, owner, arg)
|
|||
case BREAK_LOOP:
|
||||
why = WHY_BREAK;
|
||||
break;
|
||||
|
||||
|
||||
case RAISE_EXCEPTION:
|
||||
v = POP();
|
||||
w = POP();
|
||||
oparg = 2;
|
||||
/* 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 */
|
||||
while (is_tupleobject(w) && gettuplesize(w) > 0) {
|
||||
u = w;
|
||||
w = GETTUPLEITEM(u, 0);
|
||||
object *t = w;
|
||||
w = GETTUPLEITEM(t, 0);
|
||||
INCREF(w);
|
||||
DECREF(u);
|
||||
DECREF(t);
|
||||
}
|
||||
if (is_stringobject(w)) {
|
||||
err_setval(w, v);
|
||||
;
|
||||
} else if (is_classobject(w)) {
|
||||
if (!is_instanceobject(v)
|
||||
|| !issubclass((object*)((instanceobject*)v)->in_class,
|
||||
w))
|
||||
w)) {
|
||||
err_setstr(TypeError,
|
||||
"a class exception must have a value that is an instance of the class");
|
||||
else
|
||||
err_setval(w,v);
|
||||
goto raise_error;
|
||||
}
|
||||
} else if (is_instanceobject(w)) {
|
||||
if (v != None)
|
||||
if (v != None) {
|
||||
err_setstr(TypeError,
|
||||
"an instance exception may not have a separate value");
|
||||
goto raise_error;
|
||||
}
|
||||
else {
|
||||
DECREF(v);
|
||||
v = w;
|
||||
w = (object*) ((instanceobject*)w)->in_class;
|
||||
INCREF(w);
|
||||
err_setval(w, v);
|
||||
}
|
||||
} else
|
||||
}
|
||||
else {
|
||||
err_setstr(TypeError,
|
||||
"exceptions must be strings, classes, or instances");
|
||||
DECREF(v);
|
||||
DECREF(w);
|
||||
goto raise_error;
|
||||
}
|
||||
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;
|
||||
break;
|
||||
|
||||
|
@ -876,11 +921,8 @@ eval_code(co, globals, locals, owner, arg)
|
|||
}
|
||||
else if (is_stringobject(v) || is_classobject(v)) {
|
||||
w = POP();
|
||||
err_setval(v, w);
|
||||
DECREF(w);
|
||||
w = POP();
|
||||
tb_store(w);
|
||||
DECREF(w);
|
||||
u = POP();
|
||||
err_restore(v, w, u);
|
||||
why = WHY_RERAISE;
|
||||
}
|
||||
else if (v != None) {
|
||||
|
@ -1000,6 +1042,7 @@ eval_code(co, globals, locals, owner, arg)
|
|||
err_setstr(TypeError,
|
||||
"bad argument list");
|
||||
why = WHY_EXCEPTION;
|
||||
DECREF(v);
|
||||
break;
|
||||
}
|
||||
n = gettuplesize(v);
|
||||
|
@ -1308,8 +1351,7 @@ eval_code(co, globals, locals, owner, arg)
|
|||
}
|
||||
x = call_object(x, w);
|
||||
DECREF(w);
|
||||
if (x)
|
||||
PUSH(x);
|
||||
PUSH(x);
|
||||
break;
|
||||
|
||||
case IMPORT_FROM:
|
||||
|
@ -1402,6 +1444,85 @@ eval_code(co, globals, locals, owner, arg)
|
|||
f, "line", None);
|
||||
}
|
||||
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:
|
||||
fprintf(stderr,
|
||||
|
@ -1613,7 +1734,7 @@ call_trace(p_trace, p_newtrace, f, msg, arg)
|
|||
char *msg;
|
||||
object *arg;
|
||||
{
|
||||
object *arglist, *what;
|
||||
object *args, *what;
|
||||
object *res = NULL;
|
||||
static int tracing = 0;
|
||||
|
||||
|
@ -1626,26 +1747,26 @@ call_trace(p_trace, p_newtrace, f, msg, arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
arglist = newtupleobject(3);
|
||||
if (arglist == NULL)
|
||||
args = newtupleobject(3);
|
||||
if (args == NULL)
|
||||
goto cleanup;
|
||||
what = newstringobject(msg);
|
||||
if (what == NULL)
|
||||
goto cleanup;
|
||||
INCREF(f);
|
||||
SETTUPLEITEM(arglist, 0, (object *)f);
|
||||
SETTUPLEITEM(arglist, 1, what);
|
||||
SETTUPLEITEM(args, 0, (object *)f);
|
||||
SETTUPLEITEM(args, 1, what);
|
||||
if (arg == NULL)
|
||||
arg = None;
|
||||
INCREF(arg);
|
||||
SETTUPLEITEM(arglist, 2, arg);
|
||||
SETTUPLEITEM(args, 2, arg);
|
||||
tracing++;
|
||||
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);
|
||||
tracing--;
|
||||
cleanup:
|
||||
XDECREF(arglist);
|
||||
XDECREF(args);
|
||||
if (res == NULL) {
|
||||
/* The trace proc raised an exception */
|
||||
tb_here(f);
|
||||
|
|
100
Python/compile.c
100
Python/compile.c
|
@ -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
|
||||
com_call_function(c, n)
|
||||
struct compiling *c;
|
||||
node *n; /* EITHER testlist OR ')' */
|
||||
node *n; /* EITHER arglist OR ')' */
|
||||
{
|
||||
if (TYPE(n) == RPAR) {
|
||||
com_addoparg(c, BUILD_TUPLE, 0);
|
||||
com_addbyte(c, BINARY_CALL);
|
||||
com_addoparg(c, CALL_FUNCTION, 0);
|
||||
}
|
||||
else {
|
||||
REQ(n, testlist);
|
||||
com_list(c, n, 1);
|
||||
com_addbyte(c, BINARY_CALL);
|
||||
int inkeywords, i, na, nk;
|
||||
REQ(n, arglist);
|
||||
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;
|
||||
node *n;
|
||||
{
|
||||
REQ(n, raise_stmt); /* 'raise' test [',' test] */
|
||||
REQ(n, raise_stmt); /* 'raise' test [',' test [',' test]] */
|
||||
com_node(c, CHILD(n, 1));
|
||||
if (NCH(n) > 3)
|
||||
com_node(c, CHILD(n, 3));
|
||||
else
|
||||
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
|
||||
|
@ -1980,19 +2038,16 @@ com_argdefs(c, n, argcount_return)
|
|||
if (TYPE(n) != varargslist)
|
||||
return -1;
|
||||
/* varargslist:
|
||||
(fpdef ['=' test] ',')* '*' NAME |
|
||||
(fpdef ['=' test] ',')* '*' NAME ....... |
|
||||
fpdef ['=' test] (',' fpdef ['=' test])* [','] */
|
||||
nch = NCH(n);
|
||||
if (nch >= 2 && TYPE(CHILD(n, nch-2)) == STAR) {
|
||||
star = 1;
|
||||
nch -= 2;
|
||||
}
|
||||
else
|
||||
star = 0;
|
||||
nargs = 0;
|
||||
ndefs = 0;
|
||||
star = 0;
|
||||
for (i = 0; i < nch; i++) {
|
||||
int t;
|
||||
if (TYPE(CHILD(n, i)) == STAR)
|
||||
break;
|
||||
nargs++;
|
||||
i++;
|
||||
if (i >= nch)
|
||||
|
@ -2285,17 +2340,18 @@ com_arglist(c, n)
|
|||
int nch, op, nargs, i, t;
|
||||
REQ(n, varargslist);
|
||||
/* varargslist:
|
||||
(fpdef ['=' test] ',')* '*' NAME |
|
||||
(fpdef ['=' test] ',')* '*' NAME ..... |
|
||||
fpdef ['=' test] (',' fpdef ['=' test])* [','] */
|
||||
nch = NCH(n);
|
||||
if (nch >= 2 && TYPE(CHILD(n, nch-2)) == STAR) {
|
||||
op = UNPACK_VARARG;
|
||||
nch -= 2;
|
||||
}
|
||||
else
|
||||
op = UNPACK_ARG;
|
||||
op = UNPACK_ARG;
|
||||
nargs = 0;
|
||||
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++;
|
||||
i++;
|
||||
if (i >= nch)
|
||||
|
|
Loading…
Reference in New Issue