]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
* Include/classobject.h, Objects/classobject.c, Python/ceval.c:
authorGuido van Rossum <guido@python.org>
Wed, 28 Sep 1994 15:51:32 +0000 (15:51 +0000)
committerGuido van Rossum <guido@python.org>
Wed, 28 Sep 1994 15:51:32 +0000 (15:51 +0000)
entirely redone operator overloading.  The rules for class
instances are now much more relaxed than for other built-in types
(whose coerce must still return two objects of the same type)

* Objects/floatobject.c: add overflow check when converting float
to int and implement truncation towards zero using ceil/float

* Objects/longobject.c: change ValueError to OverflowError when
converting to int

* Objects/rangeobject.c: modernized

* Objects/stringobject.c: use HAVE_LIMITS instead of __STDC__

* Objects/xxobject.c: changed to use new style (not finished?)

Objects/classobject.c
Objects/floatobject.c
Objects/longobject.c
Objects/rangeobject.c
Objects/stringobject.c
Objects/xxobject.c

index 8b7e4dad649e5baade048b48dd860d5b77427059..923ad45ab312a70c80e3028986dab97640f1636f 100644 (file)
@@ -25,9 +25,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 /* Class object implementation */
 
 #include "allobjects.h"
-#include "modsupport.h"
 #include "structmember.h"
-#include "ceval.h"
 
 /* Forward */
 static object *class_lookup PROTO((classobject *, char *, classobject **));
@@ -520,33 +518,22 @@ instance_repr(inst)
 
 static int
 instance_compare(inst, other)
-       instanceobject *inst, *other;
+       object *inst, *other;
 {
-       object *func;
-       object *res;
+       object *result;
        int outcome;
-
-       func = instance_getattr(inst, "__cmp__");
-       if (func == NULL) {
-               err_clear();
-               if (inst < other)
-                       return -1;
-               if (inst > other)
-                       return 1;
-               return 0;
-       }
-       res = call_object(func, (object *)other);
-       DECREF(func);
-       if (res == NULL) {
-               err_clear(); /* XXX Should report the error, bot how...??? */
-               return 0;
-       }
-       if (is_intobject(res))
-               outcome = getintvalue(res);
-       else
-               outcome = 0; /* XXX Should report the error, bot how...??? */
-       DECREF(res);
-       return outcome;
+       result  = instancebinop(inst, other, "__cmp__", "__rcmp__");
+       if (result == NULL)
+               return -2;
+       outcome = getintvalue(result);
+       DECREF(result);
+       if (outcome == -1 && err_occurred())
+               return -2;
+       if (outcome < 0)
+               return -1;
+       else if (outcome > 0)
+               return 1;
+       return 0;
 }
 
 static long
@@ -680,47 +667,6 @@ static mapping_methods instance_as_mapping = {
        (objobjargproc)instance_ass_subscript, /*mp_ass_subscript*/
 };
 
-static object *
-instance_concat(inst, other)
-       instanceobject *inst, *other;
-{
-       object *func, *arg, *res;
-
-       func = instance_getattr(inst, "__add__");
-       if (func == NULL)
-               return NULL;
-       arg = mkvalue("(O)", other);
-       if (arg == NULL) {
-               DECREF(func);
-               return NULL;
-       }
-       res = call_object(func, arg);
-       DECREF(func);
-       DECREF(arg);
-       return res;
-}
-
-static object *
-instance_repeat(inst, count)
-       instanceobject *inst;
-       int count;
-{
-       object *func, *arg, *res;
-
-       func = instance_getattr(inst, "__mul__");
-       if (func == NULL)
-               return NULL;
-       arg = newintobject((long)count);
-       if (arg == NULL) {
-               DECREF(func);
-               return NULL;
-       }
-       res = call_object(func, arg);
-       DECREF(func);
-       DECREF(arg);
-       return res;
-}
-
 static object *
 instance_item(inst, i)
        instanceobject *inst;
