From 2dac0576a7b43cdff7bac89da8a135b5d7a28464 Mon Sep 17 00:00:00 2001 From: Sebastian Schmidt Date: Wed, 20 Mar 2019 16:29:50 +0200 Subject: [PATCH] Add shortcut functions for evaluating directly into a value type + Added shortcut functions `eval_[type]` and `eval_[type]_with_configuration` for each value type + Added integration tests for the above Partially implements #15 --- CHANGELOG.md | 4 +- src/error/mod.rs | 22 ++++++++ src/interface/mod.rs | 127 +++++++++++++++++++++++++++++++++++++++++++ tests/integration.rs | 29 ++++++++++ 4 files changed, 181 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bf3bbfd..491dade 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,9 @@ ### Added - * Made internal alias `IntType` and `FloatType` used by the `Value` enum public + * Internal alias `IntType` and `FloatType` used by the `Value` enum are now public + * Error types for expecting each value type + * Shortcut functions like `eval_int` to evaluate directly into a value type ### Removed diff --git a/src/error/mod.rs b/src/error/mod.rs index 7d5f617..d214a90 100644 --- a/src/error/mod.rs +++ b/src/error/mod.rs @@ -27,6 +27,12 @@ pub enum Error { actual: usize, }, + /// A string value was expected. + ExpectedString { + /// The actual value. + actual: Value, + }, + /// An integer value was expected. ExpectedInt { /// The actual value. @@ -52,6 +58,12 @@ pub enum Error { actual: Value, }, + /// A tuple value was expected. + ExpectedTuple { + /// The actual value. + actual: Value, + }, + /// The given expression is empty EmptyExpression, @@ -158,6 +170,11 @@ impl Error { Error::TypeError { actual, expected } } + /// Constructs `Error::ExpectedString(actual)`. + pub fn expected_string(actual: Value) -> Self { + Error::ExpectedString { actual } + } + /// Constructs `Error::ExpectedInt(actual)`. pub fn expected_int(actual: Value) -> Self { Error::ExpectedInt { actual } @@ -178,6 +195,11 @@ impl Error { Error::ExpectedBoolean { actual } } + /// Constructs `Error::ExpectedTuple(actual)`. + pub fn expected_tuple(actual: Value) -> Self { + Error::ExpectedTuple { actual } + } + pub(crate) fn unmatched_partial_token( first: PartialToken, second: Option, diff --git a/src/interface/mod.rs b/src/interface/mod.rs index 4445fcb..6e5bbf5 100644 --- a/src/interface/mod.rs +++ b/src/interface/mod.rs @@ -3,6 +3,8 @@ use tree; use Configuration; use EmptyConfiguration; use Error; +use FloatType; +use IntType; use Node; use Value; @@ -70,3 +72,128 @@ pub fn eval_with_configuration( pub fn build_operator_tree(string: &str) -> Result { tree::tokens_to_operator_tree(token::tokenize(string)?) } + +/// Evaluate the given expression string expecting a string. +/// +/// *See the [crate doc](index.html) for more examples and explanations of the expression format.* +pub fn eval_string(string: &str) -> Result { + match eval(string) { + Ok(Value::String(string)) => Ok(string), + Ok(value) => Err(Error::expected_string(value)), + Err(error) => Err(error), + } +} + +/// Evaluate the given expression string expecting an integer. +/// +/// *See the [crate doc](index.html) for more examples and explanations of the expression format.* +pub fn eval_int(string: &str) -> Result { + match eval(string) { + Ok(Value::Int(int)) => Ok(int), + Ok(value) => Err(Error::expected_int(value)), + Err(error) => Err(error), + } +} + +/// Evaluate the given expression string expecting a float. +/// +/// *See the [crate doc](index.html) for more examples and explanations of the expression format.* +pub fn eval_float(string: &str) -> Result { + match eval(string) { + Ok(Value::Float(float)) => Ok(float), + Ok(value) => Err(Error::expected_float(value)), + Err(error) => Err(error), + } +} + +/// Evaluate the given expression string expecting a boolean. +/// +/// *See the [crate doc](index.html) for more examples and explanations of the expression format.* +pub fn eval_boolean(string: &str) -> Result { + match eval(string) { + Ok(Value::Boolean(boolean)) => Ok(boolean), + Ok(value) => Err(Error::expected_boolean(value)), + Err(error) => Err(error), + } +} + +/// Evaluate the given expression string expecting a tuple. +/// +/// *See the [crate doc](index.html) for more examples and explanations of the expression format.* +pub fn eval_tuple(string: &str) -> Result, Error> { + match eval(string) { + Ok(Value::Tuple(tuple)) => Ok(tuple), + Ok(value) => Err(Error::expected_tuple(value)), + Err(error) => Err(error), + } +} + +/// Evaluate the given expression string expecting a string with the given configuration. +/// +/// *See the [crate doc](index.html) for more examples and explanations of the expression format.* +pub fn eval_string_with_configuration( + string: &str, + configuration: &Configuration, +) -> Result { + match eval_with_configuration(string, configuration) { + Ok(Value::String(string)) => Ok(string), + Ok(value) => Err(Error::expected_string(value)), + Err(error) => Err(error), + } +} + +/// Evaluate the given expression string expecting an integer with the given configuration. +/// +/// *See the [crate doc](index.html) for more examples and explanations of the expression format.* +pub fn eval_int_with_configuration( + string: &str, + configuration: &Configuration, +) -> Result { + match eval_with_configuration(string, configuration) { + Ok(Value::Int(int)) => Ok(int), + Ok(value) => Err(Error::expected_int(value)), + Err(error) => Err(error), + } +} + +/// Evaluate the given expression string expecting a float with the given configuration. +/// +/// *See the [crate doc](index.html) for more examples and explanations of the expression format.* +pub fn eval_float_with_configuration( + string: &str, + configuration: &Configuration, +) -> Result { + match eval_with_configuration(string, configuration) { + Ok(Value::Float(float)) => Ok(float), + Ok(value) => Err(Error::expected_float(value)), + Err(error) => Err(error), + } +} + +/// Evaluate the given expression string expecting a boolean with the given configuration. +/// +/// *See the [crate doc](index.html) for more examples and explanations of the expression format.* +pub fn eval_boolean_with_configuration( + string: &str, + configuration: &Configuration, +) -> Result { + match eval_with_configuration(string, configuration) { + Ok(Value::Boolean(boolean)) => Ok(boolean), + Ok(value) => Err(Error::expected_boolean(value)), + Err(error) => Err(error), + } +} + +/// Evaluate the given expression string expecting a tuple with the given configuration. +/// +/// *See the [crate doc](index.html) for more examples and explanations of the expression format.* +pub fn eval_tuple_with_configuration( + string: &str, + configuration: &Configuration, +) -> Result, Error> { + match eval_with_configuration(string, configuration) { + Ok(Value::Tuple(tuple)) => Ok(tuple), + Ok(value) => Err(Error::expected_tuple(value)), + Err(error) => Err(error), + } +} diff --git a/tests/integration.rs b/tests/integration.rs index 36c5f74..b1c7b93 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -336,3 +336,32 @@ fn test_no_panic() { )) .is_ok()); } + +#[test] +fn test_shortcut_functions() { + let mut configuration = HashMapConfiguration::new(); + configuration.insert_variable("string", Value::from("a string")); + + // assert_eq!(eval_string("???")); + assert_eq!( + eval_string_with_configuration("string", &configuration), + Ok("a string".to_string()) + ); + assert_eq!(eval_float("3.3"), Ok(3.3)); + assert_eq!( + eval_float_with_configuration("3.3", &configuration), + Ok(3.3) + ); + assert_eq!(eval_int("3"), Ok(3)); + assert_eq!(eval_int_with_configuration("3", &configuration), Ok(3)); + assert_eq!(eval_boolean("true"), Ok(true)); + assert_eq!( + eval_boolean_with_configuration("true", &configuration), + Ok(true) + ); + assert_eq!(eval_tuple("3,3"), Ok(vec![Value::Int(3), Value::Int(3)])); + assert_eq!( + eval_tuple_with_configuration("3,3", &configuration), + Ok(vec![Value::Int(3), Value::Int(3)]) + ); +}