From 5b9dd9ca67c0db20d647c49caabb977feae289d9 Mon Sep 17 00:00:00 2001 From: Nilstrieb Date: Sat, 24 Apr 2021 15:06:02 +0200 Subject: [PATCH] seperate files --- bfi-rust/src/interpreter/mod.rs | 338 +------------------------------- bfi-rust/src/interpreter/o0.rs | 67 +++++++ bfi-rust/src/interpreter/o1.rs | 110 +++++++++++ bfi-rust/src/interpreter/o2.rs | 220 +++++++++++++++++++++ bfi-rust/src/main.rs | 6 +- 5 files changed, 406 insertions(+), 335 deletions(-) create mode 100644 bfi-rust/src/interpreter/o0.rs create mode 100644 bfi-rust/src/interpreter/o1.rs create mode 100644 bfi-rust/src/interpreter/o2.rs diff --git a/bfi-rust/src/interpreter/mod.rs b/bfi-rust/src/interpreter/mod.rs index df0817d..ac97b21 100644 --- a/bfi-rust/src/interpreter/mod.rs +++ b/bfi-rust/src/interpreter/mod.rs @@ -1,8 +1,11 @@ +pub mod o0; +pub mod o1; +pub mod o2; + const MEM_SIZE: usize = 0xFFFF; type Memory = [u8; MEM_SIZE]; - #[derive(Debug, PartialOrd, PartialEq, Ord, Eq, Clone)] enum Statement { Inc, @@ -42,339 +45,6 @@ fn parse(chars: Vec) -> Vec { return loop_stack.pop().unwrap(); } - -/// -/// # optimization time -/// -/// first parse the bf so that it can be executed faster -/// most importantly: loop jumps should be immediate -/// -pub(crate) mod o1 { - use std::io::{Read, stdin}; - - use crate::interpreter::{MEM_SIZE, Memory, minify, parse, Statement}; - - pub fn run(pgm: &str) -> String { - let pgm = minify(pgm); - let pgm = parse(pgm.chars().collect()); - let out = interpret(&pgm); - out - } - - fn interpret(pgm: &Vec) -> String { - let mut out = String::new(); - let mut pointer: usize = 0; - let mut mem: [u8; MEM_SIZE] = [0; MEM_SIZE]; - - for s in pgm { - execute(s, &mut mem, &mut pointer, &mut out) - } - - out - } - - fn execute(statement: &Statement, mem: &mut Memory, pointer: &mut usize, out: &mut String) { - match statement { - Statement::R => if *pointer == MEM_SIZE - 1 { *pointer = 0 } else { *pointer += 1 }, - Statement::L => if *pointer == 0 { *pointer = MEM_SIZE - 1 } else { *pointer -= 1 }, - Statement::Inc => mem[*pointer] = mem[*pointer].wrapping_add(1), - Statement::Dec => mem[*pointer] = mem[*pointer].wrapping_sub(1), - Statement::Out => out.push(mem[*pointer] as u8 as char), - Statement::In => { - let mut in_buffer = [0, 1]; - stdin().read(&mut in_buffer).unwrap(); - mem[*pointer] = in_buffer[0] as u8; - } - Statement::Loop(vec) => { - while mem[*pointer] != 0 { - for s in vec { - execute(&s, mem, pointer, out); - } - } - } - } - } - - - #[cfg(test)] - mod test { - use crate::interpreter::o1::{execute, run, Statement}; - - #[test] - fn execute_simple() { - let mut pointer: usize = 0; - let mut mem: [u8; 65535] = [0; 65535]; - let mut out = String::new(); - - execute(&Statement::R, &mut mem, &mut pointer, &mut out); - assert_eq!(pointer, 1); - execute(&Statement::L, &mut mem, &mut pointer, &mut out); - assert_eq!(pointer, 0); - execute(&Statement::Inc, &mut mem, &mut pointer, &mut out); - assert_eq!(mem[pointer], 1); - execute(&Statement::Dec, &mut mem, &mut pointer, &mut out); - assert_eq!(mem[pointer], 0); - } - - #[test] - fn execute_false_loop() { - let statement = Statement::Loop(vec![Statement::Inc, Statement::Inc, Statement::R]); - let mut pointer: usize = 0; - let mut mem: [u8; 65535] = [0; 65535]; - - execute(&statement, &mut mem, &mut pointer, &mut String::new()); - assert_eq!(mem[0], 0); - assert_eq!(mem[1], 0); - } - - #[test] - fn execute_loop() { - let statement = Statement::Loop(vec![Statement::Inc, Statement::Inc, Statement::R]); - let mut pointer: usize = 0; - let mut mem: [u8; 65535] = [0; 65535]; - mem[0] = 1; - - execute(&statement, &mut mem, &mut pointer, &mut String::new()); - assert_eq!(mem[0], 3); - assert_eq!(mem[1], 0); - } - - #[test] - fn run_loop() { - let program = "++++++++++[>++++++++++<-]>."; - let out = run(program); - assert_eq!(out, String::from("d")); - } - - #[test] - fn hello_world() { - let program = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++."; - let out = run(program); - assert_eq!(out, String::from("Hello World!\n")); - } - } -} - -/// -/// # optimization time -/// some better optimizations like set null, repeating and doing more stuff with simplifying stuff -pub mod o2 { - use std::io::{Read, stdin}; - - use crate::interpreter::{minify, parse, Statement}; - use std::error::Error; - use std::fmt::{Display, Formatter}; - use std::fmt; - use std::ops::Deref; - - const MEM_SIZE: usize = 0xFFFF; - - type Memory = [u8; MEM_SIZE]; - - #[derive(PartialOrd, PartialEq, Ord, Eq, Clone, Debug)] - enum ExStatement { - Inc, - Dec, - R, - L, - Out, - In, - Loop(Vec), - SetNull, - Repeat(Box, usize), - } - - impl From for ExStatement { - fn from(s: Statement) -> Self { - match s { - Statement::L => ExStatement::L, - Statement::R => ExStatement::R, - Statement::Inc => ExStatement::Inc, - Statement::Dec => ExStatement::Dec, - Statement::In => ExStatement::In, - Statement::Out => ExStatement::Out, - Statement::Loop(v) => ExStatement::Loop( - v.into_iter().map(|s| ExStatement::from(s)).collect() - ), - } - } - } - - #[derive(Debug)] - pub struct BfErr { - msg: &'static str - } - - impl BfErr { - pub fn new(msg: &'static str) -> BfErr { - BfErr { msg } - } - } - - impl Display for BfErr { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "Error interpreting brainfuck code: {}", self.msg) - } - } - - impl Error for BfErr {} - - - pub fn run(pgm: &str) -> Result { - let pgm = minify(pgm); - if pgm.len() < 1 { return Err(BfErr::new("no program found")); }; - let pgm = parse(pgm.chars().collect()); - let pgm = optimize(&pgm); - let out = interpret(&pgm); - Ok(out) - } - - fn optimize(code: &Vec) -> Vec { - let code = o_set_null(code); - let code = o_repeat(code); - code - } - - fn o_set_null(code: &Vec) -> Vec { - code.iter().map(|s| { - match s { - Statement::Loop(v) => { - if let [Statement::Dec] = v[..] { - ExStatement::SetNull - } else { - ExStatement::Loop(optimize(v)) - } - } - Statement::Inc => ExStatement::Inc, - Statement::Dec => ExStatement::Dec, - Statement::R => ExStatement::R, - Statement::L => ExStatement::L, - Statement::Out => ExStatement::Out, - Statement::In => ExStatement::In, - } - }).collect() - } - - fn o_repeat(code: Vec) -> Vec { - let mut amount = 0; - let mut result: Vec = vec![]; - - for i in 0..code.len() { - if code.get(i) == code.get(i + 1) { - amount += 1; - } else if amount == 0 { - result.push(code[i].clone()) - } else { - amount += 1; - result.push(ExStatement::Repeat(Box::new(code[i].clone()), amount as usize)); - amount = 0; - } - } - - result - } - - fn interpret(pgm: &Vec) -> String { - let mut out = String::new(); - let mut pointer: usize = 0; - let mut mem: [u8; MEM_SIZE] = [0; MEM_SIZE]; - - for s in pgm { - execute(s, &mut mem, &mut pointer, &mut out) - } - - out - } - - fn execute(statement: &ExStatement, mem: &mut Memory, pointer: &mut usize, out: &mut String) { - match statement { - ExStatement::R => if *pointer == MEM_SIZE - 1 { *pointer = 0 } else { *pointer += 1 }, - ExStatement::L => if *pointer == 0 { *pointer = MEM_SIZE - 1 } else { *pointer -= 1 }, - ExStatement::Inc => mem[*pointer] = mem[*pointer].wrapping_add(1), - ExStatement::Dec => mem[*pointer] = mem[*pointer].wrapping_sub(1), - ExStatement::SetNull => mem[*pointer] = 0, - ExStatement::Out => out.push(mem[*pointer] as u8 as char), - ExStatement::In => { - let mut in_buffer = [0, 1]; - stdin().read(&mut in_buffer).unwrap(); - mem[*pointer] = in_buffer[0] as u8; - } - ExStatement::Loop(vec) => { - while mem[*pointer] != 0 { - for s in vec { - execute(&s, mem, pointer, out); - } - } - } - ExStatement::Repeat(statement, amount) => { - match statement.deref() { - ExStatement::R => { - *pointer += amount; - if *pointer > MEM_SIZE { - *pointer %= MEM_SIZE - } - } - ExStatement::L => *pointer = (*pointer).wrapping_sub(*amount), - ExStatement::Inc => mem[*pointer] = mem[*pointer].wrapping_add(*amount as u8), - ExStatement::Dec => mem[*pointer] = mem[*pointer].wrapping_sub(*amount as u8), - ExStatement::Out => { - for _ in 0..*amount { - execute(&ExStatement::Out, mem, pointer, out) - } - } - ExStatement::In => { - for _ in 0..*amount { - execute(&ExStatement::In, mem, pointer, out) - } - } - ExStatement::Loop(v) => { - for _ in 0..*amount { - execute(&ExStatement::Loop(v.clone()), mem, pointer, out) - } - } - _ => panic!("Invalid statement in repeat: {:?}", *statement) - } - } - }; - } - - - #[cfg(test)] - mod test { - use crate::interpreter::o2::{run, o_repeat}; - use crate::interpreter::o2::ExStatement::{L, R, Inc, Dec, Repeat}; - - #[test] - fn run_loop() { - let program = "++++++++++[>++++++++++<-]>."; - let out = run(program).unwrap(); - assert_eq!(out, String::from("d")); - } - - #[test] - fn hello_world() { - let program = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++."; - let out = run(program).unwrap(); - assert_eq!(out, String::from("Hello World!\n")); - } - - #[test] - fn o_repeat_simple() { - let code = vec![Inc, Inc, Inc, R]; - let expected = vec![Repeat(Box::new(Inc), 3), R]; - println!("{}", code.len()); - assert_eq!(expected, o_repeat(code)); - } - - #[test] - fn o_repeat_long() { - let code = vec![Inc, Inc, Inc, R, L, L, L, Dec, L, L, Dec]; - let expected = vec![Repeat(Box::new(Inc), 3), R, Repeat(Box::new(L), 3), Dec, Repeat(Box::new(L), 2), Dec]; - assert_eq!(expected, o_repeat(code)); - } - } -} - #[cfg(test)] mod tests { use crate::interpreter::parse; diff --git a/bfi-rust/src/interpreter/o0.rs b/bfi-rust/src/interpreter/o0.rs new file mode 100644 index 0000000..b402f41 --- /dev/null +++ b/bfi-rust/src/interpreter/o0.rs @@ -0,0 +1,67 @@ +use crate::interpreter::{MEM_SIZE, minify}; +use std::io::{stdin, Read}; + +pub fn run(program: &str) -> String{ + let program = minify(program); + let out = interpret(program.chars().collect()); + out +} + +fn interpret(pgm: Vec) -> String { + let mut out = String::new(); + let mut pointer: usize = 0; + let mut mem: [u8; MEM_SIZE] = [0; MEM_SIZE]; + let mut in_buffer = [0; 1]; + let mut pc = 0; + let len = pgm.len(); + + while pc < len { + match pgm[pc] { + '>' => if pointer == MEM_SIZE - 1 { pointer = 0 } else { pointer += 1 }, + '<' => if pointer == 0 { pointer = MEM_SIZE - 1 } else { pointer -= 1 }, + '+' => mem[pointer] = mem[pointer].wrapping_add(1), + '-' => mem[pointer] = mem[pointer].wrapping_sub(1), + '.' => out.push(mem[pointer] as u8 as char), + ',' => { + stdin().read(&mut in_buffer).unwrap(); + mem[pointer] = in_buffer[0] as u8; + } + '[' => { + //jump to corresponding ] + if mem[pointer] == 0 { + let mut level = 0; + while pgm[pc] != ']' || level > -1 { + pc += 1; + match pgm[pc] { + '[' => { + level += 1 + } + ']' => { + level -= 1 + } + _ => (), + } + } + } + } + ']' => { + if mem[pointer] != 0 { + //jump to corresponding [ + let mut level = 0; + while pgm[pc] != '[' || level > -1 { + pc -= 1; + match pgm[pc] { + '[' => level -= 1, + ']' => level += 1, + _ => (), + } + } + } + } + _ => (), + } + pc += 1; + } + + out +} \ No newline at end of file diff --git a/bfi-rust/src/interpreter/o1.rs b/bfi-rust/src/interpreter/o1.rs new file mode 100644 index 0000000..fe1cca9 --- /dev/null +++ b/bfi-rust/src/interpreter/o1.rs @@ -0,0 +1,110 @@ +/*! + # optimization time + + first parse the bf so that it can be executed faster + most importantly: loop jumps should be immediate +*/ + +use std::io::{Read, stdin}; + +use crate::interpreter::{MEM_SIZE, Memory, minify, parse, Statement}; + +pub fn run(pgm: &str) -> String { + let pgm = minify(pgm); + let pgm = parse(pgm.chars().collect()); + let out = interpret(&pgm); + out +} + +fn interpret(pgm: &Vec) -> String { + let mut out = String::new(); + let mut pointer: usize = 0; + let mut mem: [u8; MEM_SIZE] = [0; MEM_SIZE]; + + for s in pgm { + execute(s, &mut mem, &mut pointer, &mut out) + } + + out +} + +fn execute(statement: &Statement, mem: &mut Memory, pointer: &mut usize, out: &mut String) { + match statement { + Statement::R => if *pointer == MEM_SIZE - 1 { *pointer = 0 } else { *pointer += 1 }, + Statement::L => if *pointer == 0 { *pointer = MEM_SIZE - 1 } else { *pointer -= 1 }, + Statement::Inc => mem[*pointer] = mem[*pointer].wrapping_add(1), + Statement::Dec => mem[*pointer] = mem[*pointer].wrapping_sub(1), + Statement::Out => out.push(mem[*pointer] as u8 as char), + Statement::In => { + let mut in_buffer = [0, 1]; + stdin().read(&mut in_buffer).unwrap(); + mem[*pointer] = in_buffer[0] as u8; + } + Statement::Loop(vec) => { + while mem[*pointer] != 0 { + for s in vec { + execute(&s, mem, pointer, out); + } + } + } + } +} + + +#[cfg(test)] +mod test { + use crate::interpreter::o1::{execute, run, Statement}; + + #[test] + fn execute_simple() { + let mut pointer: usize = 0; + let mut mem: [u8; 65535] = [0; 65535]; + let mut out = String::new(); + + execute(&Statement::R, &mut mem, &mut pointer, &mut out); + assert_eq!(pointer, 1); + execute(&Statement::L, &mut mem, &mut pointer, &mut out); + assert_eq!(pointer, 0); + execute(&Statement::Inc, &mut mem, &mut pointer, &mut out); + assert_eq!(mem[pointer], 1); + execute(&Statement::Dec, &mut mem, &mut pointer, &mut out); + assert_eq!(mem[pointer], 0); + } + + #[test] + fn execute_false_loop() { + let statement = Statement::Loop(vec![Statement::Inc, Statement::Inc, Statement::R]); + let mut pointer: usize = 0; + let mut mem: [u8; 65535] = [0; 65535]; + + execute(&statement, &mut mem, &mut pointer, &mut String::new()); + assert_eq!(mem[0], 0); + assert_eq!(mem[1], 0); + } + + #[test] + fn execute_loop() { + let statement = Statement::Loop(vec![Statement::Inc, Statement::Inc, Statement::R]); + let mut pointer: usize = 0; + let mut mem: [u8; 65535] = [0; 65535]; + mem[0] = 1; + + execute(&statement, &mut mem, &mut pointer, &mut String::new()); + assert_eq!(mem[0], 3); + assert_eq!(mem[1], 0); + } + + #[test] + fn run_loop() { + let program = "++++++++++[>++++++++++<-]>."; + let out = run(program); + assert_eq!(out, String::from("d")); + } + + #[test] + fn hello_world() { + let program = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++."; + let out = run(program); + assert_eq!(out, String::from("Hello World!\n")); + } +} \ No newline at end of file diff --git a/bfi-rust/src/interpreter/o2.rs b/bfi-rust/src/interpreter/o2.rs new file mode 100644 index 0000000..9b0947e --- /dev/null +++ b/bfi-rust/src/interpreter/o2.rs @@ -0,0 +1,220 @@ +/*! +# optimization time +some better optimizations like set null, repeating and doing more stuff with simplifying stuff + */ + +use std::io::{Read, stdin}; + +use crate::interpreter::{minify, parse, Statement}; +use std::error::Error; +use std::fmt::{Display, Formatter}; +use std::fmt; +use std::ops::Deref; + +const MEM_SIZE: usize = 0xFFFF; + +type Memory = [u8; MEM_SIZE]; + +#[derive(PartialOrd, PartialEq, Ord, Eq, Clone, Debug)] +enum ExStatement { + Inc, + Dec, + R, + L, + Out, + In, + Loop(Vec), + SetNull, + Repeat(Box, usize), +} + +impl From for ExStatement { + fn from(s: Statement) -> Self { + match s { + Statement::L => ExStatement::L, + Statement::R => ExStatement::R, + Statement::Inc => ExStatement::Inc, + Statement::Dec => ExStatement::Dec, + Statement::In => ExStatement::In, + Statement::Out => ExStatement::Out, + Statement::Loop(v) => ExStatement::Loop( + v.into_iter().map(|s| ExStatement::from(s)).collect() + ), + } + } +} + +#[derive(Debug)] +pub struct BfErr { + msg: &'static str +} + +impl BfErr { + pub fn new(msg: &'static str) -> BfErr { + BfErr { msg } + } +} + +impl Display for BfErr { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!(f, "Error interpreting brainfuck code: {}", self.msg) + } +} + +impl Error for BfErr {} + + +pub fn run(pgm: &str) -> Result { + let pgm = minify(pgm); + if pgm.len() < 1 { return Err(BfErr::new("no program found")); }; + let pgm = parse(pgm.chars().collect()); + let pgm = optimize(&pgm); + let out = interpret(&pgm); + Ok(out) +} + +fn optimize(code: &Vec) -> Vec { + let code = o_set_null(code); + let code = o_repeat(code); + code +} + +fn o_set_null(code: &Vec) -> Vec { + code.iter().map(|s| { + match s { + Statement::Loop(v) => { + if let [Statement::Dec] = v[..] { + ExStatement::SetNull + } else { + ExStatement::Loop(optimize(v)) + } + } + Statement::Inc => ExStatement::Inc, + Statement::Dec => ExStatement::Dec, + Statement::R => ExStatement::R, + Statement::L => ExStatement::L, + Statement::Out => ExStatement::Out, + Statement::In => ExStatement::In, + } + }).collect() +} + +fn o_repeat(code: Vec) -> Vec { + let mut amount = 0; + let mut result: Vec = vec![]; + + for i in 0..code.len() { + if code.get(i) == code.get(i + 1) { + amount += 1; + } else if amount == 0 { + result.push(code[i].clone()) + } else { + amount += 1; + result.push(ExStatement::Repeat(Box::new(code[i].clone()), amount as usize)); + amount = 0; + } + } + + result +} + +fn interpret(pgm: &Vec) -> String { + let mut out = String::new(); + let mut pointer: usize = 0; + let mut mem: [u8; MEM_SIZE] = [0; MEM_SIZE]; + + for s in pgm { + execute(s, &mut mem, &mut pointer, &mut out) + } + + out +} + +fn execute(statement: &ExStatement, mem: &mut Memory, pointer: &mut usize, out: &mut String) { + match statement { + ExStatement::R => if *pointer == MEM_SIZE - 1 { *pointer = 0 } else { *pointer += 1 }, + ExStatement::L => if *pointer == 0 { *pointer = MEM_SIZE - 1 } else { *pointer -= 1 }, + ExStatement::Inc => mem[*pointer] = mem[*pointer].wrapping_add(1), + ExStatement::Dec => mem[*pointer] = mem[*pointer].wrapping_sub(1), + ExStatement::SetNull => mem[*pointer] = 0, + ExStatement::Out => out.push(mem[*pointer] as u8 as char), + ExStatement::In => { + let mut in_buffer = [0, 1]; + stdin().read(&mut in_buffer).unwrap(); + mem[*pointer] = in_buffer[0] as u8; + } + ExStatement::Loop(vec) => { + while mem[*pointer] != 0 { + for s in vec { + execute(&s, mem, pointer, out); + } + } + } + ExStatement::Repeat(statement, amount) => { + match statement.deref() { + ExStatement::R => { + *pointer += amount; + if *pointer > MEM_SIZE { + *pointer %= MEM_SIZE + } + } + ExStatement::L => *pointer = (*pointer).wrapping_sub(*amount), + ExStatement::Inc => mem[*pointer] = mem[*pointer].wrapping_add(*amount as u8), + ExStatement::Dec => mem[*pointer] = mem[*pointer].wrapping_sub(*amount as u8), + ExStatement::Out => { + for _ in 0..*amount { + execute(&ExStatement::Out, mem, pointer, out) + } + } + ExStatement::In => { + for _ in 0..*amount { + execute(&ExStatement::In, mem, pointer, out) + } + } + ExStatement::Loop(v) => { + for _ in 0..*amount { + execute(&ExStatement::Loop(v.clone()), mem, pointer, out) + } + } + _ => panic!("Invalid statement in repeat: {:?}", *statement) + } + } + }; +} + + +#[cfg(test)] +mod test { + use crate::interpreter::o2::{run, o_repeat}; + use crate::interpreter::o2::ExStatement::{L, R, Inc, Dec, Repeat}; + + #[test] + fn run_loop() { + let program = "++++++++++[>++++++++++<-]>."; + let out = run(program).unwrap(); + assert_eq!(out, String::from("d")); + } + + #[test] + fn hello_world() { + let program = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++."; + let out = run(program).unwrap(); + assert_eq!(out, String::from("Hello World!\n")); + } + + #[test] + fn o_repeat_simple() { + let code = vec![Inc, Inc, Inc, R]; + let expected = vec![Repeat(Box::new(Inc), 3), R]; + println!("{}", code.len()); + assert_eq!(expected, o_repeat(code)); + } + + #[test] + fn o_repeat_long() { + let code = vec![Inc, Inc, Inc, R, L, L, L, Dec, L, L, Dec]; + let expected = vec![Repeat(Box::new(Inc), 3), R, Repeat(Box::new(L), 3), Dec, Repeat(Box::new(L), 2), Dec]; + assert_eq!(expected, o_repeat(code)); + } +} + diff --git a/bfi-rust/src/main.rs b/bfi-rust/src/main.rs index 2f267d4..c8e398d 100644 --- a/bfi-rust/src/main.rs +++ b/bfi-rust/src/main.rs @@ -20,6 +20,9 @@ fn main() { fn run(path: String) { println!("Path: {}", path); let program = fs::read_to_string(path).unwrap(); + let start0 = SystemTime::now(); + let out0 = interpreter::o0::run(&*program); + let end0 = start0.elapsed().unwrap(); let start1 = SystemTime::now(); let out = interpreter::o1::run(&*program); let end1 = start1.elapsed().unwrap(); @@ -27,5 +30,6 @@ fn run(path: String) { let out2 = interpreter::o2::run(&*program).unwrap(); let end2 = start2.elapsed().unwrap(); assert_eq!(out, out2); - println!("{}\nFinished execution. Took o1: {}ms, o2: {}ms", out, end1.as_millis(), end2.as_millis()); + assert_eq!(out0, out2); + println!("{}\nFinished execution. Took o0: {}ms, o1: {}ms, o2: {}ms", out, end0.as_millis(), end1.as_millis(), end2.as_millis()); } \ No newline at end of file