1use crate::intern::{StringPool, Symbol};
2use crate::value::Value;
3use std::collections::HashMap;
4
5#[derive(Debug, Clone)]
7struct Binding {
8 sym: Symbol,
9 value: Value,
10 mutable: bool,
11}
12
13#[derive(Debug, Clone)]
19pub struct Env {
20 frames: Vec<Vec<Binding>>,
21 pool: StringPool,
22}
23
24impl Default for Env {
25 fn default() -> Self {
26 Self::new()
27 }
28}
29
30impl Env {
31 pub fn new() -> Self {
32 Self {
33 frames: vec![Vec::new()],
34 pool: StringPool::new(),
35 }
36 }
37
38 pub fn pool(&self) -> &StringPool {
40 &self.pool
41 }
42
43 pub fn pool_mut(&mut self) -> &mut StringPool {
45 &mut self.pool
46 }
47
48 pub fn intern(&mut self, s: &str) -> Symbol {
50 self.pool.intern(s)
51 }
52
53 pub fn resolve(&self, sym: Symbol) -> &str {
55 self.pool.resolve(sym)
56 }
57
58 pub fn push_scope(&mut self) {
60 self.frames.push(Vec::new());
61 }
62
63 pub fn pop_scope(&mut self) {
65 self.frames.pop();
66 }
67
68 pub fn define(&mut self, name: String, value: Value, mutable: bool) {
70 let sym = self.pool.intern(&name);
71 self.define_sym(sym, value, mutable);
72 }
73
74 pub fn define_sym(&mut self, sym: Symbol, value: Value, mutable: bool) {
76 let frame = self.frames.last_mut().unwrap();
77 for binding in frame.iter_mut() {
79 if binding.sym == sym {
80 binding.value = value;
81 binding.mutable = mutable;
82 return;
83 }
84 }
85 frame.push(Binding {
86 sym,
87 value,
88 mutable,
89 });
90 }
91
92 pub fn get(&self, name: &str) -> Option<&Value> {
94 let sym = self.pool.map_get(name)?;
95 self.get_sym(sym)
96 }
97
98 pub fn get_sym(&self, sym: Symbol) -> Option<&Value> {
100 for frame in self.frames.iter().rev() {
101 for binding in frame.iter().rev() {
102 if binding.sym == sym {
103 return Some(&binding.value);
104 }
105 }
106 }
107 None
108 }
109
110 pub fn set(&mut self, name: &str, value: Value) -> Result<(), String> {
112 let sym = self.pool.intern(name);
113 self.set_sym(sym, value)
114 }
115
116 pub fn set_sym(&mut self, sym: Symbol, value: Value) -> Result<(), String> {
118 for frame in self.frames.iter_mut().rev() {
119 for binding in frame.iter_mut().rev() {
120 if binding.sym == sym {
121 if !binding.mutable {
122 return Err(format!(
123 "{}'{}'",
124 ion_str!("cannot assign to immutable variable "),
125 self.pool.resolve(sym),
126 ));
127 }
128 binding.value = value;
129 return Ok(());
130 }
131 }
132 }
133 Err(format!(
134 "{}{}",
135 ion_str!("undefined variable: "),
136 self.pool.resolve(sym)
137 ))
138 }
139
140 pub fn top_level(&self) -> HashMap<String, Value> {
142 self.frames
143 .first()
144 .map(|f| {
145 f.iter()
146 .map(|b| (self.pool.resolve(b.sym).to_string(), b.value.clone()))
147 .collect()
148 })
149 .unwrap_or_default()
150 }
151
152 pub fn capture(&self) -> HashMap<String, Value> {
154 let mut captured = HashMap::new();
155 for frame in &self.frames {
156 for b in frame {
157 captured.insert(self.pool.resolve(b.sym).to_string(), b.value.clone());
158 }
159 }
160 captured
161 }
162}