From 13004867cea66b6744cd14a3c55017e0425209f8 Mon Sep 17 00:00:00 2001 From: Sebastian Schmidt Date: Wed, 16 Mar 2022 16:13:37 +0200 Subject: [PATCH 01/14] Sync README. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d83d5f7..f493b02 100644 --- a/README.md +++ b/README.md @@ -344,6 +344,7 @@ This crate offers a set of builtin functions. | `floor` | 1 | Numeric | Returns the largest integer less than or equal to a number | | `round` | 1 | Numeric | Returns the nearest integer to a number. Rounds half-way cases away from 0.0 | | `ceil` | 1 | Numeric | Returns the smallest integer greater than or equal to a number | +| `if` | 3 | Boolean, Any, Any | If the first argument is true, returns the second argument, otherwise, returns the third | | `math::ln` | 1 | Numeric | Returns the natural logarithm of the number | | `math::log` | 2 | Numeric, Numeric | Returns the logarithm of the number with respect to an arbitrary base | | `math::log2` | 1 | Numeric | Returns the base 2 logarithm of the number | From c86dbcd74c703cd6bf4ea7c60f207b8d2a868ade Mon Sep 17 00:00:00 2001 From: Sebastian Schmidt Date: Wed, 16 Mar 2022 16:18:32 +0200 Subject: [PATCH 02/14] Prepare changelog for 7.2.0 release. --- CHANGELOG.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0181fa9..25cd780 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,19 @@ ### Contributors -## [7.1.1](https://github.com/ISibboI/evalexpr/compare/7.1.1...7.1.1) - 2022-03-14 +## [7.2.0](https://github.com/ISibboI/evalexpr/compare/7.1.1...7.2.0) - 2022-03-16 + +### Added + + * The builtin function `if`, which mimics the if-else construct existing in many programming languages. + +### Contributors + +My warmhearted thanks goes to: + + * [Ophir LOJKINE](https://github.com/lovasoa) + +## [7.1.1](https://github.com/ISibboI/evalexpr/compare/7.1.0...7.1.1) - 2022-03-14 ### Fixed From e3b7e3c63cb6bf8cbcd1f4a22cd5d9d2a6a69953 Mon Sep 17 00:00:00 2001 From: Sebastian Schmidt Date: Wed, 16 Mar 2022 16:22:14 +0200 Subject: [PATCH 03/14] Add sync-readme check to CI. --- .github/workflows/ci.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2caa341..6c29ca8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,6 +33,12 @@ jobs: command: clippy args: --all-features --tests --benches components: clippy + - toolchain: stable + command: + name: Sync readme + command: sync-readme + args: --check + components: cargo-sync-readme steps: - uses: actions/checkout@v2 From 117405e226b117f024345e58d88debf329ef192e Mon Sep 17 00:00:00 2001 From: Sebastian Schmidt Date: Wed, 16 Mar 2022 16:26:11 +0200 Subject: [PATCH 04/14] Try fixing sync-readme in CI. --- .github/workflows/ci.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6c29ca8..bb46831 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,7 +38,6 @@ jobs: name: Sync readme command: sync-readme args: --check - components: cargo-sync-readme steps: - uses: actions/checkout@v2 @@ -59,6 +58,12 @@ jobs: default: true components: ${{matrix.command.components}} + - name: Install cargo-sync-readme + uses: actions-rs/cargo@v1 + with: + command: install + args: cargo-sync-readme + - name: ${{matrix.command.name}} uses: actions-rs/cargo@v1 with: From d2ee6cd3adf5c3ec8e6fa5916d6beff86e352615 Mon Sep 17 00:00:00 2001 From: Sebastian Schmidt Date: Wed, 16 Mar 2022 16:30:12 +0200 Subject: [PATCH 05/14] Release 7.2.0 evalexpr@7.2.0 Generated by cargo-workspaces --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 5da3db0..7868b66 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "evalexpr" -version = "7.1.1" +version = "7.2.0" description = "A powerful arithmetic and boolean expression evaluator" keywords = ["expression", "evaluate", "evaluator", "arithmetic", "boolean"] categories = ["parsing", "game-engines"] From ea42cf63559057e14211a08461fc07c6c463cb23 Mon Sep 17 00:00:00 2001 From: Ophir LOJKINE Date: Wed, 23 Mar 2022 13:04:09 +0100 Subject: [PATCH 06/14] Add support for is_nan, is_finite, and other floating-point testing functions --- src/function/builtin.rs | 15 +++++++++++++++ src/lib.rs | 5 +++++ tests/integration.rs | 12 ++++++++++++ 3 files changed, 32 insertions(+) diff --git a/src/function/builtin.rs b/src/function/builtin.rs index 7194da1..3b6d286 100644 --- a/src/function/builtin.rs +++ b/src/function/builtin.rs @@ -23,6 +23,16 @@ macro_rules! simple_math { }; } +fn float_is(func: fn(f64) -> bool) -> Option { + Some(Function::new(move |argument| { + if let Ok(num) = argument.as_float() { + Ok(func(num).into()) + } else { + Ok(false.into()) + } + })) +} + macro_rules! int_function { ($func:ident) => { Some(Function::new(|argument| { @@ -76,6 +86,11 @@ pub fn builtin_function(identifier: &str) -> Option { "floor" => simple_math!(floor), "round" => simple_math!(round), "ceil" => simple_math!(ceil), + "is_nan" => float_is(f64::is_nan), + "is_finite" => float_is(f64::is_finite), + "is_infinite" => float_is(f64::is_infinite), + "is_normal" => float_is(f64::is_normal), + "is_subnormal" => float_is(f64::is_subnormal), // Other "min" => Some(Function::new(|argument| { let arguments = argument.as_tuple()?; diff --git a/src/lib.rs b/src/lib.rs index f136143..237483e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -328,6 +328,11 @@ //! | `round` | 1 | Numeric | Returns the nearest integer to a number. Rounds half-way cases away from 0.0 | //! | `ceil` | 1 | Numeric | Returns the smallest integer greater than or equal to a number | //! | `if` | 3 | Boolean, Any, Any | If the first argument is true, returns the second argument, otherwise, returns the third | +//! | `is_nan` | 1 | Numeric | Returns true if the argument is the floating-point value NaN, false otherwise | +//! | `is_finite` | 1 | Numeric | Returns true if the argument is a finite floating-point number, false otherwise | +//! | `is_infinite` | 1 | Numeric | Returns true if the argument is an infinite floating-point number, false otherwise | +//! | `is_normal` | 1 | Numeric | Returns true if the argument is a floating-point number that is neither zero, infinite, subnormal, or NaN, false otherwise | +//! | `is_subnormal` | 1 | Numeric | Returns true if the argument is a [subnormal](https://en.wikipedia.org/wiki/Subnormal_number) number, false otherwise | //! | `math::ln` | 1 | Numeric | Returns the natural logarithm of the number | //! | `math::log` | 2 | Numeric, Numeric | Returns the logarithm of the number with respect to an arbitrary base | //! | `math::log2` | 1 | Numeric | Returns the base 2 logarithm of the number | diff --git a/tests/integration.rs b/tests/integration.rs index 945f000..77fc9fe 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -362,6 +362,18 @@ fn test_builtin_functions() { assert_eq!(eval("round(1.9)"), Ok(Value::Float(2.0))); assert_eq!(eval("ceil(1.1)"), Ok(Value::Float(2.0))); assert_eq!(eval("ceil(1.9)"), Ok(Value::Float(2.0))); + assert_eq!(eval("is_nan(\"xxx\")"), Ok(Value::Boolean(false))); + assert_eq!(eval("is_nan(1.0/0.0)"), Ok(Value::Boolean(false))); + assert_eq!(eval("is_nan(0.0/0.0)"), Ok(Value::Boolean(true))); + assert_eq!(eval("is_finite(1.0/0.0)"), Ok(Value::Boolean(false))); + assert_eq!(eval("is_finite(0.0/0.0)"), Ok(Value::Boolean(false))); + assert_eq!(eval("is_finite(0.0)"), Ok(Value::Boolean(true))); + assert_eq!(eval("is_infinite(0.0/0.0)"), Ok(Value::Boolean(false))); + assert_eq!(eval("is_infinite(1.0/0.0)"), Ok(Value::Boolean(true))); + assert_eq!(eval("is_normal(1.0/0.0)"), Ok(Value::Boolean(false))); + assert_eq!(eval("is_normal(0)"), Ok(Value::Boolean(false))); + assert_eq!(eval("is_subnormal(0)"), Ok(Value::Boolean(false))); + assert_eq!(eval("is_subnormal(1.0e-308)"), Ok(Value::Boolean(true))); // Other assert_eq!(eval("min(4.0, 3)"), Ok(Value::Int(3))); assert_eq!(eval("max(4.0, 3)"), Ok(Value::Float(4.0))); From 2e0ef6ea4c0099ed31dd9b69b2934aa9f8aa6cae Mon Sep 17 00:00:00 2001 From: Ophir LOJKINE Date: Wed, 23 Mar 2022 13:08:21 +0100 Subject: [PATCH 07/14] add new functions to the readme --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index f493b02..19458c3 100644 --- a/README.md +++ b/README.md @@ -345,6 +345,12 @@ This crate offers a set of builtin functions. | `round` | 1 | Numeric | Returns the nearest integer to a number. Rounds half-way cases away from 0.0 | | `ceil` | 1 | Numeric | Returns the smallest integer greater than or equal to a number | | `if` | 3 | Boolean, Any, Any | If the first argument is true, returns the second argument, otherwise, returns the third | +| `if` | 3 | Boolean, Any, Any | If the first argument is true, returns the second argument, otherwise, returns the third | +| `is_nan` | 1 | Numeric | Returns true if the argument is the floating-point value NaN, false otherwise | +| `is_finite` | 1 | Numeric | Returns true if the argument is a finite floating-point number, false otherwise | +| `is_infinite` | 1 | Numeric | Returns true if the argument is an infinite floating-point number, false otherwise | +| `is_normal` | 1 | Numeric | Returns true if the argument is a floating-point number that is neither zero, infinite, subnormal, or NaN, false otherwise | +| `is_subnormal` | 1 | Numeric | Returns true if the argument is a [subnormal](https://en.wikipedia.org/wiki/Subnormal_number) number, false otherwise | | `math::ln` | 1 | Numeric | Returns the natural logarithm of the number | | `math::log` | 2 | Numeric, Numeric | Returns the logarithm of the number with respect to an arbitrary base | | `math::log2` | 1 | Numeric | Returns the base 2 logarithm of the number | From 3c4a429e8d50292cb2c7ea05092329afcce06708 Mon Sep 17 00:00:00 2001 From: Ophir LOJKINE Date: Wed, 23 Mar 2022 13:11:41 +0100 Subject: [PATCH 08/14] Remove is_sumbnormal --- README.md | 1 - src/function/builtin.rs | 1 - src/lib.rs | 3 +-- tests/integration.rs | 1 - 4 files changed, 1 insertion(+), 5 deletions(-) diff --git a/README.md b/README.md index 19458c3..78c46d9 100644 --- a/README.md +++ b/README.md @@ -350,7 +350,6 @@ This crate offers a set of builtin functions. | `is_finite` | 1 | Numeric | Returns true if the argument is a finite floating-point number, false otherwise | | `is_infinite` | 1 | Numeric | Returns true if the argument is an infinite floating-point number, false otherwise | | `is_normal` | 1 | Numeric | Returns true if the argument is a floating-point number that is neither zero, infinite, subnormal, or NaN, false otherwise | -| `is_subnormal` | 1 | Numeric | Returns true if the argument is a [subnormal](https://en.wikipedia.org/wiki/Subnormal_number) number, false otherwise | | `math::ln` | 1 | Numeric | Returns the natural logarithm of the number | | `math::log` | 2 | Numeric, Numeric | Returns the logarithm of the number with respect to an arbitrary base | | `math::log2` | 1 | Numeric | Returns the base 2 logarithm of the number | diff --git a/src/function/builtin.rs b/src/function/builtin.rs index 3b6d286..95aca35 100644 --- a/src/function/builtin.rs +++ b/src/function/builtin.rs @@ -90,7 +90,6 @@ pub fn builtin_function(identifier: &str) -> Option { "is_finite" => float_is(f64::is_finite), "is_infinite" => float_is(f64::is_infinite), "is_normal" => float_is(f64::is_normal), - "is_subnormal" => float_is(f64::is_subnormal), // Other "min" => Some(Function::new(|argument| { let arguments = argument.as_tuple()?; diff --git a/src/lib.rs b/src/lib.rs index 237483e..0391408 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -331,8 +331,7 @@ //! | `is_nan` | 1 | Numeric | Returns true if the argument is the floating-point value NaN, false otherwise | //! | `is_finite` | 1 | Numeric | Returns true if the argument is a finite floating-point number, false otherwise | //! | `is_infinite` | 1 | Numeric | Returns true if the argument is an infinite floating-point number, false otherwise | -//! | `is_normal` | 1 | Numeric | Returns true if the argument is a floating-point number that is neither zero, infinite, subnormal, or NaN, false otherwise | -//! | `is_subnormal` | 1 | Numeric | Returns true if the argument is a [subnormal](https://en.wikipedia.org/wiki/Subnormal_number) number, false otherwise | +//! | `is_normal` | 1 | Numeric | Returns true if the argument is a floating-point number that is neither zero, infinite, [subnormal](https://en.wikipedia.org/wiki/Subnormal_number), or NaN, false otherwise | //! | `math::ln` | 1 | Numeric | Returns the natural logarithm of the number | //! | `math::log` | 2 | Numeric, Numeric | Returns the logarithm of the number with respect to an arbitrary base | //! | `math::log2` | 1 | Numeric | Returns the base 2 logarithm of the number | diff --git a/tests/integration.rs b/tests/integration.rs index 77fc9fe..63850bb 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -373,7 +373,6 @@ fn test_builtin_functions() { assert_eq!(eval("is_normal(1.0/0.0)"), Ok(Value::Boolean(false))); assert_eq!(eval("is_normal(0)"), Ok(Value::Boolean(false))); assert_eq!(eval("is_subnormal(0)"), Ok(Value::Boolean(false))); - assert_eq!(eval("is_subnormal(1.0e-308)"), Ok(Value::Boolean(true))); // Other assert_eq!(eval("min(4.0, 3)"), Ok(Value::Int(3))); assert_eq!(eval("max(4.0, 3)"), Ok(Value::Float(4.0))); From 10528d198c572670509cd50be44cbe4e0fafa6e6 Mon Sep 17 00:00:00 2001 From: Ophir LOJKINE Date: Wed, 23 Mar 2022 13:13:22 +0100 Subject: [PATCH 09/14] sync README.md --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 78c46d9..a432317 100644 --- a/README.md +++ b/README.md @@ -345,11 +345,10 @@ This crate offers a set of builtin functions. | `round` | 1 | Numeric | Returns the nearest integer to a number. Rounds half-way cases away from 0.0 | | `ceil` | 1 | Numeric | Returns the smallest integer greater than or equal to a number | | `if` | 3 | Boolean, Any, Any | If the first argument is true, returns the second argument, otherwise, returns the third | -| `if` | 3 | Boolean, Any, Any | If the first argument is true, returns the second argument, otherwise, returns the third | | `is_nan` | 1 | Numeric | Returns true if the argument is the floating-point value NaN, false otherwise | | `is_finite` | 1 | Numeric | Returns true if the argument is a finite floating-point number, false otherwise | | `is_infinite` | 1 | Numeric | Returns true if the argument is an infinite floating-point number, false otherwise | -| `is_normal` | 1 | Numeric | Returns true if the argument is a floating-point number that is neither zero, infinite, subnormal, or NaN, false otherwise | +| `is_normal` | 1 | Numeric | Returns true if the argument is a floating-point number that is neither zero, infinite, [subnormal](https://en.wikipedia.org/wiki/Subnormal_number), or NaN, false otherwise | | `math::ln` | 1 | Numeric | Returns the natural logarithm of the number | | `math::log` | 2 | Numeric, Numeric | Returns the logarithm of the number with respect to an arbitrary base | | `math::log2` | 1 | Numeric | Returns the base 2 logarithm of the number | From 678c881377875d4de046f2f933ab18dc3247d972 Mon Sep 17 00:00:00 2001 From: Ophir LOJKINE Date: Wed, 23 Mar 2022 13:55:51 +0100 Subject: [PATCH 10/14] fix test --- tests/integration.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/integration.rs b/tests/integration.rs index 63850bb..81b5128 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -372,7 +372,6 @@ fn test_builtin_functions() { assert_eq!(eval("is_infinite(1.0/0.0)"), Ok(Value::Boolean(true))); assert_eq!(eval("is_normal(1.0/0.0)"), Ok(Value::Boolean(false))); assert_eq!(eval("is_normal(0)"), Ok(Value::Boolean(false))); - assert_eq!(eval("is_subnormal(0)"), Ok(Value::Boolean(false))); // Other assert_eq!(eval("min(4.0, 3)"), Ok(Value::Int(3))); assert_eq!(eval("max(4.0, 3)"), Ok(Value::Float(4.0))); From 8eedf720e72212162be11326cce234ecec3083bc Mon Sep 17 00:00:00 2001 From: Ophir LOJKINE Date: Wed, 23 Mar 2022 16:33:53 +0100 Subject: [PATCH 11/14] Implement changes requested in PR https://github.com/ISibboI/evalexpr/pull/101#issuecomment-1076466426 --- README.md | 9 +++++---- src/function/builtin.rs | 28 +++++++++++++++++----------- src/lib.rs | 9 +++++---- tests/integration.rs | 30 +++++++++++++++++++----------- 4 files changed, 46 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index a432317..e4c535b 100644 --- a/README.md +++ b/README.md @@ -345,10 +345,11 @@ This crate offers a set of builtin functions. | `round` | 1 | Numeric | Returns the nearest integer to a number. Rounds half-way cases away from 0.0 | | `ceil` | 1 | Numeric | Returns the smallest integer greater than or equal to a number | | `if` | 3 | Boolean, Any, Any | If the first argument is true, returns the second argument, otherwise, returns the third | -| `is_nan` | 1 | Numeric | Returns true if the argument is the floating-point value NaN, false otherwise | -| `is_finite` | 1 | Numeric | Returns true if the argument is a finite floating-point number, false otherwise | -| `is_infinite` | 1 | Numeric | Returns true if the argument is an infinite floating-point number, false otherwise | -| `is_normal` | 1 | Numeric | Returns true if the argument is a floating-point number that is neither zero, infinite, [subnormal](https://en.wikipedia.org/wiki/Subnormal_number), or NaN, false otherwise | +| `typeof` | 1 | Any | returns "string", "float", "int", "boolean", "tuple", or "empty" depending on the type of the argument | +| `math::is_nan` | 1 | Numeric | Returns true if the argument is the floating-point value NaN, false if it is another floating-point value, and throws an error if it is not a number | +| `math::is_finite` | 1 | Numeric | Returns true if the argument is a finite floating-point number, false otherwise | +| `math::is_infinite` | 1 | Numeric | Returns true if the argument is an infinite floating-point number, false otherwise | +| `math::is_normal` | 1 | Numeric | Returns true if the argument is a floating-point number that is neither zero, infinite, [subnormal](https://en.wikipedia.org/wiki/Subnormal_number), or NaN, false otherwise | | `math::ln` | 1 | Numeric | Returns the natural logarithm of the number | | `math::log` | 2 | Numeric, Numeric | Returns the logarithm of the number with respect to an arbitrary base | | `math::log2` | 1 | Numeric | Returns the base 2 logarithm of the number | diff --git a/src/function/builtin.rs b/src/function/builtin.rs index 95aca35..a0600f2 100644 --- a/src/function/builtin.rs +++ b/src/function/builtin.rs @@ -24,13 +24,9 @@ macro_rules! simple_math { } fn float_is(func: fn(f64) -> bool) -> Option { - Some(Function::new(move |argument| { - if let Ok(num) = argument.as_float() { - Ok(func(num).into()) - } else { - Ok(false.into()) - } - })) + Some(Function::new(move |argument| + Ok(func(argument.as_number()?).into()) + )) } macro_rules! int_function { @@ -86,11 +82,21 @@ pub fn builtin_function(identifier: &str) -> Option { "floor" => simple_math!(floor), "round" => simple_math!(round), "ceil" => simple_math!(ceil), - "is_nan" => float_is(f64::is_nan), - "is_finite" => float_is(f64::is_finite), - "is_infinite" => float_is(f64::is_infinite), - "is_normal" => float_is(f64::is_normal), + "math::is_nan" => float_is(f64::is_nan), + "math::is_finite" => float_is(f64::is_finite), + "math::is_infinite" => float_is(f64::is_infinite), + "math::is_normal" => float_is(f64::is_normal), // Other + "typeof" => Some(Function::new(move |argument| + Ok(match argument { + Value::String(_) => "string", + Value::Float(_) => "float", + Value::Int(_) => "int", + Value::Boolean(_) => "boolean", + Value::Tuple(_) => "tuple", + Value::Empty => "empty", + }.into()) + )), "min" => Some(Function::new(|argument| { let arguments = argument.as_tuple()?; let mut min_int = IntType::max_value(); diff --git a/src/lib.rs b/src/lib.rs index 0391408..823ed8c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -328,10 +328,11 @@ //! | `round` | 1 | Numeric | Returns the nearest integer to a number. Rounds half-way cases away from 0.0 | //! | `ceil` | 1 | Numeric | Returns the smallest integer greater than or equal to a number | //! | `if` | 3 | Boolean, Any, Any | If the first argument is true, returns the second argument, otherwise, returns the third | -//! | `is_nan` | 1 | Numeric | Returns true if the argument is the floating-point value NaN, false otherwise | -//! | `is_finite` | 1 | Numeric | Returns true if the argument is a finite floating-point number, false otherwise | -//! | `is_infinite` | 1 | Numeric | Returns true if the argument is an infinite floating-point number, false otherwise | -//! | `is_normal` | 1 | Numeric | Returns true if the argument is a floating-point number that is neither zero, infinite, [subnormal](https://en.wikipedia.org/wiki/Subnormal_number), or NaN, false otherwise | +//! | `typeof` | 1 | Any | returns "string", "float", "int", "boolean", "tuple", or "empty" depending on the type of the argument | +//! | `math::is_nan` | 1 | Numeric | Returns true if the argument is the floating-point value NaN, false if it is another floating-point value, and throws an error if it is not a number | +//! | `math::is_finite` | 1 | Numeric | Returns true if the argument is a finite floating-point number, false otherwise | +//! | `math::is_infinite` | 1 | Numeric | Returns true if the argument is an infinite floating-point number, false otherwise | +//! | `math::is_normal` | 1 | Numeric | Returns true if the argument is a floating-point number that is neither zero, infinite, [subnormal](https://en.wikipedia.org/wiki/Subnormal_number), or NaN, false otherwise | //! | `math::ln` | 1 | Numeric | Returns the natural logarithm of the number | //! | `math::log` | 2 | Numeric, Numeric | Returns the logarithm of the number with respect to an arbitrary base | //! | `math::log2` | 1 | Numeric | Returns the base 2 logarithm of the number | diff --git a/tests/integration.rs b/tests/integration.rs index 81b5128..17e72e6 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -362,17 +362,22 @@ fn test_builtin_functions() { assert_eq!(eval("round(1.9)"), Ok(Value::Float(2.0))); assert_eq!(eval("ceil(1.1)"), Ok(Value::Float(2.0))); assert_eq!(eval("ceil(1.9)"), Ok(Value::Float(2.0))); - assert_eq!(eval("is_nan(\"xxx\")"), Ok(Value::Boolean(false))); - assert_eq!(eval("is_nan(1.0/0.0)"), Ok(Value::Boolean(false))); - assert_eq!(eval("is_nan(0.0/0.0)"), Ok(Value::Boolean(true))); - assert_eq!(eval("is_finite(1.0/0.0)"), Ok(Value::Boolean(false))); - assert_eq!(eval("is_finite(0.0/0.0)"), Ok(Value::Boolean(false))); - assert_eq!(eval("is_finite(0.0)"), Ok(Value::Boolean(true))); - assert_eq!(eval("is_infinite(0.0/0.0)"), Ok(Value::Boolean(false))); - assert_eq!(eval("is_infinite(1.0/0.0)"), Ok(Value::Boolean(true))); - assert_eq!(eval("is_normal(1.0/0.0)"), Ok(Value::Boolean(false))); - assert_eq!(eval("is_normal(0)"), Ok(Value::Boolean(false))); + assert_eq!(eval("math::is_nan(1.0/0.0)"), Ok(Value::Boolean(false))); + assert_eq!(eval("math::is_nan(0.0/0.0)"), Ok(Value::Boolean(true))); + assert_eq!(eval("math::is_finite(1.0/0.0)"), Ok(Value::Boolean(false))); + assert_eq!(eval("math::is_finite(0.0/0.0)"), Ok(Value::Boolean(false))); + assert_eq!(eval("math::is_finite(0.0)"), Ok(Value::Boolean(true))); + assert_eq!(eval("math::is_infinite(0.0/0.0)"), Ok(Value::Boolean(false))); + assert_eq!(eval("math::is_infinite(1.0/0.0)"), Ok(Value::Boolean(true))); + assert_eq!(eval("math::is_normal(1.0/0.0)"), Ok(Value::Boolean(false))); + assert_eq!(eval("math::is_normal(0)"), Ok(Value::Boolean(false))); // Other + assert_eq!(eval("typeof(4.0, 3)"), Ok(Value::String("tuple".into()))); + assert_eq!(eval("typeof(4.0)"), Ok(Value::String("float".into()))); + assert_eq!(eval("typeof(4)"), Ok(Value::String("int".into()))); + assert_eq!(eval("typeof(\"\")"), Ok(Value::String("string".into()))); + assert_eq!(eval("typeof(true)"), Ok(Value::String("boolean".into()))); + assert_eq!(eval("typeof()"), Ok(Value::String("empty".into()))); assert_eq!(eval("min(4.0, 3)"), Ok(Value::Int(3))); assert_eq!(eval("max(4.0, 3)"), Ok(Value::Float(4.0))); assert_eq!(eval("len(\"foobar\")"), Ok(Value::Int(6))); @@ -440,10 +445,13 @@ fn test_errors() { eval("true-"), Err(EvalexprError::WrongOperatorArgumentAmount { actual: 1, - expected: 2 + expected: 2, }) ); assert_eq!(eval("!(()true)"), Err(EvalexprError::AppendedToLeafNode)); + assert_eq!(eval("math::is_nan(\"xxx\")"), Err(EvalexprError::ExpectedNumber { + actual: Value::String("xxx".to_string()) + })); } #[test] From 9d5ef651aee2407d0c62f707b95a8e82c474167e Mon Sep 17 00:00:00 2001 From: Ophir LOJKINE Date: Wed, 23 Mar 2022 18:09:23 +0100 Subject: [PATCH 12/14] cargo fmt --- src/function/builtin.rs | 11 ++++++----- tests/integration.rs | 14 ++++++++++---- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/function/builtin.rs b/src/function/builtin.rs index a0600f2..2cee599 100644 --- a/src/function/builtin.rs +++ b/src/function/builtin.rs @@ -24,9 +24,9 @@ macro_rules! simple_math { } fn float_is(func: fn(f64) -> bool) -> Option { - Some(Function::new(move |argument| + Some(Function::new(move |argument| { Ok(func(argument.as_number()?).into()) - )) + })) } macro_rules! int_function { @@ -87,7 +87,7 @@ pub fn builtin_function(identifier: &str) -> Option { "math::is_infinite" => float_is(f64::is_infinite), "math::is_normal" => float_is(f64::is_normal), // Other - "typeof" => Some(Function::new(move |argument| + "typeof" => Some(Function::new(move |argument| { Ok(match argument { Value::String(_) => "string", Value::Float(_) => "float", @@ -95,8 +95,9 @@ pub fn builtin_function(identifier: &str) -> Option { Value::Boolean(_) => "boolean", Value::Tuple(_) => "tuple", Value::Empty => "empty", - }.into()) - )), + } + .into()) + })), "min" => Some(Function::new(|argument| { let arguments = argument.as_tuple()?; let mut min_int = IntType::max_value(); diff --git a/tests/integration.rs b/tests/integration.rs index 17e72e6..e028e1a 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -367,7 +367,10 @@ fn test_builtin_functions() { assert_eq!(eval("math::is_finite(1.0/0.0)"), Ok(Value::Boolean(false))); assert_eq!(eval("math::is_finite(0.0/0.0)"), Ok(Value::Boolean(false))); assert_eq!(eval("math::is_finite(0.0)"), Ok(Value::Boolean(true))); - assert_eq!(eval("math::is_infinite(0.0/0.0)"), Ok(Value::Boolean(false))); + assert_eq!( + eval("math::is_infinite(0.0/0.0)"), + Ok(Value::Boolean(false)) + ); assert_eq!(eval("math::is_infinite(1.0/0.0)"), Ok(Value::Boolean(true))); assert_eq!(eval("math::is_normal(1.0/0.0)"), Ok(Value::Boolean(false))); assert_eq!(eval("math::is_normal(0)"), Ok(Value::Boolean(false))); @@ -449,9 +452,12 @@ fn test_errors() { }) ); assert_eq!(eval("!(()true)"), Err(EvalexprError::AppendedToLeafNode)); - assert_eq!(eval("math::is_nan(\"xxx\")"), Err(EvalexprError::ExpectedNumber { - actual: Value::String("xxx".to_string()) - })); + assert_eq!( + eval("math::is_nan(\"xxx\")"), + Err(EvalexprError::ExpectedNumber { + actual: Value::String("xxx".to_string()) + }) + ); } #[test] From 27bd1a32d702e17c3b0aa83106f2f7b7b485067d Mon Sep 17 00:00:00 2001 From: Ophir LOJKINE Date: Wed, 30 Mar 2022 14:44:19 +0200 Subject: [PATCH 13/14] add comment Fixes https://github.com/ISibboI/evalexpr/pull/101#discussion_r838444554 --- src/function/builtin.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/function/builtin.rs b/src/function/builtin.rs index 2cee599..c24e2dc 100644 --- a/src/function/builtin.rs +++ b/src/function/builtin.rs @@ -82,6 +82,7 @@ pub fn builtin_function(identifier: &str) -> Option { "floor" => simple_math!(floor), "round" => simple_math!(round), "ceil" => simple_math!(ceil), + // Float special values "math::is_nan" => float_is(f64::is_nan), "math::is_finite" => float_is(f64::is_finite), "math::is_infinite" => float_is(f64::is_infinite), From 2275bb54423cce4c16a6077abeb5fed42b2327cb Mon Sep 17 00:00:00 2001 From: ISibboI Date: Thu, 7 Apr 2022 15:20:26 +0200 Subject: [PATCH 14/14] Update CHANGELOG.md --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25cd780..f056789 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ ### Added + * Builtin functions to check for nan, infinity and subnormality in floats (#101) + ### Removed ### Changed @@ -16,6 +18,10 @@ ### Contributors +My warmhearted thanks goes to: + + * [Ophir LOJKINE](https://github.com/lovasoa) + ## [7.2.0](https://github.com/ISibboI/evalexpr/compare/7.1.1...7.2.0) - 2022-03-16 ### Added @@ -418,4 +424,4 @@ For more details, see the following subsections. ## [1.0.0](https://github.com/ISibboI/evalexpr/tree/1.0.0) - 2019-03-20 - * First stable release \ No newline at end of file + * First stable release