summaryrefslogtreecommitdiffstatshomepage
path: root/py
diff options
context:
space:
mode:
Diffstat (limited to 'py')
-rw-r--r--py/obj.h2
-rw-r--r--py/objslice.c45
-rw-r--r--py/objstr.c3
-rw-r--r--py/sequence.c20
-rw-r--r--py/vm.c10
5 files changed, 42 insertions, 38 deletions
diff --git a/py/obj.h b/py/obj.h
index 2a9ed3acd3..5f2b9d3bef 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -517,7 +517,7 @@ mp_map_t *mp_obj_dict_get_map(mp_obj_t self_in);
void mp_obj_set_store(mp_obj_t self_in, mp_obj_t item);
// slice
-void mp_obj_slice_get(mp_obj_t self_in, machine_int_t *start, machine_int_t *stop, machine_int_t *step);
+void mp_obj_slice_get(mp_obj_t self_in, mp_obj_t *start, mp_obj_t *stop, mp_obj_t *step);
// array
uint mp_obj_array_len(mp_obj_t self_in);
diff --git a/py/objslice.c b/py/objslice.c
index 8fe65de1f8..dfd070f8d0 100644
--- a/py/objslice.c
+++ b/py/objslice.c
@@ -62,13 +62,20 @@ const mp_obj_ellipsis_t mp_const_ellipsis_obj = {{&mp_type_ellipsis}};
// CPython supports 3rd arg (step), plus args can be arbitrary Python objects.
typedef struct _mp_obj_slice_t {
mp_obj_base_t base;
- machine_int_t start;
- machine_int_t stop;
+ mp_obj_t start;
+ mp_obj_t stop;
+ mp_obj_t step;
} mp_obj_slice_t;
void slice_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) {
mp_obj_slice_t *o = o_in;
- print(env, "slice(" INT_FMT ", " INT_FMT ")", o->start, o->stop);
+ print(env, "slice(");
+ mp_obj_print_helper(print, env, o->start, PRINT_REPR);
+ print(env, ", ");
+ mp_obj_print_helper(print, env, o->stop, PRINT_REPR);
+ print(env, ", ");
+ mp_obj_print_helper(print, env, o->step, PRINT_REPR);
+ print(env, ")");
}
const mp_obj_type_t mp_type_slice = {
@@ -77,39 +84,21 @@ const mp_obj_type_t mp_type_slice = {
.print = slice_print,
};
-// TODO: Make sure to handle "empty" values, which are signified by None in CPython
mp_obj_t mp_obj_new_slice(mp_obj_t ostart, mp_obj_t ostop, mp_obj_t ostep) {
- assert(ostep == NULL);
- machine_int_t start = 0, stop = 0;
- if (ostart != mp_const_none) {
- start = mp_obj_get_int(ostart);
- }
- if (ostop != mp_const_none) {
- stop = mp_obj_get_int(ostop);
- if (stop == 0) {
- // [x:0] is a special case - in our slice object, stop = 0 means
- // "end of sequence". Fortunately, [x:0] is an empty seqence for
- // any x (including negative). [x:x] is also always empty sequence.
- // but x also can be 0. But note that b""[x:x] is b"" for any x (i.e.
- // no IndexError, at least in Python 3.3.3). So, we just use -1's to
- // signify that. -1 is catchy "special" number in case someone will
- // try to print [x:0] slice ever.
- start = stop = -1;
- }
- }
- mp_obj_slice_t *o = m_new(mp_obj_slice_t, 1);
+ mp_obj_slice_t *o = m_new_obj(mp_obj_slice_t);
o->base.type = &mp_type_slice;
- o->start = start;
- o->stop = stop;
- return (mp_obj_t)o;
+ o->start = ostart;
+ o->stop = ostop;
+ o->step = ostep;
+ return o;
}
-void mp_obj_slice_get(mp_obj_t self_in, machine_int_t *start, machine_int_t *stop, machine_int_t *step) {
+void mp_obj_slice_get(mp_obj_t self_in, mp_obj_t *start, mp_obj_t *stop, mp_obj_t *step) {
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_slice));
mp_obj_slice_t *self = self_in;
*start = self->start;
*stop = self->stop;
- *step = 1;
+ *step = self->step;
}
#endif
diff --git a/py/objstr.c b/py/objstr.c
index 4ec1034e1e..67de2ce804 100644
--- a/py/objstr.c
+++ b/py/objstr.c
@@ -355,6 +355,9 @@ STATIC mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
if (!mp_seq_get_fast_slice_indexes(self_len, index, &start, &stop)) {
assert(0);
}
+ if (start >= stop) {
+ return MP_OBJ_NEW_QSTR(MP_QSTR_);
+ }
return str_new(type, self_data + start, stop - start);
}
#endif
diff --git a/py/sequence.c b/py/sequence.c
index 966adaac03..2c1f6a836c 100644
--- a/py/sequence.c
+++ b/py/sequence.c
@@ -52,12 +52,24 @@ void mp_seq_multiply(const void *items, uint item_sz, uint len, uint times, void
}
bool mp_seq_get_fast_slice_indexes(machine_uint_t len, mp_obj_t slice, machine_uint_t *begin, machine_uint_t *end) {
- machine_int_t start, stop, step;
- mp_obj_slice_get(slice, &start, &stop, &step);
- if (step != 1) {
+ mp_obj_t ostart, ostop, ostep;
+ machine_int_t start, stop;
+ mp_obj_slice_get(slice, &ostart, &ostop, &ostep);
+ if (ostep != mp_const_none && ostep != MP_OBJ_NEW_SMALL_INT(1)) {
return false;
}
+ if (ostart == mp_const_none) {
+ start = 0;
+ } else {
+ start = MP_OBJ_SMALL_INT_VALUE(ostart);
+ }
+ if (ostop == mp_const_none) {
+ stop = len;
+ } else {
+ stop = MP_OBJ_SMALL_INT_VALUE(ostop);
+ }
+
// Unlike subscription, out-of-bounds slice indexes are never error
if (start < 0) {
start = len + start;
@@ -67,7 +79,7 @@ bool mp_seq_get_fast_slice_indexes(machine_uint_t len, mp_obj_t slice, machine_u
} else if (start > len) {
start = len;
}
- if (stop <= 0) {
+ if (stop < 0) {
stop = len + stop;
// CPython returns empty sequence in such case
if (stop < 0) {
diff --git a/py/vm.c b/py/vm.c
index 1f3f693c97..608c9096d9 100644
--- a/py/vm.c
+++ b/py/vm.c
@@ -768,12 +768,12 @@ unwind_jump:
if (unum == 2) {
obj2 = POP();
obj1 = TOP();
- SET_TOP(mp_obj_new_slice(obj1, obj2, NULL));
+ SET_TOP(mp_obj_new_slice(obj1, obj2, mp_const_none));
} else {
- obj1 = mp_obj_new_exception_msg(&mp_type_NotImplementedError, "3-argument slice is not supported");
- nlr_pop();
- fastn[0] = obj1;
- return MP_VM_RETURN_EXCEPTION;
+ mp_obj_t obj3 = POP();
+ obj2 = POP();
+ obj1 = TOP();
+ SET_TOP(mp_obj_new_slice(obj1, obj2, obj3));
}
DISPATCH();
#endif