1use crate::error::SymError;
2use crate::utils;
3use crate::{instructions::Instruction, parse::Line};
4
5pub struct VM {
6 stack: Vec<u8>,
8 pc: usize,
9 program: Vec<Line>,
10 running: bool,
11}
12
13impl VM {
14 pub fn new(program: Vec<Line>) -> Self {
15 Self {
16 stack: Vec::new(),
18 pc: 0,
19 program,
20 running: true,
21 }
22 }
23
24 pub fn run(&mut self) -> Result<(), SymError> {
25 while self.running && self.pc < self.program.len() {
26 self.pc += 1;
27 let instruction = self.program[self.pc - 1].clone();
28 self.execute_line(instruction)?;
29 }
30 Ok(())
31 }
32
33 fn execute_line(&mut self, instructions: Line) -> Result<(), SymError> {
34 if let Line::Instructions(instructions) = instructions {
35 for instruction in instructions {
36 self.execute(instruction)?;
37 }
38 }
39 Ok(())
40 }
41
42 fn binary_op<F>(&mut self, op: F) -> Result<(), SymError>
43 where
44 F: FnOnce(u8, u8) -> u8,
45 {
46 let a = self.stack.pop().ok_or(SymError::StackUnderflow)?;
47 let b = self.stack.pop().ok_or(SymError::StackUnderflow)?;
48 self.stack.push(op(a, b));
49 Ok(())
50 }
51
52 fn execute(&mut self, instruction: Instruction) -> Result<(), SymError> {
53 match instruction {
54 Instruction::Push(num) => {
55 self.stack.push(num);
56 Ok(())
57 }
58 Instruction::Pop => self.stack.pop().ok_or(SymError::StackUnderflow).map(|_| ()),
59 Instruction::Dup => {
60 let a = *self.stack.last().ok_or(SymError::StackUnderflow)?;
61 self.stack.push(a);
62 Ok(())
63 }
64 Instruction::Swap => {
65 let a = self.stack.pop().ok_or(SymError::StackUnderflow)?;
66 let b = self.stack.pop().ok_or(SymError::StackUnderflow)?;
67 self.stack.push(a);
68 self.stack.push(b);
69 Ok(())
70 }
71 Instruction::Add => Ok(self.binary_op(|a, b| a + b)?),
72 Instruction::Sub => Ok(self.binary_op(|a, b| b - a)?),
73 Instruction::Mul => Ok(self.binary_op(|a, b| a * b)?),
74 Instruction::Div => Ok(self.binary_op(|a, b| b / a)?),
75 Instruction::Mod => Ok(self.binary_op(|a, b| b % a)?),
76 Instruction::Eq => Ok(self.binary_op(|a, b| if a == b { 1 } else { 0 })?),
77 Instruction::Gt => Ok(self.binary_op(|a, b| if b > a { 1 } else { 0 })?),
78 Instruction::Lt => Ok(self.binary_op(|a, b| if b < a { 1 } else { 0 })?),
79 Instruction::Jmp(i) => {
80 self.pc = i - 1;
81 Ok(())
82 }
83 Instruction::Jz(i) => {
84 if self.stack.pop().ok_or(SymError::StackUnderflow)? == 0 {
85 self.pc = i - 1;
86 }
87 Ok(())
88 }
89 Instruction::Jnz(i) => {
90 if self.stack.pop().ok_or(SymError::StackUnderflow)? != 0 {
91 self.pc = i - 1;
92 }
93 Ok(())
94 }
95 Instruction::Halt => {
96 self.running = false;
97 Ok(())
98 }
99 Instruction::In => {
100 self.stack.push(utils::input_from_char()?);
101 Ok(())
102 }
103 Instruction::Out => {
104 let a = self.stack.pop().ok_or(SymError::StackUnderflow)?;
105 utils::out_as_char(a);
106 Ok(())
107 }
108 Instruction::DebugIn => {
109 self.stack.push(utils::input_from_u8()?);
110 Ok(())
111 }
112 Instruction::DebugOut => {
113 let a = self.stack.pop().ok_or(SymError::StackUnderflow)?;
114 utils::out_as_u8(a);
115 Ok(())
116 }
117 Instruction::None => Ok(()),
118 }
119 }
120}