Skip to main content

sim_lib_dispatch/
runtime.rs

1//! Runtime integration for the dispatch organ: a [`GenericFunction`] as a
2//! first-class callable value.
3//!
4//! runtime dispatch organ. The dispatch machinery ([`GenericFunction::call`],
5//! most-specific selection) is complete; this wraps a generic as a kernel
6//! [`Callable`] so it is an ordinary runtime value the evaluator can invoke.
7//! Calling it dispatches on the evaluated arguments and runs the single
8//! most-specific applicable primary method. Generics are constructed dynamically
9//! (there is no fixed symbol to register), so the organ's runtime surface is this
10//! value wrapper rather than a loadable set of named functions.
11
12use std::any::Any;
13use std::sync::Arc;
14
15use sim_kernel::{Args, Callable, ClassRef, Cx, Object, ObjectCompat, Result, Symbol, Value};
16
17use crate::generic::GenericFunction;
18
19impl Object for GenericFunction {
20    fn display(&self, _cx: &mut Cx) -> Result<String> {
21        Ok(format!("#<generic {}>", self.name()))
22    }
23
24    fn as_any(&self) -> &dyn Any {
25        self
26    }
27}
28
29impl ObjectCompat for GenericFunction {
30    fn class(&self, cx: &mut Cx) -> Result<ClassRef> {
31        cx.resolve_class(&Symbol::qualified("core", "Function"))
32    }
33
34    fn as_callable(&self) -> Option<&dyn Callable> {
35        Some(self)
36    }
37}
38
39impl Callable for GenericFunction {
40    fn call(&self, cx: &mut Cx, args: Args) -> Result<Value> {
41        let values = args.into_vec();
42        // Delegate to the inherent dispatch entry point (`&[Value]`).
43        GenericFunction::call(self, cx, values.as_slice())
44    }
45}
46
47/// Wraps `generic` as a runtime callable value that dispatches most-specific.
48pub fn generic_function_value(cx: &mut Cx, generic: GenericFunction) -> Result<Value> {
49    cx.factory().opaque(Arc::new(generic))
50}