Решение на Reversible Interpreter от Илиян Йорданов

Обратно към всички решения

Към профила на Илиян Йорданов

Резултати

  • 15 точки от тестове
  • 0 бонус точки
  • 15 точки общо
  • 12 успешни тест(а)
  • 0 неуспешни тест(а)

Код

#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
use super::*;
#[test]
fn test_forward() {
let mut i = Interpreter::new();
i.add_instructions(&["PUSH 3819021 jklks"]);
assert_eq!(i.forward(), Err(RuntimeError::InvalidCommand));
i.instructions.pop_front();
i.add_instructions(&["PUSH 3819021 78"]);
assert_eq!(i.forward(), Err(RuntimeError::InvalidCommand));
i.instructions.pop_front();
i.add_instructions(&["PUSH 38u19021 jklks"]);
assert_eq!(i.forward(), Err(RuntimeError::InvalidCommand));
i.instructions.pop_front();
i.add_instructions(&["PUS 3819021"]);
assert_eq!(i.forward(), Err(RuntimeError::InvalidCommand));
i.instructions.pop_front();
i.add_instructions(&["AD "]);
assert_eq!(i.forward(), Err(RuntimeError::InvalidCommand));
i.instructions.pop_front();
i.add_instructions(&["ADD 3819021"]);
assert_eq!(i.forward(), Err(RuntimeError::InvalidCommand));
i.instructions.pop_front();
assert_eq!(i.forward(), Err(RuntimeError::NoInstructions));
}
#[test]
fn test_forward_push() {
let mut i = Interpreter::new();
i.add_instructions(&[" PUSH 3819021"]);
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.stack.last().unwrap(), &3819021);
i.add_instructions(&["PUSH 3819021", "PUSH 42"]);
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.stack.last().unwrap(), &3819021);
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.stack.last().unwrap(), &42);
}
#[test]
fn test_forward_pop() {
let mut i = Interpreter::new();
i.add_instructions(&["PUSH 3", "PUSH 5", "POP", "POP", "POP"]);
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.stack.len(), 1);
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.stack.len(), 0);
assert_eq!(i.forward(), Err(RuntimeError::StackUnderflow));
}
#[test]
fn test_forward_add() {
let mut i = Interpreter::new();
i.add_instructions(&["PUSH 3", "PUSH 5", "PUSH 8", "ADD", "ADD", "ADD"]);
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.stack.len(), 2);
assert_eq!(i.stack.last().unwrap(), &13);
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.stack.len(), 1);
assert_eq!(i.stack.last().unwrap(), &16);
assert_eq!(i.forward(), Err(RuntimeError::StackUnderflow));
}
#[test]
fn test_forward_sub() {
let mut i = Interpreter::new();
i.add_instructions(&["PUSH 3", "PUSH 5", "PUSH 8", "SUB", "SUB", "SUB"]);
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.stack.len(), 2);
assert_eq!(i.stack.last().unwrap(), &3);
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.stack.len(), 1);
assert_eq!(i.stack.last().unwrap(), &0);
assert_eq!(i.forward(), Err(RuntimeError::StackUnderflow));
}
#[test]
fn test_forward_mul() {
let mut i = Interpreter::new();
i.add_instructions(&["PUSH 3", "PUSH 5", "PUSH 8", "MUL", "MUL", "MUL"]);
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.stack.len(), 2);
assert_eq!(i.stack.last().unwrap(), &40);
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.stack.len(), 1);
assert_eq!(i.stack.last().unwrap(), &120);
assert_eq!(i.forward(), Err(RuntimeError::StackUnderflow));
}
#[test]
fn test_forward_div() {
let mut i = Interpreter::new();
i.add_instructions(&["PUSH 3", "PUSH 5", "PUSH 8", "DIV", "DIV", "PUSH 5", "DIV"]);
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.stack.len(), 2);
assert_eq!(i.stack.last().unwrap(), &1);
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.stack.len(), 1);
assert_eq!(i.stack.last().unwrap(), &0);
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.forward(), Err(RuntimeError::DivideByZero));
assert_eq!(i.forward(), Err(RuntimeError::DivideByZero));
i.instructions.pop_front();
assert_eq!(i.forward(), Err(RuntimeError::NoInstructions));
while i.stack.len() != 0 {
i.stack.pop();
}
i.add_instructions(&[
"PUSH 3", "PUSH 5", "PUSH 8", "SUB", "DIV", "PUSH 5", "PUSH 3", "MUL", "ADD",
]);
assert_eq!(i.run(), Ok(()));
assert_eq!(i.instructions.len(), 0);
assert_eq!(i.stack, vec![16]);
}
#[test]
fn test_back() {
let mut interpreter = Interpreter::new();
assert_eq!(interpreter.back(), Err(RuntimeError::NoInstructions));
interpreter.add_instructions(&[" PUSH 0 ", " PUSH 42 ", " DIV "]);
assert_eq!(interpreter.forward(), Ok(()));
assert_eq!(interpreter.forward(), Ok(()));
assert_eq!(interpreter.instructions, &[" DIV "]);
assert_eq!(interpreter.stack, vec![0, 42]);
assert_eq!(interpreter.forward(), Err(RuntimeError::DivideByZero));
assert_eq!(interpreter.back(), Ok(()));
assert_eq!(interpreter.back(), Ok(()));
interpreter
.current_instruction()
.map(|i| *i = String::from("PUSH 2"));
assert_eq!(interpreter.run(), Ok(()));
assert_eq!(interpreter.instructions.len(), 0);
assert_eq!(interpreter.stack, vec![21]);
interpreter.stack.pop();
interpreter.add_instructions(&["PUSH 3", "PUSH 42", "POP", "POP"]);
assert_eq!(interpreter.forward(), Ok(()));
assert_eq!(interpreter.forward(), Ok(()));
assert_eq!(interpreter.forward(), Ok(()));
assert_eq!(interpreter.forward(), Ok(()));
assert_eq!(interpreter.stack.len(), 0);
assert_eq!(interpreter.back(), Ok(()));
assert_eq!(interpreter.back(), Ok(()));
interpreter
.current_instruction()
.map(|i| *i = String::from("ADD"));
assert_eq!(interpreter.forward(), Ok(()));
assert_eq!(interpreter.stack, vec![45]);
assert_eq!(interpreter.forward(), Ok(()));
assert_eq!(interpreter.back(), Ok(()));
assert_eq!(interpreter.back(), Ok(()));
interpreter
.current_instruction()
.map(|i| *i = String::from("SUB"));
assert_eq!(interpreter.forward(), Ok(()));
assert_eq!(interpreter.stack, vec![39]);
assert_eq!(interpreter.forward(), Ok(()));
assert_eq!(interpreter.back(), Ok(()));
assert_eq!(interpreter.back(), Ok(()));
interpreter
.current_instruction()
.map(|i| *i = String::from("MUL"));
assert_eq!(interpreter.forward(), Ok(()));
assert_eq!(interpreter.stack, vec![126]);
assert_eq!(interpreter.forward(), Ok(()));
assert_eq!(interpreter.back(), Ok(()));
assert_eq!(interpreter.back(), Ok(()));
interpreter
.current_instruction()
.map(|i| *i = String::from("DIV"));
assert_eq!(interpreter.forward(), Ok(()));
assert_eq!(interpreter.stack, vec![14]);
assert_eq!(interpreter.forward(), Ok(()));
assert_eq!(interpreter.back(), Ok(()));
assert_eq!(interpreter.back(), Ok(()));
assert_eq!(interpreter.back(), Ok(()));
assert_eq!(interpreter.back(), Ok(()));
assert_eq!(interpreter.stack.len(), 0);
assert_eq!(interpreter.run(), Ok(()));
assert_eq!(interpreter.back(), Ok(()));
assert_eq!(interpreter.instructions.len(), 1);
assert_eq!(interpreter.stack, vec![14]);
for _ in 0..3 {
assert_eq!(interpreter.back(), Ok(()));
}
assert_eq!(
interpreter.instructions,
&["PUSH 3", "PUSH 42", "DIV", "POP"]
);
assert_eq!(interpreter.stack.len(), 0);
assert_eq!(interpreter.run(), Ok(()));
assert_eq!(interpreter.back(), Ok(()));
assert_eq!(interpreter.instructions.len(), 1);
assert_eq!(interpreter.stack, vec![14]);
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum RuntimeError {
DivideByZero,
StackUnderflow,
InvalidCommand,
NoInstructions,
}
use std::collections::VecDeque;
#[derive(Debug, Default)]
pub struct Interpreter {
pub instructions: VecDeque<String>,
pub stack: Vec<i32>,
past_instructions: Vec<String>,
past_nums: Vec<i32>,
}
impl Interpreter {
pub fn new() -> Self {
return Self {
instructions: VecDeque::new(),
stack: Vec::new(),
past_instructions: Vec::new(),
past_nums: Vec::new(),
};
}
pub fn add_instructions(&mut self, instructions: &[&str]) {
for instruction in instructions {
self.instructions.push_back(instruction.to_string());
}
}
pub fn current_instruction(&mut self) -> Option<&mut String> {
if self.instructions.len() == 0 {
return None;
} else {
return Some(&mut self.instructions[0]);
}
}
pub fn forward(&mut self) -> Result<(), RuntimeError> {
if self.instructions.len() == 0 {
return Err(RuntimeError::NoInstructions);
}
let instruction = (&self.instructions[0]).trim().to_string();
let mut iter = instruction.split_whitespace();
match iter.next() {
None => Err(RuntimeError::InvalidCommand),
Some(command) => {
if command == "PUSH" {
match iter.next() {
None => return Err(RuntimeError::InvalidCommand),
Some(number) => match iter.next() {
None => match number.parse::<i32>() {
Err(_) => return Err(RuntimeError::InvalidCommand),
Ok(num) => {
self.stack.push(num);
self.past_instructions
.push(self.instructions.pop_front().unwrap());
return Ok(());
}
},
Some(_) => return Err(RuntimeError::InvalidCommand),
},
}
}
if command != "POP"
&& command != "ADD"
&& command != "SUB"
&& command != "MUL"
&& command != "DIV"
{
return Err(RuntimeError::InvalidCommand);
}
match iter.next() {
Some(_) => return Err(RuntimeError::InvalidCommand),
None => {
if command == "POP" {
if self.stack.len() == 0 {
return Err(RuntimeError::StackUnderflow);
}
self.past_nums.push(self.stack.pop().unwrap());
self.past_instructions
.push(self.instructions.pop_front().unwrap());
return Ok(());
}
if self.stack.len() < 2 {
return Err(RuntimeError::StackUnderflow);
}
if command == "DIV" && self.stack[self.stack.len() - 2] == 0 {
return Err(RuntimeError::DivideByZero);
}
self.past_nums.push(*self.stack.last().unwrap());
let num1 = self.stack.pop().unwrap();
self.past_nums.push(*self.stack.last().unwrap());
let num2 = self.stack.pop().unwrap();
if command == "ADD" {
self.stack.push(num1 + num2);
} else if command == "SUB" {
self.stack.push(num1 - num2);
} else if command == "MUL" {
self.stack.push(num1 * num2);
} else {
self.stack.push(num1 / num2);
}
self.past_instructions
.push(self.instructions.pop_front().unwrap());
return Ok(());
}
}
}
}
}
pub fn run(&mut self) -> Result<(), RuntimeError> {
loop {
match self.forward() {
Err(RuntimeError::NoInstructions) => return Ok(()),
Err(e) => return Err(e),
_ => (),
}
}
}
pub fn back(&mut self) -> Result<(), RuntimeError> {
if self.past_instructions.len() == 0 {
return Err(RuntimeError::NoInstructions);
}
let instruction = self.past_instructions.pop().unwrap().trim().to_string();
let mut iter = instruction.split_whitespace();
let command = iter.next().unwrap();
if command == "PUSH" {
self.stack.pop();
} else if command == "POP" {
self.stack.push(self.past_nums.pop().unwrap());
} else {
self.stack.pop();
self.stack.push(self.past_nums.pop().unwrap());
self.stack.push(self.past_nums.pop().unwrap());
}
self.instructions.push_front(instruction);
return Ok(());
}
}

Лог от изпълнението

Compiling solution v0.1.0 (/tmp/d20210120-1538662-1n90l1n/solution)
    Finished test [unoptimized + debuginfo] target(s) in 2.33s
     Running target/debug/deps/solution_test-8916805fc40a2dab

running 12 tests
test solution_test::test_arg_number ... ok
test solution_test::test_arithmetic_back ... ok
test solution_test::test_arithmetic_basic ... ok
test solution_test::test_div_1 ... ok
test solution_test::test_div_2 ... ok
test solution_test::test_errors_1 ... ok
test solution_test::test_errors_2 ... ok
test solution_test::test_instructions_after_error ... ok
test solution_test::test_invalid_args ... ok
test solution_test::test_pop ... ok
test solution_test::test_push ... ok
test solution_test::test_restoring_instructions ... ok

test result: ok. 12 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

История (2 версии и 0 коментара)

Илиян качи първо решение на 14.01.2021 11:46 (преди 6 месеца)

Илиян качи решение на 20.01.2021 15:45 (преди 6 месеца)

#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
use super::*;
#[test]
fn test_forward() {
let mut i = Interpreter::new();
i.add_instructions(&["PUSH 3819021 jklks"]);
assert_eq!(i.forward(), Err(RuntimeError::InvalidCommand));
i.instructions.pop_front();
i.add_instructions(&["PUSH 3819021 78"]);
assert_eq!(i.forward(), Err(RuntimeError::InvalidCommand));
i.instructions.pop_front();
i.add_instructions(&["PUSH 38u19021 jklks"]);
assert_eq!(i.forward(), Err(RuntimeError::InvalidCommand));
i.instructions.pop_front();
i.add_instructions(&["PUS 3819021"]);
assert_eq!(i.forward(), Err(RuntimeError::InvalidCommand));
i.instructions.pop_front();
i.add_instructions(&["AD "]);
assert_eq!(i.forward(), Err(RuntimeError::InvalidCommand));
i.instructions.pop_front();
i.add_instructions(&["ADD 3819021"]);
assert_eq!(i.forward(), Err(RuntimeError::InvalidCommand));
i.instructions.pop_front();
assert_eq!(i.forward(), Err(RuntimeError::NoInstructions));
}
#[test]
fn test_forward_push() {
let mut i = Interpreter::new();
i.add_instructions(&[" PUSH 3819021"]);
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.stack.last().unwrap(), &3819021);
i.add_instructions(&["PUSH 3819021", "PUSH 42"]);
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.stack.last().unwrap(), &3819021);
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.stack.last().unwrap(), &42);
}
#[test]
fn test_forward_pop() {
let mut i = Interpreter::new();
i.add_instructions(&["PUSH 3", "PUSH 5", "POP", "POP", "POP"]);
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.stack.len(), 1);
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.stack.len(), 0);
assert_eq!(i.forward(), Err(RuntimeError::StackUnderflow));
}
#[test]
fn test_forward_add() {
let mut i = Interpreter::new();
i.add_instructions(&["PUSH 3", "PUSH 5", "PUSH 8", "ADD", "ADD", "ADD"]);
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.stack.len(), 2);
assert_eq!(i.stack.last().unwrap(), &13);
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.stack.len(), 1);
assert_eq!(i.stack.last().unwrap(), &16);
assert_eq!(i.forward(), Err(RuntimeError::StackUnderflow));
}
#[test]
fn test_forward_sub() {
let mut i = Interpreter::new();
i.add_instructions(&["PUSH 3", "PUSH 5", "PUSH 8", "SUB", "SUB", "SUB"]);
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.stack.len(), 2);
assert_eq!(i.stack.last().unwrap(), &3);
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.stack.len(), 1);
assert_eq!(i.stack.last().unwrap(), &0);
assert_eq!(i.forward(), Err(RuntimeError::StackUnderflow));
}
#[test]
fn test_forward_mul() {
let mut i = Interpreter::new();
i.add_instructions(&["PUSH 3", "PUSH 5", "PUSH 8", "MUL", "MUL", "MUL"]);
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.stack.len(), 2);
assert_eq!(i.stack.last().unwrap(), &40);
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.stack.len(), 1);
assert_eq!(i.stack.last().unwrap(), &120);
assert_eq!(i.forward(), Err(RuntimeError::StackUnderflow));
}
#[test]
fn test_forward_div() {
let mut i = Interpreter::new();
i.add_instructions(&["PUSH 3", "PUSH 5", "PUSH 8", "DIV", "DIV", "PUSH 5", "DIV"]);
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.stack.len(), 2);
assert_eq!(i.stack.last().unwrap(), &1);
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.stack.len(), 1);
assert_eq!(i.stack.last().unwrap(), &0);
assert_eq!(i.forward(), Ok(()));
assert_eq!(i.forward(), Err(RuntimeError::DivideByZero));
assert_eq!(i.forward(), Err(RuntimeError::DivideByZero));
i.instructions.pop_front();
assert_eq!(i.forward(), Err(RuntimeError::NoInstructions));
while i.stack.len() != 0 {
i.stack.pop();
}
i.add_instructions(&[
"PUSH 3", "PUSH 5", "PUSH 8", "SUB", "DIV", "PUSH 5", "PUSH 3", "MUL", "ADD",
]);
assert_eq!(i.run(), Ok(()));
assert_eq!(i.instructions.len(), 0);
assert_eq!(i.stack, vec![16]);
}
#[test]
fn test_back() {
let mut interpreter = Interpreter::new();
+ assert_eq!(interpreter.back(), Err(RuntimeError::NoInstructions));
interpreter.add_instructions(&[" PUSH 0 ", " PUSH 42 ", " DIV "]);
assert_eq!(interpreter.forward(), Ok(()));
assert_eq!(interpreter.forward(), Ok(()));
assert_eq!(interpreter.instructions, &[" DIV "]);
assert_eq!(interpreter.stack, vec![0, 42]);
assert_eq!(interpreter.forward(), Err(RuntimeError::DivideByZero));
assert_eq!(interpreter.back(), Ok(()));
assert_eq!(interpreter.back(), Ok(()));
interpreter
.current_instruction()
.map(|i| *i = String::from("PUSH 2"));
assert_eq!(interpreter.run(), Ok(()));
assert_eq!(interpreter.instructions.len(), 0);
assert_eq!(interpreter.stack, vec![21]);
interpreter.stack.pop();
interpreter.add_instructions(&["PUSH 3", "PUSH 42", "POP", "POP"]);
assert_eq!(interpreter.forward(), Ok(()));
assert_eq!(interpreter.forward(), Ok(()));
assert_eq!(interpreter.forward(), Ok(()));
assert_eq!(interpreter.forward(), Ok(()));
assert_eq!(interpreter.stack.len(), 0);
assert_eq!(interpreter.back(), Ok(()));
assert_eq!(interpreter.back(), Ok(()));
interpreter
.current_instruction()
.map(|i| *i = String::from("ADD"));
assert_eq!(interpreter.forward(), Ok(()));
assert_eq!(interpreter.stack, vec![45]);
assert_eq!(interpreter.forward(), Ok(()));
assert_eq!(interpreter.back(), Ok(()));
assert_eq!(interpreter.back(), Ok(()));
interpreter
.current_instruction()
.map(|i| *i = String::from("SUB"));
assert_eq!(interpreter.forward(), Ok(()));
assert_eq!(interpreter.stack, vec![39]);
assert_eq!(interpreter.forward(), Ok(()));
assert_eq!(interpreter.back(), Ok(()));
assert_eq!(interpreter.back(), Ok(()));
interpreter
.current_instruction()
.map(|i| *i = String::from("MUL"));
assert_eq!(interpreter.forward(), Ok(()));
assert_eq!(interpreter.stack, vec![126]);
assert_eq!(interpreter.forward(), Ok(()));
assert_eq!(interpreter.back(), Ok(()));
assert_eq!(interpreter.back(), Ok(()));
interpreter
.current_instruction()
.map(|i| *i = String::from("DIV"));
assert_eq!(interpreter.forward(), Ok(()));
assert_eq!(interpreter.stack, vec![14]);
assert_eq!(interpreter.forward(), Ok(()));
assert_eq!(interpreter.back(), Ok(()));
assert_eq!(interpreter.back(), Ok(()));
assert_eq!(interpreter.back(), Ok(()));
assert_eq!(interpreter.back(), Ok(()));
assert_eq!(interpreter.stack.len(), 0);
assert_eq!(interpreter.run(), Ok(()));
assert_eq!(interpreter.back(), Ok(()));
assert_eq!(interpreter.instructions.len(), 1);
assert_eq!(interpreter.stack, vec![14]);
for _ in 0..3 {
assert_eq!(interpreter.back(), Ok(()));
}
assert_eq!(
interpreter.instructions,
&["PUSH 3", "PUSH 42", "DIV", "POP"]
);
assert_eq!(interpreter.stack.len(), 0);
assert_eq!(interpreter.run(), Ok(()));
assert_eq!(interpreter.back(), Ok(()));
assert_eq!(interpreter.instructions.len(), 1);
assert_eq!(interpreter.stack, vec![14]);
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum RuntimeError {
DivideByZero,
StackUnderflow,
InvalidCommand,
NoInstructions,
}
use std::collections::VecDeque;
#[derive(Debug, Default)]
pub struct Interpreter {
pub instructions: VecDeque<String>,
pub stack: Vec<i32>,
past_instructions: Vec<String>,
past_nums: Vec<i32>,
}
impl Interpreter {
pub fn new() -> Self {
return Self {
instructions: VecDeque::new(),
stack: Vec::new(),
past_instructions: Vec::new(),
past_nums: Vec::new(),
};
}
pub fn add_instructions(&mut self, instructions: &[&str]) {
for instruction in instructions {
self.instructions.push_back(instruction.to_string());
}
}
pub fn current_instruction(&mut self) -> Option<&mut String> {
if self.instructions.len() == 0 {
return None;
} else {
return Some(&mut self.instructions[0]);
}
}
pub fn forward(&mut self) -> Result<(), RuntimeError> {
if self.instructions.len() == 0 {
return Err(RuntimeError::NoInstructions);
}
let instruction = (&self.instructions[0]).trim().to_string();
let mut iter = instruction.split_whitespace();
match iter.next() {
None => Err(RuntimeError::InvalidCommand),
Some(command) => {
if command == "PUSH" {
match iter.next() {
None => return Err(RuntimeError::InvalidCommand),
Some(number) => match iter.next() {
None => match number.parse::<i32>() {
Err(_) => return Err(RuntimeError::InvalidCommand),
Ok(num) => {
self.stack.push(num);
self.past_instructions
.push(self.instructions.pop_front().unwrap());
return Ok(());
}
},
Some(_) => return Err(RuntimeError::InvalidCommand),
},
}
}
if command != "POP"
&& command != "ADD"
&& command != "SUB"
&& command != "MUL"
&& command != "DIV"
{
return Err(RuntimeError::InvalidCommand);
}
match iter.next() {
Some(_) => return Err(RuntimeError::InvalidCommand),
None => {
if command == "POP" {
if self.stack.len() == 0 {
return Err(RuntimeError::StackUnderflow);
}
self.past_nums.push(self.stack.pop().unwrap());
self.past_instructions
.push(self.instructions.pop_front().unwrap());
return Ok(());
}
if self.stack.len() < 2 {
return Err(RuntimeError::StackUnderflow);
}
if command == "DIV" && self.stack[self.stack.len() - 2] == 0 {
return Err(RuntimeError::DivideByZero);
}
self.past_nums.push(*self.stack.last().unwrap());
let num1 = self.stack.pop().unwrap();
self.past_nums.push(*self.stack.last().unwrap());
let num2 = self.stack.pop().unwrap();
if command == "ADD" {
self.stack.push(num1 + num2);
} else if command == "SUB" {
self.stack.push(num1 - num2);
} else if command == "MUL" {
self.stack.push(num1 * num2);
} else {
self.stack.push(num1 / num2);
}
self.past_instructions
.push(self.instructions.pop_front().unwrap());
return Ok(());
}
}
}
}
}
pub fn run(&mut self) -> Result<(), RuntimeError> {
loop {
match self.forward() {
Err(RuntimeError::NoInstructions) => return Ok(()),
Err(e) => return Err(e),
_ => (),
}
}
}
pub fn back(&mut self) -> Result<(), RuntimeError> {
if self.past_instructions.len() == 0 {
return Err(RuntimeError::NoInstructions);
}
let instruction = self.past_instructions.pop().unwrap().trim().to_string();
let mut iter = instruction.split_whitespace();
let command = iter.next().unwrap();
if command == "PUSH" {
self.stack.pop();
} else if command == "POP" {
self.stack.push(self.past_nums.pop().unwrap());
} else {
self.stack.pop();
self.stack.push(self.past_nums.pop().unwrap());
self.stack.push(self.past_nums.pop().unwrap());
}
self.instructions.push_front(instruction);
return Ok(());
}
}