use crate::core::{RustValue, Value};
use crate::eval::{ControlFlow, ErrorKind, EvalResult, Evaluator};
use anyhow::anyhow;
#[derive(Debug, Clone)]
pub struct EvalDict {
pub pairs: Vec<(Value, Value)>,
}
#[crate::rust_value_any]
impl RustValue for EvalDict {
fn dyn_clone(&self) -> Box<dyn RustValue> {
Box::new(self.clone())
}
fn eval(&self, evaluator: &mut Evaluator) -> anyhow::Result<EvalResult> {
let mut dict_map = indexmap::IndexMap::new();
for (key_expr, value_expr) in &self.pairs {
let key_val = match key_expr.eval(evaluator)? {
Ok(val) => val,
Err(e) => return Ok(Err(e)),
};
let value_val = match value_expr.eval(evaluator)? {
Ok(val) => val,
Err(e) => return Ok(Err(e)),
};
let key_str = match key_val {
Value::String(s) => s,
Value::Int(i) => i.to_string(),
Value::Float(f) => f.to_string(),
Value::Bool(b) => b.to_string(),
_ => {
return Ok(Err(ControlFlow::Error(ErrorKind::SystemError(anyhow!(
"Dictionary keys must be strings, numbers, or booleans, got {:?}",
key_val
)))))
}
};
dict_map.insert(key_str, value_val);
}
Ok(Ok(Value::new_dict_with_map(dict_map)))
}
fn str(&self) -> String {
let pairs_str = self
.pairs
.iter()
.map(|(key, value)| format!("{}: {}", key.str(), value.str()))
.collect::<Vec<_>>()
.join(", ");
format!("{{{pairs_str}}}")
}
}