From a219f0b66f46fba118afdda18da08cfd16566c42 Mon Sep 17 00:00:00 2001 From: Ophir LOJKINE Date: Mon, 14 Mar 2022 14:59:48 +0100 Subject: [PATCH 1/7] Add an "if" function If the first argument is true, returns the second argument, otherwise, return the third --- src/function/builtin.rs | 9 +++++++++ src/lib.rs | 1 + tests/integration.rs | 3 +++ 3 files changed, 13 insertions(+) diff --git a/src/function/builtin.rs b/src/function/builtin.rs index b4d6cab..1819439 100644 --- a/src/function/builtin.rs +++ b/src/function/builtin.rs @@ -121,6 +121,15 @@ pub fn builtin_function(identifier: &str) -> Option { Ok(Value::Float(max_float)) } })), + "if" => Some(Function::new(|argument| { + if let [condition, if_true, if_false] = &argument.as_fixed_len_tuple(3)?[..] { + return Ok(if condition.as_boolean()? { if_true } else { if_false }.clone()) + } + Err(EvalexprError::type_error( + argument.clone(), + vec![ValueType::Boolean, ValueType::Empty, ValueType::Empty], + )) + })), "len" => Some(Function::new(|argument| { if let Ok(subject) = argument.as_string() { Ok(Value::from(subject.len() as i64)) diff --git a/src/lib.rs b/src/lib.rs index 967a48c..e7cabaf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -327,6 +327,7 @@ //! | `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, return 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 | diff --git a/tests/integration.rs b/tests/integration.rs index d93c235..cd7639b 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -408,6 +408,9 @@ fn test_builtin_functions() { assert_eq!(eval("shl(-6, 5)"), Ok(Value::Int(-192))); assert_eq!(eval("shr(5, 1)"), Ok(Value::Int(2))); assert_eq!(eval("shr(-6, 5)"), Ok(Value::Int(-1))); + assert_eq!(eval("if(true, -6, 5)"), Ok(Value::Int(-6))); + assert_eq!(eval("if(false, -6, 5)"), Ok(Value::Int(5))); + assert_eq!(eval("if(2-1==1, \"good\", 0)"), Ok(Value::String(String::from("good")))); } #[test] From 9eedc8e93bd9920ee4db9f7c0edd129a91a88748 Mon Sep 17 00:00:00 2001 From: Ophir LOJKINE Date: Mon, 14 Mar 2022 15:07:38 +0100 Subject: [PATCH 2/7] cargo fmt --- src/function/builtin.rs | 7 ++++++- tests/integration.rs | 5 ++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/function/builtin.rs b/src/function/builtin.rs index 1819439..e51da8a 100644 --- a/src/function/builtin.rs +++ b/src/function/builtin.rs @@ -123,7 +123,12 @@ pub fn builtin_function(identifier: &str) -> Option { })), "if" => Some(Function::new(|argument| { if let [condition, if_true, if_false] = &argument.as_fixed_len_tuple(3)?[..] { - return Ok(if condition.as_boolean()? { if_true } else { if_false }.clone()) + return Ok(if condition.as_boolean()? { + if_true + } else { + if_false + } + .clone()); } Err(EvalexprError::type_error( argument.clone(), diff --git a/tests/integration.rs b/tests/integration.rs index cd7639b..6cec000 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -410,7 +410,10 @@ fn test_builtin_functions() { assert_eq!(eval("shr(-6, 5)"), Ok(Value::Int(-1))); assert_eq!(eval("if(true, -6, 5)"), Ok(Value::Int(-6))); assert_eq!(eval("if(false, -6, 5)"), Ok(Value::Int(5))); - assert_eq!(eval("if(2-1==1, \"good\", 0)"), Ok(Value::String(String::from("good")))); + assert_eq!( + eval("if(2-1==1, \"good\", 0)"), + Ok(Value::String(String::from("good"))) + ); } #[test] From 004c2c9f0387cebebcd68b35e7bf160aa5f2846b Mon Sep 17 00:00:00 2001 From: Ophir LOJKINE Date: Mon, 14 Mar 2022 15:30:52 +0100 Subject: [PATCH 3/7] more tests --- tests/integration.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/integration.rs b/tests/integration.rs index 6cec000..945f000 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -465,6 +465,12 @@ fn test_no_panic() { IntType::max_value() )) .is_ok()); + assert!(eval("if").is_err()); + assert!(eval("if()").is_err()); + assert!(eval("if(true, 1)").is_err()); + assert!(eval("if(false, 2)").is_err()); + assert!(eval("if(1,1,1)").is_err()); + assert!(eval("if(true,1,1,1)").is_err()); } #[test] From 7522df14b7564493f7cb02f09ef326dd1bc98830 Mon Sep 17 00:00:00 2001 From: Ophir LOJKINE Date: Mon, 14 Mar 2022 15:50:08 +0100 Subject: [PATCH 4/7] remove dead code --- src/function/builtin.rs | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/function/builtin.rs b/src/function/builtin.rs index e51da8a..3e44c17 100644 --- a/src/function/builtin.rs +++ b/src/function/builtin.rs @@ -122,18 +122,12 @@ pub fn builtin_function(identifier: &str) -> Option { } })), "if" => Some(Function::new(|argument| { - if let [condition, if_true, if_false] = &argument.as_fixed_len_tuple(3)?[..] { - return Ok(if condition.as_boolean()? { - if_true - } else { - if_false - } - .clone()); - } - Err(EvalexprError::type_error( - argument.clone(), - vec![ValueType::Boolean, ValueType::Empty, ValueType::Empty], - )) + let arguments = &argument.as_fixed_len_tuple(3)?; + Ok(if arguments[0].as_boolean()? { + arguments[1].clone() + } else { + arguments[2].clone() + }) })), "len" => Some(Function::new(|argument| { if let Ok(subject) = argument.as_string() { From af77f1703ef37d82132f8892368629aad2486bd8 Mon Sep 17 00:00:00 2001 From: Ophir LOJKINE Date: Mon, 14 Mar 2022 15:58:42 +0100 Subject: [PATCH 5/7] remove unnecessary clone --- src/function/builtin.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/function/builtin.rs b/src/function/builtin.rs index 3e44c17..04b50b7 100644 --- a/src/function/builtin.rs +++ b/src/function/builtin.rs @@ -122,11 +122,11 @@ pub fn builtin_function(identifier: &str) -> Option { } })), "if" => Some(Function::new(|argument| { - let arguments = &argument.as_fixed_len_tuple(3)?; + let mut arguments = argument.as_fixed_len_tuple(3)?; Ok(if arguments[0].as_boolean()? { - arguments[1].clone() + arguments.swap_remove(1) } else { - arguments[2].clone() + arguments.swap_remove(2) }) })), "len" => Some(Function::new(|argument| { From 65bf8adc9cb5cb46ca5ae5bc35da66c6971862cc Mon Sep 17 00:00:00 2001 From: Ophir LOJKINE Date: Mon, 14 Mar 2022 16:08:08 +0100 Subject: [PATCH 6/7] remove duplicated code --- src/function/builtin.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/function/builtin.rs b/src/function/builtin.rs index 04b50b7..7194da1 100644 --- a/src/function/builtin.rs +++ b/src/function/builtin.rs @@ -123,11 +123,8 @@ pub fn builtin_function(identifier: &str) -> Option { })), "if" => Some(Function::new(|argument| { let mut arguments = argument.as_fixed_len_tuple(3)?; - Ok(if arguments[0].as_boolean()? { - arguments.swap_remove(1) - } else { - arguments.swap_remove(2) - }) + let result_index = if arguments[0].as_boolean()? { 1 } else { 2 }; + Ok(arguments.swap_remove(result_index)) })), "len" => Some(Function::new(|argument| { if let Ok(subject) = argument.as_string() { From d96ab3abf4ab872842ff28543f70ca2871e32efc Mon Sep 17 00:00:00 2001 From: Ophir LOJKINE Date: Mon, 14 Mar 2022 16:09:41 +0100 Subject: [PATCH 7/7] fix typo --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index e7cabaf..f136143 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -327,7 +327,7 @@ //! | `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, return the third | +//! | `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 |