@@ -79,17 +79,19 @@ func RangeNew(metatype *Type, args Tuple, kwargs StringDict) (Object, error) {
79
79
}
80
80
81
81
func (r * Range ) M__getitem__ (key Object ) (Object , error ) {
82
+ if slice , ok := key .(* Slice ); ok {
83
+ return computeRangeSlice (r , slice )
84
+ }
85
+
82
86
index , err := Index (key )
83
87
if err != nil {
84
88
return nil , err
85
89
}
86
- // TODO(corona10): Support slice case
87
- length := computeRangeLength (r .Start , r .Stop , r .Step )
88
90
if index < 0 {
89
- index += length
91
+ index += r . Length
90
92
}
91
93
92
- if index < 0 || index >= length {
94
+ if index < 0 || index >= r . Length {
93
95
return nil , ExceptionNewf (TypeError , "range object index out of range" )
94
96
}
95
97
result := computeItem (r , index )
@@ -152,6 +154,64 @@ func computeRangeLength(start, stop, step Int) Int {
152
154
return res
153
155
}
154
156
157
+ func computeRangeSlice (r * Range , s * Slice ) (Object , error ) {
158
+ length , err := r .Length .GoInt ()
159
+ if err != nil {
160
+ return nil , err
161
+ }
162
+
163
+ start , err := IndexInt (s .Start )
164
+ if err != nil {
165
+ start = 0
166
+ }
167
+ stop , err := IndexInt (s .Stop )
168
+ if err != nil {
169
+ stop = length
170
+ }
171
+
172
+ step , err := IndexInt (s .Step )
173
+ if err != nil {
174
+ step = 1
175
+ }
176
+ if step == 0 {
177
+ return nil , ExceptionNewf (ValueError , "slice step cannot be zero" )
178
+ }
179
+ if start < 0 {
180
+ start += length
181
+ }
182
+ if stop < 0 {
183
+ stop += length
184
+ }
185
+
186
+ if start < 0 {
187
+ start = 0
188
+ } else if start >= length {
189
+ start = length
190
+ }
191
+ if stop < 0 {
192
+ stop = 0
193
+ } else if stop >= length {
194
+ stop = length
195
+ }
196
+
197
+ startIndex := computeItem (r , Int (start ))
198
+ stopIndex := computeItem (r , Int (stop ))
199
+ stepIndex := Int (step ) * r .Step
200
+ var sliceLength Int
201
+ if startIndex < stopIndex {
202
+ sliceLength = (stopIndex - startIndex - 1 ) / stepIndex + 1
203
+ } else {
204
+ sliceLength = (stopIndex - startIndex + 1 ) / stepIndex + 1
205
+ }
206
+
207
+ return & Range {
208
+ Start : startIndex ,
209
+ Stop : stopIndex ,
210
+ Step : stepIndex ,
211
+ Length : sliceLength ,
212
+ }, nil
213
+ }
214
+
155
215
// Check interface is satisfied
156
216
var _ I__getitem__ = (* Range )(nil )
157
217
var _ I__iter__ = (* Range )(nil )
0 commit comments