diff options
author | Neil Schemenauer <nascheme@enme.ucalgary.ca> | 2001-01-04 01:39:06 (GMT) |
---|---|---|
committer | Neil Schemenauer <nascheme@enme.ucalgary.ca> | 2001-01-04 01:39:06 (GMT) |
commit | 5a1f015bee85ca271316b1600ae67dae387d3dd8 (patch) | |
tree | a7844c67d0d720aa54fb0b6dc86f5a42b045ffe5 /Objects | |
parent | 0ee7d8233f1dc1f5b720cc242cd999a7d129371f (diff) | |
download | cpython-5a1f015bee85ca271316b1600ae67dae387d3dd8.zip cpython-5a1f015bee85ca271316b1600ae67dae387d3dd8.tar.gz cpython-5a1f015bee85ca271316b1600ae67dae387d3dd8.tar.bz2 |
Massive changes as per PEP 208. Read it for details.
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/abstract.c | 1046 |
1 files changed, 318 insertions, 728 deletions
diff --git a/Objects/abstract.c b/Objects/abstract.c index dfdfc43..9050a4c 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -1,7 +1,12 @@ /* Abstract Object Interface (many thanks to Jim Fulton) */ + #include "Python.h" #include <ctype.h> +#include "structmember.h" /* we need the offsetof() macro from there */ + +#define NEW_STYLE_NUMBER(o) PyType_HasFeature((o)->ob_type, \ + Py_TPFLAGS_NEWSTYLENUMBER) /* Shorthands to return certain errors */ @@ -281,830 +286,415 @@ PyNumber_Check(PyObject *o) /* Binary operators */ -#define BINOP(v, w, opname, ropname, thisfunc) \ - if (PyInstance_Check(v) || PyInstance_Check(w)) \ - return PyInstance_DoBinOp(v, w, opname, ropname, thisfunc) +/* New style number protocol support */ -PyObject * -PyNumber_Or(PyObject *v, PyObject *w) -{ - BINOP(v, w, "__or__", "__ror__", PyNumber_Or); - if (v->ob_type->tp_as_number != NULL) { - PyObject *x = NULL; - PyObject * (*f)(PyObject *, PyObject *) = NULL; - if (PyNumber_Coerce(&v, &w) != 0) - return NULL; - if (v->ob_type->tp_as_number != NULL && - (f = v->ob_type->tp_as_number->nb_or) != NULL) - x = (*f)(v, w); - Py_DECREF(v); - Py_DECREF(w); - if (f != NULL) - return x; - } - return type_error("bad operand type(s) for |"); -} +#define NB_SLOT(x) offsetof(PyNumberMethods, x) +#define NB_BINOP(nb_methods, slot) \ + ((binaryfunc*)(& ((char*)nb_methods)[slot] )) +#define NB_TERNOP(nb_methods, slot) \ + ((ternaryfunc*)(& ((char*)nb_methods)[slot] )) -PyObject * -PyNumber_Xor(PyObject *v, PyObject *w) -{ - BINOP(v, w, "__xor__", "__rxor__", PyNumber_Xor); - if (v->ob_type->tp_as_number != NULL) { - PyObject *x = NULL; - PyObject * (*f)(PyObject *, PyObject *) = NULL; - if (PyNumber_Coerce(&v, &w) != 0) - return NULL; - if (v->ob_type->tp_as_number != NULL && - (f = v->ob_type->tp_as_number->nb_xor) != NULL) - x = (*f)(v, w); - Py_DECREF(v); - Py_DECREF(w); - if (f != NULL) - return x; - } - return type_error("bad operand type(s) for ^"); -} +/* + Calling scheme used for binary operations: -PyObject * -PyNumber_And(PyObject *v, PyObject *w) -{ - BINOP(v, w, "__and__", "__rand__", PyNumber_And); - if (v->ob_type->tp_as_number != NULL) { - PyObject *x = NULL; - PyObject * (*f)(PyObject *, PyObject *) = NULL; - if (PyNumber_Coerce(&v, &w) != 0) - return NULL; - if (v->ob_type->tp_as_number != NULL && - (f = v->ob_type->tp_as_number->nb_and) != NULL) - x = (*f)(v, w); - Py_DECREF(v); - Py_DECREF(w); - if (f != NULL) - return x; - } - return type_error("bad operand type(s) for &"); -} + v w Action + ------------------------------------------------------------------- + new new 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) -PyObject * -PyNumber_Lshift(PyObject *v, PyObject *w) + 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 * +binary_op1(PyObject *v, PyObject *w, const int op_slot) { - BINOP(v, w, "__lshift__", "__rlshift__", PyNumber_Lshift); - if (v->ob_type->tp_as_number != NULL) { - PyObject *x = NULL; - PyObject * (*f)(PyObject *, PyObject *) = NULL; - if (PyNumber_Coerce(&v, &w) != 0) + 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; + } + } + 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 (!NEW_STYLE_NUMBER(v) || !NEW_STYLE_NUMBER(w)) { + int err = PyNumber_CoerceEx(&v, &w); + if (err < 0) { return NULL; - if (v->ob_type->tp_as_number != NULL && - (f = v->ob_type->tp_as_number->nb_lshift) != NULL) - x = (*f)(v, w); - Py_DECREF(v); - Py_DECREF(w); - if (f != NULL) - return x; + } + 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); + Py_DECREF(v); + Py_DECREF(w); + return x; + } + } + /* CoerceEx incremented the reference counts */ + Py_DECREF(v); + Py_DECREF(w); + } } - return type_error("bad operand type(s) for <<"); +binop_error: + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; } - -PyObject * -PyNumber_Rshift(PyObject *v, PyObject *w) + +static PyObject * +binary_op(PyObject *v, PyObject *w, const int op_slot, const char *op_name) { - BINOP(v, w, "__rshift__", "__rrshift__", PyNumber_Rshift); - if (v->ob_type->tp_as_number != NULL) { - PyObject *x = NULL; - PyObject * (*f)(PyObject *, PyObject *) = NULL; - if (PyNumber_Coerce(&v, &w) != 0) - return NULL; - if (v->ob_type->tp_as_number != NULL && - (f = v->ob_type->tp_as_number->nb_rshift) != NULL) - x = (*f)(v, w); - Py_DECREF(v); - Py_DECREF(w); - if (f != NULL) - return x; + PyObject *result = binary_op1(v, w, op_slot); + if (result == Py_NotImplemented) { + Py_DECREF(Py_NotImplemented); + PyErr_Format(PyExc_TypeError, + "unsupported operand type(s) for %s", op_name); + return NULL; } - return type_error("bad operand type(s) for >>"); + return result; } -PyObject * -PyNumber_Add(PyObject *v, PyObject *w) -{ - PySequenceMethods *m; - BINOP(v, w, "__add__", "__radd__", PyNumber_Add); - m = v->ob_type->tp_as_sequence; - if (m && m->sq_concat) - return (*m->sq_concat)(v, w); - else if (v->ob_type->tp_as_number != NULL) { - PyObject *x = NULL; - PyObject * (*f)(PyObject *, PyObject *) = NULL; - if (PyNumber_Coerce(&v, &w) != 0) - return NULL; - if (v->ob_type->tp_as_number != NULL && - (f = v->ob_type->tp_as_number->nb_add) != NULL) - x = (*f)(v, w); - Py_DECREF(v); - Py_DECREF(w); - if (f != NULL) - return x; - } - return type_error("bad operand type(s) for +"); -} +/* + Calling scheme used for ternary operations: -PyObject * -PyNumber_Subtract(PyObject *v, PyObject *w) -{ - BINOP(v, w, "__sub__", "__rsub__", PyNumber_Subtract); - if (v->ob_type->tp_as_number != NULL) { - PyObject *x = NULL; - PyObject * (*f)(PyObject *, PyObject *) = NULL; - if (PyNumber_Coerce(&v, &w) != 0) - return NULL; - if (v->ob_type->tp_as_number != NULL && - (f = v->ob_type->tp_as_number->nb_subtract) != NULL) - x = (*f)(v, w); - Py_DECREF(v); - Py_DECREF(w); - if (f != NULL) - return x; - } - return type_error("bad operand type(s) for -"); -} + 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) -PyObject * -PyNumber_Multiply(PyObject *v, PyObject *w) -{ - PyTypeObject *tp = v->ob_type; - PySequenceMethods *m; + 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. - BINOP(v, w, "__mul__", "__rmul__", PyNumber_Multiply); - if (tp->tp_as_number != NULL && - w->ob_type->tp_as_sequence != NULL) { - /* number*sequence -- swap v and w */ - PyObject *tmp = v; - v = w; - w = tmp; - tp = v->ob_type; - } - if (tp->tp_as_number != NULL) { - PyObject *x = NULL; - PyObject * (*f)(PyObject *, PyObject *) = NULL; - if (PyNumber_Coerce(&v, &w) != 0) - return NULL; - if (v->ob_type->tp_as_number != NULL && - (f = v->ob_type->tp_as_number->nb_multiply) != NULL) - x = (*f)(v, w); - Py_DECREF(v); - Py_DECREF(w); - if (f != NULL) - return x; - } - m = tp->tp_as_sequence; - if (m && m->sq_repeat) { - long mul_value; + */ - if (PyInt_Check(w)) { - mul_value = PyInt_AsLong(w); +static PyObject * +ternary_op(PyObject *v, + PyObject *w, + PyObject *z, + const int op_slot, + const char *op_name) +{ + PyNumberMethods *mv, *mw, *mz; + register PyObject *x = NULL; + register ternaryfunc *slot; + + mv = v->ob_type->tp_as_number; + if (mv != NULL && NEW_STYLE_NUMBER(v)) { + /* try v.op(v,w,z) */ + slot = NB_TERNOP(mv, op_slot); + if (*slot) { + x = (*slot)(v, w, z); + if (x != Py_NotImplemented) + return x; + /* Can't do it... fall through */ + Py_DECREF(x); } - else if (PyLong_Check(w)) { - mul_value = PyLong_AsLong(w); - if (mul_value == -1 && PyErr_Occurred()) - return NULL; + if (v->ob_type == w->ob_type && + (z == Py_None || z->ob_type == v->ob_type)) { + goto ternary_error; } - else { - return type_error( - "can't multiply sequence with non-int"); + } + 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); + if (*slot) { + x = (*slot)(v, w, z); + if (x != Py_NotImplemented) + return x; + /* Can't do it... fall through */ + Py_DECREF(x); + } + if (NEW_STYLE_NUMBER(v) && + (z == Py_None || z->ob_type == v->ob_type)) { + goto ternary_error; } - return (*m->sq_repeat)(v, (int)mul_value); } - return type_error("bad operand type(s) for *"); -} - -PyObject * -PyNumber_Divide(PyObject *v, PyObject *w) -{ - BINOP(v, w, "__div__", "__rdiv__", PyNumber_Divide); - if (v->ob_type->tp_as_number != NULL) { - PyObject *x = NULL; - PyObject * (*f)(PyObject *, PyObject *) = NULL; - if (PyNumber_Coerce(&v, &w) != 0) - return NULL; - if (v->ob_type->tp_as_number != NULL && - (f = v->ob_type->tp_as_number->nb_divide) != NULL) - x = (*f)(v, w); - Py_DECREF(v); - Py_DECREF(w); - if (f != NULL) - return x; + mz = z->ob_type->tp_as_number; + if (mz != NULL && NEW_STYLE_NUMBER(z)) { + /* try: z.op(v,w,z) */ + slot = NB_TERNOP(mz, op_slot); + if (*slot) { + x = (*slot)(v, w, z); + if (x != Py_NotImplemented) + return x; + /* Can't do it... fall through */ + Py_DECREF(x); + } } - return type_error("bad operand type(s) for /"); -} -PyObject * -PyNumber_Remainder(PyObject *v, PyObject *w) -{ - if (PyString_Check(v)) - return PyString_Format(v, w); - else if (PyUnicode_Check(v)) - return PyUnicode_Format(v, w); - BINOP(v, w, "__mod__", "__rmod__", PyNumber_Remainder); - if (v->ob_type->tp_as_number != NULL) { - PyObject *x = NULL; - PyObject * (*f)(PyObject *, PyObject *) = NULL; - if (PyNumber_Coerce(&v, &w) != 0) - return NULL; - if (v->ob_type->tp_as_number != NULL && - (f = v->ob_type->tp_as_number->nb_remainder) != NULL) - x = (*f)(v, w); + if (!NEW_STYLE_NUMBER(v) || !NEW_STYLE_NUMBER(w) || + (z != Py_None && !NEW_STYLE_NUMBER(z))) { + /* we have an old style operand, coerce */ + PyObject *v1, *z1, *w2, *z2; + int c; + + c = PyNumber_Coerce(&v, &w); + if (c != 0) + goto error3; + + /* Special case: if the third argument is None, it is + treated as absent argument and not coerced. */ + if (z == Py_None) { + if (v->ob_type->tp_as_number) { + slot = NB_TERNOP(v->ob_type->tp_as_number, + op_slot); + if (*slot) + x = (*slot)(v, w, z); + else + c = -1; + } + else + c = -1; + goto error2; + } + v1 = v; + z1 = z; + c = PyNumber_Coerce(&v1, &z1); + if (c != 0) + goto error2; + w2 = w; + z2 = z1; + c = PyNumber_Coerce(&w2, &z2); + if (c != 0) + goto error1; + + if (v1->ob_type->tp_as_number != NULL) { + slot = NB_TERNOP(v1->ob_type->tp_as_number, + op_slot); + if (*slot) + x = (*slot)(v1, w2, z2); + else + c = -1; + } + else + c = -1; + + Py_DECREF(w2); + Py_DECREF(z2); + error1: + Py_DECREF(v1); + Py_DECREF(z1); + error2: Py_DECREF(v); Py_DECREF(w); - if (f != NULL) + error3: + if (c >= 0) return x; } - return type_error("bad operand type(s) for %"); + +ternary_error: + PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %s", + op_name); + return NULL; } +#define BINARY_FUNC(func, op, op_name) \ + PyObject * \ + func(PyObject *v, PyObject *w) { \ + return binary_op(v, w, NB_SLOT(op), op_name); \ + } + +BINARY_FUNC(PyNumber_Or, nb_or, "|") +BINARY_FUNC(PyNumber_Xor, nb_xor, "^") +BINARY_FUNC(PyNumber_And, nb_and, "&") +BINARY_FUNC(PyNumber_Lshift, nb_lshift, "<<") +BINARY_FUNC(PyNumber_Rshift, nb_rshift, ">>") +BINARY_FUNC(PyNumber_Subtract, nb_subtract, "-") +BINARY_FUNC(PyNumber_Multiply, nb_multiply, "*") +BINARY_FUNC(PyNumber_Divide, nb_divide, "/") +BINARY_FUNC(PyNumber_Divmod, nb_divmod, "divmod()") + PyObject * -PyNumber_Divmod(PyObject *v, PyObject *w) +PyNumber_Add(PyObject *v, PyObject *w) { - BINOP(v, w, "__divmod__", "__rdivmod__", PyNumber_Divmod); - if (v->ob_type->tp_as_number != NULL) { - PyObject *x = NULL; - PyObject * (*f)(PyObject *, PyObject *) = NULL; - if (PyNumber_Coerce(&v, &w) != 0) - return NULL; - if (v->ob_type->tp_as_number != NULL && - (f = v->ob_type->tp_as_number->nb_divmod) != NULL) - x = (*f)(v, w); - Py_DECREF(v); - Py_DECREF(w); - if (f != NULL) - return x; + PyObject *result = binary_op1(v, w, NB_SLOT(nb_add)); + if (result == Py_NotImplemented) { + PySequenceMethods *m = v->ob_type->tp_as_sequence; + Py_DECREF(Py_NotImplemented); + if (m && m->sq_concat) { + result = (*m->sq_concat)(v, w); + } + else { + PyErr_SetString(PyExc_TypeError, + "unsupported operand types for +"); + result = NULL; + } } - return type_error("bad operand type(s) for divmod()"); + return result; } -/* Power (binary or ternary) */ - -static PyObject * -do_pow(PyObject *v, PyObject *w) +PyObject * +PyNumber_Remainder(PyObject *v, PyObject *w) { - PyObject *res; - PyObject * (*f)(PyObject *, PyObject *, PyObject *); - BINOP(v, w, "__pow__", "__rpow__", do_pow); - if (v->ob_type->tp_as_number == NULL || - w->ob_type->tp_as_number == NULL) { - PyErr_SetString(PyExc_TypeError, - "pow(x, y) requires numeric arguments"); - return NULL; - } - if (PyNumber_Coerce(&v, &w) != 0) - return NULL; - if (v->ob_type->tp_as_number != NULL && - (f = v->ob_type->tp_as_number->nb_power) != NULL) - res = (*f)(v, w, Py_None); - else - res = type_error("pow(x, y) not defined for these operands"); - Py_DECREF(v); - Py_DECREF(w); - return res; + if (PyString_Check(v)) + return PyString_Format(v, w); + else if (PyUnicode_Check(v)) + return PyUnicode_Format(v, w); + return binary_op(v, w, NB_SLOT(nb_remainder), "%"); } PyObject * PyNumber_Power(PyObject *v, PyObject *w, PyObject *z) { - PyObject *res; - PyObject *v1, *z1, *w2, *z2; - PyObject * (*f)(PyObject *, PyObject *, PyObject *); - - if (z == Py_None) - return do_pow(v, w); - /* XXX The ternary version doesn't do class instance coercions */ - if (PyInstance_Check(v)) - return v->ob_type->tp_as_number->nb_power(v, w, z); - if (v->ob_type->tp_as_number == NULL || - z->ob_type->tp_as_number == NULL || - w->ob_type->tp_as_number == NULL) { - return type_error("pow(x, y, z) requires numeric arguments"); - } - if (PyNumber_Coerce(&v, &w) != 0) - return NULL; - res = NULL; - v1 = v; - z1 = z; - if (PyNumber_Coerce(&v1, &z1) != 0) - goto error2; - w2 = w; - z2 = z1; - if (PyNumber_Coerce(&w2, &z2) != 0) - goto error1; - if (v->ob_type->tp_as_number != NULL && - (f = v1->ob_type->tp_as_number->nb_power) != NULL) - res = (*f)(v1, w2, z2); - else - res = type_error( - "pow(x, y, z) not defined for these operands"); - Py_DECREF(w2); - Py_DECREF(z2); - error1: - Py_DECREF(v1); - Py_DECREF(z1); - error2: - Py_DECREF(v); - Py_DECREF(w); - return res; + return ternary_op(v, w, z, NB_SLOT(nb_power), "** or pow()"); } /* Binary in-place operators */ /* The in-place operators are defined to fall back to the 'normal', - non in-place operations, if the in-place methods are not in place, and to - take class instances into account. This is how it is supposed to work: - - - If the left-hand-side object (the first argument) is an - instance object, try to let PyInstance_HalfBinOp() handle it. Pass the - non in-place variant of the function as callback, because it will only - be used if the left-hand object is changed by coercion. - - - Otherwise, if the left hand object is not an instance object, it has - the appropriate struct members, and they are filled, call the - appropriate function and return the result. No coercion is done on the - arguments; the left-hand object is the one the operation is performed - on, and it's up to the function to deal with the right-hand object. - - - Otherwise, in-place modification is not supported. Handle it exactly as - a non in-place operation of the same kind: + non in-place operations, if the in-place methods are not in place. - - If either object is an instance, let PyInstance_DoBinOp() handle it. + - If the left hand object has the appropriate struct members, and + they are filled, call the appropriate function and return the + result. No coercion is done on the arguments; the left-hand object + is the one the operation is performed on, and it's up to the + function to deal with the right-hand object. - - Otherwise, both arguments are C types. If the left-hand object has - the appropriate struct members filled, coerce, call the - appropriate function, and return the result. - - - Otherwise, we are out of options: raise a type error specific to - augmented assignment. + - Otherwise, in-place modification is not supported. Handle it exactly as + a non in-place operation of the same kind. */ #define HASINPLACE(t) PyType_HasFeature((t)->ob_type, Py_TPFLAGS_HAVE_INPLACEOPS) -PyObject * -PyNumber_InPlaceOr(PyObject *v, PyObject *w) -{ - PyObject * (*f)(PyObject *, PyObject *) = NULL; - PyObject *x = NULL; - - if (PyInstance_Check(v)) { - if (PyInstance_HalfBinOp(v, w, "__ior__", &x, - PyNumber_Or, 0) <= 0) - return x; - } - else if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) && - (f = v->ob_type->tp_as_number->nb_inplace_or) != NULL) - return (*f)(v, w); - - BINOP(v, w, "__or__", "__ror__", PyNumber_Or); - - if (v->ob_type->tp_as_number != NULL) { - if (PyNumber_Coerce(&v, &w) != 0) - return NULL; - if (v->ob_type->tp_as_number != NULL && - (f = v->ob_type->tp_as_number->nb_or) != NULL) - x = (*f)(v, w); - Py_DECREF(v); - Py_DECREF(w); - if (f != NULL) - return x; - } - - return type_error("bad operand type(s) for |="); -} - -PyObject * -PyNumber_InPlaceXor(PyObject *v, PyObject *w) -{ - PyObject * (*f)(PyObject *, PyObject *) = NULL; - PyObject *x = NULL; - - if (PyInstance_Check(v)) { - if (PyInstance_HalfBinOp(v, w, "__ixor__", &x, - PyNumber_Xor, 0) <= 0) - return x; - } - else if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) && - (f = v->ob_type->tp_as_number->nb_inplace_xor) != NULL) - return (*f)(v, w); - - BINOP(v, w, "__xor__", "__rxor__", PyNumber_Xor); - - if (v->ob_type->tp_as_number != NULL) { - if (PyNumber_Coerce(&v, &w) != 0) - return NULL; - if (v->ob_type->tp_as_number != NULL && - (f = v->ob_type->tp_as_number->nb_xor) != NULL) - x = (*f)(v, w); - Py_DECREF(v); - Py_DECREF(w); - if (f != NULL) - return x; - } - - return type_error("bad operand type(s) for ^="); -} - -PyObject * -PyNumber_InPlaceAnd(PyObject *v, PyObject *w) -{ - PyObject * (*f)(PyObject *, PyObject *) = NULL; - PyObject *x = NULL; - - if (PyInstance_Check(v)) { - if (PyInstance_HalfBinOp(v, w, "__iand__", &x, - PyNumber_And, 0) <= 0) - return x; - } - else if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) && - (f = v->ob_type->tp_as_number->nb_inplace_and) != NULL) - return (*f)(v, w); - - BINOP(v, w, "__and__", "__rand__", PyNumber_And); - - if (v->ob_type->tp_as_number != NULL) { - if (PyNumber_Coerce(&v, &w) != 0) - return NULL; - if (v->ob_type->tp_as_number != NULL && - (f = v->ob_type->tp_as_number->nb_and) != NULL) - x = (*f)(v, w); - Py_DECREF(v); - Py_DECREF(w); - if (f != NULL) - return x; - } - - return type_error("bad operand type(s) for &="); -} - -PyObject * -PyNumber_InPlaceLshift(PyObject *v, PyObject *w) -{ - PyObject * (*f)(PyObject *, PyObject *) = NULL; - PyObject *x = NULL; - - if (PyInstance_Check(v)) { - if (PyInstance_HalfBinOp(v, w, "__ilshift__", &x, - PyNumber_Lshift, 0) <= 0) - return x; - } - else if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) && - (f = v->ob_type->tp_as_number->nb_inplace_lshift) != NULL) - return (*f)(v, w); - - BINOP(v, w, "__lshift__", "__rlshift__", PyNumber_Lshift); - - if (v->ob_type->tp_as_number != NULL) { - if (PyNumber_Coerce(&v, &w) != 0) - return NULL; - if (v->ob_type->tp_as_number != NULL && - (f = v->ob_type->tp_as_number->nb_lshift) != NULL) - x = (*f)(v, w); - Py_DECREF(v); - Py_DECREF(w); - if (f != NULL) - return x; +static PyObject * +binary_iop(PyObject *v, PyObject *w, const int iop_slot, const int op_slot, + const char *op_name) +{ + PyNumberMethods *mv = v->ob_type->tp_as_number; + if (mv != NULL && HASINPLACE(v)) { + binaryfunc *slot = NB_BINOP(mv, iop_slot); + if (*slot) { + PyObject *x = (*slot)(v, w); + if (x != Py_NotImplemented) { + return x; + } + Py_DECREF(x); + } } - - return type_error("bad operand type(s) for <<="); + return binary_op(v, w, op_slot, op_name); } -PyObject * -PyNumber_InPlaceRshift(PyObject *v, PyObject *w) -{ - PyObject * (*f)(PyObject *, PyObject *) = NULL; - PyObject *x = NULL; - - if (PyInstance_Check(v)) { - if (PyInstance_HalfBinOp(v, w, "__irshift__", &x, - PyNumber_Rshift, 0) <= 0) - return x; - } - else if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) && - (f = v->ob_type->tp_as_number->nb_inplace_rshift) != NULL) - return (*f)(v, w); - - BINOP(v, w, "__rshift__", "__rrshift__", PyNumber_Rshift); - - if (v->ob_type->tp_as_number != NULL) { - if (PyNumber_Coerce(&v, &w) != 0) - return NULL; - if (v->ob_type->tp_as_number != NULL && - (f = v->ob_type->tp_as_number->nb_rshift) != NULL) - x = (*f)(v, w); - Py_DECREF(v); - Py_DECREF(w); - if (f != NULL) - return x; +#define INPLACE_BINOP(func, iop, op, op_name) \ + PyObject * \ + func(PyObject *v, PyObject *w) { \ + return binary_iop(v, w, NB_SLOT(iop), NB_SLOT(op), op_name); \ } - return type_error("bad operand type(s) for >>="); -} +INPLACE_BINOP(PyNumber_InPlaceOr, nb_inplace_or, nb_or, "|=") +INPLACE_BINOP(PyNumber_InPlaceXor, nb_inplace_xor, nb_xor, "^=") +INPLACE_BINOP(PyNumber_InPlaceAnd, nb_inplace_and, nb_and, "&=") +INPLACE_BINOP(PyNumber_InPlaceLshift, nb_inplace_lshift, nb_lshift, "<<=") +INPLACE_BINOP(PyNumber_InPlaceRshift, nb_inplace_rshift, nb_rshift, ">>=") +INPLACE_BINOP(PyNumber_InPlaceSubtract, nb_inplace_subtract, nb_subtract, "-=") +INPLACE_BINOP(PyNumber_InPlaceDivide, nb_inplace_divide, nb_divide, "/=") PyObject * PyNumber_InPlaceAdd(PyObject *v, PyObject *w) { - PyObject * (*f)(PyObject *, PyObject *) = NULL; - PyObject *x = NULL; - - if (PyInstance_Check(v)) { - if (PyInstance_HalfBinOp(v, w, "__iadd__", &x, - PyNumber_Add, 0) <= 0) - return x; - } - else if (HASINPLACE(v)) { - if (v->ob_type->tp_as_sequence != NULL) - f = v->ob_type->tp_as_sequence->sq_inplace_concat; - if (f == NULL && v->ob_type->tp_as_number != NULL) - f = v->ob_type->tp_as_number->nb_inplace_add; - if (f != NULL) - return (*f)(v, w); - } - - BINOP(v, w, "__add__", "__radd__", PyNumber_Add); + binaryfunc f = NULL; if (v->ob_type->tp_as_sequence != NULL) { - f = v->ob_type->tp_as_sequence->sq_concat; + if (HASINPLACE(v)) + f = v->ob_type->tp_as_sequence->sq_inplace_concat; + if (f == NULL) + f = v->ob_type->tp_as_sequence->sq_concat; if (f != NULL) return (*f)(v, w); } - if (v->ob_type->tp_as_number != NULL) { - if (PyNumber_Coerce(&v, &w) != 0) - return NULL; - if (v->ob_type->tp_as_number != NULL) { - f = v->ob_type->tp_as_number->nb_add; - if (f != NULL) - x = (*f)(v, w); - } - Py_DECREF(v); - Py_DECREF(w); - if (f != NULL) - return x; - } - - return type_error("bad operand type(s) for +="); -} - -PyObject * -PyNumber_InPlaceSubtract(PyObject *v, PyObject *w) -{ - PyObject * (*f)(PyObject *, PyObject *) = NULL; - PyObject *x = NULL; - - if (PyInstance_Check(v)) { - if (PyInstance_HalfBinOp(v, w, "__isub__", &x, - PyNumber_Subtract, 0) <= 0) - return x; - } - else if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) && - (f = v->ob_type->tp_as_number->nb_inplace_subtract) != NULL) - return (*f)(v, w); - - BINOP(v, w, "__sub__", "__rsub__", PyNumber_Subtract); - - if (v->ob_type->tp_as_number != NULL) { - if (PyNumber_Coerce(&v, &w) != 0) - return NULL; - if (v->ob_type->tp_as_number != NULL && - (f = v->ob_type->tp_as_number->nb_subtract) != NULL) - x = (*f)(v, w); - Py_DECREF(v); - Py_DECREF(w); - if (f != NULL) - return x; - } - - return type_error("bad operand type(s) for -="); + return binary_iop(v, w, NB_SLOT(nb_inplace_add), NB_SLOT(nb_add), "+="); } PyObject * PyNumber_InPlaceMultiply(PyObject *v, PyObject *w) { - PyObject * (*f)(PyObject *, PyObject *) = NULL; PyObject * (*g)(PyObject *, int) = NULL; - PyObject *x = NULL; - - if (PyInstance_Check(v)) { - if (PyInstance_HalfBinOp(v, w, "__imul__", &x, - PyNumber_Multiply, 0) <= 0) - return x; - } - else if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) && - (f = v->ob_type->tp_as_number->nb_inplace_multiply) != NULL) - return (*f)(v, w); - else if (v->ob_type->tp_as_sequence != NULL && HASINPLACE(v) && - (g = v->ob_type->tp_as_sequence->sq_inplace_repeat) != NULL) { - long mul_value; - + if (HASINPLACE(v) && v->ob_type->tp_as_sequence && + (g = v->ob_type->tp_as_sequence->sq_inplace_repeat)) { + long n; if (PyInt_Check(w)) { - mul_value = PyInt_AsLong(w); + n = PyInt_AsLong(w); } else if (PyLong_Check(w)) { - mul_value = PyLong_AsLong(w); - if (mul_value == -1 && PyErr_Occurred()) - return NULL; - } - else { - return type_error( - "can't multiply sequence with non-int"); - } - return (*g)(v, (int)mul_value); - } - - BINOP(v, w, "__mul__", "__rmul__", PyNumber_Multiply); - - if (v->ob_type->tp_as_number != NULL) { - if (PyNumber_Coerce(&v, &w) != 0) - return NULL; - if (v->ob_type->tp_as_number != NULL && - (f = v->ob_type->tp_as_number->nb_multiply) != NULL) - x = (*f)(v, w); - Py_DECREF(v); - Py_DECREF(w); - if (f != NULL) - return x; - } - else if (v->ob_type->tp_as_sequence != NULL && - (g = v->ob_type->tp_as_sequence->sq_repeat) != NULL) { - long mul_value; - - if (PyInt_Check(w)) { - mul_value = PyInt_AsLong(w); - } - else if (PyLong_Check(w)) { - mul_value = PyLong_AsLong(w); - if (mul_value == -1 && PyErr_Occurred()) - return NULL; + n = PyLong_AsLong(w); + if (n == -1 && PyErr_Occurred()) + return NULL; } else { - return type_error( - "can't multiply sequence with non-int"); + return type_error("can't multiply sequence to non-int"); } - return (*g)(v, (int)mul_value); + return (*g)(v, (int)n); } - return type_error("bad operand type(s) for *="); + return binary_iop(v, w, NB_SLOT(nb_inplace_multiply), + NB_SLOT(nb_multiply), "*="); } -PyObject * -PyNumber_InPlaceDivide(PyObject *v, PyObject *w) -{ - PyObject * (*f)(PyObject *, PyObject *) = NULL; - PyObject *x = NULL; - - if (PyInstance_Check(v)) { - if (PyInstance_HalfBinOp(v, w, "__idiv__", &x, - PyNumber_Divide, 0) <= 0) - return x; - } - else if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) && - (f = v->ob_type->tp_as_number->nb_inplace_divide) != NULL) - return (*f)(v, w); - BINOP(v, w, "__div__", "__rdiv__", PyNumber_Divide); - - if (v->ob_type->tp_as_number != NULL) { - if (PyNumber_Coerce(&v, &w) != 0) - return NULL; - if (v->ob_type->tp_as_number != NULL && - (f = v->ob_type->tp_as_number->nb_divide) != NULL) - x = (*f)(v, w); - Py_DECREF(v); - Py_DECREF(w); - if (f != NULL) - return x; - } - - return type_error("bad operand type(s) for /="); -} PyObject * PyNumber_InPlaceRemainder(PyObject *v, PyObject *w) { - PyObject * (*f)(PyObject *, PyObject *) = NULL; - PyObject *x = NULL; - - if (PyInstance_Check(v)) { - if (PyInstance_HalfBinOp(v, w, "__imod__", &x, - PyNumber_Remainder, 0) <= 0) - return x; - } - else if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) && - (f = v->ob_type->tp_as_number->nb_inplace_remainder) != NULL) - return (*f)(v, w); - if (PyString_Check(v)) return PyString_Format(v, w); else if (PyUnicode_Check(v)) return PyUnicode_Format(v, w); - - BINOP(v, w, "__mod__", "__rmod__", PyNumber_Remainder); - - if (v->ob_type->tp_as_number != NULL) { - if (PyNumber_Coerce(&v, &w) != 0) - return NULL; - if ((f = v->ob_type->tp_as_number->nb_remainder) != NULL) - x = (*f)(v, w); - Py_DECREF(v); - Py_DECREF(w); - if (f != NULL) - return x; - } - - return type_error("bad operand type(s) for %="); -} - - -/* In-place Power (binary or ternary, for API consistency) */ - -static PyObject * -do_inplace_pow(PyObject *v, PyObject *w) -{ - PyObject * (*f)(PyObject *, PyObject *, PyObject *) = NULL; - PyObject *x = NULL; - - if (PyInstance_Check(v)) { - if (PyInstance_HalfBinOp(v, w, "__ipow__", &x, do_pow, 0) <= 0) - return x; - } - else if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) && - (f = v->ob_type->tp_as_number->nb_inplace_power) != NULL) - return (*f)(v, w, Py_None); - - BINOP(v, w, "__pow__", "__rpow__", do_pow); - - if (v->ob_type->tp_as_number == NULL || - w->ob_type->tp_as_number == NULL) { - return type_error("bad operand type(s) for **="); - } - if (PyNumber_Coerce(&v, &w) != 0) - return NULL; - if ((f = v->ob_type->tp_as_number->nb_power) != NULL) - x = (*f)(v, w, Py_None); else - x = type_error("bad operand type(s) for **="); - Py_DECREF(v); - Py_DECREF(w); - return x; + return binary_iop(v, w, NB_SLOT(nb_inplace_remainder), + NB_SLOT(nb_remainder), "%="); } + PyObject * PyNumber_InPlacePower(PyObject *v, PyObject *w, PyObject *z) { - PyObject *res; - PyObject *v1, *z1, *w2, *z2, *oldv; - PyObject * (*f)(PyObject *, PyObject *, PyObject *); - - if (z == Py_None) - return do_inplace_pow(v, w); - /* XXX The ternary version doesn't do class instance coercions */ - if (PyInstance_Check(v)) - return v->ob_type->tp_as_number->nb_inplace_power(v, w, z); - if (v->ob_type->tp_as_number == NULL || - z->ob_type->tp_as_number == NULL || - w->ob_type->tp_as_number == NULL) { - return type_error( - "(inplace) pow(x, y, z) requires numeric arguments"); - } - oldv = v; - Py_INCREF(oldv); - res = NULL; - if (PyNumber_Coerce(&v, &w) != 0) - goto error3; - v1 = v; - z1 = z; - if (PyNumber_Coerce(&v1, &z1) != 0) - goto error2; - w2 = w; - z2 = z1; - if (PyNumber_Coerce(&w2, &z2) != 0) - goto error1; - if (oldv == v1 && HASINPLACE(v1) && - v->ob_type->tp_as_number != NULL && - (f = v1->ob_type->tp_as_number->nb_inplace_power) != NULL) - res = (*f)(v1, w2, z2); - else if (v1->ob_type->tp_as_number != NULL && - (f = v1->ob_type->tp_as_number->nb_power) != NULL) - res = (*f)(v1, w2, z2); - else - res = type_error( - "(inplace) pow(x, y, z) not defined for these operands"); - Py_DECREF(w2); - Py_DECREF(z2); - error1: - Py_DECREF(v1); - Py_DECREF(z1); - error2: - Py_DECREF(v); - Py_DECREF(w); - error3: - Py_DECREF(oldv); - return res; + if (HASINPLACE(v) && v->ob_type->tp_as_number && + v->ob_type->tp_as_number->nb_inplace_power != NULL) { + return ternary_op(v, w, z, NB_SLOT(nb_inplace_power), "**="); + } + else { + return ternary_op(v, w, z, NB_SLOT(nb_power), "**="); + } } |