Get rid of most of the rest of coerce (slot is still there for now).

This commit is contained in:
Neal Norwitz 2006-08-21 17:06:07 +00:00
parent 79212998a8
commit 4886cc331f
19 changed files with 131 additions and 497 deletions

View file

@ -339,8 +339,6 @@ PyNumber_Check(PyObject *o)
/* Binary operators */
/* New style number protocol support */
#define NB_SLOT(x) offsetof(PyNumberMethods, x)
#define NB_BINOP(nb_methods, slot) \
(*(binaryfunc*)(& ((char*)nb_methods)[slot]))
@ -350,23 +348,11 @@ PyNumber_Check(PyObject *o)
/*
Calling scheme used for binary operations:
v w Action
-------------------------------------------------------------------
new new w.op(v,w)[*], v.op(v,w), w.op(v,w)
new old v.op(v,w), coerce(v,w), v.op(v,w)
old new w.op(v,w), coerce(v,w), v.op(v,w)
old old coerce(v,w), v.op(v,w)
Order operations are tried until either a valid result or error:
w.op(v,w)[*], v.op(v,w), w.op(v,w)
[*] only when v->ob_type != w->ob_type && w->ob_type is a subclass of
v->ob_type
Legend:
-------
* new == new style number
* old == old style number
* Action indicates the order in which operations are tried until either
a valid result is produced or an error occurs.
*/
static PyObject *
@ -434,29 +420,8 @@ binary_op(PyObject *v, PyObject *w, const int op_slot, const char *op_name)
/*
Calling scheme used for ternary operations:
*** In some cases, w.op is called before v.op; see binary_op1. ***
v w z Action
-------------------------------------------------------------------
new new new v.op(v,w,z), w.op(v,w,z), z.op(v,w,z)
new old new v.op(v,w,z), z.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
old new new w.op(v,w,z), z.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
old old new z.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
new new old v.op(v,w,z), w.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
new old old v.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
old new old w.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
old old old coerce(v,w,z), v.op(v,w,z)
Legend:
-------
* new == new style number
* old == old style number
* Action indicates the order in which operations are tried until either
a valid result is produced or an error occurs.
* coerce(v,w,z) actually does: coerce(v,w), coerce(v,z), coerce(w,z) and
only if z != Py_None; if z == Py_None, then it is treated as absent
variable and only coerce(v,w) is tried.
Order operations are tried until either a valid result or error:
v.op(v,w,z), w.op(v,w,z), z.op(v,w,z)
*/
static PyObject *

View file

