Skip to content

Commit ecb3cd4

Browse files
committed
Fix implementation of range slicing
closes RustPython#1373
1 parent 36efb50 commit ecb3cd4

File tree

1 file changed

+47
-39
lines changed

1 file changed

+47
-39
lines changed

vm/src/obj/objrange.rs

+47-39
Original file line numberDiff line numberDiff line change
@@ -320,62 +320,70 @@ impl PyRange {
320320
fn getitem(&self, subscript: RangeIndex, vm: &VirtualMachine) -> PyResult {
321321
match subscript {
322322
RangeIndex::Slice(slice) => {
323-
let start = self.start.as_bigint();
324-
let stop = self.stop.as_bigint();
325-
let step = self.step.as_bigint();
326-
327-
let new_start = if let Some(int) = slice.start_index(vm)? {
328-
let int = ∫
329-
if let Some(i) = self.get(int) {
330-
PyInt::new(i).into_ref(vm)
331-
} else if start < stop {
332-
if stop <= int {
333-
self.stop.clone()
334-
} else {
335-
self.start.clone()
336-
}
337-
} else if int < stop {
338-
self.stop.clone()
339-
} else {
340-
self.start.clone()
323+
let range_start = self.start.as_bigint();
324+
let range_step = self.step.as_bigint();
325+
let _tmp_len = self.length();
326+
let range_length = _tmp_len.as_bigint();
327+
328+
let substep = if let Some(slice_step) = slice.step_index(vm)? {
329+
if slice_step.is_zero() {
330+
return Err(vm.new_value_error("slice step cannot be zero".to_string()));
341331
}
332+
slice_step
342333
} else {
343-
self.start.clone()
334+
BigInt::one()
344335
};
345336

346-
let new_end = if let Some(int) = slice.stop_index(vm)? {
347-
let int = &int;
348-
if let Some(i) = self.get(int) {
349-
PyInt::new(i).into_ref(vm)
350-
} else if start < stop {
351-
if int < start {
352-
self.start.clone()
337+
let negative_step = substep.is_negative();
338+
let lower_bound = if negative_step { -BigInt::one() } else { BigInt::zero() };
339+
let upper_bound = if negative_step { &lower_bound + range_length } else { range_length.clone() };
340+
341+
let substart = if let Some(slice_start) = slice.start_index(vm)? {
342+
if slice_start.is_negative() {
343+
let tmp = slice_start + range_length;
344+
if tmp < lower_bound {
345+
lower_bound.clone()
353346
} else {
354-
self.stop.clone()
347+
tmp.clone()
355348
}
356-
} else if start < int {
357-
self.start.clone()
358349
} else {
359-
self.stop.clone()
350+
if slice_start > upper_bound {
351+
upper_bound.clone()
352+
} else {
353+
slice_start.clone()
354+
}
360355
}
361356
} else {
362-
self.stop.clone()
357+
if negative_step { upper_bound.clone() } else { lower_bound.clone() }
363358
};
364359

365-
let new_step = if let Some(int) = slice.step_index(vm)? {
366-
if int.is_zero() {
367-
return Err(vm.new_value_error("slice step cannot be zero".to_string()));
360+
let substop = if let Some(slice_stop) = slice.stop_index(vm)? {
361+
if slice_stop.is_negative() {
362+
let tmp = slice_stop + range_length;
363+
if tmp < lower_bound {
364+
lower_bound.clone()
365+
} else {
366+
tmp.clone()
367+
}
368368
} else {
369-
PyInt::new(int * self.step.as_bigint()).into_ref(vm)
369+
if slice_stop > upper_bound {
370+
upper_bound.clone()
371+
} else {
372+
slice_stop.clone()
373+
}
370374
}
371375
} else {
372-
self.step.clone()
376+
if negative_step { lower_bound.clone() } else { upper_bound.clone() }
373377
};
374378

379+
let step = range_step * &substep;
380+
let start = range_start + (&substart * range_step);
381+
let stop = range_start + (&substop * range_step);
382+
375383
Ok(PyRange {
376-
start: new_start,
377-
stop: new_end,
378-
step: new_step,
384+
start: PyInt::new(start).into_ref(vm),
385+
stop: PyInt::new(stop).into_ref(vm),
386+
step: PyInt::new(step).into_ref(vm),
379387
}
380388
.into_ref(vm)
381389
.into_object())

0 commit comments

Comments
 (0)