ganit_core/eval/context/mod.rs
1use std::collections::HashMap;
2use crate::types::Value;
3
4/// Holds the named variable bindings for a formula evaluation.
5///
6/// All keys are stored and looked up in uppercase, so variable names are
7/// case-insensitive (`A1`, `a1`, and `A1` all refer to the same binding).
8pub struct Context {
9 pub vars: HashMap<String, Value>,
10}
11
12impl Context {
13 /// Create a `Context` from a map of variable name → value.
14 /// Keys are normalised to uppercase on insertion.
15 pub fn new(vars: HashMap<String, Value>) -> Self {
16 let normalized = vars.into_iter()
17 .map(|(k, v)| (k.to_uppercase(), v))
18 .collect();
19 Self { vars: normalized }
20 }
21
22 /// Create an empty `Context` with no variable bindings.
23 pub fn empty() -> Self {
24 Self { vars: HashMap::new() }
25 }
26
27 /// Look up a variable by name (case-insensitive). Returns `Value::Empty` if not found.
28 pub fn get(&self, name: &str) -> Value {
29 self.vars
30 .get(&name.to_uppercase())
31 .cloned()
32 .unwrap_or(Value::Empty)
33 }
34
35 /// Insert or overwrite a binding. Returns the previous value if one existed.
36 pub fn set(&mut self, name: String, value: Value) -> Option<Value> {
37 self.vars.insert(name.to_uppercase(), value)
38 }
39
40 /// Remove a binding. Used to restore context after lambda/let evaluation.
41 pub fn remove(&mut self, name: &str) {
42 self.vars.remove(&name.to_uppercase());
43 }
44}
45
46#[cfg(test)]
47mod tests;