diff options
author | Damien George <damien.p.george@gmail.com> | 2014-02-10 21:41:14 +0000 |
---|---|---|
committer | Damien George <damien.p.george@gmail.com> | 2014-02-10 21:41:14 +0000 |
commit | 8c2b333affea7445c457c5247df047947bed9b53 (patch) | |
tree | b697957a499162ccca3219dca426b1bcd35cd0c7 /py | |
parent | 7d0bfbedd218fadd91e2bbeb6486371ffeb7b682 (diff) | |
parent | 2e24ee8d80de20e879275c087ecc1ca9b4d27297 (diff) | |
download | micropython-8c2b333affea7445c457c5247df047947bed9b53.tar.gz micropython-8c2b333affea7445c457c5247df047947bed9b53.zip |
Merge branch 'master' of github.com:micropython/micropython
Diffstat (limited to 'py')
-rw-r--r-- | py/obj.c | 1 | ||||
-rw-r--r-- | py/obj.h | 7 | ||||
-rw-r--r-- | py/objlist.c | 76 | ||||
-rw-r--r-- | py/objtuple.c | 62 | ||||
-rw-r--r-- | py/qstrdefs.h | 1 | ||||
-rw-r--r-- | py/runtime.c | 1 | ||||
-rw-r--r-- | py/sequence.c | 85 |
7 files changed, 160 insertions, 73 deletions
@@ -253,3 +253,4 @@ mp_obj_t mp_obj_len_maybe(mp_obj_t o_in) { mp_obj_t mp_identity(mp_obj_t self) { return self; } +MP_DEFINE_CONST_FUN_OBJ_1(mp_identity_obj, mp_identity); @@ -370,6 +370,7 @@ extern const mp_obj_type_t fun_bc_type; void mp_obj_fun_bc_get(mp_obj_t self_in, int *n_args, uint *n_state, const byte **code); mp_obj_t mp_identity(mp_obj_t self); +MP_DECLARE_CONST_FUN_OBJ(mp_identity_obj); // super extern const mp_obj_type_t super_type; @@ -397,5 +398,9 @@ typedef struct _mp_obj_static_class_method_t { // sequence helpers void mp_seq_multiply(const void *items, uint item_sz, uint len, uint times, void *dest); bool m_seq_get_fast_slice_indexes(machine_uint_t len, mp_obj_t slice, machine_uint_t *begin, machine_uint_t *end); -#define m_seq_copy(dest, src, len, item_sz) memcpy(dest, src, len * sizeof(item_sz)) +#define m_seq_copy(dest, src, len, item_t) memcpy(dest, src, len * sizeof(item_t)) +#define m_seq_cat(dest, src1, len1, src2, len2, item_t) { memcpy(dest, src1, len1 * sizeof(item_t)); memcpy(dest + len1, src2, len2 * sizeof(item_t)); } bool mp_seq_cmp_bytes(int op, const byte *data1, uint len1, const byte *data2, uint len2); +bool mp_seq_cmp_objs(int op, const mp_obj_t *items1, uint len1, const mp_obj_t *items2, uint len2); +mp_obj_t mp_seq_index_obj(const mp_obj_t *items, uint len, uint n_args, const mp_obj_t *args); +mp_obj_t mp_seq_count_obj(const mp_obj_t *items, uint len, mp_obj_t value); diff --git a/py/objlist.c b/py/objlist.c index 14f3a5760a..35bab2a398 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -75,51 +75,8 @@ static bool list_cmp_helper(int op, mp_obj_t self_in, mp_obj_t another_in) { } mp_obj_list_t *self = self_in; mp_obj_list_t *another = another_in; - if (op == RT_BINARY_OP_EQUAL && self->len != another->len) { - return false; - } - - // Let's deal only with > & >= - if (op == RT_BINARY_OP_LESS || op == RT_BINARY_OP_LESS_EQUAL) { - mp_obj_t t = self; - self = another; - another = t; - if (op == RT_BINARY_OP_LESS) { - op = RT_BINARY_OP_MORE; - } else { - op = RT_BINARY_OP_MORE_EQUAL; - } - } - - int len = self->len < another->len ? self->len : another->len; - bool eq_status = true; // empty lists are equal - bool rel_status; - for (int i = 0; i < len; i++) { - eq_status = mp_obj_equal(self->items[i], another->items[i]); - if (op == RT_BINARY_OP_EQUAL && !eq_status) { - return false; - } - rel_status = (rt_binary_op(op, self->items[i], another->items[i]) == mp_const_true); - if (!eq_status && !rel_status) { - return false; - } - } - - // If we had tie in the last element... - if (eq_status) { - // ... and we have lists of different lengths... - if (self->len != another->len) { - if (self->len < another->len) { - // ... then longer list length wins (we deal only with >) - return false; - } - } else if (op == RT_BINARY_OP_MORE) { - // Otherwise, if we have strict relation, equality means failure - return false; - } - } - return true; + return mp_seq_cmp_objs(op, self->items, self->len, another->items, another->len); } static mp_obj_t list_unary_op(int op, mp_obj_t self_in) { @@ -157,8 +114,7 @@ static mp_obj_t list_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { } mp_obj_list_t *p = rhs; mp_obj_list_t *s = list_new(o->len + p->len); - memcpy(s->items, o->items, sizeof(mp_obj_t) * o->len); - memcpy(s->items + o->len, p->items, sizeof(mp_obj_t) * p->len); + m_seq_cat(s->items, o->items, o->len, p->items, p->len, mp_obj_t); return s; } case RT_BINARY_OP_INPLACE_ADD: @@ -304,38 +260,14 @@ static mp_obj_t list_copy(mp_obj_t self_in) { static mp_obj_t list_count(mp_obj_t self_in, mp_obj_t value) { assert(MP_OBJ_IS_TYPE(self_in, &list_type)); mp_obj_list_t *self = self_in; - int count = 0; - for (int i = 0; i < self->len; i++) { - if (mp_obj_equal(self->items[i], value)) { - count++; - } - } - - return mp_obj_new_int(count); + return mp_seq_count_obj(self->items, self->len, value); } static mp_obj_t list_index(uint n_args, const mp_obj_t *args) { assert(2 <= n_args && n_args <= 4); assert(MP_OBJ_IS_TYPE(args[0], &list_type)); mp_obj_list_t *self = args[0]; - mp_obj_t *value = args[1]; - uint start = 0; - uint stop = self->len; - - if (n_args >= 3) { - start = mp_get_index(self->base.type, self->len, args[2]); - if (n_args >= 4) { - stop = mp_get_index(self->base.type, self->len, args[3]); - } - } - - for (uint i = start; i < stop; i++) { - if (mp_obj_equal(self->items[i], value)) { - return mp_obj_new_int(i); - } - } - - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_ValueError, "object not in list")); + return mp_seq_index_obj(self->items, self->len, n_args, args); } static mp_obj_t list_insert(mp_obj_t self_in, mp_obj_t idx, mp_obj_t obj) { diff --git a/py/objtuple.c b/py/objtuple.c index 3e5041c9dd..7221db7746 100644 --- a/py/objtuple.c +++ b/py/objtuple.c @@ -74,6 +74,18 @@ static mp_obj_t tuple_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const m } } +// Don't pass RT_BINARY_OP_NOT_EQUAL here +static bool tuple_cmp_helper(int op, mp_obj_t self_in, mp_obj_t another_in) { + assert(MP_OBJ_IS_TYPE(self_in, &tuple_type)); + if (!MP_OBJ_IS_TYPE(another_in, &tuple_type)) { + return false; + } + mp_obj_tuple_t *self = self_in; + mp_obj_tuple_t *another = another_in; + + return mp_seq_cmp_objs(op, self->items, self->len, another->items, another->len); +} + static mp_obj_t tuple_unary_op(int op, mp_obj_t self_in) { mp_obj_tuple_t *self = self_in; switch (op) { @@ -102,6 +114,35 @@ static mp_obj_t tuple_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { uint index = mp_get_index(o->base.type, o->len, rhs); return o->items[index]; } + case RT_BINARY_OP_ADD: + { + if (!MP_OBJ_IS_TYPE(rhs, &tuple_type)) { + return NULL; + } + mp_obj_tuple_t *p = rhs; + mp_obj_tuple_t *s = mp_obj_new_tuple(o->len + p->len, NULL); + m_seq_cat(s->items, o->items, o->len, p->items, p->len, mp_obj_t); + return s; + } + case RT_BINARY_OP_MULTIPLY: + { + if (!MP_OBJ_IS_SMALL_INT(rhs)) { + return NULL; + } + int n = MP_OBJ_SMALL_INT_VALUE(rhs); + mp_obj_tuple_t *s = mp_obj_new_tuple(o->len * n, NULL); + mp_seq_multiply(o->items, sizeof(*o->items), o->len, n, s->items); + return s; + } + case RT_BINARY_OP_EQUAL: + case RT_BINARY_OP_LESS: + case RT_BINARY_OP_LESS_EQUAL: + case RT_BINARY_OP_MORE: + case RT_BINARY_OP_MORE_EQUAL: + return MP_BOOL(tuple_cmp_helper(op, lhs, rhs)); + case RT_BINARY_OP_NOT_EQUAL: + return MP_BOOL(!tuple_cmp_helper(RT_BINARY_OP_EQUAL, lhs, rhs)); + default: // op not supported return NULL; @@ -112,6 +153,26 @@ static mp_obj_t tuple_getiter(mp_obj_t o_in) { return mp_obj_new_tuple_iterator(o_in, 0); } +static mp_obj_t tuple_count(mp_obj_t self_in, mp_obj_t value) { + assert(MP_OBJ_IS_TYPE(self_in, &tuple_type)); + mp_obj_tuple_t *self = self_in; + return mp_seq_count_obj(self->items, self->len, value); +} +static MP_DEFINE_CONST_FUN_OBJ_2(tuple_count_obj, tuple_count); + +static mp_obj_t tuple_index(uint n_args, const mp_obj_t *args) { + assert(MP_OBJ_IS_TYPE(args[0], &tuple_type)); + mp_obj_tuple_t *self = args[0]; + return mp_seq_index_obj(self->items, self->len, n_args, args); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(tuple_index_obj, 2, 4, tuple_index); + +static const mp_method_t tuple_type_methods[] = { + { "count", &tuple_count_obj }, + { "index", &tuple_index_obj }, + { NULL, NULL }, // end-of-list sentinel +}; + const mp_obj_type_t tuple_type = { { &mp_const_type }, "tuple", @@ -120,6 +181,7 @@ const mp_obj_type_t tuple_type = { .unary_op = tuple_unary_op, .binary_op = tuple_binary_op, .getiter = tuple_getiter, + .methods = tuple_type_methods, }; // the zero-length tuple diff --git a/py/qstrdefs.h b/py/qstrdefs.h index 3d4f4e2488..680c4bcf73 100644 --- a/py/qstrdefs.h +++ b/py/qstrdefs.h @@ -37,6 +37,7 @@ Q(IndentationError) Q(IndexError) Q(KeyError) Q(NameError) +Q(NotImplementedError) Q(OSError) Q(SyntaxError) Q(TypeError) diff --git a/py/runtime.c b/py/runtime.c index 0ac470fbc2..aaac884d65 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -177,6 +177,7 @@ void rt_init(void) { mp_map_add_qstr(&map_builtins, MP_QSTR_OverflowError, mp_obj_new_exception(MP_QSTR_OverflowError)); mp_map_add_qstr(&map_builtins, MP_QSTR_OSError, mp_obj_new_exception(MP_QSTR_OSError)); mp_map_add_qstr(&map_builtins, MP_QSTR_AssertionError, mp_obj_new_exception(MP_QSTR_AssertionError)); + mp_map_add_qstr(&map_builtins, MP_QSTR_NotImplementedError, mp_obj_new_exception(MP_QSTR_NotImplementedError)); mp_map_add_qstr(&map_builtins, MP_QSTR_StopIteration, mp_obj_new_exception(MP_QSTR_StopIteration)); // built-in objects diff --git a/py/sequence.c b/py/sequence.c index 74b4fcfdf8..d8cfd9f3e9 100644 --- a/py/sequence.c +++ b/py/sequence.c @@ -91,3 +91,88 @@ bool mp_seq_cmp_bytes(int op, const byte *data1, uint len1, const byte *data2, u } return true; } + +// Special-case comparison function for sequences of mp_obj_t +// Don't pass RT_BINARY_OP_NOT_EQUAL here +bool mp_seq_cmp_objs(int op, const mp_obj_t *items1, uint len1, const mp_obj_t *items2, uint len2) { + if (op == RT_BINARY_OP_EQUAL && len1 != len2) { + return false; + } + + // Let's deal only with > & >= + if (op == RT_BINARY_OP_LESS || op == RT_BINARY_OP_LESS_EQUAL) { + SWAP(const mp_obj_t *, items1, items2); + SWAP(uint, len1, len2); + if (op == RT_BINARY_OP_LESS) { + op = RT_BINARY_OP_MORE; + } else { + op = RT_BINARY_OP_MORE_EQUAL; + } + } + + int len = len1 < len2 ? len1 : len2; + bool eq_status = true; // empty lists are equal + bool rel_status; + for (int i = 0; i < len; i++) { + eq_status = mp_obj_equal(items1[i], items2[i]); + if (op == RT_BINARY_OP_EQUAL && !eq_status) { + return false; + } + rel_status = (rt_binary_op(op, items1[i], items2[i]) == mp_const_true); + if (!eq_status && !rel_status) { + return false; + } + } + + // If we had tie in the last element... + if (eq_status) { + // ... and we have lists of different lengths... + if (len1 != len2) { + if (len1 < len2) { + // ... then longer list length wins (we deal only with >) + return false; + } + } else if (op == RT_BINARY_OP_MORE) { + // Otherwise, if we have strict relation, equality means failure + return false; + } + } + + return true; +} + +// Special-case of index() which searches for mp_obj_t +mp_obj_t mp_seq_index_obj(const mp_obj_t *items, uint len, uint n_args, const mp_obj_t *args) { + mp_obj_type_t *type = mp_obj_get_type(args[0]); + mp_obj_t *value = args[1]; + uint start = 0; + uint stop = len; + + if (n_args >= 3) { + start = mp_get_index(type, len, args[2]); + if (n_args >= 4) { + stop = mp_get_index(type, len, args[3]); + } + } + + for (uint i = start; i < stop; i++) { + if (mp_obj_equal(items[i], value)) { + // Common sense says this cannot overflow small int + return MP_OBJ_NEW_SMALL_INT(i); + } + } + + nlr_jump(mp_obj_new_exception_msg(MP_QSTR_ValueError, "object not in sequence")); +} + +mp_obj_t mp_seq_count_obj(const mp_obj_t *items, uint len, mp_obj_t value) { + uint count = 0; + for (uint i = 0; i < len; i++) { + if (mp_obj_equal(items[i], value)) { + count++; + } + } + + // Common sense says this cannot overflow small int + return MP_OBJ_NEW_SMALL_INT(count); +} |