Rename Context
to ContextMut
and Configuration
to Context
Get rid of two different words for the same concept. Relates to #22
This commit is contained in:
parent
7decb7c895
commit
9283d5412f
@ -4,7 +4,7 @@
|
||||
|
||||
### Added
|
||||
|
||||
* Add the `Context` trait, that is a manipulable configuration
|
||||
* Add the `ContextMut` trait, that is a manipulable configuration/context
|
||||
* Add `ContextNotManipulable` error variant for the `EmptyContext`
|
||||
|
||||
### Removed
|
||||
@ -12,6 +12,7 @@
|
||||
### Changed
|
||||
|
||||
* Get rid of some unwraps to improve safety
|
||||
* Rename `Configuration` to `Context`
|
||||
* Rename `HashMapConfiguration` to `HashMapContext` and `EmptyConfiguration` to `EmptyContext`
|
||||
|
||||
### Fixed
|
||||
|
66
README.md
66
README.md
@ -48,19 +48,19 @@ And you can use **variables** and **functions** in expressions like this:
|
||||
use evalexpr::*;
|
||||
use evalexpr::error::expect_number;
|
||||
|
||||
let mut configuration = HashMapConfiguration::new();
|
||||
configuration.insert_variable("five", 5);
|
||||
configuration.insert_variable("twelve", 12);
|
||||
configuration.insert_function("f", Function::new(Some(1) /* argument amount */, Box::new(|arguments| {
|
||||
let mut context = HashMapContext::new();
|
||||
context.set_value("five", 5).unwrap(); // Do proper error handling here
|
||||
context.set_value("twelve", 12).unwrap(); // Do proper error handling here
|
||||
context.set_function("f", Function::new(Some(1) /* argument amount */, Box::new(|arguments| {
|
||||
if let Value::Int(int) = arguments[0] {
|
||||
Ok(Value::Int(int / 2))
|
||||
} else if let Value::Float(float) = arguments[0] {
|
||||
Ok(Value::Float(float / 2.0))
|
||||
} else {
|
||||
Err(Error::expected_number(arguments[0].clone()))
|
||||
Err(EvalexprError::expected_number(arguments[0].clone()))
|
||||
}
|
||||
})));
|
||||
configuration.insert_function("avg", Function::new(Some(2) /* argument amount */, Box::new(|arguments| {
|
||||
}))).unwrap(); // Do proper error handling here
|
||||
context.set_function("avg", Function::new(Some(2) /* argument amount */, Box::new(|arguments| {
|
||||
expect_number(&arguments[0])?;
|
||||
expect_number(&arguments[1])?;
|
||||
|
||||
@ -69,14 +69,14 @@ configuration.insert_function("avg", Function::new(Some(2) /* argument amount */
|
||||
} else {
|
||||
Ok(Value::Float((arguments[0].as_float()? + arguments[1].as_float()?) / 2.0))
|
||||
}
|
||||
})));
|
||||
}))).unwrap(); // Do proper error handling here
|
||||
|
||||
assert_eq!(eval_with_configuration("five + 8 > f(twelve)", &configuration), Ok(Value::from(true)));
|
||||
// `eval_with_configuration` returns a variant of the `Value` enum,
|
||||
// while `eval_[type]_with_configuration` returns the respective type directly.
|
||||
assert_eq!(eval_with_context("five + 8 > f(twelve)", &context), Ok(Value::from(true)));
|
||||
// `eval_with_context` returns a variant of the `Value` enum,
|
||||
// while `eval_[type]_with_context` returns the respective type directly.
|
||||
// Both can be used interchangeably.
|
||||
assert_eq!(eval_boolean_with_configuration("five + 8 > f(twelve)", &configuration), Ok(true));
|
||||
assert_eq!(eval_with_configuration("avg(2, 4) == 3", &configuration), Ok(Value::from(true)));
|
||||
assert_eq!(eval_boolean_with_context("five + 8 > f(twelve)", &context), Ok(true));
|
||||
assert_eq!(eval_with_context("avg(2, 4) == 3", &context), Ok(Value::from(true)));
|
||||
```
|
||||
|
||||
You can also **precompile** expressions like this:
|
||||
@ -84,20 +84,20 @@ You can also **precompile** expressions like this:
|
||||
```rust
|
||||
use evalexpr::*;
|
||||
|
||||
let precompiled = build_operator_tree("a * b - c > 5").unwrap();
|
||||
let precompiled = build_operator_tree("a * b - c > 5").unwrap(); // Do proper error handling here
|
||||
|
||||
let mut configuration = HashMapConfiguration::new();
|
||||
configuration.insert_variable("a", 6);
|
||||
configuration.insert_variable("b", 2);
|
||||
configuration.insert_variable("c", 3);
|
||||
assert_eq!(precompiled.eval_with_configuration(&configuration), Ok(Value::from(true)));
|
||||
let mut context = HashMapContext::new();
|
||||
context.set_value("a", 6).unwrap(); // Do proper error handling here
|
||||
context.set_value("b", 2).unwrap(); // Do proper error handling here
|
||||
context.set_value("c", 3).unwrap(); // Do proper error handling here
|
||||
assert_eq!(precompiled.eval_with_context(&context), Ok(Value::from(true)));
|
||||
|
||||
configuration.insert_variable("c", 8);
|
||||
assert_eq!(precompiled.eval_with_configuration(&configuration), Ok(Value::from(false)));
|
||||
// `Node::eval_with_configuration` returns a variant of the `Value` enum,
|
||||
// while `Node::eval_[type]_with_configuration` returns the respective type directly.
|
||||
context.set_value("c", 8).unwrap(); // Do proper error handling here
|
||||
assert_eq!(precompiled.eval_with_context(&context), Ok(Value::from(false)));
|
||||
// `Node::eval_with_context` returns a variant of the `Value` enum,
|
||||
// while `Node::eval_[type]_with_context` returns the respective type directly.
|
||||
// Both can be used interchangeably.
|
||||
assert_eq!(precompiled.eval_boolean_with_configuration(&configuration), Ok(false));
|
||||
assert_eq!(precompiled.eval_boolean_with_context(&context), Ok(false));
|
||||
```
|
||||
|
||||
## Features
|
||||
@ -200,12 +200,12 @@ Values have a precedence of 200.
|
||||
This crate allows to compile parameterizable formulas by using variables.
|
||||
A variable is a literal in the formula, that does not contain whitespace or can be parsed as value.
|
||||
The user needs to provide bindings to the variables for evaluation.
|
||||
This is done with the `Configuration` trait.
|
||||
This is done with the `Context` trait.
|
||||
Two structs implementing this trait are predefined.
|
||||
There is `EmptyConfiguration`, that returns `None` for each request, and `HashMapConfiguration`, that stores mappings from literals to variables in a hash map.
|
||||
There is `EmptyContext`, that returns `None` for each request, and `HashMapContext`, that stores mappings from literals to variables in a hash map.
|
||||
|
||||
Variables do not have fixed types in the expression itself, but aer typed by the configuration.
|
||||
The `Configuration` trait contains a function that takes a string literal and returns a `Value` enum.
|
||||
Variables do not have fixed types in the expression itself, but aer typed by the context.
|
||||
The `Context` trait contains a function that takes a string literal and returns a `Value` enum.
|
||||
The variant of this enum decides the type on evaluation.
|
||||
|
||||
Variables have a precedence of 200.
|
||||
@ -229,7 +229,7 @@ Also, most numeric functions need to differentiate between being called with int
|
||||
Functions are identified by literals, like variables as well.
|
||||
A literal identifies a function, if it is followed by an opening brace `(`, another literal, or a value.
|
||||
|
||||
Same as variables, function bindings are provided by the user via a `Configuration`.
|
||||
Same as variables, function bindings are provided by the user via a `Context`.
|
||||
Functions have a precedence of 190.
|
||||
|
||||
### Examplary variables and functions in expressions:
|
||||
@ -254,15 +254,15 @@ Example parsing with [ron format](docs.rs/ron):
|
||||
extern crate ron;
|
||||
use evalexpr::*;
|
||||
|
||||
let mut configuration = HashMapConfiguration::new();
|
||||
configuration.insert_variable("five", 5);
|
||||
let mut context = HashMapContext::new();
|
||||
context.set_value("five", 5).unwrap(); // Do proper error handling here
|
||||
|
||||
// In ron format, strings are surrounded by "
|
||||
let serialized_free = "\"five * five\"";
|
||||
match ron::de::from_str::<Node>(serialized_free) {
|
||||
Ok(free) => assert_eq!(free.eval_with_configuration(&configuration), Ok(Value::from(25))),
|
||||
Ok(free) => assert_eq!(free.eval_with_context(&context), Ok(Value::from(25))),
|
||||
Err(error) => {
|
||||
// Handle error
|
||||
() // Handle error
|
||||
},
|
||||
}
|
||||
```
|
||||
|
@ -7,11 +7,11 @@ use value::value_type::ValueType;
|
||||
|
||||
use crate::value::Value;
|
||||
|
||||
/// A configuration for an expression tree.
|
||||
/// A context for an expression tree.
|
||||
///
|
||||
/// A configuration defines methods to retrieve values and functions for literals in an expression tree.
|
||||
/// This crate implements two basic variants, the `EmptyContext`, that returns `None` for each identifier, and the `HashMapContext`, that stores its mappings in hash maps.
|
||||
pub trait Configuration {
|
||||
/// A context defines methods to retrieve values and functions for literals in an expression tree.
|
||||
/// This crate implements two basic variants, the `EmptyContext`, that returns `None` for each identifier and cannot be manipulated, and the `HashMapContext`, that stores its mappings in hash maps.
|
||||
pub trait Context {
|
||||
/// Returns the value that is linked to the given identifier.
|
||||
fn get_value(&self, identifier: &str) -> Option<&Value>;
|
||||
|
||||
@ -19,12 +19,12 @@ pub trait Configuration {
|
||||
fn get_function(&self, identifier: &str) -> Option<&Function>;
|
||||
}
|
||||
|
||||
/// A context for an expression tree.
|
||||
/// A mutable context for an expression tree.
|
||||
///
|
||||
/// In addition to all functionality of a `Configuration`, a context also allows the manipulation of values and functions.
|
||||
/// This crate implements two basic variants, the `EmptyContext`, that returns `Err` for each identifier, and the `HashMapContext`, that stores its mappings in hash maps.
|
||||
/// In addition to all functionality of a `Context`, a mutable context also allows the manipulation of values and functions.
|
||||
/// This crate implements two basic variants, the `EmptyContext`, that returns an error for each manipulation, and the `HashMapContext`, that stores its mappings in hash maps.
|
||||
/// The HashMapContext is type-safe and returns an error if the user tries to assign a value of a different type than before to an identifier.
|
||||
pub trait Context: Configuration {
|
||||
pub trait ContextMut: Context {
|
||||
/// Links the given value to the given identifier.
|
||||
fn set_value<S: Into<String>, V: Into<Value>>(&mut self, identifier: S, value: V) -> EvalexprResult<()>;
|
||||
|
||||
@ -32,10 +32,10 @@ pub trait Context: Configuration {
|
||||
fn set_function<S: Into<String>>(&mut self, identifier: S, function: Function) -> EvalexprResult<()>;
|
||||
}
|
||||
|
||||
/// A configuration that returns `None` for each identifier.
|
||||
/// A context that returns `None` for each identifier.
|
||||
pub struct EmptyContext;
|
||||
|
||||
impl Configuration for EmptyContext {
|
||||
impl Context for EmptyContext {
|
||||
fn get_value(&self, _identifier: &str) -> Option<&Value> {
|
||||
None
|
||||
}
|
||||
@ -45,7 +45,7 @@ impl Configuration for EmptyContext {
|
||||
}
|
||||
}
|
||||
|
||||
impl Context for EmptyContext {
|
||||
impl ContextMut for EmptyContext {
|
||||
fn set_value<S: Into<String>, V: Into<Value>>(&mut self, _identifier: S, _value: V) -> EvalexprResult<()> {
|
||||
Err(EvalexprError::ContextNotManipulable)
|
||||
}
|
||||
@ -75,7 +75,7 @@ impl HashMapContext {
|
||||
}
|
||||
}
|
||||
|
||||
impl Configuration for HashMapContext {
|
||||
impl Context for HashMapContext {
|
||||
fn get_value(&self, identifier: &str) -> Option<&Value> {
|
||||
self.variables.get(identifier)
|
||||
}
|
||||
@ -85,7 +85,7 @@ impl Configuration for HashMapContext {
|
||||
}
|
||||
}
|
||||
|
||||
impl Context for HashMapContext {
|
||||
impl ContextMut for HashMapContext {
|
||||
fn set_value<S: Into<String>, V: Into<Value>>(&mut self, identifier: S, value: V) -> Result<(), EvalexprError> {
|
||||
let identifier = identifier.into();
|
||||
let value = value.into();
|
||||
|
@ -40,12 +40,12 @@ impl fmt::Display for EvalexprError {
|
||||
),
|
||||
VariableIdentifierNotFound(identifier) => write!(
|
||||
f,
|
||||
"Variable identifier is not bound to anything by configuration: {:?}.",
|
||||
"Variable identifier is not bound to anything by context: {:?}.",
|
||||
identifier
|
||||
),
|
||||
FunctionIdentifierNotFound(identifier) => write!(
|
||||
f,
|
||||
"Function identifier is not bound to anything by configuration: {:?}.",
|
||||
"Function identifier is not bound to anything by context: {:?}.",
|
||||
identifier
|
||||
),
|
||||
TypeError { expected, actual } => {
|
||||
|
@ -81,10 +81,10 @@ pub enum EvalexprError {
|
||||
/// If it does, please file a bug report.
|
||||
PrecedenceViolation,
|
||||
|
||||
/// A `VariableIdentifier` operation did not find its value in the configuration.
|
||||
/// A `VariableIdentifier` operation did not find its value in the context.
|
||||
VariableIdentifierNotFound(String),
|
||||
|
||||
/// A `FunctionIdentifier` operation did not find its value in the configuration.
|
||||
/// A `FunctionIdentifier` operation did not find its value in the context.
|
||||
FunctionIdentifierNotFound(String),
|
||||
|
||||
/// A value has the wrong type.
|
||||
|
@ -4,18 +4,18 @@ use value::Value;
|
||||
pub(crate) mod builtin;
|
||||
|
||||
/// A user-defined function.
|
||||
/// Functions can be used in expressions by storing them in a `Configuration`.
|
||||
/// Functions can be used in expressions by storing them in a `Context`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use evalexpr::*;
|
||||
///
|
||||
/// let mut configuration = HashMapConfiguration::new();
|
||||
/// configuration.insert_function("id", Function::new(Some(1), Box::new(|arguments| {
|
||||
/// let mut context = HashMapContext::new();
|
||||
/// context.set_function("id", Function::new(Some(1), Box::new(|arguments| {
|
||||
/// Ok(arguments[0].clone())
|
||||
/// })));
|
||||
/// assert_eq!(eval_with_configuration("id(4)", &configuration), Ok(Value::from(4)));
|
||||
/// }))).unwrap(); // Do proper error handling here
|
||||
/// assert_eq!(eval_with_context("id(4)", &context), Ok(Value::from(4)));
|
||||
/// ```
|
||||
pub struct Function {
|
||||
argument_amount: Option<usize>,
|
||||
|
@ -1,4 +1,4 @@
|
||||
use Configuration;
|
||||
use Context;
|
||||
use EmptyContext;
|
||||
use EvalexprError;
|
||||
use FloatType;
|
||||
@ -21,35 +21,35 @@ use value::TupleType;
|
||||
///
|
||||
/// *See the [crate doc](index.html) for more examples and explanations of the expression format.*
|
||||
pub fn eval(string: &str) -> Result<Value, EvalexprError> {
|
||||
eval_with_configuration(string, &EmptyContext)
|
||||
eval_with_context(string, &EmptyContext)
|
||||
}
|
||||
|
||||
/// Evaluate the given expression string with the given configuration.
|
||||
/// Evaluate the given expression string with the given context.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use evalexpr::*;
|
||||
///
|
||||
/// let mut configuration = HashMapContext::new();
|
||||
/// configuration.set_value("one", 1).unwrap(); // Do proper error handling here
|
||||
/// configuration.set_value("two", 2).unwrap(); // Do proper error handling here
|
||||
/// configuration.set_value("three", 3).unwrap(); // Do proper error handling here
|
||||
/// assert_eq!(eval_with_configuration("one + two + three", &configuration), Ok(Value::from(6)));
|
||||
/// let mut context = HashMapContext::new();
|
||||
/// context.set_value("one", 1).unwrap(); // Do proper error handling here
|
||||
/// context.set_value("two", 2).unwrap(); // Do proper error handling here
|
||||
/// context.set_value("three", 3).unwrap(); // Do proper error handling here
|
||||
/// assert_eq!(eval_with_context("one + two + three", &context), Ok(Value::from(6)));
|
||||
/// ```
|
||||
///
|
||||
/// *See the [crate doc](index.html) for more examples and explanations of the expression format.*
|
||||
pub fn eval_with_configuration(
|
||||
pub fn eval_with_context(
|
||||
string: &str,
|
||||
configuration: &Configuration,
|
||||
context: &Context,
|
||||
) -> Result<Value, EvalexprError> {
|
||||
tree::tokens_to_operator_tree(token::tokenize(string)?)?.eval_with_configuration(configuration)
|
||||
tree::tokens_to_operator_tree(token::tokenize(string)?)?.eval_with_context(context)
|
||||
}
|
||||
|
||||
/// Build the operator tree for the given expression string.
|
||||
///
|
||||
/// The operator tree can later on be evaluated directly.
|
||||
/// This saves runtime if a single expression should be evaluated multiple times, for example with differing configurations.
|
||||
/// This saves runtime if a single expression should be evaluated multiple times, for example with differing contexts.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -58,15 +58,15 @@ pub fn eval_with_configuration(
|
||||
///
|
||||
/// let precomputed = build_operator_tree("one + two + three").unwrap(); // Do proper error handling here
|
||||
///
|
||||
/// let mut configuration = HashMapContext::new();
|
||||
/// configuration.set_value("one", 1).unwrap(); // Do proper error handling here
|
||||
/// configuration.set_value("two", 2).unwrap(); // Do proper error handling here
|
||||
/// configuration.set_value("three", 3).unwrap(); // Do proper error handling here
|
||||
/// let mut context = HashMapContext::new();
|
||||
/// context.set_value("one", 1).unwrap(); // Do proper error handling here
|
||||
/// context.set_value("two", 2).unwrap(); // Do proper error handling here
|
||||
/// context.set_value("three", 3).unwrap(); // Do proper error handling here
|
||||
///
|
||||
/// assert_eq!(precomputed.eval_with_configuration(&configuration), Ok(Value::from(6)));
|
||||
/// assert_eq!(precomputed.eval_with_context(&context), Ok(Value::from(6)));
|
||||
///
|
||||
/// configuration.set_value("three", 5).unwrap(); // Do proper error handling here
|
||||
/// assert_eq!(precomputed.eval_with_configuration(&configuration), Ok(Value::from(8)));
|
||||
/// context.set_value("three", 5).unwrap(); // Do proper error handling here
|
||||
/// assert_eq!(precomputed.eval_with_context(&context), Ok(Value::from(8)));
|
||||
/// ```
|
||||
///
|
||||
/// *See the [crate doc](index.html) for more examples and explanations of the expression format.*
|
||||
@ -129,70 +129,70 @@ pub fn eval_tuple(string: &str) -> Result<TupleType, EvalexprError> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Evaluate the given expression string into a string with the given configuration.
|
||||
/// Evaluate the given expression string into a string with the given context.
|
||||
///
|
||||
/// *See the [crate doc](index.html) for more examples and explanations of the expression format.*
|
||||
pub fn eval_string_with_configuration(
|
||||
pub fn eval_string_with_context(
|
||||
string: &str,
|
||||
configuration: &Configuration,
|
||||
context: &Context,
|
||||
) -> Result<String, EvalexprError> {
|
||||
match eval_with_configuration(string, configuration) {
|
||||
match eval_with_context(string, context) {
|
||||
Ok(Value::String(string)) => Ok(string),
|
||||
Ok(value) => Err(EvalexprError::expected_string(value)),
|
||||
Err(error) => Err(error),
|
||||
}
|
||||
}
|
||||
|
||||
/// Evaluate the given expression string into an integer with the given configuration.
|
||||
/// Evaluate the given expression string into an integer with the given context.
|
||||
///
|
||||
/// *See the [crate doc](index.html) for more examples and explanations of the expression format.*
|
||||
pub fn eval_int_with_configuration(
|
||||
pub fn eval_int_with_context(
|
||||
string: &str,
|
||||
configuration: &Configuration,
|
||||
context: &Context,
|
||||
) -> Result<IntType, EvalexprError> {
|
||||
match eval_with_configuration(string, configuration) {
|
||||
match eval_with_context(string, context) {
|
||||
Ok(Value::Int(int)) => Ok(int),
|
||||
Ok(value) => Err(EvalexprError::expected_int(value)),
|
||||
Err(error) => Err(error),
|
||||
}
|
||||
}
|
||||
|
||||
/// Evaluate the given expression string into a float with the given configuration.
|
||||
/// Evaluate the given expression string into a float with the given context.
|
||||
///
|
||||
/// *See the [crate doc](index.html) for more examples and explanations of the expression format.*
|
||||
pub fn eval_float_with_configuration(
|
||||
pub fn eval_float_with_context(
|
||||
string: &str,
|
||||
configuration: &Configuration,
|
||||
context: &Context,
|
||||
) -> Result<FloatType, EvalexprError> {
|
||||
match eval_with_configuration(string, configuration) {
|
||||
match eval_with_context(string, context) {
|
||||
Ok(Value::Float(float)) => Ok(float),
|
||||
Ok(value) => Err(EvalexprError::expected_float(value)),
|
||||
Err(error) => Err(error),
|
||||
}
|
||||
}
|
||||
|
||||
/// Evaluate the given expression string into a boolean with the given configuration.
|
||||
/// Evaluate the given expression string into a boolean with the given context.
|
||||
///
|
||||
/// *See the [crate doc](index.html) for more examples and explanations of the expression format.*
|
||||
pub fn eval_boolean_with_configuration(
|
||||
pub fn eval_boolean_with_context(
|
||||
string: &str,
|
||||
configuration: &Configuration,
|
||||
context: &Context,
|
||||
) -> Result<bool, EvalexprError> {
|
||||
match eval_with_configuration(string, configuration) {
|
||||
match eval_with_context(string, context) {
|
||||
Ok(Value::Boolean(boolean)) => Ok(boolean),
|
||||
Ok(value) => Err(EvalexprError::expected_boolean(value)),
|
||||
Err(error) => Err(error),
|
||||
}
|
||||
}
|
||||
|
||||
/// Evaluate the given expression string into a tuple with the given configuration.
|
||||
/// Evaluate the given expression string into a tuple with the given context.
|
||||
///
|
||||
/// *See the [crate doc](index.html) for more examples and explanations of the expression format.*
|
||||
pub fn eval_tuple_with_configuration(
|
||||
pub fn eval_tuple_with_context(
|
||||
string: &str,
|
||||
configuration: &Configuration,
|
||||
context: &Context,
|
||||
) -> Result<TupleType, EvalexprError> {
|
||||
match eval_with_configuration(string, configuration) {
|
||||
match eval_with_context(string, context) {
|
||||
Ok(Value::Tuple(tuple)) => Ok(tuple),
|
||||
Ok(value) => Err(EvalexprError::expected_tuple(value)),
|
||||
Err(error) => Err(error),
|
||||
|
60
src/lib.rs
60
src/lib.rs
@ -35,10 +35,10 @@
|
||||
//! use evalexpr::*;
|
||||
//! use evalexpr::error::expect_number;
|
||||
//!
|
||||
//! let mut configuration = HashMapContext::new();
|
||||
//! configuration.set_value("five", 5).unwrap(); // Do proper error handling here
|
||||
//! configuration.set_value("twelve", 12).unwrap(); // Do proper error handling here
|
||||
//! configuration.set_function("f", Function::new(Some(1) /* argument amount */, Box::new(|arguments| {
|
||||
//! let mut context = HashMapContext::new();
|
||||
//! context.set_value("five", 5).unwrap(); // Do proper error handling here
|
||||
//! context.set_value("twelve", 12).unwrap(); // Do proper error handling here
|
||||
//! context.set_function("f", Function::new(Some(1) /* argument amount */, Box::new(|arguments| {
|
||||
//! if let Value::Int(int) = arguments[0] {
|
||||
//! Ok(Value::Int(int / 2))
|
||||
//! } else if let Value::Float(float) = arguments[0] {
|
||||
@ -47,7 +47,7 @@
|
||||
//! Err(EvalexprError::expected_number(arguments[0].clone()))
|
||||
//! }
|
||||
//! }))).unwrap(); // Do proper error handling here
|
||||
//! configuration.set_function("avg", Function::new(Some(2) /* argument amount */, Box::new(|arguments| {
|
||||
//! context.set_function("avg", Function::new(Some(2) /* argument amount */, Box::new(|arguments| {
|
||||
//! expect_number(&arguments[0])?;
|
||||
//! expect_number(&arguments[1])?;
|
||||
//!
|
||||
@ -58,12 +58,12 @@
|
||||
//! }
|
||||
//! }))).unwrap(); // Do proper error handling here
|
||||
//!
|
||||
//! assert_eq!(eval_with_configuration("five + 8 > f(twelve)", &configuration), Ok(Value::from(true)));
|
||||
//! // `eval_with_configuration` returns a variant of the `Value` enum,
|
||||
//! // while `eval_[type]_with_configuration` returns the respective type directly.
|
||||
//! assert_eq!(eval_with_context("five + 8 > f(twelve)", &context), Ok(Value::from(true)));
|
||||
//! // `eval_with_context` returns a variant of the `Value` enum,
|
||||
//! // while `eval_[type]_with_context` returns the respective type directly.
|
||||
//! // Both can be used interchangeably.
|
||||
//! assert_eq!(eval_boolean_with_configuration("five + 8 > f(twelve)", &configuration), Ok(true));
|
||||
//! assert_eq!(eval_with_configuration("avg(2, 4) == 3", &configuration), Ok(Value::from(true)));
|
||||
//! assert_eq!(eval_boolean_with_context("five + 8 > f(twelve)", &context), Ok(true));
|
||||
//! assert_eq!(eval_with_context("avg(2, 4) == 3", &context), Ok(Value::from(true)));
|
||||
//! ```
|
||||
//!
|
||||
//! You can also **precompile** expressions like this:
|
||||
@ -73,18 +73,18 @@
|
||||
//!
|
||||
//! let precompiled = build_operator_tree("a * b - c > 5").unwrap(); // Do proper error handling here
|
||||
//!
|
||||
//! let mut configuration = HashMapContext::new();
|
||||
//! configuration.set_value("a", 6).unwrap(); // Do proper error handling here
|
||||
//! configuration.set_value("b", 2).unwrap(); // Do proper error handling here
|
||||
//! configuration.set_value("c", 3).unwrap(); // Do proper error handling here
|
||||
//! assert_eq!(precompiled.eval_with_configuration(&configuration), Ok(Value::from(true)));
|
||||
//! let mut context = HashMapContext::new();
|
||||
//! context.set_value("a", 6).unwrap(); // Do proper error handling here
|
||||
//! context.set_value("b", 2).unwrap(); // Do proper error handling here
|
||||
//! context.set_value("c", 3).unwrap(); // Do proper error handling here
|
||||
//! assert_eq!(precompiled.eval_with_context(&context), Ok(Value::from(true)));
|
||||
//!
|
||||
//! configuration.set_value("c", 8).unwrap(); // Do proper error handling here
|
||||
//! assert_eq!(precompiled.eval_with_configuration(&configuration), Ok(Value::from(false)));
|
||||
//! // `Node::eval_with_configuration` returns a variant of the `Value` enum,
|
||||
//! // while `Node::eval_[type]_with_configuration` returns the respective type directly.
|
||||
//! context.set_value("c", 8).unwrap(); // Do proper error handling here
|
||||
//! assert_eq!(precompiled.eval_with_context(&context), Ok(Value::from(false)));
|
||||
//! // `Node::eval_with_context` returns a variant of the `Value` enum,
|
||||
//! // while `Node::eval_[type]_with_context` returns the respective type directly.
|
||||
//! // Both can be used interchangeably.
|
||||
//! assert_eq!(precompiled.eval_boolean_with_configuration(&configuration), Ok(false));
|
||||
//! assert_eq!(precompiled.eval_boolean_with_context(&context), Ok(false));
|
||||
//! ```
|
||||
//!
|
||||
//! ## Features
|
||||
@ -187,12 +187,12 @@
|
||||
//! This crate allows to compile parameterizable formulas by using variables.
|
||||
//! A variable is a literal in the formula, that does not contain whitespace or can be parsed as value.
|
||||
//! The user needs to provide bindings to the variables for evaluation.
|
||||
//! This is done with the `Configuration` trait.
|
||||
//! This is done with the `Context` trait.
|
||||
//! Two structs implementing this trait are predefined.
|
||||
//! There is `EmptyConfiguration`, that returns `None` for each request, and `HashMapConfiguration`, that stores mappings from literals to variables in a hash map.
|
||||
//! There is `EmptyContext`, that returns `None` for each request, and `HashMapContext`, that stores mappings from literals to variables in a hash map.
|
||||
//!
|
||||
//! Variables do not have fixed types in the expression itself, but aer typed by the configuration.
|
||||
//! The `Configuration` trait contains a function that takes a string literal and returns a `Value` enum.
|
||||
//! Variables do not have fixed types in the expression itself, but aer typed by the context.
|
||||
//! The `Context` trait contains a function that takes a string literal and returns a `Value` enum.
|
||||
//! The variant of this enum decides the type on evaluation.
|
||||
//!
|
||||
//! Variables have a precedence of 200.
|
||||
@ -216,7 +216,7 @@
|
||||
//! Functions are identified by literals, like variables as well.
|
||||
//! A literal identifies a function, if it is followed by an opening brace `(`, another literal, or a value.
|
||||
//!
|
||||
//! Same as variables, function bindings are provided by the user via a `Configuration`.
|
||||
//! Same as variables, function bindings are provided by the user via a `Context`.
|
||||
//! Functions have a precedence of 190.
|
||||
//!
|
||||
//! ### Examplary variables and functions in expressions:
|
||||
@ -241,15 +241,15 @@
|
||||
//! extern crate ron;
|
||||
//! use evalexpr::*;
|
||||
//!
|
||||
//! let mut configuration = HashMapContext::new();
|
||||
//! configuration.set_value("five", 5).unwrap(); // Do proper error handling here
|
||||
//! let mut context = HashMapContext::new();
|
||||
//! context.set_value("five", 5).unwrap(); // Do proper error handling here
|
||||
//!
|
||||
//! // In ron format, strings are surrounded by "
|
||||
//! let serialized_free = "\"five * five\"";
|
||||
//! match ron::de::from_str::<Node>(serialized_free) {
|
||||
//! Ok(free) => assert_eq!(free.eval_with_configuration(&configuration), Ok(Value::from(25))),
|
||||
//! Ok(free) => assert_eq!(free.eval_with_context(&context), Ok(Value::from(25))),
|
||||
//! Err(error) => {
|
||||
//! // Handle error
|
||||
//! () // Handle error
|
||||
//! },
|
||||
//! }
|
||||
//! ```
|
||||
@ -269,7 +269,7 @@ extern crate ron;
|
||||
#[cfg(feature = "serde")]
|
||||
extern crate serde;
|
||||
|
||||
pub use context::{Configuration, Context, EmptyContext, HashMapContext};
|
||||
pub use context::{Context, ContextMut, EmptyContext, HashMapContext};
|
||||
pub use error::{EvalexprError, EvalexprResult};
|
||||
pub use function::Function;
|
||||
pub use interface::*;
|
||||
|
@ -2,7 +2,7 @@ use std::fmt::{Debug, Display};
|
||||
|
||||
use function::builtin::builtin_function;
|
||||
|
||||
use crate::{context::Configuration, error::*, value::Value};
|
||||
use crate::{context::Context, error::*, value::Value};
|
||||
|
||||
mod display;
|
||||
|
||||
@ -28,11 +28,11 @@ pub trait Operator: Debug + Display {
|
||||
// Make this a const fn once #57563 is resolved
|
||||
fn argument_amount(&self) -> usize;
|
||||
|
||||
/// Evaluates the operator with the given arguments and configuration.
|
||||
/// Evaluates the operator with the given arguments and context.
|
||||
fn eval(
|
||||
&self,
|
||||
arguments: &[Value],
|
||||
configuration: &Configuration,
|
||||
context: &Context,
|
||||
) -> Result<Value, EvalexprError>;
|
||||
}
|
||||
|
||||
@ -125,7 +125,7 @@ impl Operator for RootNode {
|
||||
fn eval(
|
||||
&self,
|
||||
arguments: &[Value],
|
||||
_configuration: &Configuration,
|
||||
_context: &Context,
|
||||
) -> Result<Value, EvalexprError> {
|
||||
expect_operator_argument_amount(arguments.len(), 1)?;
|
||||
Ok(arguments[0].clone())
|
||||
@ -148,7 +148,7 @@ impl Operator for Add {
|
||||
fn eval(
|
||||
&self,
|
||||
arguments: &[Value],
|
||||
_configuration: &Configuration,
|
||||
_context: &Context,
|
||||
) -> Result<Value, EvalexprError> {
|
||||
expect_operator_argument_amount(arguments.len(), 2)?;
|
||||
expect_number(&arguments[0])?;
|
||||
@ -188,7 +188,7 @@ impl Operator for Sub {
|
||||
fn eval(
|
||||
&self,
|
||||
arguments: &[Value],
|
||||
_configuration: &Configuration,
|
||||
_context: &Context,
|
||||
) -> Result<Value, EvalexprError> {
|
||||
expect_operator_argument_amount(arguments.len(), 2)?;
|
||||
expect_number(&arguments[0])?;
|
||||
@ -228,7 +228,7 @@ impl Operator for Neg {
|
||||
fn eval(
|
||||
&self,
|
||||
arguments: &[Value],
|
||||
_configuration: &Configuration,
|
||||
_context: &Context,
|
||||
) -> Result<Value, EvalexprError> {
|
||||
expect_operator_argument_amount(arguments.len(), 1)?;
|
||||
expect_number(&arguments[0])?;
|
||||
@ -262,7 +262,7 @@ impl Operator for Mul {
|
||||
fn eval(
|
||||
&self,
|
||||
arguments: &[Value],
|
||||
_configuration: &Configuration,
|
||||
_context: &Context,
|
||||
) -> Result<Value, EvalexprError> {
|
||||
expect_operator_argument_amount(arguments.len(), 2)?;
|
||||
expect_number(&arguments[0])?;
|
||||
@ -302,7 +302,7 @@ impl Operator for Div {
|
||||
fn eval(
|
||||
&self,
|
||||
arguments: &[Value],
|
||||
_configuration: &Configuration,
|
||||
_context: &Context,
|
||||
) -> Result<Value, EvalexprError> {
|
||||
expect_operator_argument_amount(arguments.len(), 2)?;
|
||||
expect_number(&arguments[0])?;
|
||||
@ -342,7 +342,7 @@ impl Operator for Mod {
|
||||
fn eval(
|
||||
&self,
|
||||
arguments: &[Value],
|
||||
_configuration: &Configuration,
|
||||
_context: &Context,
|
||||
) -> Result<Value, EvalexprError> {
|
||||
expect_operator_argument_amount(arguments.len(), 2)?;
|
||||
expect_number(&arguments[0])?;
|
||||
@ -382,7 +382,7 @@ impl Operator for Exp {
|
||||
fn eval(
|
||||
&self,
|
||||
arguments: &[Value],
|
||||
_configuration: &Configuration,
|
||||
_context: &Context,
|
||||
) -> Result<Value, EvalexprError> {
|
||||
expect_operator_argument_amount(arguments.len(), 2)?;
|
||||
expect_number(&arguments[0])?;
|
||||
@ -413,7 +413,7 @@ impl Operator for Eq {
|
||||
fn eval(
|
||||
&self,
|
||||
arguments: &[Value],
|
||||
_configuration: &Configuration,
|
||||
_context: &Context,
|
||||
) -> Result<Value, EvalexprError> {
|
||||
expect_operator_argument_amount(arguments.len(), 2)?;
|
||||
|
||||
@ -441,7 +441,7 @@ impl Operator for Neq {
|
||||
fn eval(
|
||||
&self,
|
||||
arguments: &[Value],
|
||||
_configuration: &Configuration,
|
||||
_context: &Context,
|
||||
) -> Result<Value, EvalexprError> {
|
||||
expect_operator_argument_amount(arguments.len(), 2)?;
|
||||
|
||||
@ -469,7 +469,7 @@ impl Operator for Gt {
|
||||
fn eval(
|
||||
&self,
|
||||
arguments: &[Value],
|
||||
_configuration: &Configuration,
|
||||
_context: &Context,
|
||||
) -> Result<Value, EvalexprError> {
|
||||
expect_operator_argument_amount(arguments.len(), 2)?;
|
||||
expect_number(&arguments[0])?;
|
||||
@ -507,7 +507,7 @@ impl Operator for Lt {
|
||||
fn eval(
|
||||
&self,
|
||||
arguments: &[Value],
|
||||
_configuration: &Configuration,
|
||||
_context: &Context,
|
||||
) -> Result<Value, EvalexprError> {
|
||||
expect_operator_argument_amount(arguments.len(), 2)?;
|
||||
expect_number(&arguments[0])?;
|
||||
@ -545,7 +545,7 @@ impl Operator for Geq {
|
||||
fn eval(
|
||||
&self,
|
||||
arguments: &[Value],
|
||||
_configuration: &Configuration,
|
||||
_context: &Context,
|
||||
) -> Result<Value, EvalexprError> {
|
||||
expect_operator_argument_amount(arguments.len(), 2)?;
|
||||
expect_number(&arguments[0])?;
|
||||
@ -583,7 +583,7 @@ impl Operator for Leq {
|
||||
fn eval(
|
||||
&self,
|
||||
arguments: &[Value],
|
||||
_configuration: &Configuration,
|
||||
_context: &Context,
|
||||
) -> Result<Value, EvalexprError> {
|
||||
expect_operator_argument_amount(arguments.len(), 2)?;
|
||||
expect_number(&arguments[0])?;
|
||||
@ -621,7 +621,7 @@ impl Operator for And {
|
||||
fn eval(
|
||||
&self,
|
||||
arguments: &[Value],
|
||||
_configuration: &Configuration,
|
||||
_context: &Context,
|
||||
) -> Result<Value, EvalexprError> {
|
||||
expect_operator_argument_amount(arguments.len(), 2)?;
|
||||
let a = expect_boolean(&arguments[0])?;
|
||||
@ -651,7 +651,7 @@ impl Operator for Or {
|
||||
fn eval(
|
||||
&self,
|
||||
arguments: &[Value],
|
||||
_configuration: &Configuration,
|
||||
_context: &Context,
|
||||
) -> Result<Value, EvalexprError> {
|
||||
expect_operator_argument_amount(arguments.len(), 2)?;
|
||||
let a = expect_boolean(&arguments[0])?;
|
||||
@ -681,7 +681,7 @@ impl Operator for Not {
|
||||
fn eval(
|
||||
&self,
|
||||
arguments: &[Value],
|
||||
_configuration: &Configuration,
|
||||
_context: &Context,
|
||||
) -> Result<Value, EvalexprError> {
|
||||
expect_operator_argument_amount(arguments.len(), 1)?;
|
||||
let a = expect_boolean(&arguments[0])?;
|
||||
@ -710,7 +710,7 @@ impl Operator for Tuple {
|
||||
fn eval(
|
||||
&self,
|
||||
arguments: &[Value],
|
||||
_configuration: &Configuration,
|
||||
_context: &Context,
|
||||
) -> Result<Value, EvalexprError> {
|
||||
if let Value::Tuple(tuple) = &arguments[0] {
|
||||
let mut tuple = tuple.clone();
|
||||
@ -751,7 +751,7 @@ impl Operator for Const {
|
||||
fn eval(
|
||||
&self,
|
||||
arguments: &[Value],
|
||||
_configuration: &Configuration,
|
||||
_context: &Context,
|
||||
) -> Result<Value, EvalexprError> {
|
||||
expect_operator_argument_amount(arguments.len(), 0)?;
|
||||
|
||||
@ -775,9 +775,9 @@ impl Operator for VariableIdentifier {
|
||||
fn eval(
|
||||
&self,
|
||||
_arguments: &[Value],
|
||||
configuration: &Configuration,
|
||||
context: &Context,
|
||||
) -> Result<Value, EvalexprError> {
|
||||
if let Some(value) = configuration.get_value(&self.identifier).cloned() {
|
||||
if let Some(value) = context.get_value(&self.identifier).cloned() {
|
||||
Ok(value)
|
||||
} else {
|
||||
Err(EvalexprError::VariableIdentifierNotFound(
|
||||
@ -803,7 +803,7 @@ impl Operator for FunctionIdentifier {
|
||||
fn eval(
|
||||
&self,
|
||||
arguments: &[Value],
|
||||
configuration: &Configuration,
|
||||
context: &Context,
|
||||
) -> Result<Value, EvalexprError> {
|
||||
expect_operator_argument_amount(arguments.len(), 1)?;
|
||||
|
||||
@ -813,7 +813,7 @@ impl Operator for FunctionIdentifier {
|
||||
arguments
|
||||
};
|
||||
|
||||
if let Some(function) = configuration.get_function(&self.identifier) {
|
||||
if let Some(function) = context.get_function(&self.identifier) {
|
||||
function.call(arguments)
|
||||
} else if let Some(builtin_function) = builtin_function(&self.identifier) {
|
||||
builtin_function.call(arguments)
|
||||
|
@ -4,25 +4,25 @@ use IntType;
|
||||
use token::Token;
|
||||
use value::TupleType;
|
||||
|
||||
use crate::{context::Configuration, error::EvalexprError, operator::*, value::Value};
|
||||
use crate::{context::Context, error::EvalexprError, operator::*, value::Value};
|
||||
|
||||
mod display;
|
||||
|
||||
/// A node in the operator tree.
|
||||
/// The operator tree is created by the crate-level `build_operator_tree` method.
|
||||
/// It can be evaluated for a given configuration with the `Node::eval` method.
|
||||
/// It can be evaluated for a given context with the `Node::eval` method.
|
||||
///
|
||||
/// The advantage of constructing the operator tree separately from the actual evaluation is that it can be evaluated arbitrarily often with different configurations.
|
||||
/// The advantage of constructing the operator tree separately from the actual evaluation is that it can be evaluated arbitrarily often with different contexts.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use evalexpr::*;
|
||||
///
|
||||
/// let mut configuration = HashMapContext::new();
|
||||
/// configuration.set_value("alpha", 2).unwrap(); // Do proper error handling here
|
||||
/// let mut context = HashMapContext::new();
|
||||
/// context.set_value("alpha", 2).unwrap(); // Do proper error handling here
|
||||
/// let node = build_operator_tree("1 + alpha").unwrap(); // Do proper error handling here
|
||||
/// assert_eq!(node.eval_with_configuration(&configuration), Ok(Value::from(3)));
|
||||
/// assert_eq!(node.eval_with_context(&context), Ok(Value::from(3)));
|
||||
/// ```
|
||||
///
|
||||
#[derive(Debug)]
|
||||
@ -43,130 +43,130 @@ impl Node {
|
||||
Self::new(RootNode)
|
||||
}
|
||||
|
||||
/// Evaluates the operator tree rooted at this node with the given configuration.
|
||||
/// Evaluates the operator tree rooted at this node with the given context.
|
||||
///
|
||||
/// Fails, if one of the operators in the expression tree fails.
|
||||
pub fn eval_with_configuration(
|
||||
pub fn eval_with_context(
|
||||
&self,
|
||||
configuration: &Configuration,
|
||||
context: &Context,
|
||||
) -> Result<Value, EvalexprError> {
|
||||
let mut arguments = Vec::new();
|
||||
for child in self.children() {
|
||||
arguments.push(child.eval_with_configuration(configuration)?);
|
||||
arguments.push(child.eval_with_context(context)?);
|
||||
}
|
||||
self.operator().eval(&arguments, configuration)
|
||||
self.operator().eval(&arguments, context)
|
||||
}
|
||||
|
||||
/// Evaluates the operator tree rooted at this node with an empty configuration.
|
||||
/// Evaluates the operator tree rooted at this node with an empty context.
|
||||
///
|
||||
/// Fails, if one of the operators in the expression tree fails.
|
||||
pub fn eval(&self) -> Result<Value, EvalexprError> {
|
||||
self.eval_with_configuration(&EmptyContext)
|
||||
self.eval_with_context(&EmptyContext)
|
||||
}
|
||||
|
||||
/// Evaluates the operator tree rooted at this node into a string with an the given configuration.
|
||||
/// Evaluates the operator tree rooted at this node into a string with an the given context.
|
||||
///
|
||||
/// Fails, if one of the operators in the expression tree fails.
|
||||
pub fn eval_string_with_configuration(
|
||||
pub fn eval_string_with_context(
|
||||
&self,
|
||||
configuration: &Configuration,
|
||||
context: &Context,
|
||||
) -> Result<String, EvalexprError> {
|
||||
match self.eval_with_configuration(configuration) {
|
||||
match self.eval_with_context(context) {
|
||||
Ok(Value::String(string)) => Ok(string),
|
||||
Ok(value) => Err(EvalexprError::expected_string(value)),
|
||||
Err(error) => Err(error),
|
||||
}
|
||||
}
|
||||
|
||||
/// Evaluates the operator tree rooted at this node into a float with an the given configuration.
|
||||
/// Evaluates the operator tree rooted at this node into a float with an the given context.
|
||||
///
|
||||
/// Fails, if one of the operators in the expression tree fails.
|
||||
pub fn eval_float_with_configuration(
|
||||
pub fn eval_float_with_context(
|
||||
&self,
|
||||
configuration: &Configuration,
|
||||
context: &Context,
|
||||
) -> Result<FloatType, EvalexprError> {
|
||||
match self.eval_with_configuration(configuration) {
|
||||
match self.eval_with_context(context) {
|
||||
Ok(Value::Float(float)) => Ok(float),
|
||||
Ok(value) => Err(EvalexprError::expected_float(value)),
|
||||
Err(error) => Err(error),
|
||||
}
|
||||
}
|
||||
|
||||
/// Evaluates the operator tree rooted at this node into an integer with an the given configuration.
|
||||
/// Evaluates the operator tree rooted at this node into an integer with an the given context.
|
||||
///
|
||||
/// Fails, if one of the operators in the expression tree fails.
|
||||
pub fn eval_int_with_configuration(
|
||||
pub fn eval_int_with_context(
|
||||
&self,
|
||||
configuration: &Configuration,
|
||||
context: &Context,
|
||||
) -> Result<IntType, EvalexprError> {
|
||||
match self.eval_with_configuration(configuration) {
|
||||
match self.eval_with_context(context) {
|
||||
Ok(Value::Int(int)) => Ok(int),
|
||||
Ok(value) => Err(EvalexprError::expected_int(value)),
|
||||
Err(error) => Err(error),
|
||||
}
|
||||
}
|
||||
|
||||
/// Evaluates the operator tree rooted at this node into a boolean with an the given configuration.
|
||||
/// Evaluates the operator tree rooted at this node into a boolean with an the given context.
|
||||
///
|
||||
/// Fails, if one of the operators in the expression tree fails.
|
||||
pub fn eval_boolean_with_configuration(
|
||||
pub fn eval_boolean_with_context(
|
||||
&self,
|
||||
configuration: &Configuration,
|
||||
context: &Context,
|
||||
) -> Result<bool, EvalexprError> {
|
||||
match self.eval_with_configuration(configuration) {
|
||||
match self.eval_with_context(context) {
|
||||
Ok(Value::Boolean(boolean)) => Ok(boolean),
|
||||
Ok(value) => Err(EvalexprError::expected_boolean(value)),
|
||||
Err(error) => Err(error),
|
||||
}
|
||||
}
|
||||
|
||||
/// Evaluates the operator tree rooted at this node into a tuple with an the given configuration.
|
||||
/// Evaluates the operator tree rooted at this node into a tuple with an the given context.
|
||||
///
|
||||
/// Fails, if one of the operators in the expression tree fails.
|
||||
pub fn eval_tuple_with_configuration(
|
||||
pub fn eval_tuple_with_context(
|
||||
&self,
|
||||
configuration: &Configuration,
|
||||
context: &Context,
|
||||
) -> Result<TupleType, EvalexprError> {
|
||||
match self.eval_with_configuration(configuration) {
|
||||
match self.eval_with_context(context) {
|
||||
Ok(Value::Tuple(tuple)) => Ok(tuple),
|
||||
Ok(value) => Err(EvalexprError::expected_tuple(value)),
|
||||
Err(error) => Err(error),
|
||||
}
|
||||
}
|
||||
|
||||
/// Evaluates the operator tree rooted at this node into a string with an empty configuration.
|
||||
/// Evaluates the operator tree rooted at this node into a string with an empty context.
|
||||
///
|
||||
/// Fails, if one of the operators in the expression tree fails.
|
||||
pub fn eval_string(&self) -> Result<String, EvalexprError> {
|
||||
self.eval_string_with_configuration(&EmptyContext)
|
||||
self.eval_string_with_context(&EmptyContext)
|
||||
}
|
||||
|
||||
/// Evaluates the operator tree rooted at this node into a float with an empty configuration.
|
||||
/// Evaluates the operator tree rooted at this node into a float with an empty context.
|
||||
///
|
||||
/// Fails, if one of the operators in the expression tree fails.
|
||||
pub fn eval_float(&self) -> Result<FloatType, EvalexprError> {
|
||||
self.eval_float_with_configuration(&EmptyContext)
|
||||
self.eval_float_with_context(&EmptyContext)
|
||||
}
|
||||
|
||||
/// Evaluates the operator tree rooted at this node into an integer with an empty configuration.
|
||||
/// Evaluates the operator tree rooted at this node into an integer with an empty context.
|
||||
///
|
||||
/// Fails, if one of the operators in the expression tree fails.
|
||||
pub fn eval_int(&self) -> Result<IntType, EvalexprError> {
|
||||
self.eval_int_with_configuration(&EmptyContext)
|
||||
self.eval_int_with_context(&EmptyContext)
|
||||
}
|
||||
|
||||
/// Evaluates the operator tree rooted at this node into a boolean with an empty configuration.
|
||||
/// Evaluates the operator tree rooted at this node into a boolean with an empty context.
|
||||
///
|
||||
/// Fails, if one of the operators in the expression tree fails.
|
||||
pub fn eval_boolean(&self) -> Result<bool, EvalexprError> {
|
||||
self.eval_boolean_with_configuration(&EmptyContext)
|
||||
self.eval_boolean_with_context(&EmptyContext)
|
||||
}
|
||||
|
||||
/// Evaluates the operator tree rooted at this node into a tuple with an empty configuration.
|
||||
/// Evaluates the operator tree rooted at this node into a tuple with an empty context.
|
||||
///
|
||||
/// Fails, if one of the operators in the expression tree fails.
|
||||
pub fn eval_tuple(&self) -> Result<TupleType, EvalexprError> {
|
||||
self.eval_tuple_with_configuration(&EmptyContext)
|
||||
self.eval_tuple_with_context(&EmptyContext)
|
||||
}
|
||||
|
||||
fn children(&self) -> &[Node] {
|
||||
|
@ -98,45 +98,45 @@ fn test_boolean_examples() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_with_configuration() {
|
||||
let mut configuration = HashMapContext::new();
|
||||
configuration.set_value("tr", Value::Boolean(true)).unwrap();
|
||||
configuration.set_value("fa", Value::Boolean(false)).unwrap();
|
||||
configuration.set_value("five", Value::Int(5)).unwrap();
|
||||
configuration.set_value("six", Value::Int(6)).unwrap();
|
||||
configuration.set_value("half", Value::Float(0.5)).unwrap();
|
||||
configuration.set_value("zero", Value::Int(0)).unwrap();
|
||||
fn test_with_context() {
|
||||
let mut context = HashMapContext::new();
|
||||
context.set_value("tr", Value::Boolean(true)).unwrap();
|
||||
context.set_value("fa", Value::Boolean(false)).unwrap();
|
||||
context.set_value("five", Value::Int(5)).unwrap();
|
||||
context.set_value("six", Value::Int(6)).unwrap();
|
||||
context.set_value("half", Value::Float(0.5)).unwrap();
|
||||
context.set_value("zero", Value::Int(0)).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
eval_with_configuration("tr", &configuration),
|
||||
eval_with_context("tr", &context),
|
||||
Ok(Value::Boolean(true))
|
||||
);
|
||||
assert_eq!(
|
||||
eval_with_configuration("fa", &configuration),
|
||||
eval_with_context("fa", &context),
|
||||
Ok(Value::Boolean(false))
|
||||
);
|
||||
assert_eq!(
|
||||
eval_with_configuration("tr && false", &configuration),
|
||||
eval_with_context("tr && false", &context),
|
||||
Ok(Value::Boolean(false))
|
||||
);
|
||||
assert_eq!(
|
||||
eval_with_configuration("five + six", &configuration),
|
||||
eval_with_context("five + six", &context),
|
||||
Ok(Value::Int(11))
|
||||
);
|
||||
assert_eq!(
|
||||
eval_with_configuration("five * half", &configuration),
|
||||
eval_with_context("five * half", &context),
|
||||
Ok(Value::Float(2.5))
|
||||
);
|
||||
assert_eq!(
|
||||
eval_with_configuration("five < six && true", &configuration),
|
||||
eval_with_context("five < six && true", &context),
|
||||
Ok(Value::Boolean(true))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_functions() {
|
||||
let mut configuration = HashMapContext::new();
|
||||
configuration.set_function(
|
||||
let mut context = HashMapContext::new();
|
||||
context.set_function(
|
||||
"sub2".to_string(),
|
||||
Function::new(
|
||||
Some(1),
|
||||
@ -151,34 +151,34 @@ fn test_functions() {
|
||||
}),
|
||||
),
|
||||
).unwrap();
|
||||
configuration.set_value("five".to_string(), Value::Int(5)).unwrap();
|
||||
context.set_value("five".to_string(), Value::Int(5)).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
eval_with_configuration("sub2 5", &configuration),
|
||||
eval_with_context("sub2 5", &context),
|
||||
Ok(Value::Int(3))
|
||||
);
|
||||
assert_eq!(
|
||||
eval_with_configuration("sub2(5)", &configuration),
|
||||
eval_with_context("sub2(5)", &context),
|
||||
Ok(Value::Int(3))
|
||||
);
|
||||
assert_eq!(
|
||||
eval_with_configuration("sub2 five", &configuration),
|
||||
eval_with_context("sub2 five", &context),
|
||||
Ok(Value::Int(3))
|
||||
);
|
||||
assert_eq!(
|
||||
eval_with_configuration("sub2(five)", &configuration),
|
||||
eval_with_context("sub2(five)", &context),
|
||||
Ok(Value::Int(3))
|
||||
);
|
||||
assert_eq!(
|
||||
eval_with_configuration("sub2(3) + five", &configuration),
|
||||
eval_with_context("sub2(3) + five", &context),
|
||||
Ok(Value::Int(6))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_n_ary_functions() {
|
||||
let mut configuration = HashMapContext::new();
|
||||
configuration.set_function(
|
||||
let mut context = HashMapContext::new();
|
||||
context.set_function(
|
||||
"sub2",
|
||||
Function::new(
|
||||
Some(1),
|
||||
@ -193,7 +193,7 @@ fn test_n_ary_functions() {
|
||||
}),
|
||||
),
|
||||
).unwrap();
|
||||
configuration.set_function(
|
||||
context.set_function(
|
||||
"avg",
|
||||
Function::new(
|
||||
Some(2),
|
||||
@ -211,7 +211,7 @@ fn test_n_ary_functions() {
|
||||
}),
|
||||
),
|
||||
).unwrap();
|
||||
configuration.set_function(
|
||||
context.set_function(
|
||||
"muladd",
|
||||
Function::new(
|
||||
Some(3),
|
||||
@ -233,57 +233,57 @@ fn test_n_ary_functions() {
|
||||
}),
|
||||
),
|
||||
).unwrap();
|
||||
configuration.set_function(
|
||||
context.set_function(
|
||||
"count",
|
||||
Function::new(
|
||||
None,
|
||||
Box::new(|arguments| Ok(Value::Int(arguments.len() as IntType))),
|
||||
),
|
||||
).unwrap();
|
||||
configuration.set_value("five".to_string(), Value::Int(5)).unwrap();
|
||||
context.set_value("five".to_string(), Value::Int(5)).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
eval_with_configuration("avg(7, 5)", &configuration),
|
||||
eval_with_context("avg(7, 5)", &context),
|
||||
Ok(Value::Int(6))
|
||||
);
|
||||
assert_eq!(
|
||||
eval_with_configuration("avg(sub2 5, 5)", &configuration),
|
||||
eval_with_context("avg(sub2 5, 5)", &context),
|
||||
Ok(Value::Int(4))
|
||||
);
|
||||
assert_eq!(
|
||||
eval_with_configuration("sub2(avg(3, 6))", &configuration),
|
||||
eval_with_context("sub2(avg(3, 6))", &context),
|
||||
Ok(Value::Int(2))
|
||||
);
|
||||
assert_eq!(
|
||||
eval_with_configuration("sub2 avg(3, 6)", &configuration),
|
||||
eval_with_context("sub2 avg(3, 6)", &context),
|
||||
Ok(Value::Int(2))
|
||||
);
|
||||
assert_eq!(
|
||||
eval_with_configuration("muladd(3, 6, -4)", &configuration),
|
||||
eval_with_context("muladd(3, 6, -4)", &context),
|
||||
Ok(Value::Int(14))
|
||||
);
|
||||
assert_eq!(
|
||||
eval_with_configuration("count()", &configuration),
|
||||
eval_with_context("count()", &context),
|
||||
Err(EvalexprError::WrongOperatorArgumentAmount {
|
||||
actual: 0,
|
||||
expected: 1
|
||||
})
|
||||
);
|
||||
assert_eq!(
|
||||
eval_with_configuration("count(3, 5.5, 2)", &configuration),
|
||||
eval_with_context("count(3, 5.5, 2)", &context),
|
||||
Ok(Value::Int(3))
|
||||
);
|
||||
assert_eq!(
|
||||
eval_with_configuration("count 5", &configuration),
|
||||
eval_with_context("count 5", &context),
|
||||
Ok(Value::Int(1))
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
eval_with_configuration("min(4.0, 3)", &configuration),
|
||||
eval_with_context("min(4.0, 3)", &context),
|
||||
Ok(Value::Int(3))
|
||||
);
|
||||
assert_eq!(
|
||||
eval_with_configuration("max(4.0, 3)", &configuration),
|
||||
eval_with_context("max(4.0, 3)", &context),
|
||||
Ok(Value::Float(4.0))
|
||||
);
|
||||
}
|
||||
@ -341,29 +341,29 @@ fn test_no_panic() {
|
||||
|
||||
#[test]
|
||||
fn test_shortcut_functions() {
|
||||
let mut configuration = HashMapContext::new();
|
||||
configuration.set_value("string", Value::from("a string")).unwrap();
|
||||
let mut context = HashMapContext::new();
|
||||
context.set_value("string", Value::from("a string")).unwrap();
|
||||
|
||||
// assert_eq!(eval_string("???"));
|
||||
assert_eq!(
|
||||
eval_string_with_configuration("string", &configuration),
|
||||
eval_string_with_context("string", &context),
|
||||
Ok("a string".to_string())
|
||||
);
|
||||
assert_eq!(eval_float("3.3"), Ok(3.3));
|
||||
assert_eq!(
|
||||
eval_float_with_configuration("3.3", &configuration),
|
||||
eval_float_with_context("3.3", &context),
|
||||
Ok(3.3)
|
||||
);
|
||||
assert_eq!(eval_int("3"), Ok(3));
|
||||
assert_eq!(eval_int_with_configuration("3", &configuration), Ok(3));
|
||||
assert_eq!(eval_int_with_context("3", &context), Ok(3));
|
||||
assert_eq!(eval_boolean("true"), Ok(true));
|
||||
assert_eq!(
|
||||
eval_boolean_with_configuration("true", &configuration),
|
||||
eval_boolean_with_context("true", &context),
|
||||
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),
|
||||
eval_tuple_with_context("3,3", &context),
|
||||
Ok(vec![Value::Int(3), Value::Int(3)])
|
||||
);
|
||||
|
||||
@ -371,21 +371,21 @@ fn test_shortcut_functions() {
|
||||
assert_eq!(
|
||||
build_operator_tree("string")
|
||||
.unwrap()
|
||||
.eval_string_with_configuration(&configuration),
|
||||
.eval_string_with_context(&context),
|
||||
Ok("a string".to_string())
|
||||
);
|
||||
assert_eq!(build_operator_tree("3.3").unwrap().eval_float(), Ok(3.3));
|
||||
assert_eq!(
|
||||
build_operator_tree("3.3")
|
||||
.unwrap()
|
||||
.eval_float_with_configuration(&configuration),
|
||||
.eval_float_with_context(&context),
|
||||
Ok(3.3)
|
||||
);
|
||||
assert_eq!(build_operator_tree("3").unwrap().eval_int(), Ok(3));
|
||||
assert_eq!(
|
||||
build_operator_tree("3")
|
||||
.unwrap()
|
||||
.eval_int_with_configuration(&configuration),
|
||||
.eval_int_with_context(&context),
|
||||
Ok(3)
|
||||
);
|
||||
assert_eq!(
|
||||
@ -395,7 +395,7 @@ fn test_shortcut_functions() {
|
||||
assert_eq!(
|
||||
build_operator_tree("true")
|
||||
.unwrap()
|
||||
.eval_boolean_with_configuration(&configuration),
|
||||
.eval_boolean_with_context(&context),
|
||||
Ok(true)
|
||||
);
|
||||
assert_eq!(
|
||||
@ -405,7 +405,7 @@ fn test_shortcut_functions() {
|
||||
assert_eq!(
|
||||
build_operator_tree("3,3")
|
||||
.unwrap()
|
||||
.eval_tuple_with_configuration(&configuration),
|
||||
.eval_tuple_with_context(&context),
|
||||
Ok(vec![Value::Int(3), Value::Int(3)])
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user