1use stak_vm::{Error, Memory, PrimitiveSet, Type};
2
3pub enum ListPrimitive {
5 Assq,
7 Cons,
9 Memq,
11}
12
13impl ListPrimitive {
14 const ASSQ: usize = Self::Assq as _;
15 const CONS: usize = Self::Cons as _;
16 const MEMQ: usize = Self::Memq as _;
17}
18
19#[derive(Debug, Default)]
21pub struct ListPrimitiveSet {}
22
23impl ListPrimitiveSet {
24 pub fn new() -> Self {
26 Self::default()
27 }
28}
29
30impl PrimitiveSet for ListPrimitiveSet {
31 type Error = Error;
32
33 fn operate(&mut self, memory: &mut Memory, primitive: usize) -> Result<(), Self::Error> {
34 match primitive {
35 ListPrimitive::ASSQ => {
36 let [x, xs] = memory.pop_many();
37 let mut xs = xs.assume_cons();
38 let mut y = memory.boolean(false);
39
40 while xs != memory.null() {
41 let cons = memory.car(xs).assume_cons();
42
43 if x == memory.car(cons) {
44 y = cons;
45 break;
46 }
47
48 xs = memory.cdr(xs).assume_cons();
49 }
50
51 memory.push(y.into())?;
52 }
53 ListPrimitive::CONS => {
54 let [car, cdr] = memory.pop_many();
55
56 let rib = memory.allocate(car, cdr.set_tag(Type::Pair as _))?;
57 memory.push(rib.into())?;
58 }
59 ListPrimitive::MEMQ => {
60 let [x, xs] = memory.pop_many();
61 let mut xs = xs.assume_cons();
62 let mut y = memory.boolean(false);
63
64 while xs != memory.null() {
65 if x == memory.car(xs) {
66 y = xs;
67 break;
68 }
69
70 xs = memory.cdr(xs).assume_cons();
71 }
72
73 memory.push(y.into())?;
74 }
75 _ => return Err(Error::IllegalPrimitive),
76 }
77
78 Ok(())
79 }
80}