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 match cdr.object().downcast_ref::<ConsList>() {
29 Some(cons) => cx
30 .factory()
31 .opaque(Arc::new(ConsList::cell(car, Arc::new(cons.clone())))),
32 None => {
33 if cdr.object().as_list().is_none() {
37 return Err(Error::TypeMismatch {
38 expected: "list",
39 found: "non-list",
40 });
41 }
42 cx.factory()
43 .opaque(Arc::new(ConsList::cell_foreign(car, cdr)))
44 }
45 }
46 }
47}
48
49pub struct ConsListLib;
52
53impl Lib for ConsListLib {
54 fn manifest(&self) -> LibManifest {
58 LibManifest {
59 id: Symbol::qualified("list", "cons"),
60 version: Version(env!("CARGO_PKG_VERSION").to_owned()),
61 abi: AbiVersion { major: 0, minor: 1 },
62 target: LibTarget::HostRegistered,
63 requires: Vec::<Dependency>::new(),
64 capabilities: Vec::new(),
65 exports: Vec::<Export>::new(),
66 }
67 }
68
69 fn load(&self, _cx: &mut sim_kernel::LoadCx, _linker: &mut Linker<'_>) -> Result<()> {
70 Ok(())
71 }
72}
73
74pub fn install_cons_list_lib(cx: &mut Cx) -> Result<()> {
79 if cx
80 .registry()
81 .lib(&Symbol::qualified("list", "cons"))
82 .is_some()
83 {
84 return Ok(());
85 }
86 cx.list_registry_mut().register(Arc::new(ConsBackend));
87 cx.load_lib(&ConsListLib).map(|_| ())
88}