From 03093a248d4ef3af23a5906dea276c01e0c1ae2c Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Wed, 28 Sep 1994 15:51:32 +0000 Subject: * Include/classobject.h, Objects/classobject.c, Python/ceval.c: 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 | 319 +++++++++++++++++++++++++------------------------ Objects/floatobject.c | 19 ++- Objects/longobject.c | 2 +- Objects/rangeobject.c | 28 ++--- Objects/stringobject.c | 2 +- Objects/xxobject.c | 53 ++++---- 6 files changed, 219 insertions(+), 204 deletions(-) diff --git a/Objects/classobject.c b/Objects/classobject.c index 8b7e4da..923ad45 100644 --- a/Objects/classobject.c +++ b/Objects/classobject.c @@ -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 @@ -681,47 +668,6 @@ static mapping_methods instance_as_mapping = { }; 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; int i; @@ -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*/ diff --git a/Objects/floatobject.c b/Objects/floatobject.c index cbdcfd5..b37dd15 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -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 +#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); } diff --git a/Objects/longobject.c b/Objects/longobject.c index 45907e8..82a74c0 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -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; } diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c index f19dad8..5f9da1d 100644 --- a/Objects/rangeobject.c +++ b/Objects/rangeobject.c @@ -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*/ diff --git a/Objects/stringobject.c b/Objects/stringobject.c index 4221d68..359e4e9 100644 --- a/Objects/stringobject.c +++ b/Objects/stringobject.c @@ -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 #else #ifndef UCHAR_MAX diff --git a/Objects/xxobject.c b/Objects/xxobject.c index e135d3f..7a29925 100644 --- a/Objects/xxobject.c +++ b/Objects/xxobject.c @@ -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*/ -- cgit v0.12