From 66b557692b9994f26cb9ea14791eb8b88f7e8269 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Sat, 27 Feb 2021 15:27:40 +0800 Subject: [PATCH] Allow negative range step. --- CHANGELOG.md | 10 ++++++++++ src/packages/iter_basic.rs | 33 ++++++++++++++++++++++++++++----- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f0bbd46..2a2b88cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,16 @@ Bug fixes * Errors in native Rust functions now contain the correct function call positions. +Breaking changes +---------------- + +* Zero step in the `range` function now raises an error instead of creating an infinite stream. + +Enhancements +------------ + +* `range` function now supports negative step and decreasing streams (i.e. to < from). + Version 0.19.13 =============== diff --git a/src/packages/iter_basic.rs b/src/packages/iter_basic.rs index 51eda3dd..9d37c2c8 100644 --- a/src/packages/iter_basic.rs +++ b/src/packages/iter_basic.rs @@ -3,7 +3,7 @@ use crate::stdlib::{ boxed::Box, ops::{Add, Range}, }; -use crate::{def_package, EvalAltResult, INT}; +use crate::{def_package, EvalAltResult, Position, INT}; fn get_range(from: T, to: T) -> Result, Box> { Ok(from..to) @@ -16,6 +16,23 @@ where for<'a> &'a T: Add<&'a T, Output = T>, T: Variant + Clone + PartialOrd; +impl StepRange +where + for<'a> &'a T: Add<&'a T, Output = T>, + T: Variant + Clone + PartialOrd, +{ + pub fn new(from: T, to: T, step: T) -> Result> { + if &from + &step == from { + Err(Box::new(EvalAltResult::ErrorArithmetic( + "invalid step value".to_string(), + Position::NONE, + ))) + } else { + Ok(Self(from, to, step)) + } + } +} + impl Iterator for StepRange where for<'a> &'a T: Add<&'a T, Output = T>, @@ -24,12 +41,18 @@ where type Item = T; fn next(&mut self) -> Option { - if self.0 < self.1 { + if self.0 == self.1 { + None + } else if self.0 < self.1 { let v = self.0.clone(); - self.0 = self.0.add(&self.2); + let n = self.0.add(&self.2); + self.0 = if n >= self.1 { self.1.clone() } else { n }; Some(v) } else { - None + let v = self.0.clone(); + let n = self.0.add(&self.2); + self.0 = if n <= self.1 { self.1.clone() } else { n }; + Some(v) } } } @@ -39,7 +62,7 @@ where for<'a> &'a T: Add<&'a T, Output = T>, T: Variant + Clone + PartialOrd, { - Ok(StepRange::(from, to, step)) + StepRange::::new(from, to, step) } macro_rules! reg_range {