Skip to main content

stak_native/
type_check.rs

1use stak_vm::{Error, Heap, Memory, PrimitiveSet, Type};
2use winter_maybe_async::maybe_async;
3
4/// A type check primitive.
5pub enum TypeCheckPrimitive {
6    /// A null type check.
7    Null,
8    /// A pair type check.
9    Pair,
10}
11
12impl TypeCheckPrimitive {
13    const NULL: usize = Self::Null as _;
14    const PAIR: usize = Self::Pair as _;
15}
16
17/// A type check primitive set.
18#[derive(Debug, Default)]
19pub struct TypeCheckPrimitiveSet {}
20
21impl TypeCheckPrimitiveSet {
22    /// Creates a primitive set.
23    pub fn new() -> Self {
24        Self::default()
25    }
26}
27
28impl<H: Heap> PrimitiveSet<H> for TypeCheckPrimitiveSet {
29    type Error = Error;
30
31    #[maybe_async]
32    fn operate(&mut self, memory: &mut Memory<H>, primitive: usize) -> Result<(), Self::Error> {
33        match primitive {
34            TypeCheckPrimitive::NULL => memory.operate_top(|memory, value| {
35                Ok(memory.boolean(value == memory.null()?.into())?.into())
36            })?,
37            TypeCheckPrimitive::PAIR => memory.operate_top(|memory, value| {
38                Ok(memory
39                    .boolean(
40                        value
41                            .to_cons()
42                            .map(|cons| Ok::<_, Error>(memory.cdr(cons)?.tag() == Type::Pair as _))
43                            .transpose()?
44                            .unwrap_or_default(),
45                    )?
46                    .into())
47            })?,
48            _ => return Err(Error::IllegalPrimitive),
49        }
50
51        Ok(())
52    }
53}