diff --git a/py/obj.h b/py/obj.h index 0ec3c29ef6..2418b28453 100644 --- a/py/obj.h +++ b/py/obj.h @@ -573,3 +573,8 @@ mp_obj_t mp_seq_index_obj(const mp_obj_t *items, uint len, uint n_args, const mp mp_obj_t mp_seq_count_obj(const mp_obj_t *items, uint len, mp_obj_t value); // Helper to clear stale pointers from allocated, but unused memory, to preclude GC problems #define mp_seq_clear(start, len, alloc_len, item_sz) memset((byte*)(start) + (len) * (item_sz), 0, ((alloc_len) - (len)) * (item_sz)) +#define mp_seq_replace_slice_no_grow(dest, dest_len, beg, end, slice, slice_len, item_t) \ + /*printf("memcpy(%p, %p, %d)\n", dest + beg, slice, slice_len * sizeof(item_t));*/ \ + 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)); diff --git a/py/objlist.c b/py/objlist.c index 08c1716179..4432b2447b 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -173,6 +173,26 @@ STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { uint index_val = mp_get_index(self->base.type, self->len, index, false); return self->items[index_val]; } else { +#if MICROPY_ENABLE_SLICE + if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) { + mp_obj_list_t *self = self_in; + assert(MP_OBJ_IS_TYPE(value, &mp_type_list)); + mp_obj_list_t *slice = value; + machine_uint_t start, stop; + if (!mp_seq_get_fast_slice_indexes(self->len, index, &start, &stop)) { + assert(0); + } + 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)); + self->len += len_adj; + // TODO: apply allocation policy re: alloc_size + return mp_const_none; + } +#endif mp_obj_list_store(self_in, index, value); return mp_const_none; } diff --git a/tests/basics/list_slice_assign.py b/tests/basics/list_slice_assign.py new file mode 100644 index 0000000000..f880520461 --- /dev/null +++ b/tests/basics/list_slice_assign.py @@ -0,0 +1,27 @@ +# test slices; only 2 argument version supported by Micro Python at the moment +x = list(range(10)) + +# Assignment +l = list(x) +l[1:3] = [10, 20] +print(l) +l = list(x) +l[1:3] = [10] +print(l) +l = list(x) +l[1:3] = [] +print(l) + +l = list(x) +l[:3] = [10, 20] +print(l) +l = list(x) +l[:3] = [] +print(l) + +l = list(x) +l[:-3] = [10, 20] +print(l) +l = list(x) +l[:-3] = [] +print(l)