Format code

This commit is contained in:
Sebastian Schmidt 2019-03-27 18:35:16 +01:00
parent 24ca11e52a
commit b18521b8aa
7 changed files with 168 additions and 277 deletions

View File

@ -26,10 +26,18 @@ pub trait Context {
/// 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 ContextMut: Context { 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<()>;
/// Links the given function to the given identifier. /// Links the given function to the given identifier.
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 context that returns `None` for each identifier. /// A context that returns `None` for each identifier.
@ -46,11 +54,19 @@ impl Context for EmptyContext {
} }
impl ContextMut 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)
} }
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<()> {
Err(EvalexprError::ContextNotManipulable) Err(EvalexprError::ContextNotManipulable)
} }
} }
@ -86,7 +102,11 @@ impl Context for HashMapContext {
} }
impl ContextMut 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();
if let Some(existing_value) = self.variables.get_mut(&identifier) { if let Some(existing_value) = self.variables.get_mut(&identifier) {
@ -103,8 +123,12 @@ impl ContextMut for HashMapContext {
Ok(()) Ok(())
} }
fn set_function<S: Into<String>>(&mut self, identifier: S, function: Function) -> Result<(), EvalexprError> { fn set_function<S: Into<String>>(
&mut self,
identifier: S,
function: Function,
) -> Result<(), EvalexprError> {
self.functions.insert(identifier.into(), function); self.functions.insert(identifier.into(), function);
Ok(()) Ok(())
} }
} }

View File

@ -6,8 +6,7 @@
//! They are meant as shortcuts to not write the same error checking code everywhere. //! They are meant as shortcuts to not write the same error checking code everywhere.
use token::PartialToken; use token::PartialToken;
use value::TupleType; use value::{TupleType, value_type::ValueType};
use value::value_type::ValueType;
use crate::value::Value; use crate::value::Value;

View File

@ -39,10 +39,7 @@ pub fn eval(string: &str) -> Result<Value, EvalexprError> {
/// ``` /// ```
/// ///
/// *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( pub fn eval_with_context(string: &str, context: &Context) -> Result<Value, EvalexprError> {
string: &str,
context: &Context,
) -> Result<Value, EvalexprError> {
tree::tokens_to_operator_tree(token::tokenize(string)?)?.eval_with_context(context) tree::tokens_to_operator_tree(token::tokenize(string)?)?.eval_with_context(context)
} }
@ -132,10 +129,7 @@ pub fn eval_tuple(string: &str) -> Result<TupleType, EvalexprError> {
/// 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( pub fn eval_string_with_context(string: &str, context: &Context) -> Result<String, EvalexprError> {
string: &str,
context: &Context,
) -> Result<String, EvalexprError> {
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)),
@ -146,10 +140,7 @@ pub fn eval_string_with_context(
/// 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( pub fn eval_int_with_context(string: &str, context: &Context) -> Result<IntType, EvalexprError> {
string: &str,
context: &Context,
) -> Result<IntType, EvalexprError> {
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)),
@ -174,10 +165,7 @@ pub fn eval_float_with_context(
/// 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( pub fn eval_boolean_with_context(string: &str, context: &Context) -> Result<bool, EvalexprError> {
string: &str,
context: &Context,
) -> Result<bool, EvalexprError> {
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)),

View File