@ -573,65 +573,20 @@ complex_nonzero(PyComplexObject *v)
return v->cval.real != 0.0 || v->cval.imag != 0.0;
}
static int
complex_coerce(PyObject **pv, PyObject **pw)
{
Py_complex cval;
cval.imag = 0.;
if (PyInt_Check(*pw)) {
cval.real = (double)PyInt_AsLong(*pw);
*pw = PyComplex_FromCComplex(cval);
Py_INCREF(*pv);
return 0;
}
else if (PyLong_Check(*pw)) {
cval.real = PyLong_AsDouble(*pw);
if (cval.real == -1.0 && PyErr_Occurred())
return -1;
*pw = PyComplex_FromCComplex(cval);
Py_INCREF(*pv);
return 0;
}
else if (PyFloat_Check(*pw)) {
cval.real = PyFloat_AsDouble(*pw);
*pw = PyComplex_FromCComplex(cval);
Py_INCREF(*pv);
return 0;
}
else if (PyComplex_Check(*pw)) {
Py_INCREF(*pv);
Py_INCREF(*pw);
return 0;
}
return 1; /* Can't do it */
}
static PyObject *
complex_richcompare(PyObject *v, PyObject *w, int op)
{
int c;
Py_complex i, j;
PyObject *res;
c = PyNumber_CoerceEx(&v, &w);
if (c < 0)
return NULL;
if (c > 0) {
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
/* Make sure both arguments are complex. */
if (!(PyComplex_Check(v) && PyComplex_Check(w))) {
Py_DECREF(v);
Py_DECREF(w);
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
i = ((PyComplexObject *)v)->cval;
j = ((PyComplexObject *)w)->cval;
Py_DECREF(v);
Py_DECREF(w);
if (op != Py_EQ && op != Py_NE) {
PyErr_SetString(PyExc_TypeError,
@ -996,7 +951,7 @@ static PyNumberMethods complex_as_number = {
0, /* nb_and */
0, /* nb_xor */
0, /* nb_or */
complex_coerce, /* nb_coerce */
(coercion)0, /* nb_coerce */
complex_int, /* nb_int */
complex_long, /* nb_long */
complex_float, /* nb_float */

View file

@ -842,31 +842,6 @@ float_nonzero(PyFloatObject *v)
return v->ob_fval != 0.0;
}
static int
float_coerce(PyObject **pv, PyObject **pw)
{
if (PyInt_Check(*pw)) {
long x = PyInt_AsLong(*pw);
*pw = PyFloat_FromDouble((double)x);
Py_INCREF(*pv);
return 0;
}
else if (PyLong_Check(*pw)) {
double x = PyLong_AsDouble(*pw);
if (x == -1.0 && PyErr_Occurred())
return -1;
*pw = PyFloat_FromDouble(x);
Py_INCREF(*pv);
return 0;
}
else if (PyFloat_Check(*pw)) {
Py_INCREF(*pv);
Py_INCREF(*pw);
return 0;
}
return 1; /* Can't do it */
}
static PyObject *
float_long(PyObject *v)
{
@ -1119,7 +1094,7 @@ static PyNumberMethods float_as_number = {
0, /*nb_and*/
0, /*nb_xor*/
0, /*nb_or*/
float_coerce, /*nb_coerce*/
(coercion)0, /*nb_coerce*/
float_int, /*nb_int*/
float_long, /*nb_long*/
float_float, /*nb_float*/

View file

@ -580,7 +580,7 @@ i_divmod(register long x, register long y,
}
static PyObject *
int_div(PyIntObject *x, PyIntObject *y)
int_floor_div(PyIntObject *x, PyIntObject *y)
{
long xi, yi;
long d, m;
@ -872,17 +872,6 @@ int_or(PyIntObject *v, PyIntObject *w)
return PyInt_FromLong(a | b);
}
static int
int_coerce(PyObject **pv, PyObject **pw)
{
if (PyInt_Check(*pw)) {
Py_INCREF(*pv);
Py_INCREF(*pw);
return 0;
}
return 1; /* Can't do it */
}
static PyObject *
int_int(PyIntObject *v)
{
@ -1036,7 +1025,7 @@ static PyNumberMethods int_as_number = {
(binaryfunc)int_and, /*nb_and*/
(binaryfunc)int_xor, /*nb_xor*/
(binaryfunc)int_or, /*nb_or*/
int_coerce, /*nb_coerce*/
0, /*nb_coerce*/
(unaryfunc)int_int, /*nb_int*/
(unaryfunc)int_long, /*nb_long*/
(unaryfunc)int_float, /*nb_float*/
@ -1052,7 +1041,7 @@ static PyNumberMethods int_as_number = {
0, /*nb_inplace_and*/
0, /*nb_inplace_xor*/
0, /*nb_inplace_or*/
(binaryfunc)int_div, /* nb_floor_divide */
(binaryfunc)int_floor_div, /* nb_floor_divide */
int_true_divide, /* nb_true_divide */
0, /* nb_inplace_floor_divide */
0, /* nb_inplace_true_divide */

View file

@ -681,9 +681,7 @@ try_3way_compare(PyObject *v, PyObject *w)
b) have different types or a type without tp_compare; and
c) don't have a user-defined tp_compare.
tp_compare implementations in C assume that both arguments
have their type, so we give up if the coercion fails or if
it yields types which are still incompatible (which can
happen with a user-defined nb_coerce).
have their type, so we give up if the coercion fails.
*/
c = PyNumber_CoerceEx(&v, &w);
if (c < 0)
@ -1513,22 +1511,6 @@ PyNumber_CoerceEx(PyObject **pv, PyObject **pw)
return 1;
}
/* Coerce two numeric types to the "larger" one.
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).
*/
int
PyNumber_Coerce(PyObject **pv, PyObject **pw)
{
int err = PyNumber_CoerceEx(pv, pw);
if (err <= 0)
return err;
PyErr_SetString(PyExc_TypeError, "number coercion failed");
return -1;
}
/* Test whether an object can be called */
int

View file

@ -3326,34 +3326,6 @@ wrap_binaryfunc_r(PyObject *self, PyObject *args, void *wrapped)
return (*func)(other, self);
}
static PyObject *
wrap_coercefunc(PyObject *self, PyObject *args, void *wrapped)
{
coercion func = (coercion)wrapped;
PyObject *other, *res;
int ok;
if (!check_num_args(args, 1))
return NULL;
other = PyTuple_GET_ITEM(args, 0);
ok = func(&self, &other);
if (ok < 0)
return NULL;
if (ok > 0) {
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
res = PyTuple_New(2);
if (res == NULL) {
Py_DECREF(self);
Py_DECREF(other);
return NULL;
}
PyTuple_SET_ITEM(res, 0, self);
PyTuple_SET_ITEM(res, 1, other);
return res;
}
static PyObject *
wrap_ternaryfunc(PyObject *self, PyObject *args, void *wrapped)
{
@ -4247,64 +4219,6 @@ SLOT1BIN(slot_nb_and, nb_and, "__and__", "__rand__")
SLOT1BIN(slot_nb_xor, nb_xor, "__xor__", "__rxor__")
SLOT1BIN(slot_nb_or, nb_or, "__or__", "__ror__")
static int
slot_nb_coerce(PyObject **a, PyObject **b)
{
static PyObject *coerce_str;
PyObject *self = *a, *other = *b;
if (self->ob_type->tp_as_number != NULL &&
self->ob_type->tp_as_number->nb_coerce == slot_nb_coerce) {
PyObject *r;
r = call_maybe(
self, "__coerce__", &coerce_str, "(O)", other);
if (r == NULL)
return -1;
if (r == Py_NotImplemented) {
Py_DECREF(r);
}
else {
if (!PyTuple_Check(r) || PyTuple_GET_SIZE(r) != 2) {
PyErr_SetString(PyExc_TypeError,
"__coerce__ didn't return a 2-tuple");
Py_DECREF(r);
return -1;
}
*a = PyTuple_GET_ITEM(r, 0);
Py_INCREF(*a);
*b = PyTuple_GET_ITEM(r, 1);
Py_INCREF(*b);
Py_DECREF(r);
return 0;
}
}
if (other->ob_type->tp_as_number != NULL &&
other->ob_type->tp_as_number->nb_coerce == slot_nb_coerce) {
PyObject *r;
r = call_maybe(
other, "__coerce__", &coerce_str, "(O)", self);
if (r == NULL)
return -1;
if (r == Py_NotImplemented) {
Py_DECREF(r);
return 1;
}
if (!PyTuple_Check(r) || PyTuple_GET_SIZE(r) != 2) {
PyErr_SetString(PyExc_TypeError,
"__coerce__ didn't return a 2-tuple");
Py_DECREF(r);
return -1;
}
*a = PyTuple_GET_ITEM(r, 1);
Py_INCREF(*a);
*b = PyTuple_GET_ITEM(r, 0);
Py_INCREF(*b);
Py_DECREF(r);
return 0;
}
return 1;
}
SLOT0(slot_nb_int, "__int__")
SLOT0(slot_nb_long, "__long__")
SLOT0(slot_nb_float, "__float__")
@ -4958,8 +4872,6 @@ static slotdef slotdefs[] = {
RBINSLOT("__rxor__", nb_xor, slot_nb_xor, "^"),
BINSLOT("__or__", nb_or, slot_nb_or, "|"),
RBINSLOT("__ror__", nb_or, slot_nb_or, "|"),
NBSLOT("__coerce__", nb_coerce, slot_nb_coerce, wrap_coercefunc,
"x.__coerce__(y) <==> coerce(x, y)"),
UNSLOT("__int__", nb_int, slot_nb_int, wrap_unaryfunc,
"int(x)"),
UNSLOT("__long__", nb_long, slot_nb_long, wrap_unaryfunc,