Skip to main content

sim_table_override/
override_table.rs

1//! The [`OverrideTable`] object: an overlay of layered tables whose lookups
2//! resolve front-to-back, implementing the kernel table, object-encoding, and
3//! citizen contracts.
4
5use std::collections::BTreeSet;
6
7use sim_kernel::{
8    Cx, Error, Expr, Object, ObjectEncode, ObjectEncoding, Result, Symbol, Table, Value,
9    id::CORE_TABLE_CLASS_ID, object::ClassRef,
10};
11
12/// Overlay table that layers one or more tables and resolves lookups
13/// front-to-back, so earlier layers shadow later ones.
14///
15/// Reads (`get`/`has`/`keys`/`entries`/`len`) consult layers in order and take
16/// the first match, while writes (`set`/`del`/`clear`) target only the front
17/// (first) layer. Each layer is itself a table [`Value`]; the override holds
18/// references to them rather than copying their contents, so changes to the
19/// underlying layers are visible through the overlay. Implements the kernel
20/// [`Table`] contract along with the object-encoding and citizen contracts.
21#[derive(Clone)]
22pub struct OverrideTable {
23    layers: Vec<Value>,
24}
25
26impl OverrideTable {
27    /// Construct an override table over `layers`, ordered front (shadowing) to
28    /// back (shadowed).
29    ///
30    /// # Errors
31    ///
32    /// Returns an error if `layers` is empty or if any layer value is not a
33    /// table.
34    pub fn new(layers: Vec<Value>) -> Result<Self> {
35        if layers.is_empty() {
36            return Err(Error::Eval(
37                "table/override: expected at least one table layer".to_owned(),
38            ));
39        }
40        for layer in &layers {
41            if layer.object().as_table_impl().is_none() {
42                return Err(Error::Eval(
43                    "table/override: every layer must be a table".to_owned(),
44                ));
45            }
46        }
47        Ok(Self { layers })
48    }
49
50    /// The layer tables, ordered front (shadowing) to back (shadowed).
51    pub fn layers(&self) -> &[Value] {
52        &self.layers
53    }
54
55    fn front(&self) -> &Value {
56        &self.layers[0]
57    }
58}
59
60impl Object for OverrideTable {
61    fn display(&self, _cx: &mut Cx) -> Result<String> {
62        Ok(format!("table/override[layers={}]", self.layers.len()))
63    }
64
65    fn as_any(&self) -> &dyn std::any::Any {
66        self
67    }
68}
69
70impl sim_kernel::ObjectCompat for OverrideTable {
71    fn class(&self, cx: &mut Cx) -> Result<ClassRef> {
72        let symbol = Symbol::qualified("core", "Table");
73        if let Some(value) = cx.registry().class_by_symbol(&symbol) {
74            return Ok(value.clone());
75        }
76        cx.factory().class_stub(CORE_TABLE_CLASS_ID, symbol)
77    }
78    fn as_expr(&self, cx: &mut Cx) -> Result<Expr> {
79        self.as_table_expr(cx)
80    }
81    fn truth(&self, cx: &mut Cx) -> Result<bool> {
82        Ok(!self.is_empty(cx)?)
83    }
84    fn as_table_impl(&self) -> Option<&dyn Table> {
85        Some(self)
86    }
87    fn as_object_encoder(&self) -> Option<&dyn ObjectEncode> {
88        Some(self)
89    }
90}
91
92impl ObjectEncode for OverrideTable {
93    fn object_encoding(&self, cx: &mut Cx) -> Result<ObjectEncoding> {
94        let args = self
95            .layers
96            .iter()
97            .map(|layer| layer.object().as_expr(cx))
98            .collect::<Result<Vec<_>>>()?;
99        Ok(ObjectEncoding::Constructor {
100            class: Symbol::new("OverrideTable"),
101            args,
102        })
103    }
104}
105
106impl sim_citizen::Citizen for OverrideTable {
107    fn citizen_symbol() -> Symbol {
108        Symbol::new("OverrideTable")
109    }
110
111    fn citizen_version() -> u32 {
112        0
113    }
114
115    fn citizen_arity() -> usize {
116        1
117    }
118
119    fn citizen_fields() -> &'static [&'static str] {
120        &["layer"]
121    }
122}
123
124impl Table for OverrideTable {
125    fn backend_symbol(&self) -> Symbol {
126        Symbol::qualified("table", "override")
127    }
128
129    fn get(&self, cx: &mut Cx, key: Symbol) -> Result<Value> {
130        for layer in &self.layers {
131            let table = layer
132                .object()
133                .as_table_impl()
134                .expect("validated table layer");
135            if table.has(cx, key.clone())? {
136                return table.get(cx, key);
137            }
138        }
139        cx.factory().nil()
140    }
141
142    fn set(&self, cx: &mut Cx, key: Symbol, value: Value) -> Result<()> {
143        self.front()
144            .object()
145            .as_table_impl()
146            .expect("validated table layer")
147            .set(cx, key, value)
148    }
149
150    fn has(&self, cx: &mut Cx, key: Symbol) -> Result<bool> {
151        for layer in &self.layers {
152            if layer
153                .object()
154                .as_table_impl()
155                .expect("validated table layer")
156                .has(cx, key.clone())?
157            {
158                return Ok(true);
159            }
160        }
161        Ok(false)
162    }
163
164    fn del(&self, cx: &mut Cx, key: Symbol) -> Result<Value> {
165        self.front()
166            .object()
167            .as_table_impl()
168            .expect("validated table layer")
169            .del(cx, key)
170    }
171
172    fn keys(&self, cx: &mut Cx) -> Result<Vec<Symbol>> {
173        let mut seen = BTreeSet::new();
174        let mut out = Vec::new();
175        for layer in &self.layers {
176            for key in layer
177                .object()
178                .as_table_impl()
179                .expect("validated table layer")
180                .keys(cx)?
181            {
182                if seen.insert(key.clone()) {
183                    out.push(key);
184                }
185            }
186        }
187        Ok(out)
188    }
189
190    fn entries(&self, cx: &mut Cx) -> Result<Vec<(Symbol, Value)>> {
191        let mut seen = BTreeSet::new();
192        let mut out = Vec::new();
193        for layer in &self.layers {
194            for (key, value) in layer
195                .object()
196                .as_table_impl()
197                .expect("validated table layer")
198                .entries(cx)?
199            {
200                if seen.insert(key.clone()) {
201                    out.push((key, value));
202                }
203            }
204        }
205        Ok(out)
206    }
207
208    fn len(&self, cx: &mut Cx) -> Result<usize> {
209        Ok(self.keys(cx)?.len())
210    }
211
212    fn clear(&self, cx: &mut Cx) -> Result<()> {
213        self.front()
214            .object()
215            .as_table_impl()
216            .expect("validated table layer")
217            .clear(cx)
218    }
219}