module restructuring

This commit is contained in:
nora 2021-04-25 10:09:37 +02:00
parent 6d7205bc4b
commit 42fc197341
6 changed files with 53 additions and 30 deletions

View file

@ -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<Statement>),
}
@ -23,7 +24,7 @@ fn minify(code: &str) -> String {
code.chars().filter(|c| ALLOWED_CHARS.contains(c)).collect()
}
fn parse(chars: Vec<char>) -> Vec<Statement> {
fn parse(chars: Vec<char>, direct_print: bool) -> Vec<Statement> {
let mut loop_stack = vec![vec![]];
for c in chars {
@ -32,7 +33,13 @@ fn parse(chars: Vec<char>) -> Vec<Statement> {
'-' => 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);
}

View file

@ -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<ExStatement>),
SetNull,
@ -35,6 +38,7 @@ impl From<Statement> 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<String, BfErr> {
pub fn run(pgm: &str, direct_print: bool) -> Result<String, BfErr> {
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<Statement>) -> Vec<ExStatement> {
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"));
}

View file

@ -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 {}

View file

@ -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() {

View file

@ -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());