Improve map type functionality

This commit is contained in:
Jeff 2023-06-23 22:47:02 -04:00
parent f2ae0d952f
commit 47cc649f8d
2 changed files with 31 additions and 12 deletions

View File

@ -4,7 +4,7 @@
//! 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. //! 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. //! 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::BTreeMap; use std::{collections::BTreeMap, fmt::Display};
use crate::{ use crate::{
function::Function, function::Function,
@ -46,6 +46,18 @@ pub struct VariableMap {
variables: BTreeMap<String, Value>, variables: BTreeMap<String, Value>,
} }
impl Display for VariableMap {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "(")?;
for (key, value) in &self.variables {
write!(f, " {} = {};", key, value)?;
}
write!(f, " )")
}
}
impl PartialEq for VariableMap { impl PartialEq for VariableMap {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
if self.variables.len() != other.variables.len() { if self.variables.len() != other.variables.len() {
@ -85,31 +97,38 @@ impl Context for VariableMap {
impl ContextWithMutableVariables for VariableMap { impl ContextWithMutableVariables for VariableMap {
fn set_value(&mut self, identifier: &str, value: Value) -> EvalexprResult<()> { fn set_value(&mut self, identifier: &str, value: Value) -> EvalexprResult<()> {
println!("{:#?}", self);
println!("{}", identifier);
let split = identifier.split_once("."); let split = identifier.split_once(".");
if let Some((map_name, next_identifier)) = split { if let Some((map_name, next_identifier)) = split {
if let Some(map_value) = self.variables.get_mut(map_name) { if let Some(map_value) = self.variables.get_mut(map_name) {
if let Value::Map(map) = map_value { if let Value::Map(map) = map_value {
map.set_value(next_identifier, value)?; map.set_value(next_identifier, value)
} else { } else {
return Err(EvalexprError::ExpectedMap { return Err(EvalexprError::ExpectedMap {
actual: map_value.clone(), actual: map_value.clone(),
}); });
} }
} else { } else {
let mut new_map = BTreeMap::new(); let mut new_map = VariableMap {
new_map.insert(next_identifier.to_string(), value); variables: BTreeMap::new(),
let map_var = Value::Map(VariableMap { variables: new_map }); };
self.variables.insert(map_name.to_string(), map_var);
} new_map.set_value(next_identifier, value)?;
} else { self.variables
self.variables.insert(identifier.to_string(), value); .insert(map_name.to_string(), Value::Map(new_map));
}
Ok(()) Ok(())
} }
} else if self.variables.contains_key(identifier) {
Err(EvalexprError::ExpectedMap {
actual: value.clone(),
})
} else {
self.variables.insert(identifier.to_string(), value);
Ok(())
}
}
} }
impl ContextWithMutableFunctions for VariableMap { impl ContextWithMutableFunctions for VariableMap {

View File

@ -23,7 +23,7 @@ impl Display for Value {
write!(f, ")") write!(f, ")")
}, },
Value::Empty => write!(f, "()"), Value::Empty => write!(f, "()"),
Value::Map(_) => write!(f, "{:?}", self), Value::Map(map) => write!(f, "{}", map),
} }
} }
} }