sim_lib_sequence/
persistent.rs1use std::sync::Arc;
2
3use sim_kernel::{Cx, Error, Expr, Object, ObjectCompat, Result, Symbol, Value, force_list_to_vec};
4
5#[sim_citizen_derive::non_citizen(
6 reason = "persistent vector wrapper; canonical form is native Expr::Vector data",
7 kind = "marker"
8)]
9#[derive(Clone, Debug)]
15pub struct PersistentVector {
16 items: Arc<[Value]>,
17}
18
19impl PersistentVector {
20 pub fn new(items: Vec<Value>) -> Self {
22 Self {
23 items: Arc::from(items),
24 }
25 }
26
27 pub fn items(&self) -> &[Value] {
29 &self.items
30 }
31}
32
33impl Object for PersistentVector {
34 fn display(&self, _cx: &mut Cx) -> Result<String> {
35 Ok(format!("#<sequence-vector {}>", self.items.len()))
36 }
37
38 fn as_any(&self) -> &dyn std::any::Any {
39 self
40 }
41}
42
43impl ObjectCompat for PersistentVector {
44 fn as_expr(&self, cx: &mut Cx) -> Result<Expr> {
45 Ok(Expr::Vector(
46 self.items
47 .iter()
48 .map(|value| value.object().as_expr(cx))
49 .collect::<Result<Vec<_>>>()?,
50 ))
51 }
52
53 fn truth(&self, _cx: &mut Cx) -> Result<bool> {
54 Ok(!self.items.is_empty())
55 }
56}
57
58#[sim_citizen_derive::non_citizen(
59 reason = "persistent set wrapper; canonical form is native Expr::Set data",
60 kind = "marker"
61)]
62#[derive(Clone, Debug)]
68pub struct PersistentSet {
69 items: Arc<[Value]>,
70}
71
72impl PersistentSet {
73 pub fn new(cx: &mut Cx, items: Vec<Value>) -> Result<Self> {
75 let mut unique = Vec::new();
76 for item in items {
77 if !contains_canonical(cx, &unique, &item)? {
78 unique.push(item);
79 }
80 }
81 Ok(Self {
82 items: Arc::from(unique),
83 })
84 }
85
86 pub fn items(&self) -> &[Value] {
88 &self.items
89 }
90}
91
92impl Object for PersistentSet {
93 fn display(&self, _cx: &mut Cx) -> Result<String> {
94 Ok(format!("#<sequence-set {}>", self.items.len()))
95 }
96
97 fn as_any(&self) -> &dyn std::any::Any {
98 self
99 }
100}
101
102impl ObjectCompat for PersistentSet {
103 fn as_expr(&self, cx: &mut Cx) -> Result<Expr> {
104 Ok(Expr::Set(
105 self.items
106 .iter()
107 .map(|value| value.object().as_expr(cx))
108 .collect::<Result<Vec<_>>>()?,
109 ))
110 }
111
112 fn truth(&self, _cx: &mut Cx) -> Result<bool> {
113 Ok(!self.items.is_empty())
114 }
115}
116
117pub fn persistent_list(cx: &mut Cx, items: Vec<Value>) -> Result<Value> {
119 cx.new_list(items)
120}
121
122pub fn persistent_list_push(cx: &mut Cx, list: &Value, item: Value) -> Result<Value> {
124 let mut items = list_items(cx, list)?;
125 items.push(item);
126 cx.new_list(items)
127}
128
129pub fn persistent_vector(cx: &mut Cx, items: Vec<Value>) -> Result<Value> {
148 cx.factory().opaque(Arc::new(PersistentVector::new(items)))
149}
150
151pub fn persistent_vector_push(cx: &mut Cx, vector: &Value, item: Value) -> Result<Value> {
153 let vector = vector_value(vector)?;
154 let mut items = vector.items().to_vec();
155 items.push(item);
156 persistent_vector(cx, items)
157}
158
159pub fn persistent_set(cx: &mut Cx, items: Vec<Value>) -> Result<Value> {
161 let set = PersistentSet::new(cx, items)?;
162 cx.factory().opaque(Arc::new(set))
163}
164
165pub fn persistent_set_insert(cx: &mut Cx, set: &Value, item: Value) -> Result<Value> {
167 let set = set_value(set)?;
168 let mut items = set.items().to_vec();
169 if !contains_canonical(cx, &items, &item)? {
170 items.push(item);
171 }
172 persistent_set(cx, items)
173}
174
175pub fn persistent_map(cx: &mut Cx, entries: Vec<(Symbol, Value)>) -> Result<Value> {
177 cx.new_table(entries)
178}
179
180pub fn persistent_map_assoc(cx: &mut Cx, map: &Value, key: Symbol, value: Value) -> Result<Value> {
184 let table = map.object().as_table_impl().ok_or(Error::TypeMismatch {
185 expected: "table",
186 found: "non-table",
187 })?;
188 let mut entries = table.entries(cx)?;
189 match entries.iter_mut().find(|(candidate, _)| *candidate == key) {
190 Some((_, slot)) => *slot = value,
191 None => entries.push((key, value)),
192 }
193 cx.new_table(entries)
194}
195
196fn list_items(cx: &mut Cx, value: &Value) -> Result<Vec<Value>> {
197 let list = value.object().as_list().ok_or(Error::TypeMismatch {
198 expected: "list",
199 found: "non-list",
200 })?;
201 force_list_to_vec(cx, list, "sequence persistent list")
202}
203
204fn vector_value(value: &Value) -> Result<&PersistentVector> {
205 value
206 .object()
207 .downcast_ref::<PersistentVector>()
208 .ok_or(Error::TypeMismatch {
209 expected: "sequence vector",
210 found: "non-vector",
211 })
212}
213
214fn set_value(value: &Value) -> Result<&PersistentSet> {
215 value
216 .object()
217 .downcast_ref::<PersistentSet>()
218 .ok_or(Error::TypeMismatch {
219 expected: "sequence set",
220 found: "non-set",
221 })
222}
223
224fn contains_canonical(cx: &mut Cx, values: &[Value], candidate: &Value) -> Result<bool> {
225 let candidate = candidate.object().as_expr(cx)?;
226 for value in values {
227 if value.object().as_expr(cx)?.canonical_eq(&candidate) {
228 return Ok(true);
229 }
230 }
231 Ok(false)
232}