1use thiserror::Error;
2
3use crate::{environment::ValueCell, frame::Frame};
4
5type Result<T> = std::result::Result<T, StackError>;
6
7#[derive(Debug)]
8pub struct Stack {
9 global: Frame,
10 frame: Vec<Frame>,
11 has_break: bool,
12 has_continue: bool,
13}
14
15impl Stack {
16 pub fn new() -> Self {
17 Stack {
18 global: Frame::new(),
19 frame: vec![],
20 has_break: false,
21 has_continue: false,
22 }
23 }
24
25 pub fn is_name_in_local_scope(&self, name: &String) -> bool {
26 self.get_innermost_frame().get_env().has(name)
27 }
28
29 pub fn define(&mut self, name: String, value: ValueCell) -> Result<()> {
30 let scope = self.get_innermost_scope_mut();
31
32 if scope.get_env().has(&name) {
33 return Err(StackError::AlreadyDeclared);
34 }
35
36 scope.get_env_mut().set(name, value);
37
38 Ok(())
39 }
40
41 pub fn assign(&mut self, name: String, value: ValueCell) -> Result<()> {
42 let frame = self
43 .frame
44 .iter_mut()
45 .rev()
46 .find(|frame| frame.get_env().has(&name))
47 .unwrap_or(&mut self.global);
48
49 if frame.get_env().has(&name) {
50 frame.get_env_mut().set(name, value);
51 Ok(())
52 } else {
53 Err(StackError::AssignToUndefined(name))
54 }
55 }
56
57 pub fn lookup(&mut self, name: &str) -> Option<&ValueCell> {
58 for frame in self.frame.iter().rev() {
59 if let Some(var) = frame.get_env().get(name) {
60 return Some(var);
61 }
62 }
63
64 self.global.get_env().get(name)
65 }
66
67 pub fn push(&mut self, frame: Frame) {
68 self.frame.push(frame);
69 }
70
71 pub fn pop(&mut self) {
72 if self.get_innermost_frame().get_return_value().is_some() {
73 self.shift_return_to_upper_frame();
74 }
75
76 self.frame.pop();
77 }
78
79 pub fn set_return_value(&mut self, value: ValueCell) {
80 self.get_innermost_scope_mut().set_return_value(value);
81 }
82
83 pub fn has_return_value(&self) -> bool {
84 self.get_innermost_frame().get_return_value().is_some()
85 }
86
87 pub fn consume_return_value(&mut self) -> Option<ValueCell> {
88 let value = self.get_innermost_frame().get_return_value().cloned();
89
90 self.get_innermost_scope_mut().clear_return_value();
91
92 value
93 }
94
95 pub fn set_loop_break_flag(&mut self, value: bool) {
96 self.has_break = value;
97 }
98
99 pub fn has_loop_break_flag(&self) -> bool {
100 self.has_break
101 }
102
103 pub fn set_loop_continue_flag(&mut self, value: bool) {
104 self.has_continue = value;
105 }
106
107 pub fn has_loop_continue_flag(&self) -> bool {
108 self.has_continue
109 }
110
111 pub fn global(&self) -> &Frame {
112 &self.global
113 }
114
115 pub fn global_mut(&mut self) -> &mut Frame {
116 &mut self.global
117 }
118}
119
120impl Stack {
121 fn get_innermost_frame(&self) -> &Frame {
122 self.frame.last().unwrap_or(&self.global)
123 }
124
125 fn get_innermost_scope_mut(&mut self) -> &mut Frame {
126 self.frame.last_mut().unwrap_or(&mut self.global)
127 }
128
129 fn shift_return_to_upper_frame(&mut self) {
130 let len = self.frame.len();
131
132 let return_value = match self.get_innermost_frame().get_return_value().cloned() {
133 Some(value) => value,
134 None => return,
135 };
136
137 let last_index = len - 1;
138 let decremented_index = last_index - 1;
139
140 let scope_above = match self.frame.get_mut(decremented_index) {
141 Some(scope) => scope,
142 None => return,
143 };
144
145 scope_above.set_return_value(return_value.clone());
146 }
147}
148
149impl<'a> IntoIterator for &'a Stack {
150 type Item = &'a Frame;
151 type IntoIter = std::vec::IntoIter<&'a Frame>;
152
153 fn into_iter(self) -> Self::IntoIter {
154 let mut frames: Vec<&Frame> = Vec::with_capacity(self.frame.len() + 1);
155 frames.push(&self.global);
156 frames.extend(self.frame.iter());
157 frames.into_iter()
158 }
159}
160
161impl Default for Stack {
162 fn default() -> Self {
163 Self::new()
164 }
165}
166
167#[derive(Error, Debug, PartialEq, Clone)]
168pub enum StackError {
169 #[error("variable already declared")]
170 AlreadyDeclared,
171
172 #[error("assignment to undefined variable")]
173 AssignToUndefined(String),
174}