]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
* classobject.[ch], {float,long,int}object.c, bltinmodule.c:
authorGuido van Rossum <guido@python.org>
Fri, 14 Aug 1992 12:06:52 +0000 (12:06 +0000)
committerGuido van Rossum <guido@python.org>
Fri, 14 Aug 1992 12:06:52 +0000 (12:06 +0000)
  coercion is now completely generic.
* ceval.c: for instances, don't coerce for + and *; * reverses
  arguments if left one is non-instance numeric and right one sequence.

Include/classobject.h
Include/object.h
Objects/classobject.c
Objects/floatobject.c
Objects/longobject.c
Python/bltinmodule.c
Python/ceval.c

index 1d24a7c86a7ebb01f55d8f7535d0b56b43a3f273..b33cacce61f5b225ca79db9b2dba3afd6605b36b 100644 (file)
@@ -43,5 +43,4 @@ extern object *newinstancemethodobject PROTO((object *, object *));
 extern object *instancemethodgetfunc PROTO((object *));
 extern object *instancemethodgetself PROTO((object *));
 
-extern int instance_coerce PROTO((object **, object **));
 extern object *instance_convert PROTO((object *, char *));
index d987efb5fa305c72cd213a9b9ae678c7378622a7..a66629c8ee2fb5992a950668063d40544a8ff284 100644 (file)
@@ -142,6 +142,7 @@ typedef struct {
        object *(*nb_and) FPROTO((object *, object *));
        object *(*nb_xor) FPROTO((object *, object *));
        object *(*nb_or) FPROTO((object *, object *));
+       int (*nb_coerce) FPROTO((object **, object **));
 } number_methods;
 
 typedef struct {
index 40fe0c9b34f5d10a569bb7605f19f00eb98ca2e7..8164cedf3b49e2ba7c4ee7cbf4e47644fc5d7cb7 100644 (file)
@@ -417,13 +417,19 @@ static object *
 instance_concat(inst, other)
        instanceobject *inst, *other;
 {
-       object *func, *res;
+       object *func, *arg, *res;
 
        func = instance_getattr(inst, "__add__");
        if (func == NULL)
                return NULL;
-       res = call_object(func, (object *)other);
+       arg = mkvalue("(O)", other);
+       if (arg == NULL) {
+               DECREF(func);
+               return NULL;
+       }
+       res = call_object(func, arg);
        DECREF(func);
+       DECREF(arg);
        return res;
 }
 
@@ -568,12 +574,18 @@ generic_binary_op(self, other, methodname)
        object *other;
        char *methodname;
 {
-       object *func, *res;
+       object *func, *arg, *res;
 
        if ((func = instance_getattr(self, methodname)) == NULL)
                return NULL;
-       res = call_object(func, other);
+       arg = mkvalue("O", other);
+       if (arg == NULL) {
+               DECREF(func);
+               return NULL;
+       }
+       res = call_object(func, arg);
        DECREF(func);
+       DECREF(arg);
        return res;
 }
 
@@ -653,6 +665,45 @@ BINARY(instance_and, "__and__")
 BINARY(instance_xor, "__xor__")
 BINARY(instance_or, "__or__")
 
+static int
+instance_coerce(pv, pw)
+       object **pv, **pw;
+{
+       object *v =  *pv;
+       object *w = *pw;
+       object *func;
+       object *res;
+       int outcome;
+
+       if (!is_instanceobject(v))
+               return 1; /* XXX shouldn't be possible */
+       func = instance_getattr((instanceobject *)v, "__coerce__");
+       if (func == NULL) {
+               err_clear();
+               return 1;
+       }
+       res = call_object(func, w);
+       if (res == NULL)
+               return -1;
+       if (res == None) {
+               DECREF(res);
+               return 1;
+       }
+       outcome = getargs(res, "(OO)", &v, &w);
+       if (!outcome || v->ob_type != w->ob_type ||
+                       v->ob_type->tp_as_number == NULL) {
+               DECREF(res);
+               err_setstr(TypeError, "bad __coerce__ result");
+               return -1;
+       }
+       INCREF(v);
+       INCREF(w);
+       DECREF(res);
+       *pv = v;
+       *pw = w;
+       return 0;
+}
+
 static number_methods instance_as_number = {
        instance_add,           /*nb_add*/
        instance_sub,           /*nb_subtract*/
@@ -671,6 +722,7 @@ static number_methods instance_as_number = {
        instance_and,           /*nb_and*/
        instance_xor,           /*nb_xor*/
        instance_or,            /*nb_or*/
+       instance_coerce,        /*nb_coerce*/
 };
 
 typeobject Instancetype = {
@@ -690,58 +742,6 @@ typeobject Instancetype = {
        &instance_as_mapping,   /*tp_as_mapping*/
 };
 
-static int
-one_coerce(pv, pw)
-       object **pv, **pw;
-{
-       object *v = *pv;
-       object *w = *pw;
-       object *func;
-
-       if (!is_instanceobject(v))
-               return 1;
-       func = instance_getattr((instanceobject *)v, "__coerce__");
-       if (func == NULL) {
-               err_clear();
-               return 1;
-       }
-       if (func != NULL) {
-               object *res = call_object(func, w);
-               int outcome;
-               if (res == NULL)
-                       return -1;
-               outcome = getargs(res, "(OO)", &v, &w);
-               if (!outcome || v->ob_type != w->ob_type ||
-                               v->ob_type->tp_as_number == NULL) {
-                       DECREF(res);
-                       err_setstr(TypeError, "bad __coerce__ result");
-                       return -1;
-               }
-               INCREF(v);
-               INCREF(w);
-               DECREF(res);
-               *pv = v;
-               *pw = w;
-               return 0;
-       }
-}
-
-int
-instance_coerce(pv, pw)
-       object **pv, **pw;
-{
-       int outcome;
-       outcome = one_coerce(pv, pw);
-       if (outcome > 0) {
-               outcome = one_coerce(pw, pv);
-               if (outcome > 0) {
-                       err_setstr(TypeError, "uncoerceable instance");
-                       outcome = -1;
-               }
-       }
-       return outcome;
-}
-
 object *
 instance_convert(inst, methodname)
        object *inst;
index d154cab1c0f8c7364762147b644a79d11ad35b6f..5ce620220a97995bbce6a185df5da3d5f5f598e9 100644 (file)
@@ -299,6 +299,25 @@ float_nonzero(v)
        return v->ob_fval != 0.0;
 }
 
+int
+float_coerce(pv, pw)
+       object **pv;
+       object **pw;
+{
+       if (is_intobject(*pw)) {
+               long x = getintvalue(*pw);
+               *pw = newfloatobject((double)x);
+               INCREF(*pv);
+               return 0;
+       }
+       else if (is_longobject(*pw)) {
+               *pw = newfloatobject(dgetlongvalue(*pw));
+               INCREF(*pv);
+               return 0;
+       }
+       return 1; /* Can't do it */
+}
+
 static number_methods float_as_number = {
        float_add,      /*nb_add*/
        float_sub,      /*nb_subtract*/
@@ -317,6 +336,7 @@ static number_methods float_as_number = {
        0,              /*nb_and*/
        0,              /*nb_xor*/
        0,              /*nb_or*/
+       float_coerce,   /*nb_coerce*/
 };
 
 typeobject Floattype = {
index bf62c1fb0f43a353d501d6712b04992aa55c7bcc..f9e37650f3281acb16234090fdd5c60a96acc90f 100644 (file)
@@ -1253,6 +1253,19 @@ long_or(a, b)
        return long_bitwise(a, '|', b);
 }
 
+int
+long_coerce(pv, pw)
+       object **pv;
+       object **pw;
+{
+       if (is_intobject(*pw)) {
+               *pw = newlongobject(getintvalue(*pw));
+               INCREF(*pv);
+               return 0;
+       }
+       return 1; /* Can't do it */
+}
+
 #define UF (object* (*) FPROTO((object *))) /* Unary function */
 #define BF (object* (*) FPROTO((object *, object *))) /* Binary function */
 #define IF (int (*) FPROTO((object *))) /* Int function */
@@ -1275,6 +1288,8 @@ static number_methods long_as_number = {
        BF long_and,    /*nb_and*/
        BF long_xor,    /*nb_xor*/
        BF long_or,     /*nb_or*/
+       (int (*) FPROTO((object **, object **)))
+       long_coerce,    /*nb_coerce*/
 };
 
 typeobject Longtype = {
index cce19e1ed84926fc2cfb8deb61986b982c774ec4..86deac3eaa86ec6bd4c6fa260937b4e8baa198fb 100644 (file)
@@ -781,10 +781,7 @@ initbuiltin()
    Increment the reference count on each argument.
    Return -1 and raise an exception if no coercion is possible
    (and then no reference count is incremented).
-   XXX This should be distributed over the various numeric types,
-   XXX but for now I don't see how to implement that.
-   XXX So, for now, if you add a new numeric type,
-   XXX you must add to this function as well. */
+*/
 
 int
 coerce(pv, pw)
@@ -792,36 +789,23 @@ coerce(pv, pw)
 {
        register object *v = *pv;
        register object *w = *pw;
+       int res;
+
        if (v->ob_type == w->ob_type) {
                INCREF(v);
                INCREF(w);
                return 0;
        }
-       if (is_instanceobject(v) || is_instanceobject(w))
-               return instance_coerce(pv, pw);
-       if (v->ob_type->tp_as_number == NULL ||
-                                       w->ob_type->tp_as_number == NULL) {
-               err_setstr(TypeError, "mixing number and non-number");
-               return -1;
-       }
-       if (is_floatobject(v) || is_floatobject(w)) {
-               v = builtin_float((object *)0, v);
-               w = builtin_float((object *)0, w);
-       }
-       else if (is_longobject(v) || is_longobject(w)) {
-               v = builtin_long((object *)0, v);
-               w = builtin_long((object *)0, w);
-       }
-       else {
-               err_setstr(TypeError, "can't coerce numeric types?!?!?");
-               return -1;
+       if (v->ob_type->tp_as_number && v->ob_type->tp_as_number->nb_coerce) {
+               res = (*v->ob_type->tp_as_number->nb_coerce)(pv, pw);
+               if (res <= 0)
+                       return res;
        }
-       if (v == NULL || w == NULL) {
-               XDECREF(v);
-               XDECREF(w);
-               return -1;
+       if (w->ob_type->tp_as_number && w->ob_type->tp_as_number->nb_coerce) {
+               res = (*w->ob_type->tp_as_number->nb_coerce)(pw, pv);
+               if (res <= 0)
+                       return res;
        }
-       *pv = v;
-       *pw = w;
-       return 0;
+       err_setstr(TypeError, "number coercion failed");
+       return -1;
 }
index ad679a68861d5eea35fee66443868b827aea9a64..5b72d8eeb7e917dd0d7c7915011ed43b9ed0296e 100644 (file)
@@ -1532,7 +1532,9 @@ static object *
 add(v, w)
        object *v, *w;
 {
-       if (v->ob_type->tp_as_number != NULL) {
+       if (v->ob_type->tp_as_sequence != NULL)
+               return (*v->ob_type->tp_as_sequence->sq_concat)(v, w);
+       else if (v->ob_type->tp_as_number != NULL) {
                object *x;
                if (coerce(&v, &w) != 0)
                        return NULL;
@@ -1541,8 +1543,6 @@ add(v, w)
                DECREF(w);
                return x;
        }
-       else if (v->ob_type->tp_as_sequence != NULL)
-               return (*v->ob_type->tp_as_sequence->sq_concat)(v, w);
        else {
                err_setstr(TypeError, "+ not supported by operands");
                return NULL;
@@ -1571,16 +1571,27 @@ mul(v, w)
        object *v, *w;
 {
        typeobject *tp;
-       if (is_intobject(v) && w->ob_type->tp_as_sequence != NULL) {
-               /* int*sequence -- swap v and w */
+       tp = v->ob_type;
+       if (tp->tp_as_number != NULL &&
+           w->ob_type->tp_as_sequence != NULL &&
+           !is_instanceobject(v)) {
+               /* number*sequence -- swap v and w */
                object *tmp = v;
                v = w;
                w = tmp;
+               tp = v->ob_type;
        }
-       tp = v->ob_type;
        if (tp->tp_as_number != NULL) {
                object *x;
-               if (coerce(&v, &w) != 0)
+               if (is_instanceobject(v)) {
+                       /* Instances of user-defined classes get their
+                          other argument uncoerced, so they may
+                          implement sequence*number as well as
+                          number*number. */
+                       INCREF(v);
+                       INCREF(w);
+               }
+               else if (coerce(&v, &w) != 0)
                        return NULL;
                x = (*v->ob_type->tp_as_number->nb_multiply)(v, w);
                DECREF(v);