objlist: Implement support for arbitrary (3-arg) slices.

This commit is contained in:
Paul Sokolovsky 2014-05-25 22:12:56 +03:00
parent de4b9329f9
commit 5fd5af98d0
7 changed files with 33 additions and 6 deletions

View File

@ -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); 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_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_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 // 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_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) \ #define mp_seq_replace_slice_no_grow(dest, dest_len, beg, end, slice, slice_len, item_t) \

View File

@ -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; mp_bound_slice_t slice;
if (!mp_seq_get_fast_slice_indexes(o->len, index_in, &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); mp_obj_array_t *res = array_new(o->typecode, slice.stop - slice.start);
int sz = mp_binary_get_size('@', o->typecode, NULL); int sz = mp_binary_get_size('@', o->typecode, NULL);

View File

@ -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)) { if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
mp_bound_slice_t slice; mp_bound_slice_t slice;
if (!mp_seq_get_fast_slice_indexes(self->len, index, &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_obj_list_t *res = list_new(slice.stop - slice.start);
mp_seq_copy(res->items, self->items + slice.start, res->len, mp_obj_t); mp_seq_copy(res->items, self->items + slice.start, res->len, mp_obj_t);

View File

@ -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)) { if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
mp_bound_slice_t slice; mp_bound_slice_t slice;
if (!mp_seq_get_fast_slice_indexes(self_len, index, &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); return str_new(type, self_data + slice.start, slice.stop - slice.start);
} }

View File

@ -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)) { if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
mp_bound_slice_t slice; mp_bound_slice_t slice;
if (!mp_seq_get_fast_slice_indexes(self->len, index, &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_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); mp_seq_copy(res->items, self->items + slice.start, res->len, mp_obj_t);

View File

@ -95,8 +95,6 @@ bool mp_seq_get_fast_slice_indexes(machine_uint_t len, mp_obj_t slice, mp_bound_
indexes->stop = stop; indexes->stop = stop;
if (ostep != mp_const_none && ostep != MP_OBJ_NEW_SMALL_INT(1)) { 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); indexes->step = MP_OBJ_SMALL_INT_VALUE(ostep);
return false; 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; 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 // Special-case comparison function for sequences of bytes
// Don't pass MP_BINARY_OP_NOT_EQUAL here // 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) { bool mp_seq_cmp_bytes(int op, const byte *data1, uint len1, const byte *data2, uint len2) {

View File

@ -0,0 +1,4 @@
x = list(range(10))
print(x[::-1])
print(x[::2])
print(x[::-2])