From f10570b9eb556b015a4a068377cf6cadf380a39d Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Fri, 7 Jul 1995 22:53:21 +0000 Subject: 3rd arg for raise; INCOMPLETE keyword parameter passing (currently f(kw=value) is seen as f('kw', value)) --- Python/ceval.c | 181 ++++++++++++++++++++++++++++++++++++++++++++++--------- Python/compile.c | 100 +++++++++++++++++++++++------- 2 files changed, 229 insertions(+), 52 deletions(-) diff --git a/Python/ceval.c b/Python/ceval.c index 3fa03c0..a55451c 100644 --- a/Python/ceval.c +++ b/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); diff --git a/Python/compile.c b/Python/compile.c index a178bdb..df81f8f 100644 --- a/Python/compile.c +++ b/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) -- cgit v0.12