1use std::collections::HashMap;
2use std::sync::Arc;
3
4use rexlang_ast::expr::Symbol;
5
6use crate::value::Pointer;
7
8#[derive(Clone, Debug, PartialEq)]
9pub struct Env(Arc<EnvFrame>);
10
11#[derive(Default, Debug, PartialEq)]
12struct EnvFrame {
13 parent: Option<Env>,
14 bindings: HashMap<Symbol, Pointer>,
15}
16
17impl Env {
18 pub fn new() -> Self {
19 Env(Arc::new(EnvFrame::default()))
20 }
21
22 pub fn extend(&self, name: Symbol, value: Pointer) -> Self {
23 let mut bindings = HashMap::new();
24 bindings.insert(name, value);
25 Env(Arc::new(EnvFrame {
26 parent: Some(self.clone()),
27 bindings,
28 }))
29 }
30
31 pub fn extend_many(&self, bindings: HashMap<Symbol, Pointer>) -> Self {
32 Env(Arc::new(EnvFrame {
33 parent: Some(self.clone()),
34 bindings,
35 }))
36 }
37
38 pub fn get(&self, name: &Symbol) -> Option<Pointer> {
39 let mut current: Option<&Env> = Some(self);
40 while let Some(env) = current {
41 if let Some(v) = env.0.bindings.get(name) {
42 return Some(*v);
43 }
44 current = env.0.parent.as_ref();
45 }
46 None
47 }
48
49 pub(crate) fn parent(&self) -> Option<&Env> {
50 self.0.parent.as_ref()
51 }
52
53 pub(crate) fn bindings(&self) -> &HashMap<Symbol, Pointer> {
54 &self.0.bindings
55 }
56}
57
58impl Default for Env {
59 fn default() -> Self {
60 Self::new()
61 }
62}