@@ -79,18 +79,18 @@ 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
- if index < 0 {
89
- index += length
90
- }
90
+ index = computeNegativeIndex (index , r .Length )
91
91
92
- if index < 0 || index >= length {
93
- return nil , ExceptionNewf (TypeError , "range object index out of range" )
92
+ if index < 0 || index >= r . Length {
93
+ return nil , ExceptionNewf (IndexError , "range object index out of range" )
94
94
}
95
95
result := computeItem (r , index )
96
96
return result , nil
@@ -152,6 +152,69 @@ func computeRangeLength(start, stop, step Int) Int {
152
152
return res
153
153
}
154
154
155
+ func computeNegativeIndex (index , length Int ) Int {
156
+ if index < 0 {
157
+ index += length
158
+ }
159
+ return index
160
+ }
161
+
162
+ func computeBoundIndex (index , length Int ) Int {
163
+ if index < 0 {
164
+ index = 0
165
+ } else if index > length {
166
+ index = length
167
+ }
168
+ return index
169
+ }
170
+
171
+ func computeRangeSlice (r * Range , s * Slice ) (Object , error ) {
172
+ start , err := Index (s .Start )
173
+ if err != nil {
174
+ start = 0
175
+ }
176
+ stop , err := Index (s .Stop )
177
+ if err != nil {
178
+ stop = r .Length
179
+ }
180
+
181
+ step , err := Index (s .Step )
182
+ if err != nil {
183
+ step = 1
184
+ }
185
+ if step == 0 {
186
+ return nil , ExceptionNewf (ValueError , "slice step cannot be zero" )
187
+ }
188
+ start = computeNegativeIndex (start , r .Length )
189
+ stop = computeNegativeIndex (stop , r .Length )
190
+
191
+ start = computeBoundIndex (start , r .Length )
192
+ stop = computeBoundIndex (stop , r .Length )
193
+
194
+ startIndex := computeItem (r , start )
195
+ stopIndex := computeItem (r , stop )
196
+ stepIndex := step * r .Step
197
+
198
+ var sliceLength Int
199
+ if start < stop {
200
+ if stepIndex < 0 {
201
+ startIndex , stopIndex = stopIndex - 1 , startIndex - 1
202
+ }
203
+ } else {
204
+ if stepIndex < 0 {
205
+ startIndex , stopIndex = stopIndex + 1 , startIndex + 1
206
+ }
207
+ }
208
+ sliceLength = computeRangeLength (startIndex , stopIndex , stepIndex )
209
+
210
+ return & Range {
211
+ Start : startIndex ,
212
+ Stop : stopIndex ,
213
+ Step : stepIndex ,
214
+ Length : sliceLength ,
215
+ }, nil
216
+ }
217
+
155
218
// Check interface is satisfied
156
219
var _ I__getitem__ = (* Range )(nil )
157
220
var _ I__iter__ = (* Range )(nil )
0 commit comments