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