Skip to main content

sim_list_cell/
backend.rs

1//! Library registration for the cons-cell list backend: the [`ConsBackend`]
2//! `ListBackend` implementation, the [`ConsListLib`] manifest, and the
3//! [`install_cons_list_lib`] entry point.
4
5use std::sync::Arc;
6
7use sim_kernel::{
8    AbiVersion, Cx, Dependency, Error, Export, Lib, LibManifest, LibTarget, Linker, ListBackend,
9    Result, Symbol, Value, Version,
10};
11
12use crate::ConsList;
13
14/// The `cons` [`ListBackend`]: constructs [`ConsList`] objects for the
15/// runtime's list-construction and `cons` operations.
16pub struct ConsBackend;
17
18impl ListBackend for ConsBackend {
19    fn name(&self) -> &str {
20        "cons"
21    }
22
23    fn new_list(&self, cx: &mut Cx, items: Vec<Value>) -> Result<Value> {
24        cx.factory().opaque(ConsList::from_vec(items))
25    }
26
27    fn new_cons(&self, cx: &mut Cx, car: Value, cdr: Value) -> Result<Value> {
28        let tail = match cdr.object().downcast_ref::<ConsList>() {
29            Some(cons) => Arc::new(cons.clone()),
30            None => {
31                let Some(list) = cdr.object().as_list() else {
32                    return Err(Error::TypeMismatch {
33                        expected: "list",
34                        found: "non-list",
35                    });
36                };
37                ConsList::from_vec(list.to_vec(cx, None)?)
38            }
39        };
40        cx.factory().opaque(Arc::new(ConsList::cell(car, tail)))
41    }
42}
43
44/// The loadable [`Lib`] manifest for the cons-cell list backend, registered
45/// under the `list/cons` id by [`install_cons_list_lib`].
46pub struct ConsListLib;
47
48impl Lib for ConsListLib {
49    fn manifest(&self) -> LibManifest {
50        LibManifest {
51            id: Symbol::qualified("list", "cons"),
52            version: Version(env!("CARGO_PKG_VERSION").to_owned()),
53            abi: AbiVersion { major: 0, minor: 1 },
54            target: LibTarget::HostRegistered,
55            requires: Vec::<Dependency>::new(),
56            capabilities: Vec::new(),
57            exports: Vec::<Export>::new(),
58        }
59    }
60
61    fn load(&self, _cx: &mut sim_kernel::LoadCx, _linker: &mut Linker<'_>) -> Result<()> {
62        Ok(())
63    }
64}
65
66/// Registers the [`ConsBackend`] in the list registry and loads
67/// [`ConsListLib`], making cons-cell lists available to `cx`.
68///
69/// Idempotent: returns early if the `list/cons` lib is already present.
70pub fn install_cons_list_lib(cx: &mut Cx) -> Result<()> {
71    if cx
72        .registry()
73        .lib(&Symbol::qualified("list", "cons"))
74        .is_some()
75    {
76        return Ok(());
77    }
78    cx.list_registry_mut().register(Arc::new(ConsBackend));
79    cx.load_lib(&ConsListLib).map(|_| ())
80}