From 42fc197341ecd71665d6a82615fa4e3218ee605b Mon Sep 17 00:00:00 2001 From: Nilstrieb Date: Sun, 25 Apr 2021 10:09:37 +0200 Subject: [PATCH] module restructuring --- bfi-rust/src/interpreter/mod.rs | 23 +++++++---- .../interpreter/{o2.rs => optimized/mod.rs} | 40 ++++++++++--------- .../src/interpreter/optimized/patterns.rs | 8 ++++ bfi-rust/src/interpreter/{o1.rs => parsed.rs} | 10 +++-- bfi-rust/src/interpreter/{o0.rs => simple.rs} | 0 bfi-rust/src/main.rs | 2 +- 6 files changed, 53 insertions(+), 30 deletions(-) rename bfi-rust/src/interpreter/{o2.rs => optimized/mod.rs} (88%) create mode 100644 bfi-rust/src/interpreter/optimized/patterns.rs rename bfi-rust/src/interpreter/{o1.rs => parsed.rs} (91%) rename bfi-rust/src/interpreter/{o0.rs => simple.rs} (100%) diff --git a/bfi-rust/src/interpreter/mod.rs b/bfi-rust/src/interpreter/mod.rs index 83bb177..e636598 100644 --- a/bfi-rust/src/interpreter/mod.rs +++ b/bfi-rust/src/interpreter/mod.rs @@ -1,6 +1,6 @@ -pub mod o0; -pub mod o1; -pub mod o2; +pub mod simple; +pub mod parsed; +pub mod optimized; const MEM_SIZE: usize = 0xFFFF; @@ -13,6 +13,7 @@ enum Statement { R, L, Out, + DOut, In, Loop(Vec), } @@ -23,7 +24,7 @@ fn minify(code: &str) -> String { code.chars().filter(|c| ALLOWED_CHARS.contains(c)).collect() } -fn parse(chars: Vec) -> Vec { +fn parse(chars: Vec, direct_print: bool) -> Vec { let mut loop_stack = vec![vec![]]; for c in chars { @@ -32,7 +33,13 @@ fn parse(chars: Vec) -> Vec { '-' => loop_stack.last_mut().unwrap().push(Statement::Dec), '>' => loop_stack.last_mut().unwrap().push(Statement::R), '<' => loop_stack.last_mut().unwrap().push(Statement::L), - '.' => loop_stack.last_mut().unwrap().push(Statement::Out), + '.' => { + if direct_print { + loop_stack.last_mut().unwrap().push(Statement::DOut) + } else { + loop_stack.last_mut().unwrap().push(Statement::Out) + } + } ',' => loop_stack.last_mut().unwrap().push(Statement::In), '[' => loop_stack.push(vec![]), ']' => { @@ -62,7 +69,7 @@ mod tests { fn parse_no_loop() { let program = "+-<>,."; let statements = vec![Inc, Dec, L, R, In, Out]; - let result = parse(program.chars().collect()); + let result = parse(program.chars().collect(), false); assert_eq!(statements, result); } @@ -71,7 +78,7 @@ mod tests { fn parse_simple_loop() { let program = "+[<<]-"; let statements = vec![Inc, Loop(vec![L, L]), Dec]; - let result = parse(program.chars().collect()); + let result = parse(program.chars().collect(), false); assert_eq!(statements, result); } @@ -80,7 +87,7 @@ mod tests { fn parse_complex_loops() { let program = ">[<[][<[<]>]>[>]]"; let statements = vec![R, Loop(vec![L, Loop(vec![]), Loop(vec![L, Loop(vec![L]), R]), R, Loop(vec![R])])]; - let result = parse(program.chars().collect()); + let result = parse(program.chars().collect(), false); assert_eq!(statements, result); } diff --git a/bfi-rust/src/interpreter/o2.rs b/bfi-rust/src/interpreter/optimized/mod.rs similarity index 88% rename from bfi-rust/src/interpreter/o2.rs rename to bfi-rust/src/interpreter/optimized/mod.rs index 0ac2ed5..9745171 100644 --- a/bfi-rust/src/interpreter/o2.rs +++ b/bfi-rust/src/interpreter/optimized/mod.rs @@ -2,7 +2,9 @@ //! some better optimizations like set null, repeating and doing more stuff with simplifying stuff //! -use std::io::{Read, stdin}; +mod patterns; + +use std::io::{Read, stdin, Write}; use crate::interpreter::{minify, parse, Statement, Memory, MEM_SIZE}; use std::error::Error; @@ -17,6 +19,7 @@ enum ExStatement { R, L, Out, + DOut, In, Loop(Vec), SetNull, @@ -35,6 +38,7 @@ impl From for ExStatement { Statement::Loop(v) => ExStatement::Loop( v.into_iter().map(|s| ExStatement::from(s)).collect() ), + Statement::DOut => ExStatement::DOut } } } @@ -59,10 +63,10 @@ impl Display for BfErr { impl Error for BfErr {} -pub fn run(pgm: &str) -> Result { +pub fn run(pgm: &str, direct_print: bool) -> Result { let pgm = minify(pgm); if pgm.len() < 1 { return Err(BfErr::new("no program found")); }; - let pgm = parse(pgm.chars().collect()); + let pgm = parse(pgm.chars().collect(), direct_print); let pgm = optimize(&pgm); let out = interpret(&pgm); Ok(out) @@ -89,6 +93,7 @@ fn o_set_null(code: &Vec) -> Vec { Statement::R => ExStatement::R, Statement::L => ExStatement::L, Statement::Out => ExStatement::Out, + Statement::DOut => ExStatement::DOut, Statement::In => ExStatement::In, } }).collect() @@ -133,6 +138,10 @@ fn execute(statement: &ExStatement, mem: &mut Memory, pointer: &mut usize, out: 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::DOut => { + print!("{}", mem[*pointer] as u8 as char); + std::io::stdout().flush().unwrap(); + } ExStatement::In => { let mut in_buffer = [0, 1]; stdin().read(&mut in_buffer).unwrap(); @@ -156,22 +165,16 @@ fn execute(statement: &ExStatement, mem: &mut Memory, pointer: &mut usize, out: 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) + s => { + for _ in 0..*amount { + execute(s, mem, pointer, out) + } + } } } }; @@ -180,20 +183,21 @@ fn execute(statement: &ExStatement, mem: &mut Memory, pointer: &mut usize, out: #[cfg(test)] mod test { - use crate::interpreter::o2::{run, o_repeat}; - use crate::interpreter::o2::ExStatement::{L, R, Inc, Dec, Repeat}; + use crate::interpreter::optimized::{run, o_repeat}; + use crate::interpreter::optimized::ExStatement::{Inc, Repeat, R, L}; + use crate::interpreter::Statement::Dec; #[test] fn run_loop() { let program = "++++++++++[>++++++++++<-]>."; - let out = run(program).unwrap(); + let out = run(program, false).unwrap(); assert_eq!(out, String::from("d")); } #[test] fn hello_world() { let program = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++."; - let out = run(program).unwrap(); + let out = run(program, false).unwrap(); assert_eq!(out, String::from("Hello World!\n")); } diff --git a/bfi-rust/src/interpreter/optimized/patterns.rs b/bfi-rust/src/interpreter/optimized/patterns.rs new file mode 100644 index 0000000..0d9ebf4 --- /dev/null +++ b/bfi-rust/src/interpreter/optimized/patterns.rs @@ -0,0 +1,8 @@ +//! +//! # Patterns find and replace +//! Pattern-match ExStatements and replace them with optimizations like add, multiply etc +//! +//! A pattern might look a bit like this: `Loop(Dec)` -> `SetNull` + + +struct Pattern {} \ No newline at end of file diff --git a/bfi-rust/src/interpreter/o1.rs b/bfi-rust/src/interpreter/parsed.rs similarity index 91% rename from bfi-rust/src/interpreter/o1.rs rename to bfi-rust/src/interpreter/parsed.rs index e49bcc2..eb9f769 100644 --- a/bfi-rust/src/interpreter/o1.rs +++ b/bfi-rust/src/interpreter/parsed.rs @@ -5,13 +5,13 @@ //! most importantly: loop jumps should be immediate #![allow(dead_code)] -use std::io::{Read, stdin}; +use std::io::{Read, stdin, Write}; 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 pgm = parse(pgm.chars().collect(), false); let out = interpret(&pgm); out } @@ -47,13 +47,17 @@ fn execute(statement: &Statement, mem: &mut Memory, pointer: &mut usize, out: &m } } } + Statement::DOut => { + print!("{}", mem[*pointer] as u8 as char); + std::io::stdout().flush().unwrap(); + } } } #[cfg(test)] mod test { - use crate::interpreter::o1::{execute, run, Statement}; + use crate::interpreter::parsed::{execute, run, Statement}; #[test] fn execute_simple() { diff --git a/bfi-rust/src/interpreter/o0.rs b/bfi-rust/src/interpreter/simple.rs similarity index 100% rename from bfi-rust/src/interpreter/o0.rs rename to bfi-rust/src/interpreter/simple.rs diff --git a/bfi-rust/src/main.rs b/bfi-rust/src/main.rs index 215ef8e..c6099cd 100644 --- a/bfi-rust/src/main.rs +++ b/bfi-rust/src/main.rs @@ -30,7 +30,7 @@ fn run(program: String) { let out = interpreter::o1::run(&*program); let end1 = start1.elapsed().unwrap();*/ let start2 = SystemTime::now(); - let out2 = interpreter::o2::run(&*program).unwrap(); + let out2 = interpreter::o2::run(&*program, false).unwrap(); let end2 = start2.elapsed().unwrap(); //assert_eq!(out, out2); //println!("{}\nFinished execution. Took o1: 18008ms (for hanoi), o2: {}ms", out2/*, end1.as_millis()*/, end2.as_millis());