@ -29,11 +29,7 @@ pub trait Operator: Debug + Display {
fn argument_amount(&self) -> usize; fn argument_amount(&self) -> usize;
/// Evaluates the operator with the given arguments and context. /// Evaluates the operator with the given arguments and context.
fn eval( fn eval(&self, arguments: &[Value], context: &Context) -> Result<Value, EvalexprError>;
&self,
arguments: &[Value],
context: &Context,
) -> Result<Value, EvalexprError>;
} }
#[derive(Debug)] #[derive(Debug)]
@ -122,11 +118,7 @@ impl Operator for RootNode {
1 1
} }
fn eval( fn eval(&self, arguments: &[Value], _context: &Context) -> Result<Value, EvalexprError> {
&self,
arguments: &[Value],
_context: &Context,
) -> 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())
} }
@ -145,11 +137,7 @@ impl Operator for Add {
2 2
} }
fn eval( fn eval(&self, arguments: &[Value], _context: &Context) -> Result<Value, EvalexprError> {
&self,
arguments: &[Value],
_context: &Context,
) -> 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])?;
expect_number(&arguments[1])?; expect_number(&arguments[1])?;
@ -185,11 +173,7 @@ impl Operator for Sub {
2 2
} }
fn eval( fn eval(&self, arguments: &[Value], _context: &Context) -> Result<Value, EvalexprError> {
&self,
arguments: &[Value],
_context: &Context,
) -> 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])?;
expect_number(&arguments[1])?; expect_number(&arguments[1])?;
@ -225,11 +209,7 @@ impl Operator for Neg {
1 1
} }
fn eval( fn eval(&self, arguments: &[Value], _context: &Context) -> Result<Value, EvalexprError> {
&self,
arguments: &[Value],
_context: &Context,
) -> 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])?;
@ -259,11 +239,7 @@ impl Operator for Mul {
2 2
} }
fn eval( fn eval(&self, arguments: &[Value], _context: &Context) -> Result<Value, EvalexprError> {
&self,
arguments: &[Value],
_context: &Context,
) -> 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])?;
expect_number(&arguments[1])?; expect_number(&arguments[1])?;
@ -299,11 +275,7 @@ impl Operator for Div {
2 2
} }
fn eval( fn eval(&self, arguments: &[Value], _context: &Context) -> Result<Value, EvalexprError> {
&self,
arguments: &[Value],
_context: &Context,
) -> 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])?;
expect_number(&arguments[1])?; expect_number(&arguments[1])?;
@ -339,11 +311,7 @@ impl Operator for Mod {
2 2
} }
fn eval( fn eval(&self, arguments: &[Value], _context: &Context) -> Result<Value, EvalexprError> {
&self,
arguments: &[Value],
_context: &Context,
) -> 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])?;
expect_number(&arguments[1])?; expect_number(&arguments[1])?;
@ -379,11 +347,7 @@ impl Operator for Exp {
2 2
} }
fn eval( fn eval(&self, arguments: &[Value], _context: &Context) -> Result<Value, EvalexprError> {
&self,
arguments: &[Value],
_context: &Context,
) -> 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])?;
expect_number(&arguments[1])?; expect_number(&arguments[1])?;
@ -410,11 +374,7 @@ impl Operator for Eq {
2 2
} }
fn eval( fn eval(&self, arguments: &[Value], _context: &Context) -> Result<Value, EvalexprError> {
&self,
arguments: &[Value],
_context: &Context,
) -> Result<Value, EvalexprError> {
expect_operator_argument_amount(arguments.len(), 2)?; expect_operator_argument_amount(arguments.len(), 2)?;
if arguments[0] == arguments[1] { if arguments[0] == arguments[1] {
@ -438,11 +398,7 @@ impl Operator for Neq {
2 2
} }
fn eval( fn eval(&self, arguments: &[Value], _context: &Context) -> Result<Value, EvalexprError> {
&self,
arguments: &[Value],
_context: &Context,
) -> Result<Value, EvalexprError> {
expect_operator_argument_amount(arguments.len(), 2)?; expect_operator_argument_amount(arguments.len(), 2)?;
if arguments[0] != arguments[1] { if arguments[0] != arguments[1] {
@ -466,11 +422,7 @@ impl Operator for Gt {
2 2
} }
fn eval( fn eval(&self, arguments: &[Value], _context: &Context) -> Result<Value, EvalexprError> {
&self,
arguments: &[Value],
_context: &Context,
) -> 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])?;
expect_number(&arguments[1])?; expect_number(&arguments[1])?;
@ -504,11 +456,7 @@ impl Operator for Lt {
2 2
} }
fn eval( fn eval(&self, arguments: &[Value], _context: &Context) -> Result<Value, EvalexprError> {
&self,
arguments: &[Value],
_context: &Context,
) -> 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])?;
expect_number(&arguments[1])?; expect_number(&arguments[1])?;
@ -542,11 +490,7 @@ impl Operator for Geq {
2 2
} }
fn eval( fn eval(&self, arguments: &[Value], _context: &Context) -> Result<Value, EvalexprError> {
&self,
arguments: &[Value],
_context: &Context,
) -> 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])?;
expect_number(&arguments[1])?; expect_number(&arguments[1])?;
@ -580,11 +524,7 @@ impl Operator for Leq {
2 2
} }
fn eval( fn eval(&self, arguments: &[Value], _context: &Context) -> Result<Value, EvalexprError> {
&self,
arguments: &[Value],
_context: &Context,
) -> 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])?;
expect_number(&arguments[1])?; expect_number(&arguments[1])?;
@ -618,11 +558,7 @@ impl Operator for And {
2 2
} }
fn eval( fn eval(&self, arguments: &[Value], _context: &Context) -> Result<Value, EvalexprError> {
&self,
arguments: &[Value],
_context: &Context,
) -> 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])?;
let b = expect_boolean(&arguments[1])?; let b = expect_boolean(&arguments[1])?;
@ -648,11 +584,7 @@ impl Operator for Or {
2 2
} }
fn eval( fn eval(&self, arguments: &[Value], _context: &Context) -> Result<Value, EvalexprError> {
&self,
arguments: &[Value],
_context: &Context,
) -> 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])?;
let b = expect_boolean(&arguments[1])?; let b = expect_boolean(&arguments[1])?;
@ -678,11 +610,7 @@ impl Operator for Not {
1 1
} }
fn eval( fn eval(&self, arguments: &[Value], _context: &Context) -> Result<Value, EvalexprError> {
&self,
arguments: &[Value],
_context: &Context,
) -> 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])?;
@ -707,11 +635,7 @@ impl Operator for Tuple {
2 2
} }
fn eval( fn eval(&self, arguments: &[Value], _context: &Context) -> Result<Value, EvalexprError> {
&self,
arguments: &[Value],
_context: &Context,
) -> 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();
if let Value::Tuple(tuple2) = &arguments[1] { if let Value::Tuple(tuple2) = &arguments[1] {
@ -748,11 +672,7 @@ impl Operator for Const {
0 0
} }
fn eval( fn eval(&self, arguments: &[Value], _context: &Context) -> Result<Value, EvalexprError> {
&self,
arguments: &[Value],
_context: &Context,
) -> Result<Value, EvalexprError> {
expect_operator_argument_amount(arguments.len(), 0)?; expect_operator_argument_amount(arguments.len(), 0)?;
Ok(self.value.clone()) Ok(self.value.clone())
@ -772,11 +692,7 @@ impl Operator for VariableIdentifier {
0 0
} }
fn eval( fn eval(&self, _arguments: &[Value], context: &Context) -> Result<Value, EvalexprError> {
&self,
_arguments: &[Value],
context: &Context,
) -> Result<Value, EvalexprError> {
if let Some(value) = context.get_value(&self.identifier).cloned() { if let Some(value) = context.get_value(&self.identifier).cloned() {
Ok(value) Ok(value)
} else { } else {
@ -800,11 +716,7 @@ impl Operator for FunctionIdentifier {
1 1
} }
fn eval( fn eval(&self, arguments: &[Value], context: &Context) -> Result<Value, EvalexprError> {
&self,
arguments: &[Value],
context: &Context,
) -> Result<Value, EvalexprError> {
expect_operator_argument_amount(arguments.len(), 1)?; expect_operator_argument_amount(arguments.len(), 1)?;
let arguments = if let Value::Tuple(arguments) = &arguments[0] { let arguments = if let Value::Tuple(arguments) = &arguments[0] {

View File

@ -46,10 +46,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( pub fn eval_with_context(&self, context: &Context) -> Result<Value, EvalexprError> {
&self,
context: &Context,
) -> 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_context(context)?); arguments.push(child.eval_with_context(context)?);
@ -67,10 +64,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( pub fn eval_string_with_context(&self, context: &Context) -> Result<String, EvalexprError> {
&self,
context: &Context,
) -> Result<String, EvalexprError> {
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)),
@ -81,10 +75,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( pub fn eval_float_with_context(&self, context: &Context) -> Result<FloatType, EvalexprError> {
&self,
context: &Context,
) -> Result<FloatType, EvalexprError> {
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)),
@ -95,10 +86,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( pub fn eval_int_with_context(&self, context: &Context) -> Result<IntType, EvalexprError> {
&self,
context: &Context,
) -> Result<IntType, EvalexprError> {
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)),
@ -109,10 +97,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( pub fn eval_boolean_with_context(&self, context: &Context) -> Result<bool, EvalexprError> {
&self,
context: &Context,
) -> Result<bool, EvalexprError> {
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)),
@ -123,10 +108,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( pub fn eval_tuple_with_context(&self, context: &Context) -> Result<TupleType, EvalexprError> {
&self,
context: &Context,
) -> Result<TupleType, EvalexprError> {
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)),

View File

@ -37,4 +37,4 @@ impl From<&&mut Value> for ValueType {
fn from(value: &&mut Value) -> Self { fn from(value: &&mut Value) -> Self {
From::<&Value>::from(*value) From::<&Value>::from(*value)
} }
} }

View File

@ -107,14 +107,8 @@ fn test_with_context() {
context.set_value("half", Value::Float(0.5)).unwrap(); context.set_value("half", Value::Float(0.5)).unwrap();
context.set_value("zero", Value::Int(0)).unwrap(); context.set_value("zero", Value::Int(0)).unwrap();
assert_eq!( assert_eq!(eval_with_context("tr", &context), Ok(Value::Boolean(true)));
eval_with_context("tr", &context), assert_eq!(eval_with_context("fa", &context), Ok(Value::Boolean(false)));
Ok(Value::Boolean(true))
);
assert_eq!(
eval_with_context("fa", &context),
Ok(Value::Boolean(false))
);
assert_eq!( assert_eq!(
eval_with_context("tr && false", &context), eval_with_context("tr && false", &context),
Ok(Value::Boolean(false)) Ok(Value::Boolean(false))
@ -136,39 +130,31 @@ fn test_with_context() {
#[test] #[test]
fn test_functions() { fn test_functions() {
let mut context = HashMapContext::new(); let mut context = HashMapContext::new();
context.set_function( context
"sub2".to_string(), .set_function(
Function::new( "sub2".to_string(),
Some(1), Function::new(
Box::new(|arguments| { Some(1),
if let Value::Int(int) = arguments[0] { Box::new(|arguments| {
Ok(Value::Int(int - 2)) if let Value::Int(int) = arguments[0] {
} else if let Value::Float(float) = arguments[0] { Ok(Value::Int(int - 2))
Ok(Value::Float(float - 2.0)) } else if let Value::Float(float) = arguments[0] {
} else { Ok(Value::Float(float - 2.0))
Err(EvalexprError::expected_number(arguments[0].clone())) } else {
} Err(EvalexprError::expected_number(arguments[0].clone()))
}), }
), }),
).unwrap(); ),
context.set_value("five".to_string(), Value::Int(5)).unwrap(); )
.unwrap();
context
.set_value("five".to_string(), Value::Int(5))
.unwrap();
assert_eq!( assert_eq!(eval_with_context("sub2 5", &context), Ok(Value::Int(3)));
eval_with_context("sub2 5", &context), assert_eq!(eval_with_context("sub2(5)", &context), Ok(Value::Int(3)));
Ok(Value::Int(3)) assert_eq!(eval_with_context("sub2 five", &context), Ok(Value::Int(3)));
); assert_eq!(eval_with_context("sub2(five)", &context), Ok(Value::Int(3)));
assert_eq!(
eval_with_context("sub2(5)", &context),
Ok(Value::Int(3))
);
assert_eq!(
eval_with_context("sub2 five", &context),
Ok(Value::Int(3))
);
assert_eq!(
eval_with_context("sub2(five)", &context),
Ok(Value::Int(3))
);
assert_eq!( assert_eq!(
eval_with_context("sub2(3) + five", &context), eval_with_context("sub2(3) + five", &context),
Ok(Value::Int(6)) Ok(Value::Int(6))
@ -178,74 +164,81 @@ fn test_functions() {
#[test] #[test]
fn test_n_ary_functions() { fn test_n_ary_functions() {
let mut context = HashMapContext::new(); let mut context = HashMapContext::new();
context.set_function( context
"sub2", .set_function(
Function::new( "sub2",
Some(1), Function::new(
Box::new(|arguments| { Some(1),
if let Value::Int(int) = arguments[0] { Box::new(|arguments| {
Ok(Value::Int(int - 2)) if let Value::Int(int) = arguments[0] {
} else if let Value::Float(float) = arguments[0] { Ok(Value::Int(int - 2))
Ok(Value::Float(float - 2.0)) } else if let Value::Float(float) = arguments[0] {
} else { Ok(Value::Float(float - 2.0))
Err(EvalexprError::expected_number(arguments[0].clone())) } else {
} Err(EvalexprError::expected_number(arguments[0].clone()))
}), }
), }),
).unwrap(); ),
context.set_function( )
"avg", .unwrap();
Function::new( context
Some(2), .set_function(
Box::new(|arguments| { "avg",
expect_number(&arguments[0])?; Function::new(
expect_number(&arguments[1])?; Some(2),
Box::new(|arguments| {
expect_number(&arguments[0])?;
expect_number(&arguments[1])?;
if let (Value::Int(a), Value::Int(b)) = (&arguments[0], &arguments[1]) { if let (Value::Int(a), Value::Int(b)) = (&arguments[0], &arguments[1]) {
Ok(Value::Int((a + b) / 2)) Ok(Value::Int((a + b) / 2))
} else { } else {
Ok(Value::Float( Ok(Value::Float(
(arguments[0].as_float()? + arguments[1].as_float()?) / 2.0, (arguments[0].as_float()? + arguments[1].as_float()?) / 2.0,
)) ))
} }
}), }),
), ),
).unwrap(); )
context.set_function( .unwrap();
"muladd", context
Function::new( .set_function(
Some(3), "muladd",
Box::new(|arguments| { Function::new(
expect_number(&arguments[0])?; Some(3),
expect_number(&arguments[1])?; Box::new(|arguments| {
expect_number(&arguments[2])?; expect_number(&arguments[0])?;
expect_number(&arguments[1])?;
expect_number(&arguments[2])?;
if let (Value::Int(a), Value::Int(b), Value::Int(c)) = if let (Value::Int(a), Value::Int(b), Value::Int(c)) =
(&arguments[0], &arguments[1], &arguments[2]) (&arguments[0], &arguments[1], &arguments[2])
{ {
Ok(Value::Int(a * b + c)) Ok(Value::Int(a * b + c))
} else { } else {
Ok(Value::Float( Ok(Value::Float(
arguments[0].as_float()? * arguments[1].as_float()? arguments[0].as_float()? * arguments[1].as_float()?
+ arguments[2].as_float()?, + arguments[2].as_float()?,
)) ))
} }
}), }),
), ),
).unwrap(); )
context.set_function( .unwrap();
"count", context
Function::new( .set_function(
None, "count",
Box::new(|arguments| Ok(Value::Int(arguments.len() as IntType))), Function::new(
), None,
).unwrap(); Box::new(|arguments| Ok(Value::Int(arguments.len() as IntType))),
context.set_value("five".to_string(), Value::Int(5)).unwrap(); ),
)
.unwrap();
context
.set_value("five".to_string(), Value::Int(5))
.unwrap();
assert_eq!( assert_eq!(eval_with_context("avg(7, 5)", &context), Ok(Value::Int(6)));
eval_with_context("avg(7, 5)", &context),
Ok(Value::Int(6))
);
assert_eq!( assert_eq!(
eval_with_context("avg(sub2 5, 5)", &context), eval_with_context("avg(sub2 5, 5)", &context),
Ok(Value::Int(4)) Ok(Value::Int(4))
@ -273,10 +266,7 @@ fn test_n_ary_functions() {
eval_with_context("count(3, 5.5, 2)", &context), eval_with_context("count(3, 5.5, 2)", &context),
Ok(Value::Int(3)) Ok(Value::Int(3))
); );
assert_eq!( assert_eq!(eval_with_context("count 5", &context), Ok(Value::Int(1)));
eval_with_context("count 5", &context),
Ok(Value::Int(1))
);
assert_eq!( assert_eq!(
eval_with_context("min(4.0, 3)", &context), eval_with_context("min(4.0, 3)", &context),
@ -342,7 +332,9 @@ fn test_no_panic() {
#[test] #[test]
fn test_shortcut_functions() { fn test_shortcut_functions() {
let mut context = HashMapContext::new(); let mut context = HashMapContext::new();
context.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!(
@ -350,17 +342,11 @@ fn test_shortcut_functions() {
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_context("3.3", &context), Ok(3.3));
eval_float_with_context("3.3", &context),
Ok(3.3)
);
assert_eq!(eval_int("3"), Ok(3)); assert_eq!(eval_int("3"), Ok(3));
assert_eq!(eval_int_with_context("3", &context), 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_context("true", &context), Ok(true));
eval_boolean_with_context("true", &context),
Ok(true)
);
assert_eq!(eval_tuple("3,3"), Ok(vec![Value::Int(3), Value::Int(3)])); assert_eq!(eval_tuple("3,3"), Ok(vec![Value::Int(3), Value::Int(3)]));
assert_eq!( assert_eq!(
eval_tuple_with_context("3,3", &context), eval_tuple_with_context("3,3", &context),