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 {
55 LibManifest {
56 id: Symbol::qualified("list", "cons"),
57 version: Version(env!("CARGO_PKG_VERSION").to_owned()),
58 abi: AbiVersion { major: 0, minor: 1 },
59 target: LibTarget::HostRegistered,
60 requires: Vec::<Dependency>::new(),
61 capabilities: Vec::new(),
62 exports: Vec::<Export>::new(),
63 }
64 }
65
66 fn load(&self, _cx: &mut sim_kernel::LoadCx, _linker: &mut Linker<'_>) -> Result<()> {
67 Ok(())
68 }
69}
70
71pub fn install_cons_list_lib(cx: &mut Cx) -> Result<()> {
76 if cx
77 .registry()
78 .lib(&Symbol::qualified("list", "cons"))
79 .is_some()
80 {
81 return Ok(());
82 }
83 cx.list_registry_mut().register(Arc::new(ConsBackend));
84 cx.load_lib(&ConsListLib).map(|_| ())
85}