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+
61114STATIC 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
77135const 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+
95178void 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 );
0 commit comments