]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
3rd arg for raise; INCOMPLETE keyword parameter passing (currently f(kw=value) is...
authorGuido van Rossum <guido@python.org>
Fri, 7 Jul 1995 22:53:21 +0000 (22:53 +0000)
committerGuido van Rossum <guido@python.org>
Fri, 7 Jul 1995 22:53:21 +0000 (22:53 +0000)
Python/ceval.c
Python/compile.c

index 3fa03c0afd4f109f3b3fa8c66438970c9d28726d..a55451c3e467578afb62a8c444e32fe87f379be8 100644 (file)
@@ -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);
index a178bdb4ab445ad8d2194a6f20769d353510388b..df81f8f86fb511c99a92c1a04ac03e1b3f9e9f4e 100644 (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
 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)