mirror of
https://github.com/python/cpython.git
synced 2025-08-03 16:39:00 +00:00
Get rid of most of the rest of coerce (slot is still there for now).
This commit is contained in:
parent
79212998a8
commit
4886cc331f
19 changed files with 131 additions and 497 deletions
|
@ -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 *
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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*/
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue