Merge pull request #101 from lovasoa/main
Add support for is_nan and other floating-point functions
This commit is contained in:
commit
c4b39deee4
@ -345,6 +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 |
|
| `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 |
|
| `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 |
|
||||||
|
| `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::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::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 |
|
| `math::log2` | 1 | Numeric | Returns the base 2 logarithm of the number |
|
||||||
|
@ -23,6 +23,12 @@ macro_rules! simple_math {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn float_is(func: fn(f64) -> bool) -> Option<Function> {
|
||||||
|
Some(Function::new(move |argument| {
|
||||||
|
Ok(func(argument.as_number()?).into())
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! int_function {
|
macro_rules! int_function {
|
||||||
($func:ident) => {
|
($func:ident) => {
|
||||||
Some(Function::new(|argument| {
|
Some(Function::new(|argument| {
|
||||||
@ -76,7 +82,23 @@ pub fn builtin_function(identifier: &str) -> Option<Function> {
|
|||||||
"floor" => simple_math!(floor),
|
"floor" => simple_math!(floor),
|
||||||
"round" => simple_math!(round),
|
"round" => simple_math!(round),
|
||||||
"ceil" => simple_math!(ceil),
|
"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),
|
||||||
|
"math::is_normal" => float_is(f64::is_normal),
|
||||||
// Other
|
// 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| {
|
"min" => Some(Function::new(|argument| {
|
||||||
let arguments = argument.as_tuple()?;
|
let arguments = argument.as_tuple()?;
|
||||||
let mut min_int = IntType::max_value();
|
let mut min_int = IntType::max_value();
|
||||||
|
@ -328,6 +328,11 @@
|
|||||||
//! | `round` | 1 | Numeric | Returns the nearest integer to a number. Rounds half-way cases away from 0.0 |
|
//! | `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 |
|
//! | `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 |
|
||||||
|
//! | `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::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::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 |
|
//! | `math::log2` | 1 | Numeric | Returns the base 2 logarithm of the number |
|
||||||
|
@ -362,7 +362,25 @@ fn test_builtin_functions() {
|
|||||||
assert_eq!(eval("round(1.9)"), Ok(Value::Float(2.0)));
|
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.1)"), Ok(Value::Float(2.0)));
|
||||||
assert_eq!(eval("ceil(1.9)"), Ok(Value::Float(2.0)));
|
assert_eq!(eval("ceil(1.9)"), Ok(Value::Float(2.0)));
|
||||||
|
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
|
// 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("min(4.0, 3)"), Ok(Value::Int(3)));
|
||||||
assert_eq!(eval("max(4.0, 3)"), Ok(Value::Float(4.0)));
|
assert_eq!(eval("max(4.0, 3)"), Ok(Value::Float(4.0)));
|
||||||
assert_eq!(eval("len(\"foobar\")"), Ok(Value::Int(6)));
|
assert_eq!(eval("len(\"foobar\")"), Ok(Value::Int(6)));
|
||||||
@ -430,10 +448,16 @@ fn test_errors() {
|
|||||||
eval("true-"),
|
eval("true-"),
|
||||||
Err(EvalexprError::WrongOperatorArgumentAmount {
|
Err(EvalexprError::WrongOperatorArgumentAmount {
|
||||||
actual: 1,
|
actual: 1,
|
||||||
expected: 2
|
expected: 2,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
assert_eq!(eval("!(()true)"), Err(EvalexprError::AppendedToLeafNode));
|
assert_eq!(eval("!(()true)"), Err(EvalexprError::AppendedToLeafNode));
|
||||||
|
assert_eq!(
|
||||||
|
eval("math::is_nan(\"xxx\")"),
|
||||||
|
Err(EvalexprError::ExpectedNumber {
|
||||||
|
actual: Value::String("xxx".to_string())
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
Loading…
Reference in New Issue
Block a user