Skip to main content

tenda_runtime/
stack.rs

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}