open_pql/vm/
stack.rs

1use super::*;
2
3#[derive(Debug, Clone, Default)]
4pub struct VmStack {
5    inner: VecDeque<VmStackValue>,
6}
7
8impl VmStack {
9    pub fn push(&mut self, v: VmStackValue) {
10        self.inner.push_front(v);
11    }
12
13    pub fn pop(&mut self) -> Result<VmStackValue, PQLError> {
14        self.inner
15            .pop_front()
16            .map_or_else(|| Err(InternalError::BrokenStack.into()), Ok)
17    }
18
19    pub fn downcast_pop<T>(&mut self) -> Result<T, PQLError>
20    where
21        T: TryFrom<VmStackValue>,
22    {
23        T::try_from(self.pop()?)
24            .map_or_else(|_| Err(InternalError::BrokenStack.into()), Ok)
25    }
26}
27
28#[cfg(test)]
29mod tests {
30    use super::*;
31    use crate::*;
32
33    #[test]
34    fn test_push() {
35        let mut stack = VmStack::default();
36        let v = VmStackValue::default_of(PQLType::Long).unwrap();
37
38        stack.push(v);
39
40        assert_eq!(1, stack.inner.len());
41        assert_eq!(v, stack.inner[0]);
42    }
43
44    #[test]
45    fn test_pop() {
46        let mut stack = VmStack::default();
47        let v = VmStackValue::default_of(PQLType::Long).unwrap();
48
49        stack.push(v);
50
51        assert_eq!(Ok(v), stack.pop());
52        assert!(stack.pop().is_err());
53    }
54
55    #[test]
56    fn test_downcast_pop() {
57        fn downcase<T>(v: T) -> Result<T, PQLError>
58        where
59            T: Copy + PartialEq + fmt::Debug + TryFrom<VmStackValue>,
60            VmStackValue: From<T>,
61        {
62            let mut stack = VmStack::default();
63            let v = VmStackValue::from(v);
64
65            stack.push(v);
66
67            stack.downcast_pop::<T>()
68        }
69
70        fn assert_ok<T>(v: T)
71        where
72            T: Copy + PartialEq + fmt::Debug + TryFrom<VmStackValue>,
73            VmStackValue: From<T>,
74        {
75            let got = downcase(v);
76
77            assert_eq!(got, Ok(v));
78        }
79
80        assert_ok(PQLLong::default());
81        assert_ok(PQLDouble::default());
82        assert_ok(PQLStreet::default());
83
84        let mut stack = VmStack::default();
85
86        assert!(stack.downcast_pop::<PQLLong>().is_err());
87
88        stack.push(PQLCard::default().into());
89        assert!(stack.downcast_pop::<PQLLong>().is_err());
90    }
91}