py/sequence: Fix reverse slicing of lists.

This commit is contained in:
Fabio Utzig 2016-10-30 14:25:04 -02:00
parent e429daa572
commit 8908e505ce
2 changed files with 54 additions and 14 deletions

View File

@ -53,15 +53,35 @@ bool mp_seq_get_fast_slice_indexes(mp_uint_t len, mp_obj_t slice, mp_bound_slice
mp_int_t start, stop; mp_int_t start, stop;
mp_obj_slice_get(slice, &ostart, &ostop, &ostep); mp_obj_slice_get(slice, &ostart, &ostop, &ostep);
if (ostep != mp_const_none && ostep != MP_OBJ_NEW_SMALL_INT(1)) {
indexes->step = mp_obj_get_int(ostep);
if (indexes->step == 0) {
mp_raise_ValueError("slice step cannot be zero");
}
} else {
indexes->step = 1;
}
if (ostart == mp_const_none) { if (ostart == mp_const_none) {
start = 0; if (indexes->step > 0) {
start = 0;
} else {
start = len - 1;
}
} else { } else {
start = mp_obj_get_int(ostart); start = mp_obj_get_int(ostart);
} }
if (ostop == mp_const_none) { if (ostop == mp_const_none) {
stop = len; if (indexes->step > 0) {
stop = len;
} else {
stop = 0;
}
} else { } else {
stop = mp_obj_get_int(ostop); stop = mp_obj_get_int(ostop);
if (stop >= 0 && indexes->step < 0) {
stop += 1;
}
} }
// Unlike subscription, out-of-bounds slice indexes are never error // Unlike subscription, out-of-bounds slice indexes are never error
@ -70,29 +90,31 @@ bool mp_seq_get_fast_slice_indexes(mp_uint_t len, mp_obj_t slice, mp_bound_slice
if (start < 0) { if (start < 0) {
start = 0; start = 0;
} }
} else if ((mp_uint_t)start > len) { } else if (indexes->step > 0 && (mp_uint_t)start > len) {
start = len; start = len;
} else if (indexes->step < 0 && (mp_uint_t)start > len - 1) {
start = len - 1;
} }
if (stop < 0) { if (stop < 0) {
stop = len + stop; stop = len + stop;
if (indexes->step < 0) {
stop += 1;
}
} else if ((mp_uint_t)stop > len) { } else if ((mp_uint_t)stop > len) {
stop = len; stop = len;
} }
// CPython returns empty sequence in such case, or point for assignment is at start // CPython returns empty sequence in such case, or point for assignment is at start
if (start > stop) { if (indexes->step > 0 && start > stop) {
stop = start; stop = start;
} else if (indexes->step < 0 && start < stop) {
stop = start + 1;
} }
indexes->start = start; indexes->start = start;
indexes->stop = stop; indexes->stop = stop;
if (ostep != mp_const_none && ostep != MP_OBJ_NEW_SMALL_INT(1)) { return indexes->step == 1;
indexes->step = mp_obj_get_int(ostep);
return false;
}
indexes->step = 1;
return true;
} }
#endif #endif
@ -106,10 +128,9 @@ mp_obj_t mp_seq_extract_slice(mp_uint_t len, const mp_obj_t *seq, mp_bound_slice
mp_obj_t res = mp_obj_new_list(0, NULL); mp_obj_t res = mp_obj_new_list(0, NULL);
if (step < 0) { if (step < 0) {
stop--; while (start >= stop) {
while (start <= stop) { mp_obj_list_append(res, seq[start]);
mp_obj_list_append(res, seq[stop]); start += step;
stop += step;
} }
} else { } else {
while (start < stop) { while (start < stop) {

View File

@ -7,3 +7,22 @@ x = list(range(9))
print(x[::-1]) print(x[::-1])
print(x[::2]) print(x[::2])
print(x[::-2]) print(x[::-2])
x = list(range(5))
print(x[:0:-1])
print(x[:1:-1])
print(x[:2:-1])
print(x[0::-1])
print(x[1::-1])
print(x[2::-1])
x = list(range(5))
print(x[0:0:-1])
print(x[4:4:-1])
print(x[5:5:-1])
x = list(range(10))
print(x[-1:-1:-1])
print(x[-1:-2:-1])
print(x[-1:-11:-1])
print(x[-10:-11:-1])