Merge pull request #75 from ISibboI/isibboi/i73_add_call_function

Change context trait.
This commit is contained in:
ISibboI 2021-05-28 14:20:28 +03:00 committed by GitHub
commit 4b3ae378a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 138 additions and 85 deletions

View File

@ -1,33 +1,50 @@
//! A context defines methods to retrieve variable values and call functions for literals in an expression tree.
//! If mutable, it also allows to assign to variables.
//!
//! 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.
//! 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.
use std::collections::HashMap; use std::collections::HashMap;
use crate::{function::Function, value::value_type::ValueType, EvalexprError, EvalexprResult}; use crate::{function::Function, value::value_type::ValueType, EvalexprError, EvalexprResult};
use crate::value::Value; use crate::value::Value;
/// A mutable context for an expression tree. /// An immutable context.
///
/// A context defines methods to retrieve values and functions for literals in an expression tree.
/// In addition, it also allows the manipulation of values and functions.
/// 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.
/// 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 { 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>;
/// Returns the function that is linked to the given identifier. /// Calls the function that is linked to the given identifier with the given argument.
fn get_function(&self, identifier: &str) -> Option<&Function>; /// If no function with the given identifier is found, this method returns `EvalexprError::FunctionIdentifierNotFound`.
fn call_function(&self, identifier: &str, argument: &Value) -> EvalexprResult<Value>;
}
/// Links the given value to the given identifier. /// A context that allows to assign to variables.
pub trait ContextWithMutableVariables: Context {
/// Sets the variable with the given identifier to the given value.
fn set_value(&mut self, _identifier: String, _value: Value) -> EvalexprResult<()> { fn set_value(&mut self, _identifier: String, _value: Value) -> EvalexprResult<()> {
Err(EvalexprError::ContextNotManipulable) Err(EvalexprError::ContextNotMutable)
}
/// Links the given function to the given identifier.
fn set_function(&mut self, _identifier: String, _function: Function) -> EvalexprResult<()> {
Err(EvalexprError::ContextNotManipulable)
} }
} }
/// A context that allows to assign to function identifiers.
pub trait ContextWithMutableFunctions: Context {
/// Sets the function with the given identifier to the given function.
fn set_function(&mut self, _identifier: String, _function: Function) -> EvalexprResult<()> {
Err(EvalexprError::ContextNotMutable)
}
}
/*/// A context that allows to retrieve functions programmatically.
pub trait GetFunctionContext: Context {
/// Returns the function that is linked to the given identifier.
///
/// This might not be possible for all functions, as some might be hard-coded.
/// In this case, a special error variant should be returned (Not yet implemented).
fn get_function(&self, identifier: &str) -> Option<&Function>;
}*/
/// A context that returns `None` for each identifier. /// A context that returns `None` for each identifier.
pub struct EmptyContext; pub struct EmptyContext;
@ -36,8 +53,10 @@ impl Context for EmptyContext {
None None
} }
fn get_function(&self, _identifier: &str) -> Option<&Function> { fn call_function(&self, identifier: &str, _argument: &Value) -> EvalexprResult<Value> {
None Err(EvalexprError::FunctionIdentifierNotFound(
identifier.to_string(),
))
} }
} }
@ -66,10 +85,18 @@ impl Context for HashMapContext {
self.variables.get(identifier) self.variables.get(identifier)
} }
fn get_function(&self, identifier: &str) -> Option<&Function> { fn call_function(&self, identifier: &str, argument: &Value) -> EvalexprResult<Value> {
self.functions.get(identifier) if let Some(function) = self.functions.get(identifier) {
function.call(argument)
} else {
Err(EvalexprError::FunctionIdentifierNotFound(
identifier.to_string(),
))
}
} }
}
impl ContextWithMutableVariables for HashMapContext {
fn set_value(&mut self, identifier: String, value: Value) -> EvalexprResult<()> { fn set_value(&mut self, identifier: String, value: Value) -> EvalexprResult<()> {
if let Some(existing_value) = self.variables.get_mut(&identifier) { if let Some(existing_value) = self.variables.get_mut(&identifier) {
if ValueType::from(&existing_value) == ValueType::from(&value) { if ValueType::from(&existing_value) == ValueType::from(&value) {
@ -84,7 +111,9 @@ impl Context for HashMapContext {
self.variables.insert(identifier, value); self.variables.insert(identifier, value);
Ok(()) Ok(())
} }
}
impl ContextWithMutableFunctions for HashMapContext {
fn set_function(&mut self, identifier: String, function: Function) -> EvalexprResult<()> { fn set_function(&mut self, identifier: String, function: Function) -> EvalexprResult<()> {
self.functions.insert(identifier, function); self.functions.insert(identifier, function);
Ok(()) Ok(())

View File

@ -106,7 +106,7 @@ impl fmt::Display for EvalexprError {
"Regular expression {:?} is invalid: {:?}", "Regular expression {:?} is invalid: {:?}",
regex, message regex, message
), ),
ContextNotManipulable => write!(f, "Cannot manipulate context"), ContextNotMutable => write!(f, "Cannot manipulate context"),
IllegalEscapeSequence(string) => write!(f, "Illegal escape sequence: {}", string), IllegalEscapeSequence(string) => write!(f, "Illegal escape sequence: {}", string),
CustomMessage(message) => write!(f, "Error: {}", message), CustomMessage(message) => write!(f, "Error: {}", message),
} }

View File

@ -191,7 +191,7 @@ pub enum EvalexprError {
}, },
/// A modification was attempted on a `Context` that does not allow modifications. /// A modification was attempted on a `Context` that does not allow modifications.
ContextNotManipulable, ContextNotMutable,
/// An escape sequence within a string literal is illegal. /// An escape sequence within a string literal is illegal.
IllegalEscapeSequence(String), IllegalEscapeSequence(String),

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
token, tree, value::TupleType, Context, EmptyType, EvalexprError, EvalexprResult, FloatType, token, tree, value::TupleType, Context, ContextWithMutableVariables, EmptyType, EvalexprError,
HashMapContext, IntType, Node, Value, EMPTY_VALUE, EvalexprResult, FloatType, HashMapContext, IntType, Node, Value, EMPTY_VALUE,
}; };
/// Evaluate the given expression string. /// Evaluate the given expression string.
@ -33,7 +33,7 @@ pub fn eval(string: &str) -> EvalexprResult<Value> {
/// ``` /// ```
/// ///
/// *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_context(string: &str, context: &dyn Context) -> EvalexprResult<Value> { pub fn eval_with_context<C: Context>(string: &str, context: &C) -> EvalexprResult<Value> {
tree::tokens_to_operator_tree(token::tokenize(string)?)?.eval_with_context(context) tree::tokens_to_operator_tree(token::tokenize(string)?)?.eval_with_context(context)
} }
@ -52,7 +52,10 @@ pub fn eval_with_context(string: &str, context: &dyn Context) -> EvalexprResult<
/// ``` /// ```
/// ///
/// *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_context_mut(string: &str, context: &mut dyn Context) -> EvalexprResult<Value> { pub fn eval_with_context_mut<C: ContextWithMutableVariables>(
string: &str,
context: &mut C,
) -> EvalexprResult<Value> {
tree::tokens_to_operator_tree(token::tokenize(string)?)?.eval_with_context_mut(context) tree::tokens_to_operator_tree(token::tokenize(string)?)?.eval_with_context_mut(context)
} }
@ -137,7 +140,7 @@ pub fn eval_empty(string: &str) -> EvalexprResult<EmptyType> {
/// Evaluate the given expression string into a string with the given context. /// 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_context(string: &str, context: &dyn Context) -> EvalexprResult<String> { pub fn eval_string_with_context<C: Context>(string: &str, context: &C) -> EvalexprResult<String> {
match eval_with_context(string, context) { 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)),
@ -148,7 +151,7 @@ pub fn eval_string_with_context(string: &str, context: &dyn Context) -> Evalexpr
/// Evaluate the given expression string into an integer with the given context. /// 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_context(string: &str, context: &dyn Context) -> EvalexprResult<IntType> { pub fn eval_int_with_context<C: Context>(string: &str, context: &C) -> EvalexprResult<IntType> {
match eval_with_context(string, context) { 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)),
@ -159,7 +162,7 @@ pub fn eval_int_with_context(string: &str, context: &dyn Context) -> EvalexprRes
/// Evaluate the given expression string into a float with the given context. /// 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_context(string: &str, context: &dyn Context) -> EvalexprResult<FloatType> { pub fn eval_float_with_context<C: Context>(string: &str, context: &C) -> EvalexprResult<FloatType> {
match eval_with_context(string, context) { 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)),
@ -171,7 +174,10 @@ pub fn eval_float_with_context(string: &str, context: &dyn Context) -> EvalexprR
/// If the result of the expression is an integer, it is silently converted into a float. /// If the result of the expression is an integer, it is silently converted into a float.
/// ///
/// *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_number_with_context(string: &str, context: &dyn Context) -> EvalexprResult<FloatType> { pub fn eval_number_with_context<C: Context>(
string: &str,
context: &C,
) -> EvalexprResult<FloatType> {
match eval_with_context(string, context) { match eval_with_context(string, context) {
Ok(Value::Float(float)) => Ok(float), Ok(Value::Float(float)) => Ok(float),
Ok(Value::Int(int)) => Ok(int as FloatType), Ok(Value::Int(int)) => Ok(int as FloatType),
@ -183,7 +189,7 @@ pub fn eval_number_with_context(string: &str, context: &dyn Context) -> Evalexpr
/// Evaluate the given expression string into a boolean with the given context. /// 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_context(string: &str, context: &dyn Context) -> EvalexprResult<bool> { pub fn eval_boolean_with_context<C: Context>(string: &str, context: &C) -> EvalexprResult<bool> {
match eval_with_context(string, context) { 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)),
@ -194,7 +200,7 @@ pub fn eval_boolean_with_context(string: &str, context: &dyn Context) -> Evalexp
/// Evaluate the given expression string into a tuple with the given context. /// 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_context(string: &str, context: &dyn Context) -> EvalexprResult<TupleType> { pub fn eval_tuple_with_context<C: Context>(string: &str, context: &C) -> EvalexprResult<TupleType> {
match eval_with_context(string, context) { 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)),
@ -205,7 +211,7 @@ pub fn eval_tuple_with_context(string: &str, context: &dyn Context) -> EvalexprR
/// Evaluate the given expression string into an empty value with the given context. /// Evaluate the given expression string into an empty value 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_empty_with_context(string: &str, context: &dyn Context) -> EvalexprResult<EmptyType> { pub fn eval_empty_with_context<C: Context>(string: &str, context: &C) -> EvalexprResult<EmptyType> {
match eval_with_context(string, context) { match eval_with_context(string, context) {
Ok(Value::Empty) => Ok(EMPTY_VALUE), Ok(Value::Empty) => Ok(EMPTY_VALUE),
Ok(value) => Err(EvalexprError::expected_empty(value)), Ok(value) => Err(EvalexprError::expected_empty(value)),
@ -216,9 +222,9 @@ pub fn eval_empty_with_context(string: &str, context: &dyn Context) -> EvalexprR
/// Evaluate the given expression string into a string with the given mutable context. /// Evaluate the given expression string into a string with the given mutable 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_context_mut( pub fn eval_string_with_context_mut<C: ContextWithMutableVariables>(
string: &str, string: &str,
context: &mut dyn Context, context: &mut C,
) -> EvalexprResult<String> { ) -> EvalexprResult<String> {
match eval_with_context_mut(string, context) { match eval_with_context_mut(string, context) {
Ok(Value::String(string)) => Ok(string), Ok(Value::String(string)) => Ok(string),
@ -230,9 +236,9 @@ pub fn eval_string_with_context_mut(
/// Evaluate the given expression string into an integer with the given mutable context. /// Evaluate the given expression string into an integer with the given mutable 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_context_mut( pub fn eval_int_with_context_mut<C: ContextWithMutableVariables>(
string: &str, string: &str,
context: &mut dyn Context, context: &mut C,
) -> EvalexprResult<IntType> { ) -> EvalexprResult<IntType> {
match eval_with_context_mut(string, context) { match eval_with_context_mut(string, context) {
Ok(Value::Int(int)) => Ok(int), Ok(Value::Int(int)) => Ok(int),
@ -244,9 +250,9 @@ pub fn eval_int_with_context_mut(
/// Evaluate the given expression string into a float with the given mutable context. /// Evaluate the given expression string into a float with the given mutable 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_context_mut( pub fn eval_float_with_context_mut<C: ContextWithMutableVariables>(
string: &str, string: &str,
context: &mut dyn Context, context: &mut C,
) -> EvalexprResult<FloatType> { ) -> EvalexprResult<FloatType> {
match eval_with_context_mut(string, context) { match eval_with_context_mut(string, context) {
Ok(Value::Float(float)) => Ok(float), Ok(Value::Float(float)) => Ok(float),
@ -259,9 +265,9 @@ pub fn eval_float_with_context_mut(
/// If the result of the expression is an integer, it is silently converted into a float. /// If the result of the expression is an integer, it is silently converted into a float.
/// ///
/// *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_number_with_context_mut( pub fn eval_number_with_context_mut<C: ContextWithMutableVariables>(
string: &str, string: &str,
context: &mut dyn Context, context: &mut C,
) -> EvalexprResult<FloatType> { ) -> EvalexprResult<FloatType> {
match eval_with_context_mut(string, context) { match eval_with_context_mut(string, context) {
Ok(Value::Float(float)) => Ok(float), Ok(Value::Float(float)) => Ok(float),
@ -274,9 +280,9 @@ pub fn eval_number_with_context_mut(
/// Evaluate the given expression string into a boolean with the given mutable context. /// Evaluate the given expression string into a boolean with the given mutable 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_context_mut( pub fn eval_boolean_with_context_mut<C: ContextWithMutableVariables>(
string: &str, string: &str,
context: &mut dyn Context, context: &mut C,
) -> EvalexprResult<bool> { ) -> EvalexprResult<bool> {
match eval_with_context_mut(string, context) { match eval_with_context_mut(string, context) {
Ok(Value::Boolean(boolean)) => Ok(boolean), Ok(Value::Boolean(boolean)) => Ok(boolean),
@ -288,9 +294,9 @@ pub fn eval_boolean_with_context_mut(
/// Evaluate the given expression string into a tuple with the given mutable context. /// Evaluate the given expression string into a tuple with the given mutable 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_context_mut( pub fn eval_tuple_with_context_mut<C: ContextWithMutableVariables>(
string: &str, string: &str,
context: &mut dyn Context, context: &mut C,
) -> EvalexprResult<TupleType> { ) -> EvalexprResult<TupleType> {
match eval_with_context_mut(string, context) { match eval_with_context_mut(string, context) {
Ok(Value::Tuple(tuple)) => Ok(tuple), Ok(Value::Tuple(tuple)) => Ok(tuple),
@ -302,9 +308,9 @@ pub fn eval_tuple_with_context_mut(
/// Evaluate the given expression string into an empty value with the given mutable context. /// Evaluate the given expression string into an empty value with the given mutable 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_empty_with_context_mut( pub fn eval_empty_with_context_mut<C: ContextWithMutableVariables>(
string: &str, string: &str,
context: &mut dyn Context, context: &mut C,
) -> EvalexprResult<EmptyType> { ) -> EvalexprResult<EmptyType> {
match eval_with_context_mut(string, context) { match eval_with_context_mut(string, context) {
Ok(Value::Empty) => Ok(EMPTY_VALUE), Ok(Value::Empty) => Ok(EMPTY_VALUE),

View File

@ -196,7 +196,7 @@
//! use evalexpr::*; //! use evalexpr::*;
//! //!
//! let mut context = HashMapContext::new(); //! let mut context = HashMapContext::new();
//! assert_eq!(eval_with_context("a = 5", &context), Err(EvalexprError::ContextNotManipulable)); //! assert_eq!(eval_with_context("a = 5", &context), Err(EvalexprError::ContextNotMutable));
//! assert_eq!(eval_empty_with_context_mut("a = 5", &mut context), Ok(EMPTY_VALUE)); //! assert_eq!(eval_empty_with_context_mut("a = 5", &mut context), Ok(EMPTY_VALUE));
//! assert_eq!(eval_empty_with_context_mut("a = 5.0", &mut context), //! assert_eq!(eval_empty_with_context_mut("a = 5.0", &mut context),
//! Err(EvalexprError::expected_int(5.0.into()))); //! Err(EvalexprError::expected_int(5.0.into())));
@ -259,7 +259,7 @@
//! let mut context = HashMapContext::new(); //! let mut context = HashMapContext::new();
//! assert_eq!(eval_with_context_mut("a = 5;", &mut context), Ok(Value::from(()))); //! assert_eq!(eval_with_context_mut("a = 5;", &mut context), Ok(Value::from(())));
//! // Assignments require mutable contexts //! // Assignments require mutable contexts
//! assert_eq!(eval_with_context("a = 6", &context), Err(EvalexprError::ContextNotManipulable)); //! assert_eq!(eval_with_context("a = 6", &context), Err(EvalexprError::ContextNotMutable));
//! // The HashMapContext is type safe //! // The HashMapContext is type safe
//! assert_eq!(eval_with_context_mut("a = 5.5", &mut context), //! assert_eq!(eval_with_context_mut("a = 5.5", &mut context),
//! Err(EvalexprError::ExpectedInt { actual: Value::from(5.5) })); //! Err(EvalexprError::ExpectedInt { actual: Value::from(5.5) }));
@ -488,7 +488,10 @@ extern crate serde;
extern crate serde_derive; extern crate serde_derive;
pub use crate::{ pub use crate::{
context::{Context, EmptyContext, HashMapContext}, context::{
Context, ContextWithMutableFunctions, ContextWithMutableVariables, EmptyContext,
HashMapContext,
},
error::{EvalexprError, EvalexprResult}, error::{EvalexprError, EvalexprResult},
function::Function, function::Function,
interface::*, interface::*,

View File

@ -1,6 +1,6 @@
use crate::function::builtin::builtin_function; use crate::function::builtin::builtin_function;
use crate::{context::Context, error::*, value::Value}; use crate::{context::Context, error::*, value::Value, ContextWithMutableVariables};
use std::borrow::Borrow; use std::borrow::Borrow;
mod display; mod display;
@ -169,7 +169,11 @@ impl Operator {
} }
/// Evaluates the operator with the given arguments and context. /// Evaluates the operator with the given arguments and context.
pub(crate) fn eval(&self, arguments: &[Value], context: &dyn Context) -> EvalexprResult<Value> { pub(crate) fn eval<C: Context>(
&self,
arguments: &[Value],
context: &C,
) -> EvalexprResult<Value> {
use crate::operator::Operator::*; use crate::operator::Operator::*;
match self { match self {
RootNode => { RootNode => {
@ -408,7 +412,7 @@ impl Operator {
Ok(Value::Boolean(!a)) Ok(Value::Boolean(!a))
}, },
Assign | AddAssign | SubAssign | MulAssign | DivAssign | ModAssign | ExpAssign Assign | AddAssign | SubAssign | MulAssign | DivAssign | ModAssign | ExpAssign
| AndAssign | OrAssign => Err(EvalexprError::ContextNotManipulable), | AndAssign | OrAssign => Err(EvalexprError::ContextNotMutable),
Tuple => Ok(Value::Tuple(arguments.into())), Tuple => Ok(Value::Tuple(arguments.into())),
Chain => { Chain => {
if arguments.is_empty() { if arguments.is_empty() {
@ -437,24 +441,27 @@ impl Operator {
expect_operator_argument_amount(arguments.len(), 1)?; expect_operator_argument_amount(arguments.len(), 1)?;
let arguments = &arguments[0]; let arguments = &arguments[0];
if let Some(function) = context.get_function(&identifier) { match context.call_function(&identifier, arguments) {
function.call(arguments) Err(EvalexprError::FunctionIdentifierNotFound(_)) => {
} else if let Some(builtin_function) = builtin_function(&identifier) { if let Some(builtin_function) = builtin_function(&identifier) {
builtin_function.call(arguments) builtin_function.call(arguments)
} else { } else {
Err(EvalexprError::FunctionIdentifierNotFound( Err(EvalexprError::FunctionIdentifierNotFound(
identifier.clone(), identifier.clone(),
)) ))
}
},
result => result,
} }
}, },
} }
} }
/// Evaluates the operator with the given arguments and mutable context. /// Evaluates the operator with the given arguments and mutable context.
pub(crate) fn eval_mut( pub(crate) fn eval_mut<C: ContextWithMutableVariables>(
&self, &self,
arguments: &[Value], arguments: &[Value],
context: &mut dyn Context, context: &mut C,
) -> EvalexprResult<Value> { ) -> EvalexprResult<Value> {
use crate::operator::Operator::*; use crate::operator::Operator::*;
match self { match self {

View File

@ -1,11 +1,10 @@
use crate::{ use crate::{
token::Token, token::Token,
value::{TupleType, EMPTY_VALUE}, value::{TupleType, EMPTY_VALUE},
EmptyType, FloatType, HashMapContext, IntType, Context, ContextWithMutableVariables, EmptyType, FloatType, HashMapContext, IntType,
}; };
use crate::{ use crate::{
context::Context,
error::{EvalexprError, EvalexprResult}, error::{EvalexprError, EvalexprResult},
operator::*, operator::*,
value::Value, value::Value,
@ -119,7 +118,7 @@ impl Node {
/// Evaluates the operator tree rooted at this node with the given context. /// 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_context(&self, context: &dyn Context) -> EvalexprResult<Value> { pub fn eval_with_context<C: Context>(&self, context: &C) -> EvalexprResult<Value> {
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_context(context)?); arguments.push(child.eval_with_context(context)?);
@ -130,7 +129,10 @@ impl Node {
/// Evaluates the operator tree rooted at this node with the given mutable context. /// Evaluates the operator tree rooted at this node with the given mutable 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_context_mut(&self, context: &mut dyn Context) -> EvalexprResult<Value> { pub fn eval_with_context_mut<C: ContextWithMutableVariables>(
&self,
context: &mut C,
) -> EvalexprResult<Value> {
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_context_mut(context)?); arguments.push(child.eval_with_context_mut(context)?);
@ -148,7 +150,7 @@ impl Node {
/// Evaluates the operator tree rooted at this node into a string with an the given context. /// 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_context(&self, context: &dyn Context) -> EvalexprResult<String> { pub fn eval_string_with_context<C: Context>(&self, context: &C) -> EvalexprResult<String> {
match self.eval_with_context(context) { 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)),
@ -159,7 +161,7 @@ impl Node {
/// Evaluates the operator tree rooted at this node into a float with an the given context. /// 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_context(&self, context: &dyn Context) -> EvalexprResult<FloatType> { pub fn eval_float_with_context<C: Context>(&self, context: &C) -> EvalexprResult<FloatType> {
match self.eval_with_context(context) { 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)),
@ -170,7 +172,7 @@ impl Node {
/// Evaluates the operator tree rooted at this node into an integer with an the given context. /// 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_context(&self, context: &dyn Context) -> EvalexprResult<IntType> { pub fn eval_int_with_context<C: Context>(&self, context: &C) -> EvalexprResult<IntType> {
match self.eval_with_context(context) { 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)),
@ -182,7 +184,7 @@ impl Node {
/// If the result of the expression is an integer, it is silently converted into a float. /// If the result of the expression is an integer, it is silently converted into a float.
/// ///
/// 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_number_with_context(&self, context: &dyn Context) -> EvalexprResult<FloatType> { pub fn eval_number_with_context<C: Context>(&self, context: &C) -> EvalexprResult<FloatType> {
match self.eval_with_context(context) { match self.eval_with_context(context) {
Ok(Value::Int(int)) => Ok(int as FloatType), Ok(Value::Int(int)) => Ok(int as FloatType),
Ok(Value::Float(float)) => Ok(float), Ok(Value::Float(float)) => Ok(float),
@ -194,7 +196,7 @@ impl Node {
/// Evaluates the operator tree rooted at this node into a boolean with an the given context. /// 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_context(&self, context: &dyn Context) -> EvalexprResult<bool> { pub fn eval_boolean_with_context<C: Context>(&self, context: &C) -> EvalexprResult<bool> {
match self.eval_with_context(context) { 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)),
@ -205,7 +207,7 @@ impl Node {
/// Evaluates the operator tree rooted at this node into a tuple with an the given context. /// 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_context(&self, context: &dyn Context) -> EvalexprResult<TupleType> { pub fn eval_tuple_with_context<C: Context>(&self, context: &C) -> EvalexprResult<TupleType> {
match self.eval_with_context(context) { 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)),
@ -216,7 +218,7 @@ impl Node {
/// Evaluates the operator tree rooted at this node into an empty value with an the given context. /// Evaluates the operator tree rooted at this node into an empty value 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_empty_with_context(&self, context: &dyn Context) -> EvalexprResult<EmptyType> { pub fn eval_empty_with_context<C: Context>(&self, context: &C) -> EvalexprResult<EmptyType> {
match self.eval_with_context(context) { match self.eval_with_context(context) {
Ok(Value::Empty) => Ok(EMPTY_VALUE), Ok(Value::Empty) => Ok(EMPTY_VALUE),
Ok(value) => Err(EvalexprError::expected_empty(value)), Ok(value) => Err(EvalexprError::expected_empty(value)),
@ -227,9 +229,9 @@ impl Node {
/// Evaluates the operator tree rooted at this node into a string with an the given mutable context. /// Evaluates the operator tree rooted at this node into a string with an the given mutable 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_context_mut( pub fn eval_string_with_context_mut<C: ContextWithMutableVariables>(
&self, &self,
context: &mut dyn Context, context: &mut C,
) -> EvalexprResult<String> { ) -> EvalexprResult<String> {
match self.eval_with_context_mut(context) { match self.eval_with_context_mut(context) {
Ok(Value::String(string)) => Ok(string), Ok(Value::String(string)) => Ok(string),
@ -241,9 +243,9 @@ impl Node {
/// Evaluates the operator tree rooted at this node into a float with an the given mutable context. /// Evaluates the operator tree rooted at this node into a float with an the given mutable 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_context_mut( pub fn eval_float_with_context_mut<C: ContextWithMutableVariables>(
&self, &self,
context: &mut dyn Context, context: &mut C,
) -> EvalexprResult<FloatType> { ) -> EvalexprResult<FloatType> {
match self.eval_with_context_mut(context) { match self.eval_with_context_mut(context) {
Ok(Value::Float(float)) => Ok(float), Ok(Value::Float(float)) => Ok(float),
@ -255,7 +257,10 @@ impl Node {
/// Evaluates the operator tree rooted at this node into an integer with an the given mutable context. /// Evaluates the operator tree rooted at this node into an integer with an the given mutable 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_context_mut(&self, context: &mut dyn Context) -> EvalexprResult<IntType> { pub fn eval_int_with_context_mut<C: ContextWithMutableVariables>(
&self,
context: &mut C,
) -> EvalexprResult<IntType> {
match self.eval_with_context_mut(context) { match self.eval_with_context_mut(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)),
@ -267,9 +272,9 @@ impl Node {
/// If the result of the expression is an integer, it is silently converted into a float. /// If the result of the expression is an integer, it is silently converted into a float.
/// ///
/// 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_number_with_context_mut( pub fn eval_number_with_context_mut<C: ContextWithMutableVariables>(
&self, &self,
context: &mut dyn Context, context: &mut C,
) -> EvalexprResult<FloatType> { ) -> EvalexprResult<FloatType> {
match self.eval_with_context_mut(context) { match self.eval_with_context_mut(context) {
Ok(Value::Int(int)) => Ok(int as FloatType), Ok(Value::Int(int)) => Ok(int as FloatType),
@ -282,7 +287,10 @@ impl Node {
/// Evaluates the operator tree rooted at this node into a boolean with an the given mutable context. /// Evaluates the operator tree rooted at this node into a boolean with an the given mutable 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_context_mut(&self, context: &mut dyn Context) -> EvalexprResult<bool> { pub fn eval_boolean_with_context_mut<C: ContextWithMutableVariables>(
&self,
context: &mut C,
) -> EvalexprResult<bool> {
match self.eval_with_context_mut(context) { match self.eval_with_context_mut(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)),
@ -293,9 +301,9 @@ impl Node {
/// Evaluates the operator tree rooted at this node into a tuple with an the given mutable context. /// Evaluates the operator tree rooted at this node into a tuple with an the given mutable 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_context_mut( pub fn eval_tuple_with_context_mut<C: ContextWithMutableVariables>(
&self, &self,
context: &mut dyn Context, context: &mut C,
) -> EvalexprResult<TupleType> { ) -> EvalexprResult<TupleType> {
match self.eval_with_context_mut(context) { match self.eval_with_context_mut(context) {
Ok(Value::Tuple(tuple)) => Ok(tuple), Ok(Value::Tuple(tuple)) => Ok(tuple),
@ -307,9 +315,9 @@ impl Node {
/// Evaluates the operator tree rooted at this node into an empty value with an the given mutable context. /// Evaluates the operator tree rooted at this node into an empty value with an the given mutable 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_empty_with_context_mut( pub fn eval_empty_with_context_mut<C: ContextWithMutableVariables>(
&self, &self,
context: &mut dyn Context, context: &mut C,
) -> EvalexprResult<EmptyType> { ) -> EvalexprResult<EmptyType> {
match self.eval_with_context_mut(context) { match self.eval_with_context_mut(context) {
Ok(Value::Empty) => Ok(EMPTY_VALUE), Ok(Value::Empty) => Ok(EMPTY_VALUE),