Fix calling functions without arguments

This commit is contained in:
Jeff 2023-06-24 01:11:36 -04:00
parent da7d52caef
commit e730028185
2 changed files with 31 additions and 18 deletions

View File

@ -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<Option<Value>>;
/// 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<String, Value>,
}
@ -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<Option<Value>> {
let split = identifier.split_once(".");
if let Some((map_name, next_identifier)) = split {
let value = self.variables.get(map_name)?;
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 {
None
Err(EvalexprError::ExpectedMap {
actual: value.clone(),
})
}
} else {
self.variables.get(identifier).or_else(|| {
self.call_function(identifier, &Value::Empty);
None
})
Ok(None)
}
} else {
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));

View File

@ -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(