@@ -827,8 +773,8 @@ instance_ass_slice(inst, i, j, value)
 
 static sequence_methods instance_as_sequence = {
        (inquiry)instance_length, /*sq_length*/
-       (binaryfunc)instance_concat, /*sq_concat*/
-       (intargfunc)instance_repeat, /*sq_repeat*/
+       0, /*sq_concat*/
+       0, /*sq_repeat*/
        (intargfunc)instance_item, /*sq_item*/
        (intintargfunc)instance_slice, /*sq_slice*/
        (intobjargproc)instance_ass_item, /*sq_ass_item*/
@@ -836,57 +782,133 @@ static sequence_methods instance_as_sequence = {
 };
 
 static object *
-generic_binary_op(self, other, methodname)
+generic_unary_op(self, methodname)
        instanceobject *self;
-       object *other;
        char *methodname;
 {
-       object *func, *arg, *res;
+       object *func, *res;
 
        if ((func = instance_getattr(self, methodname)) == NULL)
                return NULL;
-       arg = mkvalue("O", other);
-       if (arg == NULL) {
-               DECREF(func);
-               return NULL;
-       }
-       res = call_object(func, arg);
+       res = call_object(func, (object *)NULL);
        DECREF(func);
-       DECREF(arg);
        return res;
 }
 
-static object *
-generic_unary_op(self, methodname)
-       instanceobject *self;
-       char *methodname;
+
+/* Forward */
+static int halfbinop PROTO((object *, object *, char *, object **));
+
+
+/* Implement a binary operator involving at least one class instance. */
+
+object *
+instancebinop(v, w, opname, ropname)
+       object *v;
+       object *w;
+       char *opname;
+       char *ropname;
 {
-       object *func, *res;
+       char buf[256];
+       object *result = NULL;
+       if (halfbinop(v, w, opname, &result) <= 0)
+               return result;
+       if (halfbinop(w, v, ropname, &result) <= 0)
+               return result;
+       sprintf(buf, "%s nor %s defined for these operands", opname, ropname);
+       err_setstr(TypeError, buf);
+       return NULL;
+}
 
-       if ((func = instance_getattr(self, methodname)) == NULL)
-               return NULL;
-       res = call_object(func, (object *)NULL);
+
+/* Try one half of a binary operator involving a class instance.
+   Return value:
+   -1 if an exception is to be reported right away
+   0  if we have a valid result
+   1  if we could try another operation
+*/
+
+static int
+halfbinop(v, w, opname, r_result)
+       object *v;
+       object *w;
+       char *opname;
+       object **r_result;
+{
+       object *func;
+       object *args;
+       object *coerce;
+       object *coerced = NULL;
+       object *v1;
+       
+       if (!is_instanceobject(v))
+               return 1;
+       func = getattr(v, opname);
+       if (func == NULL) {
+               if (err_occurred() != AttributeError)
+                       return -1;
+               err_clear();
+               return 1;
+       }
+       coerce = getattr(v, "__coerce__");
+       if (coerce == NULL) {
+               err_clear();
+       }
+       else {
+               args = mkvalue("(O)", w);
+               if (args == NULL) {
+                       DECREF(func);
+                       return -1;
+               }
+               coerced = call_object(coerce, args);
+               DECREF(args);
+               DECREF(coerce);
+               if (coerced == NULL) {
+                       DECREF(func);
+                       return -1;
+               }
+               if (coerced == None) {
+                       DECREF(coerced);
+                       DECREF(func);
+                       return 1;
+               }
+               if (!is_tupleobject(coerced) || gettuplesize(coerced) != 2) {
+                       DECREF(coerced);
+                       DECREF(func);
+                       err_setstr(TypeError, "coercion should return None or 2-tuple");
+                       return -1;
+               }
+               v1 = gettupleitem(coerced, 0);
+               if (v1 != v) {
+                       v = v1;
+                       DECREF(func);
+                       func = getattr(v, opname);
+                       if (func == NULL) {
+                               XDECREF(coerced);
+                               return -1;
+                       }
+               }
+               w = gettupleitem(coerced, 1);
+       }
+       args = mkvalue("(O)", w);
+       if (args == NULL) {
+               DECREF(func);
+               XDECREF(coerced);
+               return -1;
+       }
+       *r_result = call_object(func, args);
+       DECREF(args);
        DECREF(func);
-       return res;
+       XDECREF(coerced);
+       return *r_result == NULL ? -1 : 0;
 }
 
-#define BINARY(funcname, methodname) \
-static object * funcname(self, other) instanceobject *self; object *other; { \
-       return generic_binary_op(self, other, methodname); \
-}
 
 #define UNARY(funcname, methodname) \
 static object *funcname(self) instanceobject *self; { \
        return generic_unary_op(self, methodname); \
 }
 
-BINARY(instance_add, "__add__")
-BINARY(instance_sub, "__sub__")
-BINARY(instance_mul, "__mul__")
-BINARY(instance_div, "__div__")
-BINARY(instance_mod, "__mod__")
-BINARY(instance_divmod, "__divmod__")
-BINARY(instance_pow, "__pow__")
 UNARY(instance_neg, "__neg__")
 UNARY(instance_pos, "__pos__")
 UNARY(instance_abs, "__abs__")
@@ -926,76 +948,56 @@ instance_nonzero(self)
 }
 
 UNARY(instance_invert, "__invert__")
