Skip to content

Commit e0ef7e3

Browse files
committed
Add indices() support to slice.
1 parent 12fa5b3 commit e0ef7e3

3 files changed

Lines changed: 116 additions & 0 deletions

File tree

atmel-samd/mpconfigport.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#define MICROPY_PY_BUILTINS_REVERSED (0)
4444
#define MICROPY_PY_BUILTINS_SET (1)
4545
#define MICROPY_PY_BUILTINS_SLICE (1)
46+
#define MICROPY_PY_BUILTINS_SLICE_ATTRS (1)
4647
#define MICROPY_PY_BUILTINS_PROPERTY (1)
4748
#define MICROPY_PY_BUILTINS_MIN_MAX (1)
4849
#define MICROPY_PY___FILE__ (1)

py/objslice.c

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929

3030
#include "py/nlr.h"
3131
#include "py/obj.h"
32+
#include "py/runtime.h"
3233
#include "py/runtime0.h"
3334

3435
/******************************************************************************/
@@ -58,6 +59,58 @@ STATIC void slice_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t
5859
}
5960

6061
#if MICROPY_PY_BUILTINS_SLICE_ATTRS
62+
STATIC mp_obj_t slice_indices(mp_obj_t self_in, mp_obj_t length_obj) {
63+
mp_obj_slice_t *self = MP_OBJ_TO_PTR(self_in);
64+
if (!MP_OBJ_IS_SMALL_INT(length_obj)) {
65+
mp_raise_TypeError("Length must be an int");
66+
}
67+
68+
int length = MP_OBJ_SMALL_INT_VALUE(length_obj);
69+
if (length < 0) {
70+
mp_raise_ValueError("Length must be non-negative");
71+
}
72+
73+
mp_obj_t indices[3] = {MP_OBJ_NEW_SMALL_INT(0), length_obj, MP_OBJ_NEW_SMALL_INT(1)};
74+
mp_obj_t slice[2] = {self->start, self->stop};
75+
76+
int step = 1;
77+
if (self->step != mp_const_none) {
78+
indices[2] = self->step;
79+
step = MP_OBJ_SMALL_INT_VALUE(self->step);
80+
if (step < 0) {
81+
indices[0] = MP_OBJ_NEW_SMALL_INT(length - 1);
82+
indices[1] = MP_OBJ_NEW_SMALL_INT(-1);
83+
}
84+
if (step == 0) {
85+
mp_raise_ValueError("slice step cannot be zero");
86+
}
87+
}
88+
for (int i = 0; i < 2; i++) {
89+
if (slice[i] == mp_const_none) {
90+
continue;
91+
}
92+
int value = MP_OBJ_SMALL_INT_VALUE(slice[i]);
93+
if (value < 0) {
94+
value += length;
95+
}
96+
if (value < 0) {
97+
if (step > 0) {
98+
value = 0;
99+
} else if (step < 0) {
100+
value = -1;
101+
}
102+
} else if (value > length) {
103+
value = length;
104+
}
105+
indices[i] = MP_OBJ_NEW_SMALL_INT(value);
106+
}
107+
108+
mp_obj_t tuple = mp_obj_new_tuple(3, indices);
109+
110+
return tuple;
111+
}
112+
MP_DEFINE_CONST_FUN_OBJ_2(slice_indices_obj, slice_indices);
113+
61114
STATIC void slice_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
62115
if (dest[0] != MP_OBJ_NULL) {
63116
// not load attribute
@@ -70,15 +123,21 @@ STATIC void slice_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
70123
dest[0] = self->stop;
71124
} else if (attr == MP_QSTR_step) {
72125
dest[0] = self->step;
126+
} else if (attr == MP_QSTR_indices) {
127+
mp_convert_member_lookup(self_in, self->base.type, (mp_obj_t) &slice_indices_obj, dest);
73128
}
74129
}
130+
131+
STATIC mp_obj_t slice_make_new(const mp_obj_type_t *type,
132+
mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args);
75133
#endif
76134

77135
const mp_obj_type_t mp_type_slice = {
78136
{ &mp_type_type },
79137
.name = MP_QSTR_slice,
80138
.print = slice_print,
81139
#if MICROPY_PY_BUILTINS_SLICE_ATTRS
140+
.make_new = slice_make_new,
82141
.attr = slice_attr,
83142
#endif
84143
};
@@ -92,6 +151,30 @@ mp_obj_t mp_obj_new_slice(mp_obj_t ostart, mp_obj_t ostop, mp_obj_t ostep) {
92151
return MP_OBJ_FROM_PTR(o);
93152
}
94153

154+
#if MICROPY_PY_BUILTINS_SLICE_ATTRS
155+
STATIC mp_obj_t slice_make_new(const mp_obj_type_t *type,
156+
mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
157+
// check number of arguments
158+
mp_arg_check_num(n_args, n_kw, 1, 3, false);
159+
160+
// 1st argument is the pin
161+
mp_obj_t start = mp_const_none;
162+
mp_obj_t stop = mp_const_none;
163+
mp_obj_t step = mp_const_none;
164+
if (n_args == 1) {
165+
stop = args[0];
166+
} else {
167+
start = args[0];
168+
stop = args[1];
169+
if (n_args == 3) {
170+
step = args[2];
171+
}
172+
}
173+
174+
return mp_obj_new_slice(start, stop, step);
175+
}
176+
#endif
177+
95178
void mp_obj_slice_get(mp_obj_t self_in, mp_obj_t *start, mp_obj_t *stop, mp_obj_t *step) {
96179
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_slice));
97180
mp_obj_slice_t *self = MP_OBJ_TO_PTR(self_in);

tests/basics/builtin_slice.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,35 @@ def __getitem__(self, idx):
99

1010
# check type
1111
print(type(s) is slice)
12+
13+
s = slice(10)
14+
print(s)
15+
16+
s = slice(0, 4)
17+
print(s)
18+
19+
s = slice(0, 4, 2)
20+
print(s)
21+
22+
s = slice(-1)
23+
print(s)
24+
print(s.indices(10))
25+
26+
s = slice(-5, -1)
27+
print(s)
28+
print(s.indices(10))
29+
30+
s = slice(-100, -2, -1)
31+
print(s)
32+
print(s.indices(10))
33+
34+
s = slice(None, None, -2)
35+
print(s)
36+
print(s.indices(10))
37+
38+
s = slice(-100, -2, 0)
39+
print(s)
40+
try:
41+
print(s.indices(10))
42+
except Exception as e:
43+
print(e)

0 commit comments

Comments
 (0)