interactive brainfuck repl

This commit is contained in:
nora 2021-05-03 18:06:46 +02:00
parent 5cc058267b
commit c17bea08e0
7 changed files with 168 additions and 43 deletions

View file

@ -0,0 +1,111 @@
use std::fmt::{Display, Formatter};
use std::fmt;
use std::io::{stdin, stdout, Write};
use crate::interpreter::{minify, parse, parsed, Memory, MEM_SIZE};
use crate::interpreter::optimized::PrintMode;
pub struct BrainfuckState {
pub memory: Memory,
pub pointer: usize,
}
impl Display for BrainfuckState {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{}", display_state(self))
}
}
fn display_state(state: &BrainfuckState) -> String {
let start = if state.pointer < 5 {
0
} else if state.pointer > MEM_SIZE - 10 {
MEM_SIZE - 10
} else {
state.pointer - 5
};
format!("{}-\n|{}|\n{}-\n{}|\n{}|\n{}|\n{}-\n {}^^^^",
"----------".repeat(10),
{
let mut out = String::new();
let end = start + 10;
for i in start..end {
out.push_str(&*format!(" {: >5} ", i));
}
out
},
"----------".repeat(10),
"| ".repeat(10),
{
let mut out = String::new();
let end = start + 10;
for i in start..end {
out.push_str(&*format!("| {: >3} ", state.memory[i]));
}
out
},
"| ".repeat(10),
"----------".repeat(10),
" ".repeat(state.pointer - start))
}
pub fn start_repl() {
println!("Brainfuck REPL");
let mut state = BrainfuckState {
memory: [0; MEM_SIZE],
pointer: 0,
};
println!("Enter Brainfuck programs and they will be executed immediatly.");
println!("State is kept.");
println!("{}", state);
loop {
print!(">> ");
stdout().flush().unwrap();
match read_line() {
Ok(s) => {
match &*s {
":q" => break,
":?" | "help" | "?" => print_help(),
":r" => {
reset(&mut state);
println!("{}", state);
},
_ => {
print!("Output: ");
println!();
parse_input(s, &mut state);
println!("{}", state);
}
}
}
Err(why) => println!("Error reading input: {}\nPlease try again.", why)
}
}
}
fn reset(state: &mut BrainfuckState) {
state.pointer = 0;
state.memory = [0; MEM_SIZE];
}
fn print_help() {
println!("Brainfuck REPL help
:q => quit
:? => help
:r => reset state");
}
fn parse_input(pgm: String, state: &mut BrainfuckState) {
let pgm = minify(&*pgm);
let pgm = parse(pgm.chars(), PrintMode::DirectPrint);
parsed::interpret_with_state(&*pgm, state);
}
pub fn read_line() -> Result<String, std::io::Error> {
let mut buf = String::new();
stdin().read_line(&mut buf)?;
buf.pop();
Ok(buf)
}