py: Improve __bool__ and __len__ dispatch; add slots for them.
This commit is contained in:
parent
b25711ea8f
commit
09a0c64bce
25
py/obj.c
25
py/obj.c
|
@ -236,33 +236,16 @@ uint mp_get_index(const mp_obj_type_t *type, machine_uint_t len, mp_obj_t index)
|
||||||
|
|
||||||
// may return MP_OBJ_NULL
|
// may return MP_OBJ_NULL
|
||||||
mp_obj_t mp_obj_len_maybe(mp_obj_t o_in) {
|
mp_obj_t mp_obj_len_maybe(mp_obj_t o_in) {
|
||||||
mp_small_int_t len = 0;
|
|
||||||
if (MP_OBJ_IS_STR(o_in)) {
|
if (MP_OBJ_IS_STR(o_in)) {
|
||||||
len = mp_obj_str_get_len(o_in);
|
return MP_OBJ_NEW_SMALL_INT((machine_int_t)mp_obj_str_get_len(o_in));
|
||||||
} else if (MP_OBJ_IS_TYPE(o_in, &tuple_type)) {
|
|
||||||
uint seq_len;
|
|
||||||
mp_obj_t *seq_items;
|
|
||||||
mp_obj_tuple_get(o_in, &seq_len, &seq_items);
|
|
||||||
len = seq_len;
|
|
||||||
} else if (MP_OBJ_IS_TYPE(o_in, &list_type)) {
|
|
||||||
uint seq_len;
|
|
||||||
mp_obj_t *seq_items;
|
|
||||||
mp_obj_list_get(o_in, &seq_len, &seq_items);
|
|
||||||
len = seq_len;
|
|
||||||
} else if (MP_OBJ_IS_TYPE(o_in, &dict_type)) {
|
|
||||||
len = mp_obj_dict_len(o_in);
|
|
||||||
} else {
|
} else {
|
||||||
mp_obj_type_t *type = mp_obj_get_type(o_in);
|
mp_obj_type_t *type = mp_obj_get_type(o_in);
|
||||||
if (type->unary_op != NULL) {
|
if (type->unary_op != NULL) {
|
||||||
mp_obj_t result = type->unary_op(RT_UNARY_OP_LEN, o_in);
|
return type->unary_op(RT_UNARY_OP_LEN, o_in);
|
||||||
if (result != MP_OBJ_NULL) {
|
} else {
|
||||||
return result;
|
return MP_OBJ_NULL;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return MP_OBJ_NULL;
|
|
||||||
}
|
}
|
||||||
return MP_OBJ_NEW_SMALL_INT(len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return input argument. Useful as .getiter for objects which are
|
// Return input argument. Useful as .getiter for objects which are
|
||||||
|
|
|
@ -47,7 +47,7 @@ static mp_obj_t dict_unary_op(int op, mp_obj_t self_in) {
|
||||||
mp_obj_dict_t *self = self_in;
|
mp_obj_dict_t *self = self_in;
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case RT_UNARY_OP_BOOL: return MP_BOOL(self->map.used != 0);
|
case RT_UNARY_OP_BOOL: return MP_BOOL(self->map.used != 0);
|
||||||
case RT_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(self->map.used);
|
case RT_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT((machine_int_t)self->map.used);
|
||||||
default: return MP_OBJ_NULL; // op not supported for None
|
default: return MP_OBJ_NULL; // op not supported for None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
24
py/objtype.c
24
py/objtype.c
|
@ -116,6 +116,29 @@ static mp_obj_t class_make_new(mp_obj_t self_in, uint n_args, uint n_kw, const m
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const qstr unary_op_method_name[] = {
|
||||||
|
[RT_UNARY_OP_BOOL] = MP_QSTR___bool__,
|
||||||
|
[RT_UNARY_OP_LEN] = MP_QSTR___len__,
|
||||||
|
//[RT_UNARY_OP_POSITIVE,
|
||||||
|
//[RT_UNARY_OP_NEGATIVE,
|
||||||
|
//[RT_UNARY_OP_INVERT,
|
||||||
|
[RT_UNARY_OP_NOT] = MP_QSTR_, // not implemented, used to make sure array has full size
|
||||||
|
};
|
||||||
|
|
||||||
|
static mp_obj_t class_unary_op(int op, mp_obj_t self_in) {
|
||||||
|
mp_obj_class_t *self = self_in;
|
||||||
|
qstr op_name = unary_op_method_name[op];
|
||||||
|
if (op_name == 0) {
|
||||||
|
return MP_OBJ_NULL;
|
||||||
|
}
|
||||||
|
mp_obj_t member = mp_obj_class_lookup(self->base.type, op_name);
|
||||||
|
if (member != MP_OBJ_NULL) {
|
||||||
|
return rt_call_function_1(member, self_in);
|
||||||
|
} else {
|
||||||
|
return MP_OBJ_NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static const qstr binary_op_method_name[] = {
|
static const qstr binary_op_method_name[] = {
|
||||||
[RT_BINARY_OP_SUBSCR] = MP_QSTR___getitem__,
|
[RT_BINARY_OP_SUBSCR] = MP_QSTR___getitem__,
|
||||||
/*
|
/*
|
||||||
|
@ -330,6 +353,7 @@ mp_obj_t mp_obj_new_type(const char *name, mp_obj_t bases_tuple, mp_obj_t locals
|
||||||
o->name = name;
|
o->name = name;
|
||||||
o->print = class_print;
|
o->print = class_print;
|
||||||
o->make_new = class_make_new;
|
o->make_new = class_make_new;
|
||||||
|
o->unary_op = class_unary_op;
|
||||||
o->binary_op = class_binary_op;
|
o->binary_op = class_binary_op;
|
||||||
o->load_attr = class_load_attr;
|
o->load_attr = class_load_attr;
|
||||||
o->store_attr = class_store_attr;
|
o->store_attr = class_store_attr;
|
||||||
|
|
|
@ -13,6 +13,8 @@ Q(__next__)
|
||||||
Q(__qualname__)
|
Q(__qualname__)
|
||||||
Q(__repl_print__)
|
Q(__repl_print__)
|
||||||
|
|
||||||
|
Q(__bool__)
|
||||||
|
Q(__len__)
|
||||||
Q(__getitem__)
|
Q(__getitem__)
|
||||||
Q(__add__)
|
Q(__add__)
|
||||||
Q(__sub__)
|
Q(__sub__)
|
||||||
|
|
16
py/runtime.c
16
py/runtime.c
|
@ -304,23 +304,23 @@ void rt_assign_inline_asm_code(uint unique_code_id, void *fun, uint len, int n_a
|
||||||
|
|
||||||
int rt_is_true(mp_obj_t arg) {
|
int rt_is_true(mp_obj_t arg) {
|
||||||
DEBUG_OP_printf("is true %p\n", arg);
|
DEBUG_OP_printf("is true %p\n", arg);
|
||||||
if (MP_OBJ_IS_SMALL_INT(arg)) {
|
if (arg == mp_const_false) {
|
||||||
|
return 0;
|
||||||
|
} else if (arg == mp_const_true) {
|
||||||
|
return 1;
|
||||||
|
} else if (arg == mp_const_none) {
|
||||||
|
return 0;
|
||||||
|
} else if (MP_OBJ_IS_SMALL_INT(arg)) {
|
||||||
if (MP_OBJ_SMALL_INT_VALUE(arg) == 0) {
|
if (MP_OBJ_SMALL_INT_VALUE(arg) == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else if (arg == mp_const_none) {
|
|
||||||
return 0;
|
|
||||||
} else if (arg == mp_const_false) {
|
|
||||||
return 0;
|
|
||||||
} else if (arg == mp_const_true) {
|
|
||||||
return 1;
|
|
||||||
} else {
|
} else {
|
||||||
mp_obj_type_t *type = mp_obj_get_type(arg);
|
mp_obj_type_t *type = mp_obj_get_type(arg);
|
||||||
if (type->unary_op != NULL) {
|
if (type->unary_op != NULL) {
|
||||||
mp_obj_t result = type->unary_op(RT_UNARY_OP_BOOL, arg);
|
mp_obj_t result = type->unary_op(RT_UNARY_OP_BOOL, arg);
|
||||||
if (result != NULL) {
|
if (result != MP_OBJ_NULL) {
|
||||||
return result == mp_const_true;
|
return result == mp_const_true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
class A:
|
||||||
|
def __bool__(self):
|
||||||
|
print('__bool__')
|
||||||
|
return True
|
||||||
|
def __len__(self):
|
||||||
|
print('__len__')
|
||||||
|
return 1
|
||||||
|
|
||||||
|
class B:
|
||||||
|
def __len__(self):
|
||||||
|
print('__len__')
|
||||||
|
return 0
|
||||||
|
|
||||||
|
print(bool(A()))
|
||||||
|
print(len(A()))
|
||||||
|
print(bool(B()))
|
||||||
|
print(len(B()))
|
Loading…
Reference in New Issue