ram_machine/
interpreter.rs

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}