1use crate::parser::{
2 instruction::Instruction,
3 operand::{CellOperand, CellValue, ExpandError, Operand},
4 CodeParseError, RamCode,
5};
6use tabled::{settings::Style, Table};
7use thiserror::Error;
8
9#[derive(Debug, PartialEq, Eq)]
10pub struct RamMachine {
11 code: RamCode,
12 tape: Vec<Option<CellValue>>,
13 pointer: usize,
14 input: Vec<CellValue>,
15 input_pointer: usize,
16 output: Vec<CellValue>,
17}
18
19#[derive(Error, Debug, PartialEq, Eq)]
20#[error("Buffer could not be accessed, because its value was never set.")]
21pub struct BufferError;
22
23#[derive(Error, Debug, PartialEq, Eq)]
24pub enum RamMachineError {
25 #[error(transparent)]
26 ExpandError(#[from] ExpandError),
27 #[error(transparent)]
28 BufferError(#[from] BufferError),
29 #[error(transparent)]
30 InputAccessError(#[from] InputAccessError),
31 #[error(transparent)]
32 JumpError(#[from] JumpError),
33 #[error("Addition of `{0}` to `{1}` failed.")]
34 AdditionFailed(CellValue, CellValue),
35 #[error("Subtraction of `{0}` from `{1}` failed.")]
36 SubtractionFailed(CellValue, CellValue),
37 #[error("Multiplication by `{0}` of `{1}` failed.")]
38 MultiplicationFailed(CellValue, CellValue),
39 #[error("Division by `{0}` of `{1}` failed.")]
40 DivisionFailed(CellValue, CellValue),
41}
42
43#[derive(Error, Debug, PartialEq, Eq)]
44pub enum InputAccessError {
45 #[error("Input at index `{0}` not found.")]
46 NotExistentInput(usize),
47}
48
49#[derive(Error, Debug, PartialEq, Eq)]
50pub enum JumpError {
51 #[error("Label `{0}` could not be found in Ram code.")]
52 LabelNotFound(String),
53}
54
55#[derive(PartialEq, Eq)]
56pub enum RunState {
57 Running,
58 Halted,
59}
60
61impl RamMachine {
62 pub fn new(code: RamCode, input: Vec<CellValue>) -> Self {
63 RamMachine {
64 code,
65 tape: vec![None],
66 pointer: 0,
67 input_pointer: 0,
68 input,
69 output: Vec::new(),
70 }
71 }
72
73 pub fn from_str(str: &str, input: Vec<CellValue>) -> Result<Self, CodeParseError> {
74 Ok(RamMachine::new(str.parse()?, input))
75 }
76
77 pub fn run(mut self) -> Result<Vec<CellValue>, RamMachineError> {
78 loop {
79 let instruction = self.code.instructions[self.pointer].clone();
80 if self.execute(&instruction)? == RunState::Halted {
81 break;
82 }
83 }
84 Ok(self.output)
85 }
86
87 pub fn run_line(&mut self) -> Result<RunState, RamMachineError> {
88 let instruction = self.code.instructions[self.pointer].clone();
89 self.execute(&instruction)
90 }
91
92 pub fn get_current_instruction(&self) -> &Instruction {
93 self.code
94 .instructions
95 .get(self.pointer)
96 .unwrap_or(&Instruction::Halt)
97 }
98
99 pub fn print_state(&self) {
100 let tab: Vec<String> = self
101 .tape
102 .iter()
103 .map(|x| match x {
104 Some(v) => v.to_string(),
105 None => "?".to_string(),
106 })
107 .collect();
108 let table = Table::builder(tab)
109 .index()
110 .transpose()
111 .column(0)
112 .build()
113 .with(Style::rounded())
114 .to_string();
115
116 let next_instruction = self.get_current_instruction();
117
118 println!("{table}");
119 println!(
120 "Input:{}",
121 self.input
122 .iter()
123 .fold("".to_string(), |s, v| format!("{s} {v}"))
124 );
125 println!(
126 "Output:{}",
127 self.output
128 .iter()
129 .fold("".to_string(), |s, v| format!("{s} {v}"))
130 );
131 println!("Next instruction: {next_instruction}");
132 }
133
134 fn jump_to(&mut self, label: &str) -> Result<RunState, JumpError> {
135 match self
136 .code
137 .jump_table
138 .get(label)
139 .ok_or_else(|| JumpError::LabelNotFound(label.to_owned()))
140 {
141 Ok(v) => {
142 if *v < self.code.instructions.len() {
143 self.pointer = *v;
144 return Ok(RunState::Running);
145 }
146 Ok(RunState::Halted)
147 }
148 Err(e) => Err(e),
149 }
150 }
151
152 fn get_input(&mut self) -> Result<&CellValue, InputAccessError> {
153 let input = self
154 .input
155 .get(self.input_pointer)
156 .ok_or(InputAccessError::NotExistentInput(self.input_pointer));
157 self.input_pointer += 1;
158 input
159 }
160
161 fn advance_pointer(&mut self) -> RunState {
162 self.pointer += 1;
163 if self.pointer < self.code.instructions.len() {
164 return RunState::Running;
165 }
166 RunState::Halted
167 }
168
169 fn get(&self, operand: &Operand) -> Result<CellValue, ExpandError> {
170 Ok(*operand.expand(&self.tape)?)
171 }
172
173 fn set(&mut self, cell_operand: &CellOperand, value: CellValue) -> Result<(), ExpandError> {
174 let index = cell_operand.expand(&self.tape)?;
175 if self.tape.len() < index + 1 {
176 self.tape.resize(index + 1, None);
177 }
178 *self.tape.get_mut(index).expect("Tape was just resized") = Some(value);
179 Ok(())
180 }
181
182 fn buffer(&self) -> Result<&CellValue, BufferError> {
183 self.tape
184 .first()
185 .and_then(|val| val.as_ref())
186 .ok_or(BufferError)
187 }
188
189 fn buffer_mut(&mut self) -> &mut Option<CellValue> {
190 self.tape
191 .get_mut(0)
192 .expect("Tape was initialized with length 1")
193 }
194
195 fn execute(&mut self, instruction: &Instruction) -> Result<RunState, RamMachineError> {
196 use Instruction::*;
197 match instruction {
198 Load(o) => {
199 *self.buffer_mut() = Some(self.get(o)?);
200 Ok(self.advance_pointer())
201 }
202 Store(o) => {
203 self.set(o, *self.buffer()?)?;
204 Ok(self.advance_pointer())
205 }
206 Add(o) => {
207 *self.buffer_mut() = Some(self.buffer()?.checked_add(self.get(o)?).ok_or(
208 RamMachineError::AdditionFailed(
209 self.get(o).expect("Checked before"),
210 *self.buffer().expect("Checked before"),
211 ),
212 )?);
213 Ok(self.advance_pointer())
214 }
215 Sub(o) => {
216 *self.buffer_mut() = Some(self.buffer()?.checked_sub(self.get(o)?).ok_or(
217 RamMachineError::SubtractionFailed(
218 self.get(o).expect("Checked before"),
219 *self.buffer().expect("Checked before"),
220 ),
221 )?);
222 Ok(self.advance_pointer())
223 }
224 Mult(o) => {
225 *self.buffer_mut() = Some(self.buffer()?.checked_mul(self.get(o)?).ok_or(
226 RamMachineError::MultiplicationFailed(
227 self.get(o).expect("Checked before"),
228 *self.buffer().expect("Checked before"),
229 ),
230 )?);
231 Ok(self.advance_pointer())
232 }
233 Div(o) => {
234 *self.buffer_mut() = Some(self.buffer()?.checked_div(self.get(o)?).ok_or(
235 RamMachineError::DivisionFailed(
236 self.get(o).expect("Checked before"),
237 *self.buffer().expect("Checked before"),
238 ),
239 )?);
240 Ok(self.advance_pointer())
241 }
242 Read(o) => {
243 let input = *self.get_input()?;
244 self.set(o, input)?;
245 Ok(self.advance_pointer())
246 }
247 Write(o) => {
248 self.output.push(self.get(o)?);
249 Ok(self.advance_pointer())
250 }
251 Jump(s) => Ok(self.jump_to(s)?),
252 Jgtz(s) => {
253 if *self.buffer()? > 0 {
254 return Ok(self.jump_to(s)?);
255 }
256 Ok(self.advance_pointer())
257 }
258 Jzero(s) => {
259 if *self.buffer()? == 0 {
260 Ok(self.jump_to(s)?)
261 } else {
262 Ok(self.advance_pointer())
263 }
264 }
265 Halt => Ok(RunState::Halted),
266 }
267 }
268}