From ad018aaae3982ddc642693d4fcf1fb313ff6be3a Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Tue, 8 Nov 2022 23:17:31 +0800 Subject: [PATCH] Move FloatWrapper into types. --- src/ast/expr.rs | 126 +---------------------------------- src/ast/mod.rs | 3 - src/eval/target.rs | 20 +++--- src/lib.rs | 8 +-- src/packages/string_basic.rs | 8 +-- src/tokenizer.rs | 4 +- src/types/dynamic.rs | 8 +-- src/types/float.rs | 115 ++++++++++++++++++++++++++++++++ src/types/mod.rs | 3 + 9 files changed, 143 insertions(+), 152 deletions(-) create mode 100644 src/types/float.rs diff --git a/src/ast/expr.rs b/src/ast/expr.rs index 163fdbc9..1d39171d 100644 --- a/src/ast/expr.rs +++ b/src/ast/expr.rs @@ -20,16 +20,6 @@ use std::{ num::{NonZeroU64, NonZeroU8, NonZeroUsize}, }; -#[cfg(not(feature = "no_float"))] -use std::{ - hash::Hasher, - ops::{Deref, DerefMut}, - str::FromStr, -}; - -#[cfg(not(feature = "no_float"))] -use num_traits::float::FloatCore as Float; - /// _(internals)_ A binary expression. /// Exported under the `internals` feature only. #[derive(Debug, Clone, Hash)] @@ -273,120 +263,6 @@ impl FnCallExpr { } } -/// A type that wraps a floating-point number and implements [`Hash`]. -/// -/// Not available under `no_float`. -#[cfg(not(feature = "no_float"))] -#[derive(Clone, Copy, PartialEq, PartialOrd)] -pub struct FloatWrapper(F); - -#[cfg(not(feature = "no_float"))] -impl Hash for FloatWrapper { - #[inline] - fn hash(&self, state: &mut H) { - self.0.to_ne_bytes().hash(state); - } -} - -#[cfg(not(feature = "no_float"))] -impl AsRef for FloatWrapper { - #[inline(always)] - #[must_use] - fn as_ref(&self) -> &F { - &self.0 - } -} - -#[cfg(not(feature = "no_float"))] -impl AsMut for FloatWrapper { - #[inline(always)] - #[must_use] - fn as_mut(&mut self) -> &mut F { - &mut self.0 - } -} - -#[cfg(not(feature = "no_float"))] -impl Deref for FloatWrapper { - type Target = F; - - #[inline(always)] - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -#[cfg(not(feature = "no_float"))] -impl DerefMut for FloatWrapper { - #[inline(always)] - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } -} - -#[cfg(not(feature = "no_float"))] -impl fmt::Debug for FloatWrapper { - #[cold] - #[inline(never)] - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&self.0, f) - } -} - -#[cfg(not(feature = "no_float"))] -impl> fmt::Display for FloatWrapper { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let abs = self.0.abs(); - if abs.is_zero() { - f.write_str("0.0") - } else if abs > Self::MAX_NATURAL_FLOAT_FOR_DISPLAY.into() - || abs < Self::MIN_NATURAL_FLOAT_FOR_DISPLAY.into() - { - write!(f, "{:e}", self.0) - } else { - fmt::Display::fmt(&self.0, f)?; - if abs.fract().is_zero() { - f.write_str(".0")?; - } - Ok(()) - } - } -} - -#[cfg(not(feature = "no_float"))] -impl From for FloatWrapper { - #[inline(always)] - fn from(value: F) -> Self { - Self::new(value) - } -} - -#[cfg(not(feature = "no_float"))] -impl FromStr for FloatWrapper { - type Err = ::Err; - - #[inline] - fn from_str(s: &str) -> Result { - F::from_str(s).map(Into::into) - } -} - -#[cfg(not(feature = "no_float"))] -impl FloatWrapper { - /// Maximum floating-point number for natural display before switching to scientific notation. - pub const MAX_NATURAL_FLOAT_FOR_DISPLAY: f32 = 10_000_000_000_000.0; - - /// Minimum floating-point number for natural display before switching to scientific notation. - pub const MIN_NATURAL_FLOAT_FOR_DISPLAY: f32 = 0.000_000_000_000_1; - - /// Create a new [`FloatWrapper`]. - #[inline(always)] - #[must_use] - pub const fn new(value: F) -> Self { - Self(value) - } -} - /// _(internals)_ An expression sub-tree. /// Exported under the `internals` feature only. #[derive(Clone, Hash)] @@ -405,7 +281,7 @@ pub enum Expr { IntegerConstant(INT, Position), /// Floating-point constant. #[cfg(not(feature = "no_float"))] - FloatConstant(FloatWrapper, Position), + FloatConstant(crate::types::FloatWrapper, Position), /// Character constant. CharConstant(char, Position), /// [String][ImmutableString] constant. diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 00719a31..695f0786 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -26,9 +26,6 @@ pub use stmt::{ SwitchCasesCollection, TryCatchBlock, }; -#[cfg(not(feature = "no_float"))] -pub use expr::FloatWrapper; - /// _(internals)_ Placeholder for a script-defined function. /// Exported under the `internals` feature only. #[cfg(feature = "no_function")] diff --git a/src/eval/target.rs b/src/eval/target.rs index c48aa62a..64bfe3b3 100644 --- a/src/eval/target.rs +++ b/src/eval/target.rs @@ -9,11 +9,11 @@ use std::{ ops::{Deref, DerefMut}, }; -// Calculate an offset+len pair given an actual length of the underlying array. -// -// Negative starting positions count from the end. -// -// Values going over bounds are limited to the actual length. +/// Calculate an offset+len pair given an actual length of the underlying array. +/// +/// Negative starting positions count from the end. +/// +/// Values going over bounds are limited to the actual length. #[inline] #[allow(dead_code)] pub fn calc_offset_len(length: usize, start: crate::INT, len: crate::INT) -> (usize, usize) { @@ -41,11 +41,11 @@ pub fn calc_offset_len(length: usize, start: crate::INT, len: crate::INT) -> (us (start, len) } -// Calculate an offset+len pair given an actual length of the underlying array. -// -// Negative starting positions count from the end. -// -// Values going over bounds call the provided closure to return a default value or an error. +/// Calculate an offset+len pair given an actual length of the underlying array. +/// +/// Negative starting positions count from the end. +/// +/// Values going over bounds call the provided closure to return a default value or an error. #[inline] #[allow(dead_code)] pub fn calc_index( diff --git a/src/lib.rs b/src/lib.rs index 4fdb59f2..b4c33fc6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -299,6 +299,10 @@ pub type OptimizationLevel = (); #[cfg(feature = "internals")] pub use types::dynamic::{AccessMode, DynamicReadLock, DynamicWriteLock, Variant}; +#[cfg(feature = "internals")] +#[cfg(not(feature = "no_float"))] +pub use types::FloatWrapper; + #[cfg(feature = "internals")] pub use tokenizer::{get_next_token, parse_string_literal}; @@ -333,10 +337,6 @@ pub use ast::Namespace; #[cfg(not(feature = "no_function"))] pub use ast::EncapsulatedEnviron; -#[cfg(feature = "internals")] -#[cfg(not(feature = "no_float"))] -pub use ast::FloatWrapper; - #[cfg(feature = "internals")] pub use eval::{Caches, FnResolutionCache, FnResolutionCacheEntry, GlobalRuntimeState}; diff --git a/src/packages/string_basic.rs b/src/packages/string_basic.rs index a0763ada..d9b0d6c8 100644 --- a/src/packages/string_basic.rs +++ b/src/packages/string_basic.rs @@ -134,26 +134,26 @@ mod print_debug_functions { #[cfg(not(feature = "no_float"))] #[rhai_fn(name = "print", name = "to_string")] pub fn print_f64(number: f64) -> ImmutableString { - crate::ast::FloatWrapper::new(number).to_string().into() + crate::types::FloatWrapper::new(number).to_string().into() } /// Convert the value of `number` into a string. #[cfg(not(feature = "no_float"))] #[rhai_fn(name = "print", name = "to_string")] pub fn print_f32(number: f32) -> ImmutableString { - crate::ast::FloatWrapper::new(number).to_string().into() + crate::types::FloatWrapper::new(number).to_string().into() } /// Convert the value of `number` into a string. #[cfg(not(feature = "no_float"))] #[rhai_fn(name = "debug", name = "to_debug")] pub fn debug_f64(number: f64) -> ImmutableString { - let number = crate::ast::FloatWrapper::new(number); + let number = crate::types::FloatWrapper::new(number); format!("{number:?}").into() } /// Convert the value of `number` into a string. #[cfg(not(feature = "no_float"))] #[rhai_fn(name = "debug", name = "to_debug")] pub fn debug_f32(number: f32) -> ImmutableString { - let number = crate::ast::FloatWrapper::new(number); + let number = crate::types::FloatWrapper::new(number); format!("{number:?}").into() } diff --git a/src/tokenizer.rs b/src/tokenizer.rs index 7dea89d9..17f9087e 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -382,7 +382,7 @@ pub enum Token { /// /// Reserved under the `no_float` feature. #[cfg(not(feature = "no_float"))] - FloatConstant(crate::ast::FloatWrapper), + FloatConstant(crate::types::FloatWrapper), /// A [`Decimal`][rust_decimal::Decimal] constant. /// /// Requires the `decimal` feature. @@ -1682,7 +1682,7 @@ fn get_next_token_inner( // If integer parsing is unnecessary, try float instead #[cfg(not(feature = "no_float"))] let num = num.or_else(|_| { - crate::ast::FloatWrapper::from_str(&result).map(Token::FloatConstant) + crate::types::FloatWrapper::from_str(&result).map(Token::FloatConstant) }); // Then try decimal diff --git a/src/types/dynamic.rs b/src/types/dynamic.rs index eeee966a..8e4ad09a 100644 --- a/src/types/dynamic.rs +++ b/src/types/dynamic.rs @@ -70,7 +70,7 @@ pub enum Union { Int(INT, Tag, AccessMode), /// A floating-point value. #[cfg(not(feature = "no_float"))] - Float(crate::ast::FloatWrapper, Tag, AccessMode), + Float(super::FloatWrapper, Tag, AccessMode), /// _(decimal)_ A fixed-precision decimal value. /// Exported under the `decimal` feature only. #[cfg(feature = "decimal")] @@ -867,7 +867,7 @@ impl Dynamic { #[must_use] pub const fn from_float(value: crate::FLOAT) -> Self { Self(Union::Float( - crate::ast::FloatWrapper::new(value), + super::FloatWrapper::new(value), DEFAULT_TAG_VALUE, ReadWrite, )) @@ -1859,9 +1859,9 @@ impl From for Dynamic { } } #[cfg(not(feature = "no_float"))] -impl From> for Dynamic { +impl From> for Dynamic { #[inline(always)] - fn from(value: crate::ast::FloatWrapper) -> Self { + fn from(value: super::FloatWrapper) -> Self { Self(Union::Float(value, DEFAULT_TAG_VALUE, ReadWrite)) } } diff --git a/src/types/float.rs b/src/types/float.rs new file mode 100644 index 00000000..a3b934a6 --- /dev/null +++ b/src/types/float.rs @@ -0,0 +1,115 @@ +#![cfg(not(feature = "no_float"))] + +#[cfg(feature = "no_std")] +use std::prelude::v1::*; +use std::{ + fmt, + hash::{Hash, Hasher}, + ops::{Deref, DerefMut}, + str::FromStr, +}; + +use num_traits::float::FloatCore as Float; + +/// A type that wraps a floating-point number and implements [`Hash`]. +/// +/// Not available under `no_float`. +#[derive(Clone, Copy, PartialEq, PartialOrd)] +pub struct FloatWrapper(F); + +impl Hash for FloatWrapper { + #[inline] + fn hash(&self, state: &mut H) { + self.0.to_ne_bytes().hash(state); + } +} + +impl AsRef for FloatWrapper { + #[inline(always)] + #[must_use] + fn as_ref(&self) -> &F { + &self.0 + } +} + +impl AsMut for FloatWrapper { + #[inline(always)] + #[must_use] + fn as_mut(&mut self) -> &mut F { + &mut self.0 + } +} + +impl Deref for FloatWrapper { + type Target = F; + + #[inline(always)] + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for FloatWrapper { + #[inline(always)] + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl fmt::Debug for FloatWrapper { + #[cold] + #[inline(never)] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&self.0, f) + } +} + +impl> fmt::Display for FloatWrapper { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let abs = self.0.abs(); + if abs.is_zero() { + f.write_str("0.0") + } else if abs > Self::MAX_NATURAL_FLOAT_FOR_DISPLAY.into() + || abs < Self::MIN_NATURAL_FLOAT_FOR_DISPLAY.into() + { + write!(f, "{:e}", self.0) + } else { + fmt::Display::fmt(&self.0, f)?; + if abs.fract().is_zero() { + f.write_str(".0")?; + } + Ok(()) + } + } +} + +impl From for FloatWrapper { + #[inline(always)] + fn from(value: F) -> Self { + Self::new(value) + } +} + +impl FromStr for FloatWrapper { + type Err = ::Err; + + #[inline] + fn from_str(s: &str) -> Result { + F::from_str(s).map(Into::into) + } +} + +impl FloatWrapper { + /// Maximum floating-point number for natural display before switching to scientific notation. + pub const MAX_NATURAL_FLOAT_FOR_DISPLAY: f32 = 10_000_000_000_000.0; + + /// Minimum floating-point number for natural display before switching to scientific notation. + pub const MIN_NATURAL_FLOAT_FOR_DISPLAY: f32 = 0.000_000_000_000_1; + + /// Create a new [`FloatWrapper`]. + #[inline(always)] + #[must_use] + pub const fn new(value: F) -> Self { + Self(value) + } +} diff --git a/src/types/mod.rs b/src/types/mod.rs index 1fbf33d3..aad22a3c 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -4,6 +4,7 @@ pub mod bloom_filter; pub mod custom_types; pub mod dynamic; pub mod error; +pub mod float; pub mod fn_ptr; pub mod immutable_string; pub mod interner; @@ -18,6 +19,8 @@ pub use dynamic::Dynamic; #[cfg(not(feature = "no_time"))] pub use dynamic::Instant; pub use error::EvalAltResult; +#[cfg(not(feature = "no_float"))] +pub use float::FloatWrapper; pub use fn_ptr::FnPtr; pub use immutable_string::ImmutableString; pub use interner::StringsInterner;