brainfrsck/
interpreter.rs1
2use crate::{
5 error::{ BrainfuckError, },
6 instruction::{ Instruction },
7 components::{ Tape, Memory, IO, },
8};
9use std::{
10 iter::FromIterator,
11 fmt::{ self, Debug, Display },
12};
13
14
15pub struct Interpreter {
18 tape: Tape,
20
21 memory: Memory,
23
24 io: IO,
26} impl Interpreter {
27
28 pub fn new(tape: Tape, input: Option<Vec<u8>>) -> Self {
29 let io = if input.is_some() { IO::new(input.unwrap()) } else { IO::default() };
30 Interpreter {
31 tape,
32 memory: Memory::new(),
33 io,
34 }
35 }
36
37 fn step(&mut self) -> Result<Option<Vec<u8>>, BrainfuckError> {
39
40 match self.tape.get_instruction() {
41 Instruction::IncPtr => {
42 self.memory.inc_ptr()?;
43 },
44 Instruction::DecPtr => {
45 self.memory.dec_ptr();
46 },
47 Instruction::IncVal => {
48 self.memory.inc_val();
49 },
50 Instruction::DecVal => {
51 self.memory.dec_val();
52 },
53 Instruction::Input => {
54 self.io.write_to(&mut self.memory);
55 },
56 Instruction::Output => {
57 self.io.pull_from(&mut self.memory);
58 },
59 Instruction::SetJump => {
60 if self.memory.pull() == 0 {
61 self.tape.jump_forward()?;
62 }
63 },
64 Instruction::Jump => {
65 if self.memory.pull() != 0 {
66 self.tape.jump_back()?;
67 }
68 },
69 Instruction::EOF => {
70 return Ok(Some(self.io.output()))
71 },
72 Instruction::NOP => {
73 return Ok(None)
74 },
75 Instruction::Debug => {
76 eprintln!("{:?};\n{:?};\n{:?};", self.memory, self.io, self.tape)
77 }
78 };
79 Ok(None)
80 }
81
82 pub fn eval(&mut self) -> Result<InterpreterOutput, BrainfuckError> {
84 loop {
85 match self.step() {
86 Err(e) => return Err(e),
87 Ok(Some(output)) => return Ok(InterpreterOutput(output)),
88 Ok(None) => (),
89 }
90 }
91 }
92}
93
94pub struct InterpreterOutput(Vec<u8>);
96impl InterpreterOutput {
97 pub fn to_string(&self) -> String {
99 String::from_iter(self.0.iter().map(|byte| *byte as char))
100 }
101
102 pub fn to_vec(&self) -> Vec<u8> {
104 self.0.clone()
105 }
106}
107impl Debug for InterpreterOutput {
109 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
110 write!(f, "{:?}", self.0)
111 }
112}
113impl Display for InterpreterOutput {
115 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
116 write!(f, "{}", self.to_string())
117 }
118}
119
120pub fn eval_string(code: &'static str, input: Option<Vec<u8>>) -> Result<InterpreterOutput, BrainfuckError> {
122 Interpreter::new(Tape::from_string(code), input).eval()
123}