Merge pull request #75 from ISibboI/isibboi/i73_add_call_function
Change context trait.
This commit is contained in:
commit
4b3ae378a8
@ -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(())
|
||||||
|
@ -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),
|
||||||
}
|
}
|
||||||
|
@ -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),
|
||||||
|
@ -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),
|
||||||
|
@ -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::*,
|
||||||
|
@ -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 {
|
||||||
|
@ -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),
|
||||||
|
Loading…
Reference in New Issue
Block a user