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:
parent
5f0bd33b73
commit
4f5e165d0b
1
py/obj.h
1
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_module;
|
||||||
extern const mp_obj_type_t mp_type_staticmethod;
|
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_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_property;
|
||||||
extern const mp_obj_type_t mp_type_stringio;
|
extern const mp_obj_type_t mp_type_stringio;
|
||||||
extern const mp_obj_type_t mp_type_bytesio;
|
extern const mp_obj_type_t mp_type_bytesio;
|
||||||
|
|
|
@ -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);
|
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
|
#if MICROPY_PY_FUNCTION_ATTRS
|
||||||
STATIC void bound_meth_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
|
STATIC void bound_meth_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
|
||||||
if (dest[0] != MP_OBJ_NULL) {
|
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
|
#define BOUND_METH_TYPE_ATTR
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
STATIC MP_DEFINE_CONST_OBJ_TYPE(
|
MP_DEFINE_CONST_OBJ_TYPE(
|
||||||
mp_type_bound_meth,
|
mp_type_bound_meth,
|
||||||
MP_QSTR_bound_method,
|
MP_QSTR_bound_method,
|
||||||
MP_TYPE_FLAG_NONE,
|
MP_TYPE_FLAG_NONE,
|
||||||
BOUND_METH_TYPE_PRINT
|
BOUND_METH_TYPE_PRINT
|
||||||
BOUND_METH_TYPE_ATTR
|
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) {
|
mp_obj_t mp_obj_new_bound_meth(mp_obj_t meth, mp_obj_t self) {
|
||||||
|
|
Loading…
Reference in New Issue