1use 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
14pub 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
44pub 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
66pub 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}