1use glyph_types::Value;
4
5#[derive(Debug, Clone)]
7pub struct Stack {
8 items: Vec<Value>,
9 max_size: usize,
10}
11
12impl Stack {
13 pub fn new(max_size: usize) -> Self {
15 Stack {
16 items: Vec::with_capacity(1024),
17 max_size,
18 }
19 }
20
21 pub fn push(&mut self, value: Value) -> Result<(), StackError> {
23 if self.items.len() >= self.max_size {
24 return Err(StackError::Overflow);
25 }
26 self.items.push(value);
27 Ok(())
28 }
29
30 pub fn pop(&mut self) -> Result<Value, StackError> {
32 self.items.pop().ok_or(StackError::Underflow)
33 }
34
35 pub fn peek(&self) -> Result<&Value, StackError> {
37 self.items.last().ok_or(StackError::Underflow)
38 }
39
40 pub fn peek_n(&self, n: usize) -> Result<&Value, StackError> {
42 let len = self.items.len();
43 if n >= len {
44 return Err(StackError::Underflow);
45 }
46 Ok(&self.items[len - n - 1])
47 }
48
49 pub fn dup(&mut self) -> Result<(), StackError> {
51 let value = self.peek()?.clone();
52 self.push(value)
53 }
54
55 pub fn swap(&mut self) -> Result<(), StackError> {
57 let len = self.items.len();
58 if len < 2 {
59 return Err(StackError::Underflow);
60 }
61 self.items.swap(len - 1, len - 2);
62 Ok(())
63 }
64
65 pub fn depth(&self) -> usize {
67 self.items.len()
68 }
69
70 pub fn clear(&mut self) {
72 self.items.clear();
73 }
74
75 pub fn slice_from(&self, bp: usize) -> &[Value] {
77 &self.items[bp..]
78 }
79
80 pub fn pop_n(&mut self, n: usize) -> Result<Vec<Value>, StackError> {
82 if self.items.len() < n {
83 return Err(StackError::Underflow);
84 }
85 let split_at = self.items.len() - n;
86 Ok(self.items.split_off(split_at))
87 }
88
89 pub fn truncate(&mut self, depth: usize) {
91 self.items.truncate(depth);
92 }
93}
94
95#[derive(Debug, Clone, PartialEq)]
96pub enum StackError {
97 Overflow,
98 Underflow,
99}
100
101impl std::fmt::Display for StackError {
102 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
103 match self {
104 StackError::Overflow => write!(f, "Stack overflow"),
105 StackError::Underflow => write!(f, "Stack underflow"),
106 }
107 }
108}
109
110impl std::error::Error for StackError {}
111
112#[cfg(test)]
113mod tests {
114 use super::*;
115
116 #[test]
117 fn test_stack_operations() {
118 let mut stack = Stack::new(100);
119
120 stack.push(Value::Int(42)).unwrap();
122 stack.push(Value::Str("hello".to_string())).unwrap();
123
124 assert_eq!(stack.depth(), 2);
125 assert_eq!(stack.pop().unwrap(), Value::Str("hello".to_string()));
126 assert_eq!(stack.pop().unwrap(), Value::Int(42));
127
128 assert!(matches!(stack.pop(), Err(StackError::Underflow)));
130 }
131
132 #[test]
133 fn test_stack_overflow() {
134 let mut stack = Stack::new(2);
135
136 stack.push(Value::Int(1)).unwrap();
137 stack.push(Value::Int(2)).unwrap();
138
139 assert!(matches!(
141 stack.push(Value::Int(3)),
142 Err(StackError::Overflow)
143 ));
144 }
145
146 #[test]
147 fn test_dup_swap() {
148 let mut stack = Stack::new(100);
149
150 stack.push(Value::Int(1)).unwrap();
151 stack.push(Value::Int(2)).unwrap();
152
153 stack.dup().unwrap();
155 assert_eq!(stack.depth(), 3);
156 assert_eq!(stack.peek().unwrap(), &Value::Int(2));
157
158 stack.pop().unwrap(); stack.swap().unwrap();
161 assert_eq!(stack.pop().unwrap(), Value::Int(1));
162 assert_eq!(stack.pop().unwrap(), Value::Int(2));
163 }
164}