sim_lib_lang_islisp/
generic.rs1use std::{collections::BTreeMap, sync::Arc};
2
3use sim_kernel::{Cx, Expr, Object, ObjectCompat, Result, Shape, Symbol, Value};
4use sim_lib_dispatch::{
5 DispatchMethod, GenericFunction, MethodBody, MethodRole, MethodSpecificity,
6};
7
8#[sim_citizen_derive::non_citizen(
9 reason = "dynamic ISLISP instance shell; canonical data is the class symbol and slot table",
10 kind = "marker",
11 descriptor = "islisp/Object"
12)]
13#[derive(Clone, Debug)]
18pub struct IslispObject {
19 class: Symbol,
20 slots: BTreeMap<Symbol, Value>,
21}
22
23impl IslispObject {
24 pub fn new(class: Symbol, slots: BTreeMap<Symbol, Value>) -> Self {
26 Self { class, slots }
27 }
28
29 pub fn class(&self) -> &Symbol {
31 &self.class
32 }
33
34 pub fn slots(&self) -> &BTreeMap<Symbol, Value> {
36 &self.slots
37 }
38}
39
40impl Object for IslispObject {
41 fn display(&self, _cx: &mut Cx) -> Result<String> {
42 Ok(format!("#<islisp-object {}>", self.class))
43 }
44
45 fn as_any(&self) -> &dyn std::any::Any {
46 self
47 }
48}
49
50impl ObjectCompat for IslispObject {
51 fn as_expr(&self, cx: &mut Cx) -> Result<Expr> {
52 let slots = self
53 .slots
54 .iter()
55 .map(|(slot, value)| Ok((Expr::Symbol(slot.clone()), value.object().as_expr(cx)?)))
56 .collect::<Result<Vec<_>>>()?;
57 Ok(Expr::Map(vec![
58 (
59 Expr::Symbol(Symbol::new("class")),
60 Expr::Symbol(self.class.clone()),
61 ),
62 (Expr::Symbol(Symbol::new("slots")), Expr::Map(slots)),
63 ]))
64 }
65
66 fn truth(&self, _cx: &mut Cx) -> Result<bool> {
67 Ok(true)
68 }
69}
70
71pub fn islisp_object_value(
76 cx: &mut Cx,
77 class: Symbol,
78 slots: BTreeMap<Symbol, Value>,
79) -> Result<Value> {
80 cx.factory()
81 .opaque(Arc::new(IslispObject::new(class, slots)))
82}
83
84pub struct IslispGeneric {
90 generic: GenericFunction,
91}
92
93impl IslispGeneric {
94 pub fn new(name: Symbol) -> Self {
96 Self {
97 generic: GenericFunction::new(name),
98 }
99 }
100
101 pub fn name(&self) -> &Symbol {
103 self.generic.name()
104 }
105
106 pub fn add_primary_method(
108 &mut self,
109 id: Symbol,
110 parameter_shapes: Vec<Arc<dyn Shape>>,
111 body: MethodBody,
112 ) -> Result<()> {
113 self.generic.add_method(DispatchMethod::new(
114 id,
115 MethodRole::Primary,
116 parameter_shapes,
117 body,
118 ))
119 }
120
121 pub fn select_primary(&self, cx: &mut Cx, args: &[Value]) -> Result<MethodSpecificity> {
123 self.generic.select_primary(cx, args)
124 }
125
126 pub fn dispatch_order(&self, cx: &mut Cx, args: &[Value]) -> Result<Vec<Symbol>> {
128 self.generic.dispatch_order(cx, args)
129 }
130
131 pub fn call(&self, cx: &mut Cx, args: &[Value]) -> Result<Value> {
133 self.generic.call(cx, args)
134 }
135}