blots_core/
heap.rs

1use crate::values::{LambdaDef, PrimitiveValue, ReifiedIterableValue, Value};
2use anyhow::{Result, anyhow};
3use indexmap::IndexMap;
4use serde::{Deserialize, Serialize};
5use std::fmt::{self, Display, Formatter};
6use std::sync::LazyLock;
7
8pub static CONSTANTS: LazyLock<IndexMap<String, PrimitiveValue>> = LazyLock::new(|| {
9    let mut constants = IndexMap::new();
10    constants.insert(
11        String::from("pi"),
12        PrimitiveValue::Number(core::f64::consts::PI),
13    );
14    constants.insert(
15        String::from("e"),
16        PrimitiveValue::Number(core::f64::consts::E),
17    );
18    constants.insert(String::from("max_value"), PrimitiveValue::Number(f64::MAX));
19    constants.insert(
20        String::from("min_value"),
21        PrimitiveValue::Number(f64::MIN_POSITIVE),
22    );
23    constants
24});
25
26#[derive(Debug, Clone)]
27pub enum HeapValue {
28    List(Vec<Value>),
29    String(String),
30    Record(IndexMap<String, Value>),
31    Lambda(LambdaDef),
32}
33
34impl HeapValue {
35    pub fn get_type(&self) -> &str {
36        match self {
37            HeapValue::List(_) => "list",
38            HeapValue::String(_) => "string",
39            HeapValue::Record(_) => "record",
40            HeapValue::Lambda(_) => "function",
41        }
42    }
43
44    pub fn as_list(&self) -> Result<&Vec<Value>> {
45        match self {
46            HeapValue::List(list) => Ok(list),
47            _ => Err(anyhow!("expected a list, but got a {}", self.get_type())),
48        }
49    }
50
51    pub fn as_string(&self) -> Result<&str> {
52        match self {
53            HeapValue::String(string) => Ok(string),
54            _ => Err(anyhow!("expected a list, but got a {}", self.get_type())),
55        }
56    }
57
58    pub fn as_record(&self) -> Result<&IndexMap<String, Value>> {
59        match self {
60            HeapValue::Record(record) => Ok(record),
61            _ => Err(anyhow!("expected a list, but got a {}", self.get_type())),
62        }
63    }
64
65    pub fn as_lambda(&self) -> Result<&LambdaDef> {
66        match self {
67            HeapValue::Lambda(lambda) => Ok(lambda),
68            _ => Err(anyhow!("expected a list, but got a {}", self.get_type())),
69        }
70    }
71
72    pub fn as_iterable(&self) -> Result<ReifiedIterableValue<'_>> {
73        match self {
74            HeapValue::List(list) => Ok(ReifiedIterableValue::List(list)),
75            HeapValue::String(string) => Ok(ReifiedIterableValue::String(string)),
76            HeapValue::Record(record) => Ok(ReifiedIterableValue::Record(record)),
77            _ => Err(anyhow!(
78                "expected an iterable, but got a {}",
79                self.get_type()
80            )),
81        }
82    }
83}
84
85#[derive(Debug, Clone)]
86pub struct Heap {
87    values: Vec<HeapValue>,
88}
89
90impl Heap {
91    pub fn new() -> Self {
92        let mut s = Self { values: Vec::new() };
93        s.insert_record(
94            CONSTANTS
95                .clone()
96                .into_iter()
97                .map(|(k, v)| (k, v.into()))
98                .collect(),
99        );
100
101        s
102    }
103
104    pub fn insert(&mut self, value: HeapValue) -> usize {
105        self.values.push(value);
106
107        self.values.len() - 1
108    }
109
110    pub fn insert_list(&mut self, list: Vec<Value>) -> Value {
111        Value::List(ListPointer::new(self.insert(HeapValue::List(list))))
112    }
113
114    pub fn insert_string(&mut self, string: String) -> Value {
115        Value::String(StringPointer::new(self.insert(HeapValue::String(string))))
116    }
117
118    pub fn insert_record(&mut self, record: IndexMap<String, Value>) -> Value {
119        Value::Record(RecordPointer::new(self.insert(HeapValue::Record(record))))
120    }
121
122    pub fn insert_lambda(&mut self, lambda: LambdaDef) -> Value {
123        Value::Lambda(LambdaPointer::new(self.insert(HeapValue::Lambda(lambda))))
124    }
125
126    pub fn get(&self, id: usize) -> Option<&HeapValue> {
127        self.values.get(id)
128    }
129
130    pub fn get_mut(&mut self, id: usize) -> Option<&mut HeapValue> {
131        self.values.get_mut(id)
132    }
133}
134
135impl Default for Heap {
136    fn default() -> Self {
137        Self::new()
138    }
139}
140
141pub trait HeapPointer<'h> {
142    fn reify(&self, heap: &'h Heap) -> &'h HeapValue;
143    fn reify_mut(&self, heap: &'h mut Heap) -> &'h mut HeapValue;
144    fn get_type(&self) -> &str;
145}
146
147macro_rules! define_pointer {
148    ($name:ident, $type:literal) => {
149        #[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, PartialOrd)]
150        pub struct $name(usize);
151
152        impl $name {
153            pub fn new(index: usize) -> Self {
154                $name(index)
155            }
156
157            pub fn index(&self) -> usize {
158                self.0
159            }
160        }
161
162        impl<'h> HeapPointer<'h> for $name {
163            fn reify(&self, heap: &'h Heap) -> &'h HeapValue {
164                heap.get(self.0).expect("Dangling pointer!")
165            }
166
167            fn reify_mut(&self, heap: &'h mut Heap) -> &'h mut HeapValue {
168                heap.get_mut(self.0).expect("Dangling pointer!")
169            }
170
171            fn get_type(&self) -> &str {
172                $type
173            }
174        }
175
176        impl Display for $name {
177            fn fmt(&self, f: &mut Formatter) -> fmt::Result {
178                write!(f, "{}@{}", $type, self.0)
179            }
180        }
181    };
182}
183
184define_pointer!(ListPointer, "list");
185define_pointer!(StringPointer, "string");
186define_pointer!(RecordPointer, "record");
187define_pointer!(LambdaPointer, "function");
188
189#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, PartialOrd)]
190pub enum IterablePointer {
191    List(ListPointer),
192    String(StringPointer),
193    Record(RecordPointer),
194}
195
196impl From<ListPointer> for IterablePointer {
197    fn from(pointer: ListPointer) -> Self {
198        IterablePointer::List(pointer)
199    }
200}
201
202impl From<StringPointer> for IterablePointer {
203    fn from(pointer: StringPointer) -> Self {
204        IterablePointer::String(pointer)
205    }
206}
207
208impl From<RecordPointer> for IterablePointer {
209    fn from(pointer: RecordPointer) -> Self {
210        IterablePointer::Record(pointer)
211    }
212}
213
214impl<'h> HeapPointer<'h> for IterablePointer {
215    fn get_type(&self) -> &str {
216        match self {
217            IterablePointer::List(pointer) => pointer.get_type(),
218            IterablePointer::String(pointer) => pointer.get_type(),
219            IterablePointer::Record(pointer) => pointer.get_type(),
220        }
221    }
222
223    fn reify(&self, heap: &'h Heap) -> &'h HeapValue {
224        match self {
225            IterablePointer::List(pointer) => pointer.reify(heap),
226            IterablePointer::String(pointer) => pointer.reify(heap),
227            IterablePointer::Record(pointer) => pointer.reify(heap),
228        }
229    }
230
231    fn reify_mut(&self, heap: &'h mut Heap) -> &'h mut HeapValue {
232        match self {
233            IterablePointer::List(pointer) => pointer.reify_mut(heap),
234            IterablePointer::String(pointer) => pointer.reify_mut(heap),
235            IterablePointer::Record(pointer) => pointer.reify_mut(heap),
236        }
237    }
238}
239
240impl Display for IterablePointer {
241    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
242        match self {
243            IterablePointer::List(pointer) => write!(f, "{}", pointer),
244            IterablePointer::String(pointer) => write!(f, "{}", pointer),
245            IterablePointer::Record(pointer) => write!(f, "{}", pointer),
246        }
247    }
248}