1use 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
27pub trait Factory: Send + Sync {
34 fn opaque(&self, value: Arc<dyn RuntimeObject>) -> Result<Value>;
36 fn class_stub(&self, id: ClassId, symbol: Symbol) -> Result<Value>;
38 fn nil(&self) -> Result<Value>;
40 fn bool(&self, value: bool) -> Result<Value>;
42 fn symbol(&self, value: Symbol) -> Result<Value>;
44 fn string(&self, value: String) -> Result<Value>;
46 fn bytes(&self, value: Vec<u8>) -> Result<Value>;
48 fn list(&self, items: Vec<Value>) -> Result<Value>;
50 fn table(&self, entries: Vec<(Symbol, Value)>) -> Result<Value>;
52 fn expr(&self, expr: Expr) -> Result<Value>;
54 fn number_literal(&self, domain: Symbol, canonical: String) -> Result<Value>;
56
57 fn table_one(&self, key: Symbol, value: Value) -> Result<Value> {
59 self.table(vec![(key, value)])
60 }
61}
62
63#[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#[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}