From 41d3709db1a29aa21a537dd414e93782975bf815 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Sat, 24 Apr 2021 15:53:02 +0800 Subject: [PATCH] Fix decimal build. --- src/packages/iter_basic.rs | 95 ++++++++++++++++------- tests/for.rs | 150 ++++++++++++++++++++++++++++++++----- 2 files changed, 203 insertions(+), 42 deletions(-) diff --git a/src/packages/iter_basic.rs b/src/packages/iter_basic.rs index 961f45e4..42a984b8 100644 --- a/src/packages/iter_basic.rs +++ b/src/packages/iter_basic.rs @@ -5,24 +5,20 @@ use std::ops::Range; use std::prelude::v1::*; #[cfg(not(feature = "unchecked"))] -use num_traits::{CheckedAdd as Add, CheckedSub as Sub}; +use num_traits::{CheckedAdd, CheckedSub}; #[cfg(feature = "unchecked")] use std::ops::{Add, Sub}; -fn get_range(from: T, to: T) -> Result, Box> { - Ok(from..to) -} - // Register range function with step #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] struct StepRange(T, T, T) where - T: Variant + Copy + PartialOrd + Add + Sub; + T: Variant + Copy + PartialOrd + CheckedAdd + CheckedSub; impl StepRange where - T: Variant + Copy + PartialOrd + Add + Sub, + T: Variant + Copy + PartialOrd + CheckedAdd + CheckedSub, { pub fn new(from: T, to: T, step: T) -> Result> { #[cfg(not(feature = "unchecked"))] @@ -47,7 +43,7 @@ where impl Iterator for StepRange where - T: Variant + Copy + PartialOrd + Add + Sub, + T: Variant + Copy + PartialOrd + CheckedAdd + CheckedSub, { type Item = T; @@ -130,18 +126,11 @@ where } } -fn get_step_range(from: T, to: T, step: T) -> Result, Box> -where - T: Variant + Copy + PartialOrd + Add + Sub, -{ - StepRange::::new(from, to, step) -} - macro_rules! reg_range { ($lib:ident | $x:expr => $( $y:ty ),*) => { $( $lib.set_iterator::>(); - let _hash = $lib.set_native_fn($x, get_range::<$y>); + let _hash = $lib.set_native_fn($x, |from: $y, to: $y| Ok(from..to)); #[cfg(feature = "metadata")] $lib.update_fn_metadata(_hash, &[ @@ -154,7 +143,7 @@ macro_rules! reg_range { ($lib:ident | step $x:expr => $( $y:ty ),*) => { $( $lib.set_iterator::>(); - let _hash = $lib.set_native_fn($x, get_step_range::<$y>); + let _hash = $lib.set_native_fn($x, |from: $y, to: $y, step: $y| StepRange::new(from, to, step)); #[cfg(feature = "metadata")] $lib.update_fn_metadata(_hash, &[ @@ -192,12 +181,72 @@ def_package!(crate:BasicIteratorPackage:"Basic range iterators.", lib, { } } + #[cfg(not(feature = "no_float"))] + { + use crate::FLOAT; + + #[derive(Debug, Clone, Copy, PartialEq)] + struct StepFloatRange(FLOAT, FLOAT, FLOAT); + + impl StepFloatRange { + pub fn new(from: FLOAT, to: FLOAT, step: FLOAT) -> Result> { + #[cfg(not(feature = "unchecked"))] + if step == 0.0 { + return EvalAltResult::ErrorInFunctionCall("range".to_string(), "".to_string(), + Box::new(EvalAltResult::ErrorArithmetic("step value cannot be zero".to_string(), crate::Position::NONE)), + crate::Position::NONE, + ).into(); + } + + Ok(Self(from, to, step)) + } + } + + impl Iterator for StepFloatRange { + type Item = FLOAT; + + fn next(&mut self) -> Option { + if self.0 == self.1 { + None + } else if self.0 < self.1 { + #[cfg(not(feature = "unchecked"))] + if self.2 < 0.0 { + return None; + } + + let v = self.0; + let n = self.0 + self.2; + + self.0 = if n >= self.1 { self.1 } else { n }; + Some(v) + } else { + #[cfg(not(feature = "unchecked"))] + if self.2 > 0.0 { + return None; + } + + let v = self.0; + let n = self.0 + self.2; + + self.0 = if n <= self.1 { self.1 } else { n }; + Some(v) + } + } + } + + impl std::iter::FusedIterator for StepFloatRange {} + + lib.set_iterator::(); + + let _hash = lib.set_native_fn("range", |from, to, step| StepFloatRange::new(from, to, step)); + #[cfg(feature = "metadata")] + lib.update_fn_metadata(_hash, &["from: FLOAT", "to: FLOAT", "step: FLOAT", "Iterator"]); + } + #[cfg(feature = "decimal")] { - use rust_decimal::{ - prelude::{One, Zero}, - Decimal, - }; + use rust_decimal::Decimal; + use num_traits::Zero; #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] struct StepDecimalRange(Decimal, Decimal, Decimal); @@ -252,10 +301,6 @@ def_package!(crate:BasicIteratorPackage:"Basic range iterators.", lib, { lib.set_iterator::(); - let _hash = lib.set_native_fn("range", |from, to| StepDecimalRange::new(from, to, Decimal::one())); - #[cfg(feature = "metadata")] - lib.update_fn_metadata(_hash, &["from: Decimal", "to: Decimal", "Iterator"]); - let _hash = lib.set_native_fn("range", |from, to, step| StepDecimalRange::new(from, to, step)); #[cfg(feature = "metadata")] lib.update_fn_metadata(_hash, &["from: Decimal", "to: Decimal", "step: Decimal", "Iterator"]); diff --git a/tests/for.rs b/tests/for.rs index 3118b8a7..381809d6 100644 --- a/tests/for.rs +++ b/tests/for.rs @@ -1,31 +1,52 @@ use rhai::{Engine, EvalAltResult, Module, INT}; -#[cfg(not(feature = "no_index"))] +#[cfg(not(feature = "no_float"))] +use rhai::FLOAT; + +#[cfg(feature = "decimal")] +#[cfg(not(feature = "no_float"))] +use rust_decimal::Decimal; + #[test] fn test_for() -> Result<(), Box> { let engine = Engine::new(); - let script = " - let sum1 = 0; - let sum2 = 0; - let inputs = [1, 2, 3, 4, 5]; + #[cfg(not(feature = "no_index"))] + assert_eq!( + engine.eval::( + " + let sum1 = 0; + let sum2 = 0; + let inputs = [1, 2, 3, 4, 5]; - for x in inputs { - sum1 += x; - } + for x in inputs { + sum1 += x; + } - for x in range(1, 6) { - sum2 += x; - } + for x in range(1, 6) { + sum2 += x; + } - for x in range(1, 6, 3) { - sum2 += x; - } + for x in range(1, 6, 3) { + sum2 += x; + } - sum1 + sum2 - "; + sum1 + sum2 + " + )?, + 35 + ); - assert_eq!(engine.eval::(script)?, 35); + assert_eq!( + engine.eval::( + " + let sum = 0; + for x in range(1, 10) { sum += x; } + sum + " + )?, + 45 + ); assert_eq!( engine.eval::( @@ -71,6 +92,101 @@ fn test_for() -> Result<(), Box> { 30 ); + #[cfg(not(feature = "no_float"))] + { + assert_eq!( + engine.eval::( + " + let sum = 0.0; + for x in range(1.0, 10.0, 2.0) { sum += x; } + sum + " + )?, + 25.0 + ); + + assert_eq!( + engine.eval::( + " + let sum = 0.0; + for x in range(10.0, 1.0, 2.0) { sum += x; } + sum + " + )?, + 0.0 + ); + + assert_eq!( + engine.eval::( + " + let sum = 0.0; + for x in range(1.0, 10.0, -2.0) { sum += x; } + sum + " + )?, + 0.0 + ); + + assert_eq!( + engine.eval::( + " + let sum = 0.0; + for x in range(10.0, 1.0, -2.0) { sum += x; } + sum + " + )?, + 30.0 + ); + } + + #[cfg(not(feature = "no_float"))] + #[cfg(feature = "decimal")] + { + assert_eq!( + engine.eval::( + " + let sum = to_decimal(0); + for x in range(to_decimal(1), to_decimal(10), to_decimal(2)) { sum += x; } + sum + " + )?, + Decimal::from(25) + ); + + assert_eq!( + engine.eval::( + " + let sum = to_decimal(0); + for x in range(to_decimal(10), to_decimal(1), to_decimal(2)) { sum += x; } + sum + " + )?, + Decimal::from(0) + ); + + assert_eq!( + engine.eval::( + " + let sum = to_decimal(0); + for x in range(to_decimal(1), to_decimal(10), to_decimal(-2)) { sum += x; } + sum + " + )?, + Decimal::from(0) + ); + + assert_eq!( + engine.eval::( + " + let sum = to_decimal(0); + for x in range(to_decimal(10), to_decimal(1), to_decimal(-2)) { sum += x; } + sum + " + )?, + Decimal::from(30) + ); + } + Ok(()) }