From 47cc649f8d06d1196c294c7dcb3e678dc1798464 Mon Sep 17 00:00:00 2001 From: Jeff Date: Fri, 23 Jun 2023 22:47:02 -0400 Subject: [PATCH] Improve map type functionality --- src/context/mod.rs | 41 ++++++++++++++++++++++++++++++----------- src/value/display.rs | 2 +- 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/src/context/mod.rs b/src/context/mod.rs index 0cf7d84..341df75 100644 --- a/src/context/mod.rs +++ b/src/context/mod.rs @@ -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. //! 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::{ function::Function, @@ -46,6 +46,18 @@ pub struct VariableMap { variables: BTreeMap, } +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 { fn eq(&self, other: &Self) -> bool { if self.variables.len() != other.variables.len() { @@ -85,30 +97,37 @@ impl Context for VariableMap { impl ContextWithMutableVariables for VariableMap { fn set_value(&mut self, identifier: &str, value: Value) -> EvalexprResult<()> { - println!("{:#?}", self); - println!("{}", identifier); - let split = identifier.split_once("."); + if let Some((map_name, next_identifier)) = split { if let Some(map_value) = self.variables.get_mut(map_name) { if let Value::Map(map) = map_value { - map.set_value(next_identifier, value)?; + map.set_value(next_identifier, value) } else { return Err(EvalexprError::ExpectedMap { actual: map_value.clone(), }); } } else { - let mut new_map = BTreeMap::new(); - new_map.insert(next_identifier.to_string(), value); - let map_var = Value::Map(VariableMap { variables: new_map }); - self.variables.insert(map_name.to_string(), map_var); + let mut new_map = VariableMap { + variables: BTreeMap::new(), + }; + + new_map.set_value(next_identifier, value)?; + self.variables + .insert(map_name.to_string(), Value::Map(new_map)); + + Ok(()) } + } else if self.variables.contains_key(identifier) { + Err(EvalexprError::ExpectedMap { + actual: value.clone(), + }) } else { self.variables.insert(identifier.to_string(), value); - } - Ok(()) + Ok(()) + } } } diff --git a/src/value/display.rs b/src/value/display.rs index c8d2c96..23b112a 100644 --- a/src/value/display.rs +++ b/src/value/display.rs @@ -23,7 +23,7 @@ impl Display for Value { write!(f, ")") }, Value::Empty => write!(f, "()"), - Value::Map(_) => write!(f, "{:?}", self), + Value::Map(map) => write!(f, "{}", map), } } }