1use std::{collections::BTreeMap, sync::Arc};
2
3use sim_kernel::{Args, Cx, Error, Ref, Result, Shape, Symbol, Value};
4use sim_lib_binding::{LexicalEnv, eval_let, lexical_function_value};
5use sim_lib_control::{
6 Condition, ConditionHandler, ConditionStack, ContinuationValue, ControlResultValue, Restart,
7 RestartStack, invoke_restart, signal_condition,
8};
9use sim_lib_dispatch::{
10 DispatchMethod, GenericFunction, MethodBody, MethodRole, MethodSpecificity,
11};
12use sim_lib_mutation::{Cell, cell_value};
13use sim_lib_namespace::{Namespace, NamespaceKind};
14
15use crate::cl_lite_package_symbol;
16
17pub type ClFunctionBody =
22 Arc<dyn Fn(&mut Cx, &LexicalEnv, Vec<Value>) -> Result<Value> + Send + Sync + 'static>;
23
24pub struct ClLiteRuntime {
30 env: LexicalEnv,
31 macros: BTreeMap<Symbol, Value>,
32 variables: BTreeMap<Symbol, Value>,
33 package: Namespace,
34}
35
36impl ClLiteRuntime {
37 pub fn new() -> Result<Self> {
48 Ok(Self {
49 env: LexicalEnv::new(),
50 macros: BTreeMap::new(),
51 variables: BTreeMap::new(),
52 package: cl_lite_package()?,
53 })
54 }
55
56 pub fn environment(&self) -> &LexicalEnv {
58 &self.env
59 }
60
61 pub fn package(&self) -> &Namespace {
63 &self.package
64 }
65
66 pub fn defun(&mut self, cx: &mut Cx, name: Symbol, body: ClFunctionBody) -> Result<Value> {
68 let value = lexical_function_value(cx, name.clone(), self.env.clone(), body)?;
69 self.env.define(name, value.clone())?;
70 Ok(value)
71 }
72
73 pub fn function(&self, name: &Symbol) -> Result<Value> {
75 self.env.lookup(name)
76 }
77
78 pub fn defmacro(&mut self, cx: &mut Cx, name: Symbol, body: ClFunctionBody) -> Result<Value> {
80 let value = lexical_function_value(cx, name.clone(), self.env.clone(), body)?;
81 self.macros.insert(name, value.clone());
82 Ok(value)
83 }
84
85 pub fn macro_function(&self, name: &Symbol) -> Option<Value> {
87 self.macros.get(name).cloned()
88 }
89
90 pub fn let_form(
94 &self,
95 cx: &mut Cx,
96 bindings: Vec<(Symbol, Value)>,
97 body: impl FnOnce(&mut Cx, &LexicalEnv) -> Result<Value>,
98 ) -> Result<Value> {
99 eval_let(cx, &self.env, bindings, body)
100 }
101
102 pub fn define_variable(&mut self, cx: &mut Cx, name: Symbol, initial: Value) -> Result<Value> {
104 let cell = cell_value(cx, initial)?;
105 self.variables.insert(name, cell.clone());
106 Ok(cell)
107 }
108
109 pub fn setq(&mut self, cx: &mut Cx, name: &Symbol, value: Value) -> Result<Value> {
111 let cell_value = self
112 .variables
113 .get(name)
114 .ok_or_else(|| Error::Eval(format!("CL-lite variable {name} is not defined")))?;
115 let cell = cell_value
116 .object()
117 .downcast_ref::<Cell>()
118 .ok_or_else(|| Error::Eval(format!("CL-lite variable {name} is not mutable")))?;
119 cell.set(cx, value.clone())?;
120 Ok(value)
121 }
122
123 pub fn variable_value(&self, name: &Symbol) -> Result<Value> {
125 let cell_value = self
126 .variables
127 .get(name)
128 .ok_or_else(|| Error::Eval(format!("CL-lite variable {name} is not defined")))?;
129 let cell = cell_value
130 .object()
131 .downcast_ref::<Cell>()
132 .ok_or_else(|| Error::Eval(format!("CL-lite variable {name} is not mutable")))?;
133 cell.get()
134 }
135
136 pub fn setf_cell(&mut self, cx: &mut Cx, cell: &Cell, value: Value) -> Result<Value> {
138 cell.set(cx, value.clone())?;
139 Ok(value)
140 }
141}
142
143pub fn call_cl_value(cx: &mut Cx, value: &Value, args: Vec<Value>) -> Result<Value> {
147 let callable = value
148 .object()
149 .as_callable()
150 .ok_or_else(|| Error::Eval("CL-lite value is not callable".to_owned()))?;
151 callable.call(cx, Args::new(args))
152}
153
154pub struct ClLiteControlScope {
159 conditions: ConditionStack,
160 restarts: RestartStack,
161}
162
163impl Default for ClLiteControlScope {
164 fn default() -> Self {
165 Self::new()
166 }
167}
168
169impl ClLiteControlScope {
170 pub fn new() -> Self {
172 Self {
173 conditions: ConditionStack::new(),
174 restarts: RestartStack::new(),
175 }
176 }
177
178 pub fn push_handler(&mut self, handler: ConditionHandler) {
180 self.conditions.push(handler);
181 }
182
183 pub fn pop_handler(&mut self) -> Option<ConditionHandler> {
185 self.conditions.pop()
186 }
187
188 pub fn handler_case(
190 &self,
191 cx: &mut Cx,
192 kind: Symbol,
193 payload: Ref,
194 ) -> Result<ContinuationValue> {
195 signal_condition(cx, &self.conditions, Condition::new(kind, payload))
196 }
197
198 pub fn push_restart(&mut self, name: Symbol, continuation: ContinuationValue) {
200 self.restarts.push(Restart::new(name, continuation));
201 }
202
203 pub fn pop_restart(&mut self) -> Option<Restart> {
205 self.restarts.pop()
206 }
207
208 pub fn restart_case(
210 &self,
211 cx: &mut Cx,
212 name: &Symbol,
213 value: Ref,
214 ) -> Result<ControlResultValue> {
215 invoke_restart(cx, &self.restarts, name, value)
216 }
217}
218
219pub struct ClGenericFunction {
221 generic: GenericFunction,
222}
223
224impl ClGenericFunction {
225 pub fn new(name: Symbol) -> Self {
227 Self {
228 generic: GenericFunction::new(name),
229 }
230 }
231
232 pub fn name(&self) -> &Symbol {
234 self.generic.name()
235 }
236
237 pub fn add_primary_method(
239 &mut self,
240 id: Symbol,
241 parameter_shapes: Vec<Arc<dyn Shape>>,
242 body: MethodBody,
243 ) -> Result<()> {
244 self.generic.add_method(DispatchMethod::new(
245 id,
246 MethodRole::Primary,
247 parameter_shapes,
248 body,
249 ))
250 }
251
252 pub fn select_primary(&self, cx: &mut Cx, args: &[Value]) -> Result<MethodSpecificity> {
254 self.generic.select_primary(cx, args)
255 }
256
257 pub fn dispatch_order(&self, cx: &mut Cx, args: &[Value]) -> Result<Vec<Symbol>> {
259 self.generic.dispatch_order(cx, args)
260 }
261
262 pub fn call(&self, cx: &mut Cx, args: &[Value]) -> Result<Value> {
264 self.generic
265 .call_for_profile(cx, &crate::cl_lite_profile_symbol(), args)
266 }
267}
268
269pub fn cl_lite_package() -> Result<Namespace> {
271 let mut package = Namespace::package(cl_lite_package_symbol());
272 for name in [
273 "defun",
274 "defmacro",
275 "let",
276 "setq",
277 "handler-case",
278 "restart-case",
279 "defgeneric",
280 "defmethod",
281 "defpackage",
282 "in-package",
283 "setf",
284 ] {
285 let local = Symbol::new(name);
286 package.define(local.clone(), Symbol::qualified("cl", name))?;
287 package.export(local)?;
288 }
289 debug_assert_eq!(package.kind(), NamespaceKind::Package);
290 Ok(package)
291}