use std::cell::RefCell;
use std::rc::Rc;
use crate::core::Value;
use indexmap::IndexMap;
#[derive(Clone, Debug, Default)]
pub struct ScopeRef(Rc<RefCell<Scope>>);
#[derive(Debug, Clone)]
pub struct Scope {
vars: IndexMap<String, Value>,
parent: Option<ScopeRef>,
}
impl Default for Scope {
fn default() -> Self {
Self::new()
}
}
impl Scope {
pub fn new() -> Self {
Scope {
vars: IndexMap::new(),
parent: None,
}
}
pub fn with_parent(parent: ScopeRef) -> Self {
Scope {
vars: IndexMap::new(),
parent: Some(parent),
}
}
pub fn define(&mut self, name: impl Into<String>, value: impl Into<Value>) {
self.vars.insert(name.into(), value.into());
}
pub fn get(&self, name: &str) -> Option<Value> {
if let Some(value) = self.vars.get(name) {
Some(value.clone())
} else if let Some(parent) = &self.parent {
parent.0.borrow().get(name)
} else {
None
}
}
pub fn set(&mut self, name: &str, value: Value) -> Result<(), String> {
if self.vars.contains_key(name) {
self.vars.insert(name.to_string(), value);
Ok(())
} else if let Some(parent) = &self.parent {
parent.0.borrow_mut().set(name, value)
} else {
Err(format!("Undefined variable: {name}"))
}
}
pub fn iter(&self) -> impl Iterator<Item = (String, Value)> + '_ {
self.vars.iter().map(|(k, v)| (k.clone(), v.clone()))
}
}
impl ScopeRef {
pub fn new() -> Self {
Self(Rc::new(RefCell::new(Scope::new())))
}
pub fn child(&self) -> Self {
Self(Rc::new(RefCell::new(Scope::with_parent(self.clone()))))
}
pub fn define(&self, name: impl Into<String>, value: impl Into<Value>) {
self.0.borrow_mut().define(name, value);
}
pub fn get(&self, name: &str) -> Option<Value> {
self.0.borrow().get(name)
}
pub fn set(&self, name: &str, value: Value) -> Result<(), String> {
self.0.borrow_mut().set(name, value)
}
pub fn iter(&self) -> Vec<(String, Value)> {
self.0.borrow().iter().collect()
}
}