1use std::io::{self, Read, Write};
2use std::fmt::{self, Display};
3use instruction::{Instruction, InstructionType};
4
5pub struct Machine<'a, R: Read, W: Write> {
6 code: &'a [Instruction],
7 ip: usize,
8 memory: [usize; 30000],
9 dp: usize,
10 input: R,
11 output: W,
12 read_buf: Vec<u8>,
13}
14
15impl<'a, R: Read, W: Write> Display for Machine<'a, R, W> {
16 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
17 write!(f,
18 "Machine ( code: {:?}, dp: {:?}, buf: {:?} )",
19 self.code, self.dp, self.read_buf
20 )
21 }
22}
23
24impl<'a, R: Read, W: Write> Machine<'a, R, W> {
25 pub fn new(ins: &'a [Instruction], inp: R, out: W) -> Self {
26 Machine {
27 code: ins,
28 ip: 0,
29 memory: [0; 30000],
30 dp: 0,
31 input: inp,
32 output: out,
33 read_buf: Vec::new(),
34 }
35 }
36
37 pub fn execute(&mut self) -> Result<(), String> {
38 let mut line_count = (1, 1);
39 while self.ip < self.code.len() {
40 let ins = &self.code[self.ip];
41
42 match ins.ins_type {
43 InstructionType::PLUS => self.memory[self.dp] += ins.argument,
44 InstructionType::MINUS => self.memory[self.dp] -= ins.argument,
45 InstructionType::RIGHT => self.dp += ins.argument,
46 InstructionType::LEFT => self.dp -= ins.argument,
47 InstructionType::PUT_CHAR => {
48 for _ in 0..ins.argument {
49 match self.put_char() {
50 Ok(_) => continue,
51 Err(e) => panic!(e),
52 }
53 }
54 },
55 InstructionType::READ_CHAR => {
56 for _ in 0..ins.argument {
57 self.read_char();
58 }
59 },
60 InstructionType::JMP_IF_ZERO => {
61 if self.memory[self.dp] == 0 {
62 self.ip = ins.argument as usize;
63 continue
64 }
65 },
66 InstructionType::JMP_IF_NOT_ZERO => {
67 if self.memory[self.dp] != 0 {
68 self.ip = ins.argument as usize;
69 continue
70 }
71 },
72 InstructionType::NEW_LINE => {
73 self.ip += ins.argument;
74 line_count.0 += ins.argument;
75 line_count.1 = ins.position;
76 continue
77 },
78 InstructionType::INVALID => {
79 return Err(format!("Invalid token at line {}, char {}", line_count.0, ins.position - line_count.1));
80 },
81 }
82 self.ip += 1;
83 }
84 Ok(())
85 }
86
87 fn read_char(&mut self) {
88 let c = self.input.by_ref()
89 .bytes()
90 .next().and_then(|result| result.ok())
91 .map(|c| c as u8).unwrap();
92
93 self.read_buf.push(c);
94 self.memory[self.dp] = *self.read_buf.last().unwrap() as usize;
95 }
96
97 fn put_char(&mut self) -> io::Result<usize> {
98 self.read_buf.push(self.memory[self.dp] as u8);
99
100 match self.read_buf.last() {
101 Some(c) => self.output.write(&[c.clone()]),
102 None => Ok(0),
103 }
104 }
105}