Skip to main content

sim_kernel/
factory.rs

1//! The factory contract: constructing runtime objects from data.
2//!
3//! This is protocol the libraries implement; the kernel defines the [`Factory`]
4//! trait and a default factory, not the concrete construction behavior.
5
6use std::sync::Arc;
7
8use crate::{
9    callable::Callable,
10    class::Class,
11    datum::Datum,
12    env::Cx,
13    error::{Error, Result},
14    expr::{Expr, NumberLiteral},
15    id::{
16        CORE_BOOL_CLASS_ID, CORE_BYTES_CLASS_ID, CORE_CLASS_CLASS_ID, CORE_EXPR_CLASS_ID,
17        CORE_NIL_CLASS_ID, CORE_NUMBER_CLASS_ID, CORE_STRING_CLASS_ID, CORE_SYMBOL_CLASS_ID,
18        ClassId, Symbol,
19    },
20    list::VecList,
21    number_domain::NumberValue,
22    object::{Args, ClassRef, Object, ShapeRef, TableRef},
23    table::AssocTable,
24    value::{RuntimeObject, Value},
25};
26
27/// Constructs runtime [`Value`]s from kernel data.
28///
29/// The kernel defines this contract and threads a `&dyn Factory` through every
30/// [`Cx`]; libraries supply the concrete object representations the
31/// factory hands back. [`DefaultFactory`] provides a minimal built-in
32/// implementation for scalars and core collections.
33pub trait Factory: Send + Sync {
34    /// Wraps an arbitrary runtime object as an opaque value.
35    fn opaque(&self, value: Arc<dyn RuntimeObject>) -> Result<Value>;
36    /// Builds a class value from a class id and symbol.
37    fn class_stub(&self, id: ClassId, symbol: Symbol) -> Result<Value>;
38    /// Builds the nil value.
39    fn nil(&self) -> Result<Value>;
40    /// Builds a boolean value.
41    fn bool(&self, value: bool) -> Result<Value>;
42    /// Builds a symbol value.
43    fn symbol(&self, value: Symbol) -> Result<Value>;
44    /// Builds a string value.
45    fn string(&self, value: String) -> Result<Value>;
46    /// Builds a byte-string value.
47    fn bytes(&self, value: Vec<u8>) -> Result<Value>;
48    /// Builds a list value from its items.
49    fn list(&self, items: Vec<Value>) -> Result<Value>;
50    /// Builds a table value from its entries.
51    fn table(&self, entries: Vec<(Symbol, Value)>) -> Result<Value>;
52    /// Builds a value carrying an [`Expr`].
53    fn expr(&self, expr: Expr) -> Result<Value>;
54    /// Builds a number value from a domain symbol and canonical text.
55    fn number_literal(&self, domain: Symbol, canonical: String) -> Result<Value>;
56
57    /// Builds a single-entry table; convenience over [`table`](Factory::table).
58    fn table_one(&self, key: Symbol, value: Value) -> Result<Value> {
59        self.table(vec![(key, value)])
60    }
61}
62
63/// The built-in [`Factory`]: scalars, core collections, and class stubs.
64#[derive(Default)]
65pub struct DefaultFactory;
66
67impl DefaultFactory {
68    fn class_value(id: ClassId, symbol: Symbol) -> Value {
69        Value::from_arc(Arc::new(BasicClass { id, symbol }))
70    }
71}
72
73impl Factory for DefaultFactory {
74    fn opaque(&self, value: Arc<dyn RuntimeObject>) -> Result<Value> {
75        Ok(Value::from_arc(value))
76    }
77
78    fn class_stub(&self, id: ClassId, symbol: Symbol) -> Result<Value> {
79        Ok(Self::class_value(id, symbol))
80    }
81
82    fn nil(&self) -> Result<Value> {
83        Ok(Value::from_arc(Arc::new(BasicObject::Nil)))
84    }
85
86    fn bool(&self, value: bool) -> Result<Value> {
87        Ok(Value::from_arc(Arc::new(BasicObject::Bool(value))))
88    }
89
90    fn symbol(&self, value: Symbol) -> Result<Value> {
91        Ok(Value::from_arc(Arc::new(BasicObject::Symbol(value))))
92    }
93
94    fn string(&self, value: String) -> Result<Value> {
95        Ok(Value::from_arc(Arc::new(BasicObject::String(value))))
96    }
97
98    fn bytes(&self, value: Vec<u8>) -> Result<Value> {
99        Ok(Value::from_arc(Arc::new(BasicObject::Bytes(value))))
100    }
101
102    fn list(&self, items: Vec<Value>) -> Result<Value> {
103        Ok(Value::from_arc(Arc::new(VecList::from_vec(items))))
104    }
105
106    fn table(&self, entries: Vec<(Symbol, Value)>) -> Result<Value> {
107        Ok(Value::from_arc(Arc::new(AssocTable::with_entries(entries))))
108    }
109
110    fn expr(&self, expr: Expr) -> Result<Value> {
111        Ok(Value::from_arc(Arc::new(BasicObject::Expr(expr))))
112    }
113
114    fn number_literal(&self, domain: Symbol, canonical: String) -> Result<Value> {
115        Ok(Value::from_arc(Arc::new(BasicObject::Number(
116            NumberLiteral { domain, canonical },
117        ))))
118    }
119}
120
121// sim-non-citizen(reason = "private kernel scalar carrier; canonical form is native Expr data", kind = "private", descriptor = "")
122#[derive(Clone)]
123enum BasicObject {
124    Nil,
125    Bool(bool),
126    Number(NumberLiteral),
127    Symbol(Symbol),
128    String(String),
129    Bytes(Vec<u8>),
130    Expr(Expr),
131}
132
133impl BasicObject {
134    fn class_info(&self) -> (ClassId, Symbol) {
135        match self {
136            Self::Nil => (CORE_NIL_CLASS_ID, Symbol::qualified("core", "Nil")),
137            Self::Bool(_) => (CORE_BOOL_CLASS_ID, Symbol::qualified("core", "Bool")),
138            Self::Number(_) => (CORE_NUMBER_CLASS_ID, Symbol::qualified("core", "Number")),
139            Self::Symbol(_) => (CORE_SYMBOL_CLASS_ID, Symbol::qualified("core", "Symbol")),
140            Self::String(_) => (CORE_STRING_CLASS_ID, Symbol::qualified("core", "String")),
141            Self::Bytes(_) => (CORE_BYTES_CLASS_ID, Symbol::qualified("core", "Bytes")),
142            Self::Expr(_) => (CORE_EXPR_CLASS_ID, Symbol::qualified("core", "Expr")),
143        }
144    }
145}
146
147impl Object for BasicObject {
148    fn snapshot(&self, _cx: &mut Cx) -> Result<Option<Datum>> {
149        let datum = match self {
150            Self::Nil => Datum::Nil,
151            Self::Bool(value) => Datum::Bool(*value),
152            Self::Number(value) => Datum::Number(value.clone()),
153            Self::Symbol(value) => Datum::Symbol(value.clone()),
154            Self::String(value) => Datum::String(value.clone()),
155            Self::Bytes(value) => Datum::Bytes(value.clone()),
156            Self::Expr(expr) => match Datum::try_from(expr.clone()) {
157                Ok(datum) => datum,
158                Err(_) => return Ok(None),
159            },
160        };
161        Ok(Some(datum))
162    }
163
164    fn display(&self, _cx: &mut Cx) -> Result<String> {
165        Ok(match self {
166            Self::Nil => "nil".to_owned(),
167            Self::Bool(value) => value.to_string(),
168            Self::Number(value) => value.canonical.clone(),
169            Self::Symbol(value) => value.to_string(),
170            Self::String(value) => value.clone(),
171            Self::Bytes(value) => format!("{value:?}"),
172            Self::Expr(expr) => format!("{expr:?}"),
173        })
174    }
175
176    fn as_any(&self) -> &dyn std::any::Any {
177        self
178    }
179}
180
181impl crate::ObjectCompat for BasicObject {
182    fn class(&self, cx: &mut Cx) -> Result<ClassRef> {
183        let (id, symbol) = self.class_info();
184        if let Some(value) = cx.registry().class_by_symbol(&symbol) {
185            return Ok(value.clone());
186        }
187        Ok(DefaultFactory::class_value(id, symbol))
188    }
189    fn as_expr(&self, _cx: &mut Cx) -> Result<Expr> {
190        Ok(match self {
191            Self::Nil => Expr::Nil,
192            Self::Bool(value) => Expr::Bool(*value),
193            Self::Number(value) => Expr::Number(value.clone()),
194            Self::Symbol(value) => Expr::Symbol(value.clone()),
195            Self::String(value) => Expr::String(value.clone()),
196            Self::Bytes(value) => Expr::Bytes(value.clone()),
197            Self::Expr(expr) => expr.clone(),
198        })
199    }
200    fn truth(&self, _cx: &mut Cx) -> Result<bool> {
201        Ok(!matches!(self, Self::Nil | Self::Bool(false)))
202    }
203    fn as_number_value(&self) -> Option<&dyn NumberValue> {
204        matches!(self, Self::Number(_)).then_some(self)
205    }
206}
207
208impl NumberValue for BasicObject {
209    fn number_domain(&self, _cx: &mut Cx) -> Result<Symbol> {
210        match self {
211            Self::Number(number) => Ok(number.domain.clone()),
212            _ => Err(Error::TypeMismatch {
213                expected: "number",
214                found: "non-number",
215            }),
216        }
217    }
218
219    fn number_literal(&self, _cx: &mut Cx) -> Result<Option<NumberLiteral>> {
220        Ok(match self {
221            Self::Number(number) => Some(number.clone()),
222            _ => None,
223        })
224    }
225}
226
227struct BasicClass {
228    id: ClassId,
229    symbol: Symbol,
230}
231
232impl Object for BasicClass {
233    fn display(&self, _cx: &mut Cx) -> Result<String> {
234        Ok(format!("#<class {}>", self.symbol))
235    }
236
237    fn as_any(&self) -> &dyn std::any::Any {
238        self
239    }
240}
241
242impl crate::ObjectCompat for BasicClass {
243    fn class(&self, cx: &mut Cx) -> Result<ClassRef> {
244        if let Some(value) = cx
245            .registry()
246            .class_by_symbol(&Symbol::qualified("core", "Class"))
247        {
248            return Ok(value.clone());
249        }
250        Ok(DefaultFactory::class_value(
251            CORE_CLASS_CLASS_ID,
252            Symbol::qualified("core", "Class"),
253        ))
254    }
255    fn as_expr(&self, _cx: &mut Cx) -> Result<Expr> {
256        Ok(Expr::Symbol(self.symbol.clone()))
257    }
258    fn as_callable(&self) -> Option<&dyn Callable> {
259        Some(self)
260    }
261    fn as_class(&self) -> Option<&dyn Class> {
262        Some(self)
263    }
264}
265
266impl Callable for BasicClass {
267    fn call(&self, _cx: &mut Cx, _args: Args) -> Result<Value> {
268        Err(Error::Eval(format!(
269            "constructor {} is not implemented yet",
270            self.symbol
271        )))
272    }
273}
274
275impl Class for BasicClass {
276    fn id(&self) -> ClassId {
277        self.id
278    }
279
280    fn symbol(&self) -> Symbol {
281        self.symbol.clone()
282    }
283
284    fn constructor_shape(&self, _cx: &mut Cx) -> Result<ShapeRef> {
285        Ok(Value::from_arc(Arc::new(BasicObject::Nil)))
286    }
287
288    fn instance_shape(&self, _cx: &mut Cx) -> Result<ShapeRef> {
289        Ok(Value::from_arc(Arc::new(BasicObject::Nil)))
290    }
291
292    fn read_constructor(&self, _cx: &mut Cx) -> Result<Option<crate::object::ReadConstructorRef>> {
293        Ok(None)
294    }
295
296    fn members(&self, _cx: &mut Cx) -> Result<TableRef> {
297        Ok(Value::from_arc(Arc::new(AssocTable::new())))
298    }
299}