summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2001-09-28 23:49:48 (GMT)
committerGuido van Rossum <guido@python.org>2001-09-28 23:49:48 (GMT)
commit4bb1e36eec19b30f2e582fceffa250e1598262e1 (patch)
tree0ba999260cfc7eaa6f9ce6a7e9f251d79edcf1e7 /Objects
parent9bea3abf0d7c658a95a92a295c82d5bf0b583f08 (diff)
downloadcpython-4bb1e36eec19b30f2e582fceffa250e1598262e1.zip
cpython-4bb1e36eec19b30f2e582fceffa250e1598262e1.tar.gz
cpython-4bb1e36eec19b30f2e582fceffa250e1598262e1.tar.bz2
It's a fact: for binary operators, *under certain circumstances*,
__rop__ now takes precendence over __op__. Those circumstances are: - Both arguments are new-style classes - Both arguments are new-style numbers - Their implementation slots for tp_op differ - Their types differ - The right argument's type is a subtype of the left argument's type Also did this for the ternary operator (pow) -- only the binary case is dealt with properly though, since __rpow__ is not supported anyway.
Diffstat (limited to 'Objects')
-rw-r--r--Objects/abstract.c76
1 files changed, 48 insertions, 28 deletions
diff --git a/Objects/abstract.c b/Objects/abstract.c
index fdf1a44..c353159 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -300,11 +300,14 @@ PyNumber_Check(PyObject *o)
v w Action
-------------------------------------------------------------------
- new new v.op(v,w), w.op(v,w)
+ 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)
+ [*] only when v->ob_type != w->ob_type && w->ob_type is a subclass of
+ v->ob_type
+
Legend:
-------
* new == new style number
@@ -318,29 +321,35 @@ static PyObject *
binary_op1(PyObject *v, PyObject *w, const int op_slot)
{
PyObject *x;
- binaryfunc *slot;
- if (v->ob_type->tp_as_number != NULL && NEW_STYLE_NUMBER(v)) {
- slot = NB_BINOP(v->ob_type->tp_as_number, op_slot);
- if (*slot) {
- x = (*slot)(v, w);
- if (x != Py_NotImplemented) {
- return x;
- }
- Py_DECREF(x); /* can't do it */
- }
- if (v->ob_type == w->ob_type) {
- goto binop_error;
- }
+ binaryfunc slotv = NULL;
+ binaryfunc slotw = NULL;
+
+ if (v->ob_type->tp_as_number != NULL && NEW_STYLE_NUMBER(v))
+ slotv = *NB_BINOP(v->ob_type->tp_as_number, op_slot);
+ if (w->ob_type != v->ob_type &&
+ w->ob_type->tp_as_number != NULL && NEW_STYLE_NUMBER(w)) {
+ slotw = *NB_BINOP(w->ob_type->tp_as_number, op_slot);
+ if (slotw == slotv)
+ slotw = NULL;
+ }
+ if (slotw && PyType_IsSubtype(w->ob_type, v->ob_type)) {
+ x = slotw(v, w);
+ if (x != Py_NotImplemented)
+ return x;
+ Py_DECREF(x); /* can't do it */
+ slotw = NULL;
}
- if (w->ob_type->tp_as_number != NULL && NEW_STYLE_NUMBER(w)) {
- slot = NB_BINOP(w->ob_type->tp_as_number, op_slot);
- if (*slot) {
- x = (*slot)(v, w);
- if (x != Py_NotImplemented) {
- return x;
- }
- Py_DECREF(x); /* can't do it */
- }
+ if (slotv) {
+ x = slotv(v, w);
+ if (x != Py_NotImplemented)
+ return x;
+ Py_DECREF(x); /* can't do it */
+ }
+ if (slotw) {
+ x = slotw(v, w);
+ if (x != Py_NotImplemented)
+ return x;
+ Py_DECREF(x); /* can't do it */
}
if (!NEW_STYLE_NUMBER(v) || !NEW_STYLE_NUMBER(w)) {
int err = PyNumber_CoerceEx(&v, &w);
@@ -350,9 +359,10 @@ binary_op1(PyObject *v, PyObject *w, const int op_slot)
if (err == 0) {
PyNumberMethods *mv = v->ob_type->tp_as_number;
if (mv) {
- slot = NB_BINOP(mv, op_slot);
- if (*slot) {
- PyObject *x = (*slot)(v, w);
+ binaryfunc slot;
+ slot = *NB_BINOP(mv, op_slot);
+ if (slot) {
+ PyObject *x = slot(v, w);
Py_DECREF(v);
Py_DECREF(w);
return x;
@@ -363,7 +373,6 @@ binary_op1(PyObject *v, PyObject *w, const int op_slot)
Py_DECREF(w);
}
}
-binop_error:
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
@@ -420,6 +429,18 @@ ternary_op(PyObject *v,
register ternaryfunc *slot;
mv = v->ob_type->tp_as_number;
+ mw = w->ob_type->tp_as_number;
+ if (v->ob_type != w->ob_type && mw && NEW_STYLE_NUMBER(w)) {
+ slot = NB_TERNOP(mw, op_slot);
+ if (*slot && *slot != *NB_TERNOP(mv, op_slot) &&
+ PyType_IsSubtype(w->ob_type, v->ob_type)) {
+ x = (*slot)(v, w, z);
+ if (x != Py_NotImplemented)
+ return x;
+ /* Can't do it... fall through */
+ Py_DECREF(x);
+ }
+ }
if (mv != NULL && NEW_STYLE_NUMBER(v)) {
/* try v.op(v,w,z) */
slot = NB_TERNOP(mv, op_slot);
@@ -435,7 +456,6 @@ ternary_op(PyObject *v,
goto ternary_error;
}
}
- mw = w->ob_type->tp_as_number;
if (mw != NULL && NEW_STYLE_NUMBER(w)) {
/* try w.op(v,w,z) */
slot = NB_TERNOP(mw,op_slot);