diff --git a/py/obj.h b/py/obj.h index 5f2b9d3be..611873d2e 100644 --- a/py/obj.h +++ b/py/obj.h @@ -578,3 +578,8 @@ mp_obj_t mp_seq_count_obj(const mp_obj_t *items, uint len, mp_obj_t value); memcpy(dest + beg, slice, slice_len * sizeof(item_t)); \ /*printf("memcpy(%p, %p, %d)\n", dest + (beg + slice_len), dest + end, (dest_len - end) * sizeof(item_t));*/ \ memcpy(dest + (beg + slice_len), dest + end, (dest_len - end) * sizeof(item_t)); + +#define mp_seq_replace_slice_grow_inplace(dest, dest_len, beg, end, slice, slice_len, len_adj, item_t) \ + /*printf("memmove(%p, %p, %d)\n", dest + beg + len_adj, dest + beg, (dest_len - beg) * sizeof(item_t));*/ \ + memmove(dest + beg + len_adj, dest + beg, (dest_len - beg) * sizeof(item_t)); \ + memcpy(dest + beg, slice, slice_len * sizeof(item_t)); diff --git a/py/objlist.c b/py/objlist.c index 7a15006ad..7d9f56d2e 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -199,12 +199,21 @@ STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { } int len_adj = slice->len - (stop - start); //printf("Len adj: %d\n", len_adj); - assert(len_adj <= 0); - mp_seq_replace_slice_no_grow(self->items, self->len, start, stop, slice->items, slice->len, mp_obj_t); - // Clear "freed" elements at the end of list - mp_seq_clear(self->items, self->len + len_adj, self->len, sizeof(*self->items)); + if (len_adj > 0) { + if (self->len + len_adj > self->alloc) { + // TODO: Might optimize memory copies here by checking if block can + // be grown inplace or not + self->items = m_renew(mp_obj_t, self->items, self->alloc, self->len + len_adj); + self->alloc = self->len + len_adj; + } + mp_seq_replace_slice_grow_inplace(self->items, self->len, start, stop, slice->items, slice->len, len_adj, mp_obj_t); + } else { + mp_seq_replace_slice_no_grow(self->items, self->len, start, stop, slice->items, slice->len, mp_obj_t); + // Clear "freed" elements at the end of list + mp_seq_clear(self->items, self->len + len_adj, self->len, sizeof(*self->items)); + // TODO: apply allocation policy re: alloc_size + } self->len += len_adj; - // TODO: apply allocation policy re: alloc_size return mp_const_none; } #endif diff --git a/tests/basics/list_slice_assign_grow.py b/tests/basics/list_slice_assign_grow.py new file mode 100644 index 000000000..12b1541e3 --- /dev/null +++ b/tests/basics/list_slice_assign_grow.py @@ -0,0 +1,28 @@ +x = list(range(2)) + +l = list(x) +l[0:0] = [10] +print(l) +l = list(x) +l[:0] = [10, 20] +print(l) +l = list(x) +l[0:0] = [10, 20, 30, 40] +print(l) + +l = list(x) +l[1:1] = [10, 20, 30, 40] +print(l) + +l = list(x) +l[2:] = [10, 20, 30, 40] +print(l) + +# Weird cases +l = list(x) +l[1:0] = [10, 20, 30, 40] +print(l) + +l = list(x) +l[100:100] = [10, 20, 30, 40] +print(l)