1use std::io::Write;
2
3use crate::ast::{
4 AdditiveOperator, Expression, ExpressionListElement, Factor, Line, MultiplicativeOperator,
5 RelationalOperator, Statement, Term,
6};
7
8const STORAGE_SIZE: usize = 256;
9const NUM_VARIABLES: usize = 26;
10
11#[derive(Debug)]
12pub enum Error {
13 LineNumberOutOfRange,
14 UnknownLineNumber,
15}
16
17pub struct Evaluator<'a> {
18 storage: [Option<Line>; STORAGE_SIZE],
19 stack: Vec<usize>,
20 program_counter: usize,
21 variables: [i16; NUM_VARIABLES],
22 output: &'a mut dyn Write,
23}
24
25impl<'a> Evaluator<'a> {
26 pub fn new(output: &'a mut dyn Write) -> Self {
27 Self {
28 storage: [const { None }; STORAGE_SIZE],
29 stack: Vec::new(),
30 program_counter: 0,
31 variables: [0; NUM_VARIABLES],
32 output,
33 }
34 }
35
36 pub fn process_line(&mut self, line: Line) -> Result<(), Error> {
37 match line.number().is_some() {
38 true => self.load_line(line),
39 false => self.run_direct(line.statement())?,
40 }
41
42 Ok(())
43 }
44
45 fn load_line(&mut self, line: Line) {
46 debug_assert!(line.number().is_some());
47
48 let label = line.number().unwrap();
49 self.storage[label as usize] = Some(line);
50 }
51
52 fn jump(&mut self, line_number: u8) -> Result<(), Error> {
53 match self.storage.get(line_number as usize) {
54 Some(_) => {
55 self.program_counter = line_number as usize;
56 }
57 None => Err(Error::UnknownLineNumber)?,
58 };
59
60 Ok(())
61 }
62
63 fn run_direct(&mut self, statement: &Statement) -> Result<(), Error> {
64 match statement {
65 Statement::Print { expression_list } => {
66 for element in expression_list {
67 match element {
68 ExpressionListElement::Expression(expression) => {
69 let value = self.evaluate_expression(expression);
70 write!(self.output, "{} ", value).unwrap();
71 }
72 ExpressionListElement::StringLiteral(string_literal) => {
73 write!(
74 self.output,
75 "{} ",
76 String::from_utf8_lossy(string_literal.value())
77 )
78 .unwrap();
79 }
80 }
81 }
82 writeln!(self.output).unwrap();
83 }
84 Statement::If {
85 left,
86 operator,
87 right,
88 then,
89 } => {
90 let left_value = self.evaluate_expression(left);
91 let right_value = self.evaluate_expression(right);
92
93 let condition = match operator {
94 RelationalOperator::LessThan => left_value < right_value,
95 RelationalOperator::LessThanOrEqual => left_value <= right_value,
96 RelationalOperator::GreaterThan => left_value > right_value,
97 RelationalOperator::GreaterThanOrEqual => left_value >= right_value,
98 RelationalOperator::Equal => left_value == right_value,
99 RelationalOperator::NotEqual => left_value != right_value,
100 };
101
102 if condition {
103 self.run_direct(then)?;
104 }
105 }
106 Statement::Goto { expression } => {
107 let line_number = Self::to_line_number(self.evaluate_expression(expression))?;
108
109 self.jump(line_number)?;
110 }
111 Statement::Input { variable_list: _ } => {
112 todo!("implement input statement");
113 }
114 Statement::Let {
115 variable,
116 expression,
117 } => {
118 let value = self.evaluate_expression(expression);
119 self.store_variable(variable.identifier(), value);
120 }
121 Statement::GoSub { expression } => {
122 let line_number = Self::to_line_number(self.evaluate_expression(expression))?;
123
124 self.stack.push(self.program_counter);
125 self.jump(line_number)?;
126 }
127 Statement::Return => match self.stack.pop() {
128 Some(line_number) => self.program_counter = line_number,
129 None => {
130 self.program_counter = self.storage.len();
131 }
132 },
133 Statement::Clear => {
134 self.storage = [const { None }; STORAGE_SIZE];
135 }
136 Statement::List => {
137 self.storage.iter().for_each(|line| {
138 if let Some(line) = line {
139 writeln!(self.output, "{}", line).unwrap();
140 }
141 });
142 }
143 Statement::Run => {
144 self.program_counter = 0;
145 self.run_indirect()?;
146 }
147 Statement::End => {
148 self.program_counter = self.storage.len();
149 }
150 }
151
152 Ok(())
153 }
154
155 fn to_line_number(value: i16) -> Result<u8, Error> {
156 match u8::try_from(value) {
157 Ok(line_number) => Ok(line_number),
158 Err(_) => Err(Error::LineNumberOutOfRange)?,
159 }
160 }
161
162 fn run_indirect(&mut self) -> Result<(), Error> {
163 while self.program_counter < self.storage.len() {
164 let line = match &self.storage[self.program_counter] {
165 Some(line) => line,
166 None => {
167 self.program_counter += 1;
168 continue;
169 }
170 };
171
172 self.run_direct(&line.statement().clone())?;
173 self.program_counter += 1;
174 }
175
176 Ok(())
177 }
178
179 fn evaluate_expression(&self, expression: &Expression) -> i16 {
180 let term = expression.term();
181 let mut result = self.evaluate_term(term);
182
183 if let Some(AdditiveOperator::Subtraction) = expression.unary_operator() {
184 result = -result;
185 }
186
187 for (operator, term) in expression.others() {
188 let value = self.evaluate_term(term);
189
190 match operator {
191 AdditiveOperator::Addition => result += value,
192 AdditiveOperator::Subtraction => result -= value,
193 }
194 }
195
196 result
197 }
198
199 fn evaluate_term(&self, term: &Term) -> i16 {
200 let factor = term.factor();
201 let mut result = self.evaluate_factor(factor);
202
203 for (operator, factor) in term.operations() {
204 let value = self.evaluate_factor(factor);
205
206 match operator {
207 MultiplicativeOperator::Multiplication => result *= value,
208 MultiplicativeOperator::Division => result /= value,
209 }
210 }
211
212 result
213 }
214
215 fn evaluate_factor(&self, factor: &Factor) -> i16 {
216 match factor {
217 Factor::Variable(variable) => {
218 let identifier = variable.identifier();
219 self.load_variable(identifier)
220 }
221 Factor::NumberLiteral(number) => number.value(),
222 Factor::Expression(expression) => self.evaluate_expression(expression),
223 }
224 }
225
226 fn load_variable(&self, identifier: u8) -> i16 {
227 let offset = (identifier - b'A') as usize;
228 self.variables[offset]
229 }
230
231 fn store_variable(&mut self, identifier: u8, value: i16) {
232 let offset = (identifier - b'A') as usize;
233 self.variables[offset] = value;
234 }
235}