summaryrefslogtreecommitdiffstatshomepage
path: root/py
diff options
context:
space:
mode:
Diffstat (limited to 'py')
-rw-r--r--py/mpconfig.h6
-rw-r--r--py/obj.h20
-rw-r--r--py/objarray.c43
-rw-r--r--py/objlist.c6
4 files changed, 56 insertions, 19 deletions
diff --git a/py/mpconfig.h b/py/mpconfig.h
index ed42fbccc1..acc5f66493 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -409,6 +409,12 @@ typedef double mp_float_t;
#define MICROPY_PY_ARRAY (1)
#endif
+// Whether to support slice assignments for array (and bytearray).
+// This is rarely used, but adds ~0.5K of code.
+#ifndef MICROPY_PY_ARRAY_SLICE_ASSIGN
+#define MICROPY_PY_ARRAY_SLICE_ASSIGN (0)
+#endif
+
// Whether to provide "collections" module
#ifndef MICROPY_PY_COLLECTIONS
#define MICROPY_PY_COLLECTIONS (1)
diff --git a/py/obj.h b/py/obj.h
index db42e795a2..bfe28e1e41 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -616,15 +616,15 @@ mp_obj_t mp_seq_count_obj(const mp_obj_t *items, mp_uint_t len, mp_obj_t value);
mp_obj_t mp_seq_extract_slice(mp_uint_t len, const mp_obj_t *seq, mp_bound_slice_t *indexes);
// 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("memmove(%p, %p, %d)\n", dest + (beg + slice_len), dest + end, (dest_len - end) * sizeof(item_t));*/ \
- memmove(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));
+#define mp_seq_replace_slice_no_grow(dest, dest_len, beg, end, slice, slice_len, item_sz) \
+ /*printf("memcpy(%p, %p, %d)\n", dest + beg, slice, slice_len * (item_sz));*/ \
+ memcpy(((char*)dest) + (beg) * (item_sz), slice, slice_len * (item_sz)); \
+ /*printf("memmove(%p, %p, %d)\n", dest + (beg + slice_len), dest + end, (dest_len - end) * (item_sz));*/ \
+ memmove(((char*)dest) + (beg + slice_len) * (item_sz), ((char*)dest) + (end) * (item_sz), (dest_len - end) * (item_sz));
+
+#define mp_seq_replace_slice_grow_inplace(dest, dest_len, beg, end, slice, slice_len, len_adj, item_sz) \
+ /*printf("memmove(%p, %p, %d)\n", dest + beg + len_adj, dest + beg, (dest_len - beg) * (item_sz));*/ \
+ memmove(((char*)dest) + (beg + len_adj) * (item_sz), ((char*)dest) + (beg) * (item_sz), (dest_len - beg) * (item_sz)); \
+ memcpy(((char*)dest) + (beg) * (item_sz), slice, slice_len * (item_sz));
#endif // __MICROPY_INCLUDED_PY_OBJ_H__
diff --git a/py/objarray.c b/py/objarray.c
index e2fee1f2ed..e030548bbb 100644
--- a/py/objarray.c
+++ b/py/objarray.c
@@ -351,17 +351,48 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value
if (0) {
#if MICROPY_PY_BUILTINS_SLICE
} else if (MP_OBJ_IS_TYPE(index_in, &mp_type_slice)) {
- if (value != MP_OBJ_SENTINEL) {
- // Only getting a slice is suported so far, not assignment
- // TODO: confirmed that both bytearray and array.array support
- // slice assignment (incl. of different size)
- return MP_OBJ_NULL; // op not supported
- }
mp_bound_slice_t slice;
if (!mp_seq_get_fast_slice_indexes(o->len, index_in, &slice)) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_NotImplementedError,
"only slices with step=1 (aka None) are supported"));
}
+ if (value != MP_OBJ_SENTINEL) {
+ #if MICROPY_PY_ARRAY_SLICE_ASSIGN
+ // Assign
+ if (!MP_OBJ_IS_TYPE(value, &mp_type_array) && !MP_OBJ_IS_TYPE(value, &mp_type_bytearray)) {
+ mp_not_implemented("array required on right side");
+ }
+ mp_obj_array_t *src_slice = value;
+ int item_sz = mp_binary_get_size('@', o->typecode, NULL);
+ if (item_sz != mp_binary_get_size('@', src_slice->typecode, NULL)) {
+ mp_not_implemented("arrays should be compatible");
+ }
+
+ // TODO: check src/dst compat
+ mp_int_t len_adj = src_slice->len - (slice.stop - slice.start);
+ if (len_adj > 0) {
+ if (len_adj > o->free) {
+ // TODO: alloc policy; at the moment we go conservative
+ o->items = m_realloc(o->items, (o->len + o->free) * item_sz, (o->len + len_adj) * item_sz);
+ o->free = 0;
+ }
+ mp_seq_replace_slice_grow_inplace(o->items, o->len,
+ slice.start, slice.stop, src_slice->items, src_slice->len, len_adj, item_sz);
+ } else {
+ mp_seq_replace_slice_no_grow(o->items, o->len,
+ slice.start, slice.stop, src_slice->items, src_slice->len, item_sz);
+ // Clear "freed" elements at the end of list
+ // TODO: This is actually only needed for typecode=='O'
+ mp_seq_clear(o->items, o->len + len_adj, o->len, item_sz);
+ // TODO: alloc policy after shrinking
+ }
+ o->len += len_adj;
+ return mp_const_none;
+ #else
+ return MP_OBJ_NULL; // op not supported
+ #endif
+ }
+
mp_obj_array_t *res;
int sz = mp_binary_get_size('@', o->typecode & TYPECODE_MASK, NULL);
assert(sz > 0);
diff --git a/py/objlist.c b/py/objlist.c
index e0c8953755..03e3dda033 100644
--- a/py/objlist.c
+++ b/py/objlist.c
@@ -165,7 +165,7 @@ STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
mp_int_t len_adj = slice.start - slice.stop;
//printf("Len adj: %d\n", len_adj);
assert(len_adj <= 0);
- mp_seq_replace_slice_no_grow(self->items, self->len, slice.start, slice.stop, self->items/*NULL*/, 0, mp_obj_t);
+ mp_seq_replace_slice_no_grow(self->items, self->len, slice.start, slice.stop, self->items/*NULL*/, 0, sizeof(*self->items));
// 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;
@@ -211,10 +211,10 @@ STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
self->alloc = self->len + len_adj;
}
mp_seq_replace_slice_grow_inplace(self->items, self->len,
- slice_out.start, slice_out.stop, slice->items, slice->len, len_adj, mp_obj_t);
+ slice_out.start, slice_out.stop, slice->items, slice->len, len_adj, sizeof(*self->items));
} else {
mp_seq_replace_slice_no_grow(self->items, self->len,
- slice_out.start, slice_out.stop, slice->items, slice->len, mp_obj_t);
+ slice_out.start, slice_out.stop, slice->items, slice->len, sizeof(*self->items));
// 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