Skip to main content

coda_runtime/
env.rs

1use crate::runtime::value::Value;
2use std::{cell::RefCell, collections::HashMap, rc::Rc};
3
4#[derive(Clone, Debug)]
5pub struct Env {
6    pub values: HashMap<String, Value>,
7    pub exports: HashMap<String, Value>,
8    pub parent: Option<Rc<RefCell<Env>>>,
9}
10
11impl Env {
12    #[inline(always)]
13    pub fn new() -> Self {
14        Self {
15            values: HashMap::new(),
16            exports: HashMap::new(),
17            parent: None,
18        }
19    }
20
21    #[inline(always)]
22    pub fn new_with_parent(parent: Option<Rc<RefCell<Env>>>) -> Self {
23        Self {
24            values: HashMap::new(),
25            exports: HashMap::new(),
26            parent,
27        }
28    }
29
30    pub fn assign(&mut self, name: &str, val: Value) -> Result<(), String> {
31        if self.values.contains_key(name) {
32            self.values.insert(name.to_string(), val);
33
34            Ok(())
35        } else if let Some(parent) = &self.parent {
36            parent.borrow_mut().assign(name, val)
37        } else {
38            Err(format!("undefined variable `{name}`"))
39        }
40    }
41
42    #[inline(always)]
43    pub fn define(&mut self, name: String, val: Value) {
44        self.values.insert(name, val);
45    }
46
47    #[inline(always)]
48    pub fn get(&self, name: &str) -> Option<Value> {
49        if let Some(v) = self.values.get(name) {
50            Some(v.clone())
51        } else if let Some(parent) = &self.parent {
52            parent.borrow().get(name)
53        } else {
54            None
55        }
56    }
57    
58    #[inline(always)]
59    pub fn define_export(&mut self, name: String, value: Value) {
60        self.exports.insert(name.clone(), value.clone());
61        self.values.insert(name, value);
62    }
63    
64    #[inline(always)]
65    pub fn exported_values(&self) -> HashMap<String, Value> {
66        self.exports.clone()
67    }
68}