Skip to content

Commit 09a0c64

Browse files
committed
py: Improve __bool__ and __len__ dispatch; add slots for them.
1 parent b25711e commit 09a0c64

File tree

6 files changed

+56
-30
lines changed

6 files changed

+56
-30
lines changed

py/obj.c

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -236,33 +236,16 @@ uint mp_get_index(const mp_obj_type_t *type, machine_uint_t len, mp_obj_t index)
236236

237237
// may return MP_OBJ_NULL
238238
mp_obj_t mp_obj_len_maybe(mp_obj_t o_in) {
239-
mp_small_int_t len = 0;
240239
if (MP_OBJ_IS_STR(o_in)) {
241-
len = mp_obj_str_get_len(o_in);
242-
} else if (MP_OBJ_IS_TYPE(o_in, &tuple_type)) {
243-
uint seq_len;
244-
mp_obj_t *seq_items;
245-
mp_obj_tuple_get(o_in, &seq_len, &seq_items);
246-
len = seq_len;
247-
} else if (MP_OBJ_IS_TYPE(o_in, &list_type)) {
248-
uint seq_len;
249-
mp_obj_t *seq_items;
250-
mp_obj_list_get(o_in, &seq_len, &seq_items);
251-
len = seq_len;
252-
} else if (MP_OBJ_IS_TYPE(o_in, &dict_type)) {
253-
len = mp_obj_dict_len(o_in);
240+
return MP_OBJ_NEW_SMALL_INT((machine_int_t)mp_obj_str_get_len(o_in));
254241
} else {
255242
mp_obj_type_t *type = mp_obj_get_type(o_in);
256243
if (type->unary_op != NULL) {
257-
mp_obj_t result = type->unary_op(RT_UNARY_OP_LEN, o_in);
258-
if (result != MP_OBJ_NULL) {
259-
return result;
260-
}
244+
return type->unary_op(RT_UNARY_OP_LEN, o_in);
245+
} else {
246+
return MP_OBJ_NULL;
261247
}
262-
263-
return MP_OBJ_NULL;
264248
}
265-
return MP_OBJ_NEW_SMALL_INT(len);
266249
}
267250

268251
// Return input argument. Useful as .getiter for objects which are

py/objdict.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ static mp_obj_t dict_unary_op(int op, mp_obj_t self_in) {
4747
mp_obj_dict_t *self = self_in;
4848
switch (op) {
4949
case RT_UNARY_OP_BOOL: return MP_BOOL(self->map.used != 0);
50-
case RT_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(self->map.used);
50+
case RT_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT((machine_int_t)self->map.used);
5151
default: return MP_OBJ_NULL; // op not supported for None
5252
}
5353
}

py/objtype.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,29 @@ static mp_obj_t class_make_new(mp_obj_t self_in, uint n_args, uint n_kw, const m
116116
return o;
117117
}
118118

119+
static const qstr unary_op_method_name[] = {
120+
[RT_UNARY_OP_BOOL] = MP_QSTR___bool__,
121+
[RT_UNARY_OP_LEN] = MP_QSTR___len__,
122+
//[RT_UNARY_OP_POSITIVE,
123+
//[RT_UNARY_OP_NEGATIVE,
124+
//[RT_UNARY_OP_INVERT,
125+
[RT_UNARY_OP_NOT] = MP_QSTR_, // not implemented, used to make sure array has full size
126+
};
127+
128+
static mp_obj_t class_unary_op(int op, mp_obj_t self_in) {
129+
mp_obj_class_t *self = self_in;
130+
qstr op_name = unary_op_method_name[op];
131+
if (op_name == 0) {
132+
return MP_OBJ_NULL;
133+
}
134+
mp_obj_t member = mp_obj_class_lookup(self->base.type, op_name);
135+
if (member != MP_OBJ_NULL) {
136+
return rt_call_function_1(member, self_in);
137+
} else {
138+
return MP_OBJ_NULL;
139+
}
140+
}
141+
119142
static const qstr binary_op_method_name[] = {
120143
[RT_BINARY_OP_SUBSCR] = MP_QSTR___getitem__,
121144
/*
@@ -330,6 +353,7 @@ mp_obj_t mp_obj_new_type(const char *name, mp_obj_t bases_tuple, mp_obj_t locals
330353
o->name = name;
331354
o->print = class_print;
332355
o->make_new = class_make_new;
356+
o->unary_op = class_unary_op;
333357
o->binary_op = class_binary_op;
334358
o->load_attr = class_load_attr;
335359
o->store_attr = class_store_attr;

py/qstrdefs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ Q(__next__)
1313
Q(__qualname__)
1414
Q(__repl_print__)
1515

16+
Q(__bool__)
17+
Q(__len__)
1618
Q(__getitem__)
1719
Q(__add__)
1820
Q(__sub__)

py/runtime.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -304,23 +304,23 @@ void rt_assign_inline_asm_code(uint unique_code_id, void *fun, uint len, int n_a
304304

305305
int rt_is_true(mp_obj_t arg) {
306306
DEBUG_OP_printf("is true %p\n", arg);
307-
if (MP_OBJ_IS_SMALL_INT(arg)) {
307+
if (arg == mp_const_false) {
308+
return 0;
309+
} else if (arg == mp_const_true) {
310+
return 1;
311+
} else if (arg == mp_const_none) {
312+
return 0;
313+
} else if (MP_OBJ_IS_SMALL_INT(arg)) {
308314
if (MP_OBJ_SMALL_INT_VALUE(arg) == 0) {
309315
return 0;
310316
} else {
311317
return 1;
312318
}
313-
} else if (arg == mp_const_none) {
314-
return 0;
315-
} else if (arg == mp_const_false) {
316-
return 0;
317-
} else if (arg == mp_const_true) {
318-
return 1;
319319
} else {
320320
mp_obj_type_t *type = mp_obj_get_type(arg);
321321
if (type->unary_op != NULL) {
322322
mp_obj_t result = type->unary_op(RT_UNARY_OP_BOOL, arg);
323-
if (result != NULL) {
323+
if (result != MP_OBJ_NULL) {
324324
return result == mp_const_true;
325325
}
326326
}

tests/basics/slots_bool_len.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
class A:
2+
def __bool__(self):
3+
print('__bool__')
4+
return True
5+
def __len__(self):
6+
print('__len__')
7+
return 1
8+
9+
class B:
10+
def __len__(self):
11+
print('__len__')
12+
return 0
13+
14+
print(bool(A()))
15+
print(len(A()))
16+
print(bool(B()))
17+
print(len(B()))

0 commit comments

Comments
 (0)