1use pepl_stdlib::Value;
4use std::collections::BTreeMap;
5
6#[derive(Debug, Clone)]
8struct Scope {
9 bindings: BTreeMap<String, Value>,
10}
11
12impl Scope {
13 fn new() -> Self {
14 Self {
15 bindings: BTreeMap::new(),
16 }
17 }
18}
19
20#[derive(Debug, Clone)]
26pub struct Environment {
27 scopes: Vec<Scope>,
28}
29
30impl Environment {
31 pub fn new() -> Self {
33 Self {
34 scopes: vec![Scope::new()],
35 }
36 }
37
38 pub fn push_scope(&mut self) {
40 self.scopes.push(Scope::new());
41 }
42
43 pub fn pop_scope(&mut self) {
45 if self.scopes.len() > 1 {
46 self.scopes.pop();
47 }
48 }
49
50 pub fn define(&mut self, name: &str, value: Value) {
52 if let Some(scope) = self.scopes.last_mut() {
53 scope.bindings.insert(name.to_string(), value);
54 }
55 }
56
57 pub fn get(&self, name: &str) -> Option<&Value> {
59 for scope in self.scopes.iter().rev() {
60 if let Some(v) = scope.bindings.get(name) {
61 return Some(v);
62 }
63 }
64 None
65 }
66
67 pub fn set(&mut self, name: &str, value: Value) -> bool {
70 for scope in self.scopes.iter_mut().rev() {
71 if scope.bindings.contains_key(name) {
72 scope.bindings.insert(name.to_string(), value);
73 return true;
74 }
75 }
76 false
77 }
78
79 pub fn global_bindings(&self) -> &BTreeMap<String, Value> {
82 &self.scopes[0].bindings
83 }
84
85 pub fn restore_global(&mut self, bindings: BTreeMap<String, Value>) {
87 self.scopes[0].bindings = bindings;
88 }
89}
90
91impl Default for Environment {
92 fn default() -> Self {
93 Self::new()
94 }
95}