py/objboundmeth: Support comparing and hashing bound methods.

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 <daniel@dvdgiessen.nl>
This commit is contained in:
Daniël van de Giessen 2020-12-07 13:33:13 +01:00 committed by Damien George
parent 5f0bd33b73
commit 4f5e165d0b
2 changed files with 24 additions and 2 deletions

View File

@ -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;

View File

@ -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) {