use super::value::Value;
use std::collections::HashMap;
#[derive(Debug, Clone)]
struct Scope {
bindings: HashMap<String, Value>,
}
#[derive(Debug, Clone)]
pub struct Environment {
scopes: Vec<Scope>,
}
impl Environment {
pub fn new() -> Self {
Self {
scopes: vec![Scope {
bindings: HashMap::new(),
}],
}
}
pub fn push_scope(&mut self) {
self.scopes.push(Scope {
bindings: HashMap::new(),
});
}
pub fn pop_scope(&mut self) {
if self.scopes.len() > 1 {
self.scopes.pop();
}
}
pub fn define(&mut self, name: &str, value: Value) {
if let Some(scope) = self.scopes.last_mut() {
scope.bindings.insert(name.to_string(), value);
}
}
pub fn get(&self, name: &str) -> Option<&Value> {
for scope in self.scopes.iter().rev() {
if let Some(val) = scope.bindings.get(name) {
return Some(val);
}
}
None
}
pub fn set(&mut self, name: &str, value: Value) -> bool {
for scope in self.scopes.iter_mut().rev() {
if scope.bindings.contains_key(name) {
scope.bindings.insert(name.to_string(), value);
return true;
}
}
false
}
pub fn get_mut(&mut self, name: &str) -> Option<&mut Value> {
for scope in self.scopes.iter_mut().rev() {
if let Some(val) = scope.bindings.get_mut(name) {
return Some(val);
}
}
None
}
}
impl Default for Environment {
fn default() -> Self {
Self::new()
}
}