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}