Add !load command and some improvements😃
This commit is contained in:
parent
b6eb1ddf60
commit
6e6316b2bb
4 changed files with 125 additions and 55 deletions
|
@ -3,9 +3,6 @@ use clap::{arg, Parser, ValueEnum};
|
|||
#[derive(Parser, Debug)]
|
||||
#[command(author, about, long_about = None, version)]
|
||||
pub struct Args {
|
||||
/// To be verbose
|
||||
#[arg(short, long)]
|
||||
pub verbose: bool,
|
||||
/// The brainfuck source code file to run (if not will be entered in REPL mode)
|
||||
#[arg(default_value = None)]
|
||||
pub source: Option<String>,
|
||||
|
|
|
@ -164,3 +164,39 @@ impl BfCommand {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod error {
|
||||
use std::fmt::{Debug, Formatter};
|
||||
|
||||
struct InterpreterError {
|
||||
message: String,
|
||||
code: i32,
|
||||
}
|
||||
|
||||
impl InterpreterError {
|
||||
fn new(message: String, code: i32) -> Self {
|
||||
Self {
|
||||
message,
|
||||
code,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for InterpreterError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(f, "{}", self.message)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for InterpreterError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}, code: {}", self.message, self.code)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for InterpreterError {
|
||||
fn description(&self) -> &str {
|
||||
&self.message
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
13
src/main.rs
13
src/main.rs
|
@ -4,8 +4,10 @@ mod utils;
|
|||
mod repl;
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
extern crate pretty_env_logger;
|
||||
#[macro_use] extern crate log;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
use arguments::Args;
|
||||
|
||||
|
@ -16,15 +18,12 @@ fn main() {
|
|||
let args = Args::parse();
|
||||
info!("Parsed command line arguments: {:?}", args);
|
||||
|
||||
if args.verbose {
|
||||
info!("Verbose mode enabled");
|
||||
}
|
||||
|
||||
info!("Initializing interpreter");
|
||||
let mut interpreter = interpreter::Interpreter::new(
|
||||
args.array_size,
|
||||
utils::read_brainfuck_code_if_any(&args.source),
|
||||
args.features.unwrap_or_else(|| vec![]));
|
||||
args.features.unwrap_or_else(|| vec![])
|
||||
);
|
||||
|
||||
match args.source {
|
||||
Some(source) => {
|
||||
|
@ -40,7 +39,7 @@ fn main() {
|
|||
std::process::exit(code);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
None => {
|
||||
repl::start(interpreter)
|
||||
}
|
||||
|
|
128
src/repl.rs
128
src/repl.rs
|
@ -21,7 +21,7 @@ impl Repl {
|
|||
let mut input = String::new();
|
||||
|
||||
match std::io::stdin().read_line(&mut input) {
|
||||
Ok(_) => {},
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
error!("Failed to read input: {}", e);
|
||||
std::process::exit(1);
|
||||
|
@ -47,54 +47,92 @@ impl Repl {
|
|||
}
|
||||
|
||||
fn run_repl_cmd(&mut self, input: String) {
|
||||
match input.trim().get(1..).unwrap() {
|
||||
"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);
|
||||
}
|
||||
"history" | "h" => {
|
||||
println!("History:");
|
||||
for (i, cmd) in self.history.iter().enumerate() {
|
||||
println!("{}: {}", i, cmd);
|
||||
}
|
||||
}
|
||||
"save" | "s" => {
|
||||
/// TODO: Use custom name for file
|
||||
println!("Saving history to file: history.bfr");
|
||||
match std::fs::write("history.bfr", self.history.join("\n")) {
|
||||
Ok(_) => {
|
||||
info!("Successfully saved history to file: history.bfr");
|
||||
let mut cmd = input.split_whitespace();
|
||||
match cmd.next() {
|
||||
Some(repl_cmd) => {
|
||||
match repl_cmd {
|
||||
"fuck" => {
|
||||
println!("Bye bye :D");
|
||||
std::process::exit(0);
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Failed to save history to file: {}", e);
|
||||
"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);
|
||||
}
|
||||
"history" | "h" => {
|
||||
println!("History:");
|
||||
for (i, cmd) in self.history.iter().enumerate() {
|
||||
println!("{}: {}", i, cmd);
|
||||
}
|
||||
}
|
||||
"save" | "s" => {
|
||||
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" => {
|
||||
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}");
|
||||
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(_) => {
|
||||
info!("Successfully ran brainfuck source code from REPL");
|
||||
}
|
||||
Err((e, _)) => {
|
||||
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");
|
||||
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");
|
||||
println!("!reset, !r: reset the interpreter");
|
||||
println!("!help: show this fu*king help message");
|
||||
println!("!fuck: exit the REPL mode");
|
||||
}
|
||||
_ => println!("Unknown command: {}, type !help to show the help",
|
||||
input)
|
||||
}
|
||||
},
|
||||
"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");
|
||||
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");
|
||||
println!("!reset, !r: reset the interpreter");
|
||||
println!("!help: show this fu*king help message");
|
||||
println!("!fuck: exit the REPL mode");
|
||||
}
|
||||
_ => println!("Unknown command: {}, type !help to show the help", input)
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue