diff options
author | John R. Lenton <jlenton@gmail.com> | 2014-01-13 00:41:12 +0000 |
---|---|---|
committer | John R. Lenton <jlenton@gmail.com> | 2014-01-13 00:41:12 +0000 |
commit | 13e64f06604c1502317921201bdde33c57161808 (patch) | |
tree | 865c85e4aaa41fc86711010362b7c0b0b4dbf832 /py/objlist.c | |
parent | 813edf63a3e4c0bab3dd5edd4e7295462386c2f3 (diff) | |
parent | 34f813ee29c7191e3de455c3fc9c788496e3b29e (diff) |
Merge remote-tracking branch 'upstream/master' into containment
Diffstat (limited to 'py/objlist.c')
-rw-r--r-- | py/objlist.c | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/py/objlist.c b/py/objlist.c index 7d0402d28..fa8ec67d0 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -21,6 +21,7 @@ typedef struct _mp_obj_list_t { static mp_obj_t mp_obj_new_list_iterator(mp_obj_list_t *list, int cur); static mp_obj_list_t *list_new(uint n); +static mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in); /******************************************************************************/ /* list */ @@ -61,6 +62,61 @@ static mp_obj_t list_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args return NULL; } +// Don't pass RT_COMPARE_OP_NOT_EQUAL here +static bool list_cmp_helper(int op, mp_obj_t self_in, mp_obj_t another_in) { + assert(MP_OBJ_IS_TYPE(self_in, &list_type)); + if (!MP_OBJ_IS_TYPE(another_in, &list_type)) { + return false; + } + mp_obj_list_t *self = self_in; + mp_obj_list_t *another = another_in; + if (op == RT_COMPARE_OP_EQUAL && self->len != another->len) { + return false; + } + + // Let's deal only with > & >= + if (op == RT_COMPARE_OP_LESS || op == RT_COMPARE_OP_LESS_EQUAL) { + mp_obj_t t = self; + self = another; + another = t; + if (op == RT_COMPARE_OP_LESS) { + op = RT_COMPARE_OP_MORE; + } else { + op = RT_COMPARE_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_COMPARE_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_COMPARE_OP_MORE) { + // Otherwise, if we have strict relation, equality means failure + return false; + } + } + + return true; +} + static mp_obj_t list_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { mp_obj_list_t *o = lhs; switch (op) { @@ -81,6 +137,14 @@ static mp_obj_t list_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { memcpy(s->items + o->len, p->items, sizeof(mp_obj_t) * p->len); return s; } + case RT_BINARY_OP_INPLACE_ADD: + { + if (!MP_OBJ_IS_TYPE(rhs, &list_type)) { + return NULL; + } + list_extend(lhs, rhs); + return o; + } case RT_BINARY_OP_MULTIPLY: { if (!MP_OBJ_IS_SMALL_INT(rhs)) { @@ -96,6 +160,15 @@ static mp_obj_t list_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { } return s; } + case RT_COMPARE_OP_EQUAL: + case RT_COMPARE_OP_LESS: + case RT_COMPARE_OP_LESS_EQUAL: + case RT_COMPARE_OP_MORE: + case RT_COMPARE_OP_MORE_EQUAL: + return MP_BOOL(list_cmp_helper(op, lhs, rhs)); + case RT_COMPARE_OP_NOT_EQUAL: + return MP_BOOL(!list_cmp_helper(RT_COMPARE_OP_EQUAL, lhs, rhs)); + default: // op not supported return NULL; @@ -117,6 +190,23 @@ mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg) { return mp_const_none; // return None, as per CPython } +static mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in) { + assert(MP_OBJ_IS_TYPE(self_in, &list_type)); + assert(MP_OBJ_IS_TYPE(arg_in, &list_type)); + mp_obj_list_t *self = self_in; + mp_obj_list_t *arg = arg_in; + + if (self->len + arg->len > self->alloc) { + // TODO: use alloc policy for "4" + self->items = m_renew(mp_obj_t, self->items, self->alloc, self->len + arg->len + 4); + self->alloc = self->len + arg->len + 4; + } + + memcpy(self->items + self->len, arg->items, sizeof(mp_obj_t) * arg->len); + self->len += arg->len; + return mp_const_none; // return None, as per CPython +} + static mp_obj_t list_pop(int n_args, const mp_obj_t *args) { assert(1 <= n_args && n_args <= 2); assert(MP_OBJ_IS_TYPE(args[0], &list_type)); @@ -281,6 +371,7 @@ static mp_obj_t list_reverse(mp_obj_t self_in) { } static MP_DEFINE_CONST_FUN_OBJ_2(list_append_obj, mp_obj_list_append); +static MP_DEFINE_CONST_FUN_OBJ_2(list_extend_obj, list_extend); static MP_DEFINE_CONST_FUN_OBJ_1(list_clear_obj, list_clear); static MP_DEFINE_CONST_FUN_OBJ_1(list_copy_obj, list_copy); static MP_DEFINE_CONST_FUN_OBJ_2(list_count_obj, list_count); @@ -296,6 +387,7 @@ static const mp_method_t list_type_methods[] = { { "clear", &list_clear_obj }, { "copy", &list_copy_obj }, { "count", &list_count_obj }, + { "extend", &list_extend_obj }, { "index", &list_index_obj }, { "insert", &list_insert_obj }, { "pop", &list_pop_obj }, |