Commit b7097770 authored by Kevin Modzelewski's avatar Kevin Modzelewski

cmp() builtin

parent 9ebfc95f
......@@ -553,7 +553,7 @@ PyAPI_FUNC(int) PyNumber_CoerceEx(PyObject **, PyObject **) PYSTON_NOEXCEPT;
PyAPI_FUNC(void) PyObject_ClearWeakRefs(PyObject *) PYSTON_NOEXCEPT;
/* A slot function whose address we need to compare */
extern int _PyObject_SlotCompare(PyObject *, PyObject *);
extern int _PyObject_SlotCompare(PyObject *, PyObject *) PYSTON_NOEXCEPT;
/* Same as PyObject_Generic{Get,Set}Attr, but passing the attributes
dict as the last parameter. */
PyAPI_FUNC(PyObject *)
......
......@@ -27,6 +27,31 @@
namespace pyston {
static PyObject* type_error(const char* msg, PyObject* obj) noexcept {
PyErr_Format(PyExc_TypeError, msg, Py_TYPE(obj)->tp_name);
return NULL;
}
static PyObject* null_error(void) noexcept {
if (!PyErr_Occurred())
PyErr_SetString(PyExc_SystemError, "null argument to internal routine");
return NULL;
}
extern "C" int PyObject_Cmp(PyObject* o1, PyObject* o2, int* result) noexcept {
int r;
if (o1 == NULL || o2 == NULL) {
null_error();
return -1;
}
r = PyObject_Compare(o1, o2);
if (PyErr_Occurred())
return -1;
*result = r;
return 0;
}
extern "C" Py_ssize_t _PyObject_LengthHint(PyObject* o, Py_ssize_t defaultvalue) noexcept {
static PyObject* hintstrobj = NULL;
PyObject* ro, *hintmeth;
......@@ -227,17 +252,6 @@ extern "C" void PyBuffer_Release(Py_buffer* view) noexcept {
view->obj = NULL;
}
static PyObject* type_error(const char* msg, PyObject* obj) noexcept {
PyErr_Format(PyExc_TypeError, msg, Py_TYPE(obj)->tp_name);
return NULL;
}
static PyObject* null_error(void) noexcept {
if (!PyErr_Occurred())
PyErr_SetString(PyExc_SystemError, "null argument to internal routine");
return NULL;
}
static PyObject* objargs_mktuple(va_list va) noexcept {
int i, n = 0;
va_list countva;
......@@ -1516,9 +1530,28 @@ extern "C" int PyNumber_Coerce(PyObject**, PyObject**) noexcept {
return -1;
}
extern "C" int PyNumber_CoerceEx(PyObject**, PyObject**) noexcept {
fatalOrError(PyExc_NotImplementedError, "unimplemented");
return -1;
extern "C" int PyNumber_CoerceEx(PyObject** pv, PyObject** pw) noexcept {
PyObject* v = *pv;
PyObject* w = *pw;
int res;
/* Shortcut only for old-style types */
if (v->cls == w->cls && !PyType_HasFeature(v->cls, Py_TPFLAGS_CHECKTYPES)) {
Py_INCREF(v);
Py_INCREF(w);
return 0;
}
if (v->cls->tp_as_number && v->cls->tp_as_number->nb_coerce) {
res = (*v->cls->tp_as_number->nb_coerce)(pv, pw);
if (res <= 0)
return res;
}
if (w->cls->tp_as_number && w->cls->tp_as_number->nb_coerce) {
res = (*w->cls->tp_as_number->nb_coerce)(pw, pv);
if (res <= 0)
return res;
}
return 1;
}
extern "C" PyObject* _PyNumber_ConvertIntegralToInt(PyObject* integral, const char* error_format) noexcept {
......
This diff is collapsed.
......@@ -461,6 +461,26 @@ static PyObject* wrap_delitem(PyObject* self, PyObject* args, void* wrapped) noe
return Py_None;
}
static PyObject* wrap_cmpfunc(PyObject* self, PyObject* args, void* wrapped) noexcept {
cmpfunc func = (cmpfunc)wrapped;
int res;
PyObject* other;
if (!check_num_args(args, 1))
return NULL;
other = PyTuple_GET_ITEM(args, 0);
if (Py_TYPE(other)->tp_compare != func && !PyType_IsSubtype(Py_TYPE(other), Py_TYPE(self))) {
PyErr_Format(PyExc_TypeError, "%s.__cmp__(x,y) requires y to be a '%s', not a '%s'", Py_TYPE(self)->tp_name,
Py_TYPE(self)->tp_name, Py_TYPE(other)->tp_name);
return NULL;
}
res = (*func)(self, other);
if (PyErr_Occurred())
return NULL;
return PyInt_FromLong((long)res);
}
static PyObject* wrap_init(PyObject* self, PyObject* args, void* wrapped, PyObject* kwds) noexcept {
initproc func = (initproc)wrapped;
......@@ -565,7 +585,57 @@ static PyObject* call_maybe(PyObject* o, const char* name, PyObject** nameobj, c
return retval;
}
PyObject* slot_tp_repr(PyObject* self) noexcept {
static int half_compare(PyObject* self, PyObject* other) noexcept {
PyObject* func, *args, *res;
static PyObject* cmp_str;
Py_ssize_t c;
func = lookup_method(self, "__cmp__", &cmp_str);
if (func == NULL) {
PyErr_Clear();
} else {
args = PyTuple_Pack(1, other);
if (args == NULL)
res = NULL;
else {
res = PyObject_Call(func, args, NULL);
Py_DECREF(args);
}
Py_DECREF(func);
if (res != Py_NotImplemented) {
if (res == NULL)
return -2;
c = PyInt_AsLong(res);
Py_DECREF(res);
if (c == -1 && PyErr_Occurred())
return -2;
return (c < 0) ? -1 : (c > 0) ? 1 : 0;
}
Py_DECREF(res);
}
return 2;
}
/* This slot is published for the benefit of try_3way_compare in object.c */
extern "C" int _PyObject_SlotCompare(PyObject* self, PyObject* other) noexcept {
int c;
if (Py_TYPE(self)->tp_compare == _PyObject_SlotCompare) {
c = half_compare(self, other);
if (c <= 1)
return c;
}
if (Py_TYPE(other)->tp_compare == _PyObject_SlotCompare) {
c = half_compare(other, self);
if (c < -1)
return -2;
if (c <= 1)
return -c;
}
return (void*)self < (void*)other ? -1 : (void*)self > (void*)other ? 1 : 0;
}
static PyObject* slot_tp_repr(PyObject* self) noexcept {
try {
return repr(self);
} catch (ExcInfo e) {
......@@ -574,7 +644,7 @@ PyObject* slot_tp_repr(PyObject* self) noexcept {
}
}
PyObject* slot_tp_str(PyObject* self) noexcept {
static PyObject* slot_tp_str(PyObject* self) noexcept {
try {
return str(self);
} catch (ExcInfo e) {
......@@ -1264,6 +1334,7 @@ static slotdef slotdefs[]
TPSLOT("__getattr__", tp_getattr, NULL, NULL, ""),
TPSLOT("__setattr__", tp_setattr, NULL, NULL, ""),
TPSLOT("__delattr__", tp_setattr, NULL, NULL, ""),
TPSLOT("__cmp__", tp_compare, _PyObject_SlotCompare, wrap_cmpfunc, "x.__cmp__(y) <==> cmp(x,y)"),
TPSLOT("__repr__", tp_repr, slot_tp_repr, wrap_unaryfunc, "x.__repr__() <==> repr(x)"),
TPSLOT("__hash__", tp_hash, slot_tp_hash, wrap_hashfunc, "x.__hash__() <==> hash(x)"),
......
......@@ -969,9 +969,11 @@ Box* builtinRound(Box* _number, Box* _ndigits) {
throwCAPIException();
}
Box* builtinCmp(Box* lhs, Box* rhs) {
fatalOrError(PyExc_NotImplementedError, "unimplemented");
throwCAPIException();
Box* builtinCmp(Box* a, Box* b) {
int c;
if (PyObject_Cmp(a, b, &c) < 0)
throwCAPIException();
return PyInt_FromLong((long)c);
}
Box* builtinApply(Box* func, Box* args, Box* keywords) {
......
......@@ -306,44 +306,6 @@ extern "C" int PyObject_DelItem(PyObject* o, PyObject* key) noexcept {
return -1;
}
extern "C" PyObject* PyObject_RichCompare(PyObject* o1, PyObject* o2, int opid) noexcept {
int translated_op;
switch (opid) {
case Py_LT:
translated_op = AST_TYPE::Lt;
break;
case Py_LE:
translated_op = AST_TYPE::LtE;
break;
case Py_EQ:
translated_op = AST_TYPE::Eq;
break;
case Py_NE:
translated_op = AST_TYPE::NotEq;
break;
case Py_GT:
translated_op = AST_TYPE::Gt;
break;
case Py_GE:
translated_op = AST_TYPE::GtE;
break;
default:
fatalOrError(PyExc_NotImplementedError, "unimplemented");
return nullptr;
};
try {
return compare(o1, o2, translated_op);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
extern "C" {
int _Py_SwappedOp[] = { Py_GT, Py_GE, Py_EQ, Py_NE, Py_LT, Py_LE };
}
extern "C" long PyObject_Hash(PyObject* o) noexcept {
try {
return hash(o)->n;
......
......@@ -325,6 +325,7 @@ BoxedClass::BoxedClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset
tp_flags |= Py_TPFLAGS_HAVE_CLASS;
tp_flags |= Py_TPFLAGS_HAVE_GC;
tp_flags |= Py_TPFLAGS_HAVE_WEAKREFS;
tp_flags |= Py_TPFLAGS_HAVE_RICHCOMPARE;
if (base && (base->tp_flags & Py_TPFLAGS_HAVE_NEWBUFFER))
tp_flags |= Py_TPFLAGS_HAVE_NEWBUFFER;
......
class C(object):
def __eq__(self, rhs):
print "eq", type(self), type(rhs)
return False
def __lt__(self, rhs):
print "lt", type(self), type(rhs)
return False
def __gt__(self, rhs):
print "gt", type(self), type(rhs)
return True
class D(C):
def __cmp__(self, rhs):
print "cmp", type(self), type(rhs)
return 0
l = [C(), D()]
for lhs in l:
for rhs in l:
r = cmp(lhs, rhs)
print type(lhs), type(rhs), r
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment