1use std::rc::Rc;
9use crate::scheme::parser::Position;
10use crate::scheme::value::{Unit, SourceInfo};
11use crate::grove;
12
13#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
15pub struct ValueId(pub u32);
16
17pub const NIL_ID: ValueId = ValueId(0);
19pub const TRUE_ID: ValueId = ValueId(1);
20pub const FALSE_ID: ValueId = ValueId(2);
21pub const UNSPECIFIED_ID: ValueId = ValueId(3);
22pub const ERROR_ID: ValueId = ValueId(4);
23pub const FIRST_USER_ID: u32 = 5;
24
25#[derive(Debug)]
27pub enum ValueData {
28 Nil,
29 Bool(bool),
30 Integer(i64),
31 Real(f64),
32 Quantity { magnitude: f64, unit: Unit },
33 Char(char),
34 String(String),
35 Symbol(Rc<str>),
36 Keyword(Rc<str>),
37 Pair {
38 car: ValueId,
39 cdr: ValueId,
40 pos: Option<Position>,
41 },
42 Vector(Vec<ValueId>),
43 Procedure(ProcedureData),
44 Node(Rc<Box<dyn grove::Node>>),
45 NodeList(Rc<Box<dyn grove::NodeList>>),
46 Sosofo,
47 Unspecified,
48 Error,
49}
50
51pub enum ProcedureData {
53 Primitive {
54 name: &'static str,
55 func: fn(&mut Arena, &[ValueId]) -> Result<ValueId, String>,
56 },
57 Lambda {
58 params: Vec<String>,
59 required_count: usize,
60 optional_defaults: Vec<ValueId>,
61 body: ValueId,
62 env: ValueId,
63 source: Option<SourceInfo>,
64 name: Option<String>,
65 },
66 CompiledLambda {
68 params: Vec<String>,
69 required_count: usize,
70 optional_defaults: Vec<ValueId>,
71 body_ip: usize, env: ValueId,
73 source: Option<SourceInfo>,
74 name: Option<String>,
75 },
76}
77
78impl std::fmt::Debug for ProcedureData {
79 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
80 match self {
81 ProcedureData::Primitive { name, .. } => {
82 write!(f, "Primitive {{ name: {:?}, func: <fn> }}", name)
83 }
84 ProcedureData::Lambda { params, required_count, name, .. } => {
85 write!(f, "Lambda {{ params: {:?}, required_count: {}, name: {:?}, ... }}", params, required_count, name)
86 }
87 ProcedureData::CompiledLambda { params, required_count, body_ip, name, .. } => {
88 write!(f, "CompiledLambda {{ params: {:?}, required_count: {}, body_ip: {}, name: {:?}, ... }}", params, required_count, body_ip, name)
89 }
90 }
91 }
92}
93
94pub struct Arena {
96 values: Vec<ValueData>,
97 marks: Vec<bool>, free_list: Vec<u32>,
99 next_id: u32,
100 pub current_node: Option<Rc<Box<dyn grove::Node>>>,
102 pub grove: Option<Rc<dyn grove::Grove>>,
103}
104
105impl Arena {
106 pub fn new() -> Self {
107 let mut arena = Arena {
108 values: Vec::with_capacity(1024),
109 marks: Vec::with_capacity(1024),
110 free_list: Vec::new(),
111 next_id: FIRST_USER_ID,
112 current_node: None,
113 grove: None,
114 };
115
116 arena.values.push(ValueData::Nil);
118 arena.marks.push(true); arena.values.push(ValueData::Bool(true));
120 arena.marks.push(true);
121 arena.values.push(ValueData::Bool(false));
122 arena.marks.push(true);
123 arena.values.push(ValueData::Unspecified);
124 arena.marks.push(true);
125 arena.values.push(ValueData::Error);
126 arena.marks.push(true);
127
128 arena
129 }
130
131 pub fn alloc(&mut self, data: ValueData) -> ValueId {
132 let id = if let Some(id) = self.free_list.pop() {
133 self.values[id as usize] = data;
134 self.marks[id as usize] = false;
135 id
136 } else {
137 let id = self.next_id;
138 self.next_id += 1;
139 self.values.push(data);
140 self.marks.push(false);
141 id
142 };
143 ValueId(id)
144 }
145
146 #[inline]
147 pub fn get(&self, id: ValueId) -> &ValueData {
148 &self.values[id.0 as usize]
149 }
150
151 #[inline]
152 pub fn get_mut(&mut self, id: ValueId) -> &mut ValueData {
153 &mut self.values[id.0 as usize]
154 }
155
156 #[inline]
157 pub fn cons(&mut self, car: ValueId, cdr: ValueId) -> ValueId {
158 self.alloc(ValueData::Pair { car, cdr, pos: None })
159 }
160
161 #[inline]
162 pub fn cons_with_pos(&mut self, car: ValueId, cdr: ValueId, pos: Position) -> ValueId {
163 self.alloc(ValueData::Pair { car, cdr, pos: Some(pos) })
164 }
165
166 #[inline]
167 pub fn int(&mut self, n: i64) -> ValueId {
168 self.alloc(ValueData::Integer(n))
169 }
170
171 #[inline]
172 pub fn real(&mut self, f: f64) -> ValueId {
173 self.alloc(ValueData::Real(f))
174 }
175
176 #[inline]
177 pub fn string(&mut self, s: String) -> ValueId {
178 self.alloc(ValueData::String(s))
179 }
180
181 #[inline]
182 pub fn symbol(&mut self, s: Rc<str>) -> ValueId {
183 self.alloc(ValueData::Symbol(s))
184 }
185
186 #[inline]
187 pub fn char(&mut self, c: char) -> ValueId {
188 self.alloc(ValueData::Char(c))
189 }
190
191 #[inline]
192 pub fn keyword(&mut self, k: Rc<str>) -> ValueId {
193 self.alloc(ValueData::Keyword(k))
194 }
195
196 #[inline]
197 pub fn vector(&mut self, elements: Vec<ValueId>) -> ValueId {
198 self.alloc(ValueData::Vector(elements))
199 }
200
201 fn mark(&mut self, id: ValueId) {
203 let idx = id.0 as usize;
204
205 if self.marks[idx] {
206 return; }
208
209 self.marks[idx] = true;
210
211 let child_ids = match &self.values[idx] {
213 ValueData::Pair { car, cdr, .. } => vec![*car, *cdr],
214 ValueData::Vector(elements) => elements.clone(),
215 ValueData::Procedure(ProcedureData::Lambda {
216 optional_defaults,
217 body,
218 env,
219 ..
220 }) => {
221 let mut ids = optional_defaults.clone();
222 ids.push(*body);
223 ids.push(*env);
224 ids
225 }
226 ValueData::Procedure(ProcedureData::CompiledLambda {
227 optional_defaults,
228 env,
229 ..
230 }) => {
231 let mut ids = optional_defaults.clone();
232 ids.push(*env);
233 ids
234 }
235 _ => vec![],
236 };
237
238 for child_id in child_ids {
240 self.mark(child_id);
241 }
242 }
243
244 fn sweep(&mut self) {
246 for i in FIRST_USER_ID as usize..self.values.len() {
247 if !self.marks[i] {
248 self.values[i] = ValueData::Nil;
250 self.free_list.push(i as u32);
251 } else {
252 self.marks[i] = false;
254 }
255 }
256 }
257
258 pub fn gc(&mut self, roots: &[ValueId]) {
260 for root in roots {
262 self.mark(*root);
263 }
264
265 self.sweep();
267 }
268
269 pub fn len(&self) -> usize {
270 self.values.len() - self.free_list.len()
271 }
272
273 pub fn is_empty(&self) -> bool {
274 self.len() == FIRST_USER_ID as usize
275 }
276}
277
278impl Default for Arena {
279 fn default() -> Self {
280 Self::new()
281 }
282}
283
284#[cfg(test)]
285mod tests {
286 use super::*;
287
288 #[test]
289 fn test_arena_constants() {
290 let arena = Arena::new();
291 assert!(matches!(arena.get(NIL_ID), ValueData::Nil));
292 assert!(matches!(arena.get(TRUE_ID), ValueData::Bool(true)));
293 assert!(matches!(arena.get(FALSE_ID), ValueData::Bool(false)));
294 }
295
296 #[test]
297 fn test_cons() {
298 let mut arena = Arena::new();
299 let one = arena.int(1);
300 let two = arena.int(2);
301 let pair = arena.cons(one, two);
302
303 match arena.get(pair) {
304 ValueData::Pair { car, cdr, .. } => {
305 assert_eq!(*car, one);
306 assert_eq!(*cdr, two);
307 }
308 _ => panic!("Expected pair"),
309 }
310 }
311
312 #[test]
313 fn test_gc_keeps_reachable() {
314 let mut arena = Arena::new();
315
316 let one = arena.int(1);
317 let two = arena.int(2);
318 let pair = arena.cons(one, two);
319
320 arena.gc(&[pair]);
321
322 assert!(matches!(arena.get(pair), ValueData::Pair { .. }));
324 assert!(matches!(arena.get(one), ValueData::Integer(1)));
325 assert!(matches!(arena.get(two), ValueData::Integer(2)));
326 }
327
328 #[test]
329 fn test_gc_collects_unreachable() {
330 let mut arena = Arena::new();
331
332 let one = arena.int(1);
333 let _two = arena.int(2); let three = arena.int(3);
335 let pair = arena.cons(one, three);
336
337 let before = arena.len();
338 arena.gc(&[pair]);
339 let after = arena.len();
340
341 assert_eq!(before - after, 1);
343 }
344}