1use stak_vm::{Error, Memory, PrimitiveSet, Type};
2
3pub enum EqualPrimitive {
5 Eqv,
7 EqualInner,
9}
10
11impl EqualPrimitive {
12 const EQV: usize = Self::Eqv as _;
13 const EQUAL_INNER: usize = Self::EqualInner as _;
14}
15
16#[derive(Debug, Default)]
18pub struct EqualPrimitiveSet {}
19
20impl EqualPrimitiveSet {
21 pub fn new() -> Self {
23 Self::default()
24 }
25}
26
27impl PrimitiveSet for EqualPrimitiveSet {
28 type Error = Error;
29
30 fn operate(&mut self, memory: &mut Memory, primitive: usize) -> Result<(), Self::Error> {
31 match primitive {
32 EqualPrimitive::EQV => {
33 let [x, y] = memory.pop_many();
34
35 memory.push(
36 memory
37 .boolean(
38 x == y
39 || if let (Some(x), Some(y)) = (x.to_cons(), y.to_cons()) {
40 memory.cdr(x).tag() == Type::Character as _
41 && memory.cdr(y).tag() == Type::Character as _
42 && memory.car(x) == memory.car(y)
43 } else {
44 false
45 },
46 )
47 .into(),
48 )?;
49 }
50 EqualPrimitive::EQUAL_INNER => {
51 let [x, y] = memory.pop_many();
52
53 memory.push(
54 memory
55 .boolean(if let (Some(x), Some(y)) = (x.to_cons(), y.to_cons()) {
56 memory.cdr(x).tag() == memory.cdr(y).tag()
59 && ![Type::Boolean as _, Type::Null as _, Type::Symbol as _]
60 .contains(&memory.cdr(x).tag())
61 && (memory.car(x).is_cons() || memory.car(x) == memory.car(y))
62 } else {
63 false
64 })
65 .into(),
66 )?;
67 }
68
69 _ => return Err(Error::IllegalPrimitive),
70 }
71
72 Ok(())
73 }
74}