From e730028185f75bc895a91e55248c1335f4f133b3 Mon Sep 17 00:00:00 2001 From: Jeff Date: Sat, 24 Jun 2023 01:11:36 -0400 Subject: [PATCH] Fix calling functions without arguments --- src/context/mod.rs | 47 +++++++++++++++++++++++++++++---------------- src/operator/mod.rs | 2 +- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/src/context/mod.rs b/src/context/mod.rs index 9475227..a61efdc 100644 --- a/src/context/mod.rs +++ b/src/context/mod.rs @@ -5,6 +5,7 @@ //! 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::{ + cell::Cell, collections::BTreeMap, fmt::Display, fs, @@ -25,7 +26,7 @@ mod predefined; /// An immutable context. pub trait Context { /// Returns the value that is linked to the given identifier. - fn get_value(&self, identifier: &str) -> Option<&Value>; + fn get_value(&self, identifier: &str) -> EvalexprResult>; /// Calls the function that is linked to the given identifier with the given argument. /// If no function with the given identifier is found, this method returns `EvalexprError::FunctionIdentifierNotFound`. @@ -49,7 +50,7 @@ pub trait ContextWithMutableFunctions: Context { } /// A context that stores its mappings in hash maps. -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct VariableMap { variables: BTreeMap, } @@ -87,25 +88,36 @@ impl PartialEq for VariableMap { impl VariableMap { /// Create a new instace. pub fn new() -> Self { - Default::default() + VariableMap { + variables: BTreeMap::new(), + } } } impl Context for VariableMap { - fn get_value(&self, identifier: &str) -> Option<&Value> { + fn get_value(&self, identifier: &str) -> EvalexprResult> { let split = identifier.split_once("."); - if let Some((map_name, next_identifier)) = split { - let value = self.variables.get(map_name)?; - if let Value::Map(map) = value { - map.get_value(next_identifier) + if let Some((identifier, next_identifier)) = split { + if let Some(value) = self.variables.get(identifier) { + if let Value::Map(map) = value { + map.get_value(next_identifier) + } else { + Err(EvalexprError::ExpectedMap { + actual: value.clone(), + }) + } } else { - None + Ok(None) } } else { - self.variables.get(identifier).or_else(|| { - self.call_function(identifier, &Value::Empty); - None - }) + let value = self.variables.get(identifier); + + if let Some(value) = value { + Ok(Some(value.clone())) + } else { + self.call_function(identifier, &Value::Empty) + .map(|value| Some(value)) + } } } @@ -119,7 +131,9 @@ impl ContextWithMutableVariables for VariableMap { let split = identifier.split_once("."); if let Some((map_name, next_identifier)) = split { - if let Some(map_value) = self.variables.get_mut(map_name) { + let get_value = self.variables.get_mut(map_name); + + if let Some(map_value) = get_value { if let Value::Map(map) = map_value { map.set_value(next_identifier, value) } else { @@ -128,11 +142,10 @@ impl ContextWithMutableVariables for VariableMap { }); } } else { - let mut new_map = VariableMap { - variables: BTreeMap::new(), - }; + let mut new_map = VariableMap::new(); new_map.set_value(next_identifier, value)?; + self.variables .insert(map_name.to_string(), Value::Map(new_map)); diff --git a/src/operator/mod.rs b/src/operator/mod.rs index 9c8825d..919d7c2 100644 --- a/src/operator/mod.rs +++ b/src/operator/mod.rs @@ -446,7 +446,7 @@ impl Operator { VariableIdentifierRead { identifier } => { expect_operator_argument_amount(arguments.len(), 0)?; - if let Some(value) = context.get_value(identifier).cloned() { + if let Some(value) = context.get_value(identifier)? { Ok(value) } else { Err(EvalexprError::VariableIdentifierNotFound(