bfy/src/repl.rs

162 lines
6.6 KiB
Rust
Raw Normal View History

2022-10-08 10:01:28 +00:00
use crate::bf_interpreter::interpreter::Interpreter;
2022-10-07 23:06:35 +00:00
use std::io::Write;
2022-10-07 22:28:14 +00:00
struct Repl {
interpreter: Interpreter,
history: Vec<String>,
}
impl Repl {
pub fn new(interpreter: Interpreter) -> Self {
Self {
interpreter,
history: Vec::new(),
}
}
pub fn run(mut self) {
loop {
print!("\n> ");
std::io::stdout().flush().unwrap();
let mut input = String::new();
match std::io::stdin().read_line(&mut input) {
Ok(_) => {}
2022-10-07 22:28:14 +00:00
Err(e) => {
error!("Failed to read input: {}", e);
std::process::exit(1);
}
}
input = input.trim().to_string(); // Remove trailing newline
self.history.push(input.clone()); // Save input to history
if input.starts_with("!") {
self.run_repl_cmd(input);
} else {
match self.interpreter.run(Some(input)) {
Ok(_) => {
info!("Successfully ran brainfuck source code from REPL");
}
2022-10-07 23:05:21 +00:00
Err(e) => {
2022-10-07 22:28:14 +00:00
error!("Failed to run brainfuck source code from REPL: {}", e);
}
}
}
}
}
2022-10-07 22:33:44 +00:00
fn run_repl_cmd(&mut self, input: String) {
let mut cmd = input.split_whitespace();
match cmd.next() {
Some(repl_cmd) => {
2022-10-08 10:01:28 +00:00
match repl_cmd.get(1..).unwrap_or("") {
"fuck" => {
println!("Bye bye :D");
std::process::exit(0);
}
"array" | "a" => {
println!("Current array: {:?}", self.interpreter.cells);
}
"array_size" | "as" => {
println!("Current array size: {}", self.interpreter.array_size);
}
"pointer" | "p" => {
println!("Current pointer: {}", self.interpreter.pointer);
2022-10-07 22:28:14 +00:00
}
2022-10-08 10:01:28 +00:00
"pointer_value" | "pv" => {
println!(
"Current pointer value: {} = \'{}\' (char)",
self.interpreter.cells[self.interpreter.pointer],
self.interpreter.cells[self.interpreter.pointer] as char
);
}
"history" | "h" => {
println!("History:");
for (i, cmd) in self.history.iter().enumerate() {
println!("{}: {}", i, cmd);
}
2022-10-07 22:28:14 +00:00
}
"save" | "s" => {
2022-10-07 23:06:35 +00:00
let file_name = cmd.next().unwrap_or("brainfuck_repl_history.bfr");
println!("Saving history to file: {file_name}");
match std::fs::write(file_name, self.history.join("\n")) {
Ok(_) => {
info!("Successfully saved history to file: {file_name}");
}
Err(e) => {
error!("Failed to save history to file: {}", e);
}
}
}
"load" | "l" => {
2022-10-07 23:06:35 +00:00
let file_name = cmd.next().unwrap_or("brainfuck_repl_history.bfr");
println!("Loading history from file: {file_name}");
match std::fs::read_to_string(file_name) {
Ok(history) => {
info!("Successfully loaded history from file: {file_name}");
2022-10-07 23:06:35 +00:00
self.history = history.split("\n").map(|s| s.to_string()).collect();
// Run all commands in history
for cmd in self.history.iter() {
match self.interpreter.run(Some(cmd.clone())) {
Ok(_) => {
2022-10-07 23:06:35 +00:00
info!(
"Successfully ran brainfuck source code from REPL"
);
}
2022-10-07 23:05:21 +00:00
Err(e) => {
2022-10-07 23:06:35 +00:00
error!(
"Failed to run brainfuck source code from REPL: {}",
e
);
}
}
}
}
Err(e) => {
error!("Failed to load history from file: {}", e);
}
}
}
"reset" | "r" => {
println!("Resetting REPL");
self.interpreter.reset();
}
"help" => {
println!("!array, !a: print the current array");
println!("!array_size, !as: print the current array size");
println!("!pointer, !p: print the current pointer value");
2022-10-08 10:01:28 +00:00
println!("!pointer_value, !pv: print the current pointer value");
println!("!history, !h: print the history of the commands");
println!("!save, !s: save the history to a file");
println!("!load, !l: load the history from a file");
2022-10-08 10:01:28 +00:00
println!("!reset, !r: reset the bf_interpreter");
println!("!help: show this fu*king help message");
println!("!fuck: exit the REPL mode");
}
2022-10-07 23:06:35 +00:00
_ => println!("Unknown command: {}, type !help to show the help", input),
2022-10-07 22:28:14 +00:00
}
2022-10-07 23:06:35 +00:00
}
None => {}
2022-10-07 22:28:14 +00:00
}
}
}
pub fn start(interpreter: Interpreter) {
info!("Entering REPL mode");
println!("Welcome to the brainfuck REPL mode! :)");
2022-10-07 23:06:35 +00:00
println!(
2022-10-08 10:01:28 +00:00
"Brainfuck bf_interpreter v {}\nBy {}",
2022-10-07 23:06:35 +00:00
clap::crate_version!(),
clap::crate_authors!()
);
2022-10-07 22:28:14 +00:00
println!("Enter your brainfuck code and press enter to run it.");
println!("Enter !fuck to exit :D");
println!("Enter !help fuck to get more help");
2022-10-07 23:06:35 +00:00
Repl::new(interpreter).run();
2022-10-07 22:28:14 +00:00
}