summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorPaul Sokolovsky <pfalcon@users.sourceforge.net>2014-05-25 22:12:56 +0300
committerPaul Sokolovsky <pfalcon@users.sourceforge.net>2014-05-25 22:12:56 +0300
commit5fd5af98d0292e06f42e0e0dc6ea8278219cdd6e (patch)
tree8a49fbbaf377757b1db76f6a33e70c68e5470389
parentde4b9329f99794dc2025a7f9aa203811a156b3c4 (diff)
downloadmicropython-5fd5af98d0292e06f42e0e0dc6ea8278219cdd6e.tar.gz
micropython-5fd5af98d0292e06f42e0e0dc6ea8278219cdd6e.zip
objlist: Implement support for arbitrary (3-arg) slices.
-rw-r--r--py/obj.h1
-rw-r--r--py/objarray.c3
-rw-r--r--py/objlist.c2
-rw-r--r--py/objstr.c3
-rw-r--r--py/objtuple.c3
-rw-r--r--py/sequence.c23
-rw-r--r--tests/basics/list_slice_3arg.py4
7 files changed, 33 insertions, 6 deletions
diff --git a/py/obj.h b/py/obj.h
index 6bcebcf6ef..b1d9be2096 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -579,6 +579,7 @@ bool mp_seq_cmp_bytes(int op, const byte *data1, uint len1, const byte *data2, u
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);
+mp_obj_t mp_seq_extract_slice(uint 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) \
diff --git a/py/objarray.c b/py/objarray.c
index da57709ece..91fcec624a 100644
--- a/py/objarray.c
+++ b/py/objarray.c
@@ -178,7 +178,8 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value
}
mp_bound_slice_t slice;
if (!mp_seq_get_fast_slice_indexes(o->len, index_in, &slice)) {
- assert(0);
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_NotImplementedError,
+ "Only slices with step=1 (aka None) are supported"));
}
mp_obj_array_t *res = array_new(o->typecode, slice.stop - slice.start);
int sz = mp_binary_get_size('@', o->typecode, NULL);
diff --git a/py/objlist.c b/py/objlist.c
index 8643be41a1..647096f0dd 100644
--- a/py/objlist.c
+++ b/py/objlist.c
@@ -178,7 +178,7 @@ STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
mp_bound_slice_t slice;
if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice)) {
- assert(0);
+ return mp_seq_extract_slice(self->len, self->items, &slice);
}
mp_obj_list_t *res = list_new(slice.stop - slice.start);
mp_seq_copy(res->items, self->items + slice.start, res->len, mp_obj_t);
diff --git a/py/objstr.c b/py/objstr.c
index 84a6f30aad..f5939d1b1f 100644
--- a/py/objstr.c
+++ b/py/objstr.c
@@ -353,7 +353,8 @@ STATIC mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
mp_bound_slice_t slice;
if (!mp_seq_get_fast_slice_indexes(self_len, index, &slice)) {
- assert(0);
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_NotImplementedError,
+ "Only slices with step=1 (aka None) are supported"));
}
return str_new(type, self_data + slice.start, slice.stop - slice.start);
}
diff --git a/py/objtuple.c b/py/objtuple.c
index ffc94b5d27..c0a33dad7e 100644
--- a/py/objtuple.c
+++ b/py/objtuple.c
@@ -165,7 +165,8 @@ mp_obj_t mp_obj_tuple_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
mp_bound_slice_t slice;
if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice)) {
- assert(0);
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_NotImplementedError,
+ "Only slices with step=1 (aka None) are supported"));
}
mp_obj_tuple_t *res = mp_obj_new_tuple(slice.stop - slice.start, NULL);
mp_seq_copy(res->items, self->items + slice.start, res->len, mp_obj_t);
diff --git a/py/sequence.c b/py/sequence.c
index db5eed4c8e..c940d9f69f 100644
--- a/py/sequence.c
+++ b/py/sequence.c
@@ -95,8 +95,6 @@ bool mp_seq_get_fast_slice_indexes(machine_uint_t len, mp_obj_t slice, mp_bound_
indexes->stop = stop;
if (ostep != mp_const_none && ostep != MP_OBJ_NEW_SMALL_INT(1)) {
- nlr_raise(mp_obj_new_exception_msg(&mp_type_NotImplementedError,
- "Only slices with step=1 (aka None) are supported"));
indexes->step = MP_OBJ_SMALL_INT_VALUE(ostep);
return false;
}
@@ -104,6 +102,27 @@ bool mp_seq_get_fast_slice_indexes(machine_uint_t len, mp_obj_t slice, mp_bound_
return true;
}
+mp_obj_t mp_seq_extract_slice(uint len, const mp_obj_t *seq, mp_bound_slice_t *indexes) {
+ machine_int_t start = indexes->start, stop = indexes->stop;
+ machine_int_t step = indexes->step;
+
+ mp_obj_t res = mp_obj_new_list(0, NULL);
+
+ if (step < 0) {
+ stop--;
+ while (start <= stop) {
+ mp_obj_list_append(res, seq[stop]);
+ stop += step;
+ }
+ } else {
+ while (start < stop) {
+ mp_obj_list_append(res, seq[start]);
+ start += step;
+ }
+ }
+ return res;
+}
+
// Special-case comparison function for sequences of bytes
// Don't pass MP_BINARY_OP_NOT_EQUAL here
bool mp_seq_cmp_bytes(int op, const byte *data1, uint len1, const byte *data2, uint len2) {
diff --git a/tests/basics/list_slice_3arg.py b/tests/basics/list_slice_3arg.py
new file mode 100644
index 0000000000..1320e79236
--- /dev/null
+++ b/tests/basics/list_slice_3arg.py
@@ -0,0 +1,4 @@
+x = list(range(10))
+print(x[::-1])
+print(x[::2])
+print(x[::-2])