@@ -77,26 +77,32 @@ impl PyRange {
77
77
let start = self . start . as_bigint ( ) ;
78
78
let stop = self . stop . as_bigint ( ) ;
79
79
let step = self . step . as_bigint ( ) ;
80
+ let index = index. clone ( ) ;
81
+ if self . is_empty ( ) {
82
+ return None ;
83
+ }
84
+
85
+ let length = if start < stop {
86
+ ( stop - start - 1 ) / step + 1
87
+ } else {
88
+ ( start - stop - 1 ) / ( -step) + 1
89
+ } ;
80
90
81
- let index = if * index < BigInt :: zero ( ) {
82
- let index = stop + index;
83
- if index < BigInt :: zero ( ) {
91
+ let index = if index < BigInt :: zero ( ) {
92
+ let new_index = & length + & index;
93
+ if new_index < BigInt :: zero ( ) {
84
94
return None ;
85
95
}
86
- index
96
+ length + index
87
97
} else {
88
- index. clone ( )
98
+ if length <= index {
99
+ return None ;
100
+ }
101
+ index
89
102
} ;
90
103
91
- let result = start + step * & index;
92
-
93
- if ( self . forward ( ) && !self . is_empty ( ) && result < * stop)
94
- || ( !self . forward ( ) && !self . is_empty ( ) && result > * stop)
95
- {
96
- Some ( result)
97
- } else {
98
- None
99
- }
104
+ let result = start + step * index;
105
+ Some ( result)
100
106
}
101
107
}
102
108
@@ -293,17 +299,23 @@ impl PyRange {
293
299
#[ pymethod( name = "__getitem__" ) ]
294
300
fn getitem ( & self , subscript : RangeIndex , vm : & VirtualMachine ) -> PyResult {
295
301
match subscript {
296
- RangeIndex :: Int ( index) => {
297
- if let Some ( value) = self . get ( index. as_bigint ( ) ) {
298
- Ok ( PyInt :: new ( value) . into_ref ( vm) . into_object ( ) )
299
- } else {
300
- Err ( vm. new_index_error ( "range object index out of range" . to_string ( ) ) )
301
- }
302
- }
303
302
RangeIndex :: Slice ( slice) => {
303
+ let start = self . start . as_bigint ( ) ;
304
+ let stop = self . stop . as_bigint ( ) ;
305
+ let step = self . step . as_bigint ( ) ;
306
+
304
307
let new_start = if let Some ( int) = slice. start_index ( vm) ? {
305
- if let Some ( i) = self . get ( & int) {
308
+ let int = & int;
309
+ if let Some ( i) = self . get ( int) {
306
310
PyInt :: new ( i) . into_ref ( vm)
311
+ } else if start < stop {
312
+ if stop <= int {
313
+ self . stop . clone ( )
314
+ } else {
315
+ self . start . clone ( )
316
+ }
317
+ } else if int < stop {
318
+ self . stop . clone ( )
307
319
} else {
308
320
self . start . clone ( )
309
321
}
@@ -312,8 +324,17 @@ impl PyRange {
312
324
} ;
313
325
314
326
let new_end = if let Some ( int) = slice. stop_index ( vm) ? {
315
- if let Some ( i) = self . get ( & int) {
327
+ let int = & int;
328
+ if let Some ( i) = self . get ( int) {
316
329
PyInt :: new ( i) . into_ref ( vm)
330
+ } else if start < stop {
331
+ if int < start {
332
+ self . start . clone ( )
333
+ } else {
334
+ self . stop . clone ( )
335
+ }
336
+ } else if start < int {
337
+ self . start . clone ( )
317
338
} else {
318
339
self . stop . clone ( )
319
340
}
@@ -322,7 +343,11 @@ impl PyRange {
322
343
} ;
323
344
324
345
let new_step = if let Some ( int) = slice. step_index ( vm) ? {
325
- PyInt :: new ( int * self . step . as_bigint ( ) ) . into_ref ( vm)
346
+ if step. is_zero ( ) {
347
+ return Err ( vm. new_value_error ( "slice step cannot be zero" . to_string ( ) ) ) ;
348
+ } else {
349
+ PyInt :: new ( int * self . step . as_bigint ( ) ) . into_ref ( vm)
350
+ }
326
351
} else {
327
352
self . step . clone ( )
328
353
} ;
@@ -335,6 +360,13 @@ impl PyRange {
335
360
. into_ref ( vm)
336
361
. into_object ( ) )
337
362
}
363
+ RangeIndex :: Int ( index) => {
364
+ if let Some ( value) = self . get ( index. as_bigint ( ) ) {
365
+ Ok ( PyInt :: new ( value) . into_ref ( vm) . into_object ( ) )
366
+ } else {
367
+ Err ( vm. new_index_error ( "range object index out of range" . to_string ( ) ) )
368
+ }
369
+ }
338
370
}
339
371
}
340
372
0 commit comments