Fix implementation of range slicing

closes #1373
This commit is contained in:
Daniel Alley
2019-09-22 19:50:31 -04:00
parent 36efb50563
commit ecb3cd4df5

View File

@@ -320,62 +320,70 @@ impl PyRange {
fn getitem(&self, subscript: RangeIndex, vm: &VirtualMachine) -> PyResult {
match subscript {
RangeIndex::Slice(slice) => {
let start = self.start.as_bigint();
let stop = self.stop.as_bigint();
let step = self.step.as_bigint();
let range_start = self.start.as_bigint();
let range_step = self.step.as_bigint();
let _tmp_len = self.length();
let range_length = _tmp_len.as_bigint();
let new_start = if let Some(int) = slice.start_index(vm)? {
let int = ∫
if let Some(i) = self.get(int) {
PyInt::new(i).into_ref(vm)
} else if start < stop {
if stop <= int {
self.stop.clone()
} else {
self.start.clone()
}
} else if int < stop {
self.stop.clone()
} else {
self.start.clone()
}
} else {
self.start.clone()
};
let new_end = if let Some(int) = slice.stop_index(vm)? {
let int = &int;
if let Some(i) = self.get(int) {
PyInt::new(i).into_ref(vm)
} else if start < stop {
if int < start {
self.start.clone()
} else {
self.stop.clone()
}
} else if start < int {
self.start.clone()
} else {
self.stop.clone()
}
} else {
self.stop.clone()
};
let new_step = if let Some(int) = slice.step_index(vm)? {
if int.is_zero() {
let substep = if let Some(slice_step) = slice.step_index(vm)? {
if slice_step.is_zero() {
return Err(vm.new_value_error("slice step cannot be zero".to_string()));
}
slice_step
} else {
BigInt::one()
};
let negative_step = substep.is_negative();
let lower_bound = if negative_step { -BigInt::one() } else { BigInt::zero() };
let upper_bound = if negative_step { &lower_bound + range_length } else { range_length.clone() };
let substart = if let Some(slice_start) = slice.start_index(vm)? {
if slice_start.is_negative() {
let tmp = slice_start + range_length;
if tmp < lower_bound {
lower_bound.clone()
} else {
tmp.clone()
}
} else {
PyInt::new(int * self.step.as_bigint()).into_ref(vm)
if slice_start > upper_bound {
upper_bound.clone()
} else {
slice_start.clone()
}
}
} else {
self.step.clone()
if negative_step { upper_bound.clone() } else { lower_bound.clone() }
};
let substop = if let Some(slice_stop) = slice.stop_index(vm)? {
if slice_stop.is_negative() {
let tmp = slice_stop + range_length;
if tmp < lower_bound {
lower_bound.clone()
} else {
tmp.clone()
}
} else {
if slice_stop > upper_bound {
upper_bound.clone()
} else {
slice_stop.clone()
}
}
} else {
if negative_step { lower_bound.clone() } else { upper_bound.clone() }
};
let step = range_step * &substep;
let start = range_start + (&substart * range_step);
let stop = range_start + (&substop * range_step);
Ok(PyRange {
start: new_start,
stop: new_end,
step: new_step,
start: PyInt::new(start).into_ref(vm),
stop: PyInt::new(stop).into_ref(vm),
step: PyInt::new(step).into_ref(vm),
}
.into_ref(vm)
.into_object())