Add reversed builtin and range.__reversed__

This commit is contained in:
Joey Hain
2019-02-08 00:19:14 -08:00
parent a4b99253c9
commit 1ebacafb00
4 changed files with 58 additions and 0 deletions

View File

@@ -76,12 +76,34 @@ impl RangeType {
None
}
}
#[inline]
pub fn reversed(&self) -> Self {
match self.step.sign() {
Sign::Plus => RangeType {
start: &self.end - 1,
end: &self.start - 1,
step: -&self.step,
},
Sign::Minus => RangeType {
start: &self.end + 1,
end: &self.start + 1,
step: -&self.step,
},
Sign::NoSign => unreachable!(),
}
}
}
pub fn init(context: &PyContext) {
let ref range_type = context.range_type;
context.set_attr(&range_type, "__new__", context.new_rustfunc(range_new));
context.set_attr(&range_type, "__iter__", context.new_rustfunc(range_iter));
context.set_attr(
&range_type,
"__reversed__",
context.new_rustfunc(range_reversed),
);
context.set_attr(&range_type, "__len__", context.new_rustfunc(range_len));
context.set_attr(
&range_type,
@@ -150,6 +172,23 @@ fn range_iter(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
))
}
fn range_reversed(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(zelf, Some(vm.ctx.range_type()))]);
let range = match zelf.borrow().payload {
PyObjectPayload::Range { ref range } => range.reversed(),
_ => unreachable!(),
};
Ok(PyObject::new(
PyObjectPayload::Iterator {
position: 0,
iterated_obj: PyObject::new(PyObjectPayload::Range { range }, vm.ctx.range_type()),
},
vm.ctx.iter_type(),
))
}
fn range_len(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(zelf, Some(vm.ctx.range_type()))]);