From 4f5e165d0bf9ba338df3cdab4266556c4c5a70c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dani=C3=ABl=20van=20de=20Giessen?= Date: Mon, 7 Dec 2020 13:33:13 +0100 Subject: [PATCH] py/objboundmeth: Support comparing and hashing bound methods. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This behaviour matches CPython. It's useful to be able to store bound method objects in dicts/sets, and compare for equality, eg when storing them in a list and using list.remove(). Signed-off-by: Daniƫl van de Giessen --- py/obj.h | 1 + py/objboundmeth.c | 25 +++++++++++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/py/obj.h b/py/obj.h index de4c15b22..3c2176832 100644 --- a/py/obj.h +++ b/py/obj.h @@ -828,6 +828,7 @@ extern const mp_obj_type_t mp_type_fun_bc; extern const mp_obj_type_t mp_type_module; extern const mp_obj_type_t mp_type_staticmethod; extern const mp_obj_type_t mp_type_classmethod; +extern const mp_obj_type_t mp_type_bound_meth; extern const mp_obj_type_t mp_type_property; extern const mp_obj_type_t mp_type_stringio; extern const mp_obj_type_t mp_type_bytesio; diff --git a/py/objboundmeth.c b/py/objboundmeth.c index 8486f876f..10f52016c 100644 --- a/py/objboundmeth.c +++ b/py/objboundmeth.c @@ -83,6 +83,25 @@ STATIC mp_obj_t bound_meth_call(mp_obj_t self_in, size_t n_args, size_t n_kw, co return mp_call_method_self_n_kw(self->meth, self->self, n_args, n_kw, args); } +STATIC mp_obj_t bound_meth_unary_op(mp_unary_op_t op, mp_obj_t self_in) { + mp_obj_bound_meth_t *self = MP_OBJ_TO_PTR(self_in); + switch (op) { + case MP_UNARY_OP_HASH: + return MP_OBJ_NEW_SMALL_INT((mp_uint_t)self->self ^ (mp_uint_t)self->meth); + default: + return MP_OBJ_NULL; // op not supported + } +} + +STATIC mp_obj_t bound_meth_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { + if (!mp_obj_is_type(rhs_in, &mp_type_bound_meth) || op != MP_BINARY_OP_EQUAL) { + return MP_OBJ_NULL; // op not supported + } + mp_obj_bound_meth_t *lhs = MP_OBJ_TO_PTR(lhs_in); + mp_obj_bound_meth_t *rhs = MP_OBJ_TO_PTR(rhs_in); + return mp_obj_new_bool(lhs->self == rhs->self && lhs->meth == rhs->meth); +} + #if MICROPY_PY_FUNCTION_ATTRS STATIC void bound_meth_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { if (dest[0] != MP_OBJ_NULL) { @@ -107,13 +126,15 @@ STATIC void bound_meth_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { #define BOUND_METH_TYPE_ATTR #endif -STATIC MP_DEFINE_CONST_OBJ_TYPE( +MP_DEFINE_CONST_OBJ_TYPE( mp_type_bound_meth, MP_QSTR_bound_method, MP_TYPE_FLAG_NONE, BOUND_METH_TYPE_PRINT BOUND_METH_TYPE_ATTR - call, bound_meth_call + call, bound_meth_call, + unary_op, bound_meth_unary_op, + binary_op, bound_meth_binary_op ); mp_obj_t mp_obj_new_bound_meth(mp_obj_t meth, mp_obj_t self) {