-BINARY(instance_lshift, "__lshift__")
-BINARY(instance_rshift, "__rshift__")
-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;
-}
-
 UNARY(instance_int, "__int__")
 UNARY(instance_long, "__long__")
 UNARY(instance_float, "__float__")
 UNARY(instance_oct, "__oct__")
 UNARY(instance_hex, "__hex__")
 
+/* This version is for ternary calls only (z != None) */
+static object *
+instance_pow(v, w, z)
+       object *v;
+       object *w;
+       object *z;
+{
+       /* XXX Doesn't do coercions... */
+       object *func;
+       object *args;
+       object *result;
+       func = getattr(v, "__pow__");
+       if (func == NULL)
+               return NULL;
+       args = mkvalue("(OO)", w, z);
+       if (args == NULL) {
+               DECREF(func);
+               return NULL;
+       }
+       result = call_object(func, args);
+       DECREF(func);
+       DECREF(args);
+       return result;
+}
+
 static number_methods instance_as_number = {
-       (binaryfunc)instance_add, /*nb_add*/
-       (binaryfunc)instance_sub, /*nb_subtract*/
-       (binaryfunc)instance_mul, /*nb_multiply*/
-       (binaryfunc)instance_div, /*nb_divide*/
-       (binaryfunc)instance_mod, /*nb_remainder*/
-       (binaryfunc)instance_divmod, /*nb_divmod*/
+       0, /*nb_add*/
+       0, /*nb_subtract*/
+       0, /*nb_multiply*/
+       0, /*nb_divide*/
+       0, /*nb_remainder*/
+       0, /*nb_divmod*/
        (ternaryfunc)instance_pow, /*nb_power*/
        (unaryfunc)instance_neg, /*nb_negative*/
        (unaryfunc)instance_pos, /*nb_positive*/
        (unaryfunc)instance_abs, /*nb_absolute*/
        (inquiry)instance_nonzero, /*nb_nonzero*/
        (unaryfunc)instance_invert, /*nb_invert*/
-       (binaryfunc)instance_lshift, /*nb_lshift*/
-       (binaryfunc)instance_rshift, /*nb_rshift*/
-       (binaryfunc)instance_and, /*nb_and*/
-       (binaryfunc)instance_xor, /*nb_xor*/
-       (binaryfunc)instance_or, /*nb_or*/
-       (coercion)instance_coerce, /*nb_coerce*/
+       0, /*nb_lshift*/
+       0, /*nb_rshift*/
+       0, /*nb_and*/
+       0, /*nb_xor*/
+       0, /*nb_or*/
+       0, /*nb_coerce*/
        (unaryfunc)instance_int, /*nb_int*/
        (unaryfunc)instance_long, /*nb_long*/
        (unaryfunc)instance_float, /*nb_float*/
@@ -1011,10 +1013,9 @@ typeobject Instancetype = {
        0,
        (destructor)instance_dealloc, /*tp_dealloc*/
        0,                      /*tp_print*/
-       (object * (*) FPROTO((object *, char *)))
        (getattrfunc)instance_getattr, /*tp_getattr*/
        (setattrfunc)instance_setattr, /*tp_setattr*/
-       (cmpfunc)instance_compare, /*tp_compare*/
+       instance_compare, /*tp_compare*/
        (reprfunc)instance_repr, /*tp_repr*/
        &instance_as_number,    /*tp_as_number*/
        &instance_as_sequence,  /*tp_as_sequence*/
index cbdcfd5fdfe58944e897027759e93e98ebf80fc4..b37dd15b327da6a40257a71dd6e342c53245cd37 100644 (file)
@@ -47,6 +47,18 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 #define CHECK(x) /* Don't know how to check */
 #endif
 
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#ifndef LONG_MAX
+#define LONG_MAX 0X7FFFFFFFL
+#endif
+
+#ifndef LONG_MIN
+#define LONG_MIN (-LONG_MAX-1)
+#endif
+
 #ifndef macintosh
 extern double fmod PROTO((double, double));
 extern double pow PROTO((double, double));
@@ -397,8 +409,11 @@ float_int(v)
        object *v;
 {
        double x = getfloatvalue(v);
-       /* XXX should check for overflow */
-       /* XXX should define how we round */
+       if (x < 0 ? (x = ceil(x)) < (double)LONG_MIN
+                 : (x = floor(x)) > (double)LONG_MAX) {
+               err_setstr(OverflowError, "float to large to convert");
+               return NULL;
+       }
        return newintobject((long)x);
 }
 
index 45907e85278d5c28bff74be8214f4a93ba9d0ac9..82a74c0a12a0e38d7535b741159b49afccd2ae82 100644 (file)
@@ -159,7 +159,7 @@ getlongvalue(vv)
                prev = x;
                x = (x << SHIFT) + v->ob_digit[i];
                if ((x >> SHIFT) != prev) {
-                       err_setstr(ValueError,
+                       err_setstr(OverflowError,
                                "long int too long to convert");
                        return -1;
                }
index f19dad89ec33f41eaaeda3636ab7301777a1c2c6..5f9da1d84b4687d34185598992c5d636ddef7cce 100644 (file)
@@ -1,6 +1,6 @@
 /***********************************************************
-Copyright 1991, 1992 by Stichting Mathematisch Centrum, Amsterdam, The
-Netherlands.
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
+Amsterdam, The Netherlands.
 
                         All Rights Reserved
 
@@ -105,7 +105,7 @@ range_repr(r)
        rangeobject *r;
 {
        char buf[80];
-       sprintf(buf, "(range(%ld, %ld, %ld) * %d)",
+       sprintf(buf, "(xrange(%ld, %ld, %ld) * %d)",
                        r->start,
                        r->start + r->len * r->step,
                        r->step,
@@ -222,7 +222,7 @@ range_getattr(r, name)
        char *name;
 {
        static struct methodlist range_methods[] = {
-               {"tolist",      range_tolist},
+               {"tolist",      (method)range_tolist},
                {NULL,          NULL}
        };
 
@@ -230,11 +230,11 @@ range_getattr(r, name)
 }
 
 static sequence_methods range_as_sequence = {
-       range_length,   /*sq_length*/
-       range_concat,   /*sq_concat*/
-       range_repeat,   /*sq_repeat*/
-       range_item,     /*sq_item*/
-       range_slice,    /*sq_slice*/
+       (inquiry)range_length, /*sq_length*/
+       (binaryfunc)range_concat, /*sq_concat*/
+       (intargfunc)range_repeat, /*sq_repeat*/
+       (intargfunc)range_item, /*sq_item*/
+       (intintargfunc)range_slice, /*sq_slice*/
        0,              /*sq_ass_item*/
        0,              /*sq_ass_slice*/
 };
@@ -245,12 +245,12 @@ typeobject Rangetype = {
        "xrange",               /* Name of this type */
        sizeof(rangeobject),    /* Basic object size */
        0,                      /* Item size for varobject */
-       range_dealloc,          /*tp_dealloc*/
-       range_print,            /*tp_print*/
-       range_getattr,          /*tp_getattr*/
+       (destructor)range_dealloc, /*tp_dealloc*/
+       (printfunc)range_print, /*tp_print*/
+       (getattrfunc)range_getattr, /*tp_getattr*/
        0,                      /*tp_setattr*/
-       range_compare,          /*tp_compare*/
-       range_repr,             /*tp_repr*/
+       (cmpfunc)range_compare, /*tp_compare*/
+       (reprfunc)range_repr, /*tp_repr*/
        0,                      /*tp_as_number*/
        &range_as_sequence,     /*tp_as_sequence*/
        0,                      /*tp_as_mapping*/
index 4221d685bb29b94298434bd4eaa4bfdd94de8c5b..359e4e9c4179b0e56056d6fe57ae0e238c1471b7 100644 (file)
@@ -32,7 +32,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 int null_strings, one_strings;
 #endif
 
-#ifdef __STDC__
+#ifdef HAVE_LIMITS_H
 #include <limits.h>
 #else
 #ifndef UCHAR_MAX
index e135d3f6b799323973f5e7d0392c906dcb4ed760..7a29925db7d55e86a8c36146985205c2c8cde587 100644 (file)
@@ -34,24 +34,23 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 /* Xx objects */
 
-#include "allobjects.h"
-#include "modsupport.h"                /* For getargs() etc. */
+#include "Python.h"
 
 typedef struct {
-       OB_HEAD
-       object  *x_attr;        /* Attributes dictionary */
+       PyObject_HEAD
+       PyObject        *x_attr;        /* Attributes dictionary */
 } xxobject;
 
-staticforward typeobject Xxtype;
+staticforward PyTypeObject Xxtype;
 
 #define is_xxobject(v)         ((v)->ob_type == &Xxtype)
 
 static xxobject *
 newxxobject(arg)
-       object *arg;
+       PyObject *arg;
 {
        xxobject *xp;
-       xp = NEWOBJ(xxobject, &Xxtype);
+       xp = PyObject_NEW(xxobject, &Xxtype);
        if (xp == NULL)
                return NULL;
        xp->x_attr = NULL;
@@ -64,65 +63,65 @@ static void
 xx_dealloc(xp)
        xxobject *xp;
 {
-       XDECREF(xp->x_attr);
-       DEL(xp);
+       Py_XDECREF(xp->x_attr);
+       PyMem_DEL(xp);
 }
 
-static object *
+static PyObject *
 xx_demo(self, args)
        xxobject *self;
-       object *args;
+       PyObject *args;
 {
-       if (!getnoarg(args))
+       if (!PyArg_NoArgs(args))
                return NULL;
-       INCREF(None);
-       return None;
+       Py_INCREF(Py_None);
+       return Py_None;
 }
 
-static struct methodlist xx_methods[] = {
-       {"demo",        (method)xx_demo},
+static Py_MethodDef xx_methods[] = {
+       {"demo",        (PyCFunction)xx_demo},
        {NULL,          NULL}           /* sentinel */
 };
 
-static object *
+static PyObject *
 xx_getattr(xp, name)
        xxobject *xp;
        char *name;
 {
        if (xp->x_attr != NULL) {
-               object *v = dictlookup(xp->x_attr, name);
+               PyObject *v = PyDict_GetItemString(xp->x_attr, name);
                if (v != NULL) {
-                       INCREF(v);
+                       Py_INCREF(v);
                        return v;
                }
        }
-       return findmethod(xx_methods, (object *)xp, name);
+       return Py_FindMethod(xx_methods, (PyObject *)xp, name);
 }
 
 static int
 xx_setattr(xp, name, v)
        xxobject *xp;
        char *name;
-       object *v;
+       PyObject *v;
 {
        if (xp->x_attr == NULL) {
-               xp->x_attr = newdictobject();
+               xp->x_attr = PyDict_New();
                if (xp->x_attr == NULL)
                        return -1;
        }
        if (v == NULL) {
-               int rv = dictremove(xp->x_attr, name);
+               int rv = PyDict_DelItemString(xp->x_attr, name);
                if (rv < 0)
-                       err_setstr(AttributeError,
+                       PyErr_SetString(PyExc_AttributeError,
                                "delete non-existing xx attribute");
                return rv;
        }
        else
-               return dictinsert(xp->x_attr, name, v);
+               return PyDict_SetItemString(xp->x_attr, name, v);
 }
 
-static typeobject Xxtype = {
-       OB_HEAD_INIT(&Typetype)
+static PyTypeObject Xxtype = {
+       PyObject_HEAD_INIT(&PyType_Type)
        0,                      /*ob_size*/
        "xx",                   /*tp_name*/
        sizeof(xxobject),       /*tp_basicsize*/