Reformat the code yo 🥰🦀

This commit is contained in:
Anas Elgarhy 2022-10-12 18:59:12 +02:00
parent ade4438ce4
commit c4f35dd63c
5 changed files with 180 additions and 155 deletions

View File

@ -1,4 +1,4 @@
use std::fmt::{Debug, Formatter, Display}; use std::fmt::{Debug, Display, Formatter};
#[derive(PartialEq)] #[derive(PartialEq)]
pub struct InterpreterError { pub struct InterpreterError {
@ -62,10 +62,15 @@ impl InterpreterErrorKind {
impl Display for InterpreterErrorKind { impl Display for InterpreterErrorKind {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
match self { match self {
InterpreterErrorKind::PointerOutOfBounds(pointer) => write!(f, "Pointer out of bounds {}", pointer), InterpreterErrorKind::PointerOutOfBounds(pointer) => {
write!(f, "Pointer out of bounds {}", pointer)
}
InterpreterErrorKind::ValueOutOfBounds => write!(f, "Value out of bounds"), InterpreterErrorKind::ValueOutOfBounds => write!(f, "Value out of bounds"),
InterpreterErrorKind::IoError(error) => InterpreterErrorKind::IoError(error) => write!(
write!(f, "Failed to read byte from stdin: no bytes available: {}", error), f,
"Failed to read byte from stdin: no bytes available: {}",
error
),
InterpreterErrorKind::FlushError(e) => write!(f, "Failed to flush stdout: {}", e), InterpreterErrorKind::FlushError(e) => write!(f, "Failed to flush stdout: {}", e),
InterpreterErrorKind::UnmatchedBracket => write!(f, "Unmatched bracket"), InterpreterErrorKind::UnmatchedBracket => write!(f, "Unmatched bracket"),
InterpreterErrorKind::InvalidUtf8 => write!(f, "Invalid utf8"), InterpreterErrorKind::InvalidUtf8 => write!(f, "Invalid utf8"),
@ -88,8 +93,13 @@ mod tests {
assert_eq!(error.to_string(), "Value out of bounds"); assert_eq!(error.to_string(), "Value out of bounds");
assert_eq!(error.code, 12); assert_eq!(error.code, 12);
let error = InterpreterErrorKind::IoError(std::io::Error::new(std::io::ErrorKind::Other, "test")).to_error(); let error =
assert_eq!(error.to_string(), "Failed to read byte from stdin: no bytes available: test"); InterpreterErrorKind::IoError(std::io::Error::new(std::io::ErrorKind::Other, "test"))
.to_error();
assert_eq!(
error.to_string(),
"Failed to read byte from stdin: no bytes available: test"
);
assert_eq!(error.code, 13); assert_eq!(error.code, 13);
/*let error = InterpreterErrorKind::FlushError(e).to_error(); /*let error = InterpreterErrorKind::FlushError(e).to_error();

View File

@ -12,10 +12,7 @@ pub struct Interpreter {
} }
impl Interpreter { impl Interpreter {
pub fn new( pub fn new(array_size: usize, features: Vec<arguments::Feature>) -> Self {
array_size: usize,
features: Vec<arguments::Feature>,
) -> Self {
Self { Self {
cells: vec![0; array_size], cells: vec![0; array_size],
pointer: 0, pointer: 0,
@ -34,7 +31,6 @@ impl Interpreter {
} }
} }
// +[>++<-] // +[>++<-]
fn iterate(&mut self, code: &Vec<BfCommand>) -> Result<(), InterpreterError> { fn iterate(&mut self, code: &Vec<BfCommand>) -> Result<(), InterpreterError> {
trace!("Iterate: {:?}", code); trace!("Iterate: {:?}", code);
@ -189,11 +185,9 @@ fn to_bf_commands(bf_code: Vec<char>) -> Result<Vec<BfCommand>, InterpreterError
bf_commands.push(BfCommand::Loop(to_bf_commands(bf_code[i + 1..j].to_vec())?)); bf_commands.push(BfCommand::Loop(to_bf_commands(bf_code[i + 1..j].to_vec())?));
i = j; i = j;
} }
_ => { _ => match BfCommand::from(bf_code[i]) {
match BfCommand::from(bf_code[i]) { Some(command) => bf_commands.push(command),
Some(command) => bf_commands.push(command), None => (),
None => (),
}
}, },
} }
i += 1; i += 1;
@ -218,27 +212,24 @@ impl BfCommand {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use pretty_assertions::assert_eq; // for testing only
use crate::utils; use crate::utils;
use pretty_assertions::assert_eq; // for testing only
#[test] #[test]
fn print_h_combine_repl() { fn print_h_combine_repl() {
let mut interpreter = Interpreter::new( let mut interpreter = Interpreter::new(30000, vec![]);
30000,
vec![],
);
assert_eq!(interpreter.run(String::from(">+++++++++[<++++ ++++>-]<.")), Ok(0)); assert_eq!(
interpreter.run(String::from(">+++++++++[<++++ ++++>-]<.")),
Ok(0)
);
println!(); println!();
} }
#[test] #[test]
fn print_h_repl() { fn print_h_repl() {
let mut interpreter = Interpreter::new( let mut interpreter = Interpreter::new(30000, vec![]);
30000,
vec![],
);
assert_eq!(interpreter.run(String::from(">+++++++++")), Ok(0)); assert_eq!(interpreter.run(String::from(">+++++++++")), Ok(0));
assert_eq!(interpreter.run(String::from("[<++++ ++++>-]<.")), Ok(0)); assert_eq!(interpreter.run(String::from("[<++++ ++++>-]<.")), Ok(0));
@ -248,10 +239,7 @@ mod tests {
#[test] #[test]
fn nested_loop_level_1_combine() { fn nested_loop_level_1_combine() {
let mut interpreter = Interpreter::new( let mut interpreter = Interpreter::new(5, vec![]);
5,
vec![],
);
assert_eq!(interpreter.run(String::from("++[>++[>+<-]<-]")), Ok(0)); assert_eq!(interpreter.run(String::from("++[>++[>+<-]<-]")), Ok(0));
assert_eq!(interpreter.cells[2], 4); assert_eq!(interpreter.cells[2], 4);
@ -259,113 +247,107 @@ mod tests {
println!(); println!();
} }
#[test] #[test]
fn execute_hello_world_from_file() { fn execute_hello_world_from_file() {
let mut interpreter = Interpreter::new( let mut interpreter = Interpreter::new(30000, vec![]);
30000,
vec![],
);
println!(); println!();
assert_eq!(interpreter.run( assert_eq!(
utils::read_brainfuck_code( interpreter.run(utils::read_brainfuck_code(&String::from(
&String::from("test_code/hello_world.bf"))), Ok(0)); "test_code/hello_world.bf"
))),
Ok(0)
);
} }
#[test] #[test]
fn execute_print_hi_from_file() { fn execute_print_hi_from_file() {
let mut interpreter = Interpreter::new( let mut interpreter = Interpreter::new(30000, vec![]);
30000,
vec![],
);
println!(); println!();
assert_eq!(interpreter.run( assert_eq!(
utils::read_brainfuck_code(&String::from("test_code/print_hi.bf"))), Ok(0)); interpreter.run(utils::read_brainfuck_code(&String::from(
"test_code/print_hi.bf"
))),
Ok(0)
);
} }
#[test] #[test]
fn execute_print_hi_yooo_from_file() { fn execute_print_hi_yooo_from_file() {
let mut interpreter = Interpreter::new( let mut interpreter = Interpreter::new(30000, vec![]);
30000,
vec![],
);
println!(); println!();
assert_eq!(interpreter.run( assert_eq!(
utils::read_brainfuck_code(&String::from("test_code/print_hi_yooo.bf"))), interpreter.run(utils::read_brainfuck_code(&String::from(
Ok(0)); "test_code/print_hi_yooo.bf"
))),
Ok(0)
);
} }
#[test] #[test]
fn execute_print_my_first_name_from_formatted_file() { fn execute_print_my_first_name_from_formatted_file() {
let mut interpreter = Interpreter::new( let mut interpreter = Interpreter::new(30000, vec![]);
30000,
vec![],
);
println!(); println!();
assert_eq!(interpreter.run( assert_eq!(
utils::read_brainfuck_code(&String::from("test_code/print_my_first_name_formatted.bf"))), interpreter.run(utils::read_brainfuck_code(&String::from(
Ok(0)); "test_code/print_my_first_name_formatted.bf"
))),
Ok(0)
);
} }
#[test] #[test]
fn execute_print_my_first_name_from_file() { fn execute_print_my_first_name_from_file() {
let mut interpreter = Interpreter::new( let mut interpreter = Interpreter::new(30000, vec![]);
30000,
vec![],
);
println!(); println!();
assert_eq!(interpreter.run( assert_eq!(
utils::read_brainfuck_code(&String::from("test_code/print_my_first_name.bf"))), interpreter.run(utils::read_brainfuck_code(&String::from(
Ok(0)); "test_code/print_my_first_name.bf"
))),
Ok(0)
);
} }
#[test] #[test]
fn execute_print_my_first_name_and_last_name_from_formatted_file() { fn execute_print_my_first_name_and_last_name_from_formatted_file() {
let mut interpreter = Interpreter::new( let mut interpreter = Interpreter::new(30000, vec![]);
30000,
vec![],
);
println!(); println!();
assert_eq!(interpreter.run( assert_eq!(
utils::read_brainfuck_code( interpreter.run(utils::read_brainfuck_code(&String::from(
&String::from("test_code/print_my_first_name_and_last_name_formatted.bf"))), "test_code/print_my_first_name_and_last_name_formatted.bf"
Ok(0)); ))),
Ok(0)
);
} }
#[test] #[test]
fn execute_print_my_first_name_and_last_name_from_file() { fn execute_print_my_first_name_and_last_name_from_file() {
let mut interpreter = Interpreter::new( let mut interpreter = Interpreter::new(30000, vec![]);
30000,
vec![],
);
println!(); println!();
assert_eq!(interpreter.run(utils::read_brainfuck_code( assert_eq!(
&String::from("test_code/print_my_first_name_and_last_name.bf"))), interpreter.run(utils::read_brainfuck_code(&String::from(
Ok(0)); "test_code/print_my_first_name_and_last_name.bf"
))),
Ok(0)
);
} }
#[test] #[test]
fn reset() { fn reset() {
let mut interpreter = Interpreter::new( let mut interpreter = Interpreter::new(30000, vec![]);
30000,
vec![],
);
assert_eq!(interpreter.run(String::from(">++++")), Ok(0)); assert_eq!(interpreter.run(String::from(">++++")), Ok(0));

View File

@ -1,2 +1,2 @@
pub mod error;
pub mod interpreter; pub mod interpreter;
pub mod error;

View File

@ -1,8 +1,7 @@
mod arguments; mod arguments;
mod bf_interpreter;
mod repl; mod repl;
mod utils; mod utils;
mod bf_interpreter;
use clap::Parser; use clap::Parser;
extern crate pretty_env_logger; extern crate pretty_env_logger;
@ -21,24 +20,33 @@ fn main() {
info!("Parsed command line arguments: {:?}", args); info!("Parsed command line arguments: {:?}", args);
info!("Initializing interpreter"); info!("Initializing interpreter");
let mut interpreter = Interpreter::new( let mut interpreter =
args.array_size, Interpreter::new(args.array_size, args.features.unwrap_or_else(|| vec![]));
args.features.unwrap_or_else(|| vec![]),
);
match args.source { match args.source {
Some(source) => { Some(source) => {
info!("Running brainfuck source code from file: {}", source); info!("Running brainfuck source code from file: {}", source);
match interpreter.run(utils::read_brainfuck_code(&source)) { match interpreter.run(utils::read_brainfuck_code(&source)) {
Ok(exit_code) => { Ok(exit_code) => {
info!("Finished running brainfuck source code from file: {}", source); info!(
"Finished running brainfuck source code from file: {}",
source
);
if !args.without_tiles { if !args.without_tiles {
println!("{}", format!( println!(
"Successfully ran brainfuck source code from file: {}", "{}",
source format!(
).bold().green()); "Successfully ran brainfuck source code from file: {}",
println!("{}{}", "Exiting with code: ".truecolor(33, 97, 61), source
exit_code.to_string().bold().green()); )
.bold()
.green()
);
println!(
"{}{}",
"Exiting with code: ".truecolor(33, 97, 61),
exit_code.to_string().bold().green()
);
std::process::exit(exit_code); std::process::exit(exit_code);
} }
} }

View File

@ -1,7 +1,6 @@
use crate::bf_interpreter::interpreter::Interpreter; use crate::bf_interpreter::interpreter::Interpreter;
use std::io::{Write, BufRead};
use colored::Colorize; use colored::Colorize;
use std::io::Write;
struct Repl { struct Repl {
pub interpreter: Interpreter, pub interpreter: Interpreter,
@ -27,12 +26,13 @@ impl Repl {
// #[no_panic] // #[no_panic]
pub fn run(mut self) -> Result<(), std::io::Error> { pub fn run(mut self) -> Result<(), std::io::Error> {
loop { loop {
print!("{}", print!(
if self.loop_depth != 0 { "{}",
"........ ".yellow() if self.loop_depth != 0 {
} else { "........ ".yellow()
PROMPT.to_string().truecolor(54, 76, 76) } else {
} PROMPT.to_string().truecolor(54, 76, 76)
}
); );
std::io::stdout().flush()?; std::io::stdout().flush()?;
@ -119,13 +119,22 @@ impl Repl {
println!("{}", format!("Current array: {:?}", self.interpreter.cells)); println!("{}", format!("Current array: {:?}", self.interpreter.cells));
} }
"array_size" | "as" => { "array_size" | "as" => {
println!("{}", format!("Current array size: {}", println!(
self.interpreter.cells.len() "{}",
.to_string().bold().green())); format!(
"Current array size: {}",
self.interpreter.cells.len().to_string().bold().green()
)
);
} }
"pointer" | "p" => { "pointer" | "p" => {
println!("{}", format!("Current pointer: {}", println!(
self.interpreter.pointer.to_string().bold().green())); "{}",
format!(
"Current pointer: {}",
self.interpreter.pointer.to_string().bold().green()
)
);
} }
"pointer_value" | "pv" => { "pointer_value" | "pv" => {
println!( println!(
@ -143,11 +152,17 @@ impl Repl {
"save" | "s" => { "save" | "s" => {
let file_name = cmd.next().unwrap_or(HISTORY_FILE); let file_name = cmd.next().unwrap_or(HISTORY_FILE);
println!("{}", format!("Saving history to file: {file_name}").yellow()); println!(
"{}",
format!("Saving history to file: {file_name}").yellow()
);
match std::fs::write(file_name, self.history.join("\n")) { match std::fs::write(file_name, self.history.join("\n")) {
Ok(_) => { Ok(_) => {
println!("{}", format!("Successfully saved history to file: {file_name}") println!(
.green()); "{}",
format!("Successfully saved history to file: {file_name}")
.green()
);
} }
Err(e) => { Err(e) => {
error!("Failed to save history to file: {}", e); error!("Failed to save history to file: {}", e);
@ -157,11 +172,17 @@ impl Repl {
"load" | "l" => { "load" | "l" => {
let file_name = cmd.next().unwrap_or(HISTORY_FILE); let file_name = cmd.next().unwrap_or(HISTORY_FILE);
println!("{}", format!("Loading history from file: {file_name}").yellow()); println!(
"{}",
format!("Loading history from file: {file_name}").yellow()
);
match std::fs::read_to_string(file_name) { match std::fs::read_to_string(file_name) {
Ok(history) => { Ok(history) => {
println!("{}", format!("Successfully loaded history from file: {file_name}") println!(
.green()); "{}",
format!("Successfully loaded history from file: {file_name}")
.green()
);
self.history = history.split("\n").map(|s| s.to_string()).collect(); self.history = history.split("\n").map(|s| s.to_string()).collect();
// Run all commands in history // Run all commands in history
@ -192,7 +213,8 @@ impl Repl {
self.history = Vec::new(); self.history = Vec::new();
} }
"help" => { "help" => {
println!("!array, !a: print the current array\n\ println!(
"!array, !a: print the current array\n\
!array_size, !as: print the current array size\n\ !array_size, !as: print the current array size\n\
!pointer, !p: print the current pointer\n\ !pointer, !p: print the current pointer\n\
!pointer_value, !pv: print the current pointer value\n\ !pointer_value, !pv: print the current pointer value\n\
@ -201,11 +223,18 @@ impl Repl {
!load, !l: load the REPL history from a file\n\ !load, !l: load the REPL history from a file\n\
!reset, !r: reset the REPL\n\ !reset, !r: reset the REPL\n\
!help: print this help message\n\ !help: print this help message\n\
!fuck: exit the REPL"); !fuck: exit the REPL"
);
} }
_ => println!("{}", format!("Unknown command: {}, type {} to show the help", _ => println!(
user_input, (COMMAND_PREFIX.to_string() + "help").green() "{}",
).red()), format!(
"Unknown command: {}, type {} to show the help",
user_input,
(COMMAND_PREFIX.to_string() + "help").green()
)
.red()
),
} }
} }
None => {} None => {}
@ -218,17 +247,20 @@ impl Repl {
/// * `interpreter` - The interpreter to use /// * `interpreter` - The interpreter to use
pub fn start(interpreter: Interpreter) { pub fn start(interpreter: Interpreter) {
info!("Entering REPL mode"); info!("Entering REPL mode");
println!("{}\n\ println!(
"{}\n\
Brainfuck interpreter v {}\nBy {}\n\ Brainfuck interpreter v {}\nBy {}\n\
{}\n\ {}\n\
Type {} to exit :D\n\ Type {} to exit :D\n\
type {} to get more fu*king help", type {} to get more fu*king help",
"Welcome to the brainfuck REPL mode! :)".green(), "Welcome to the brainfuck REPL mode! :)".green(),
clap::crate_version!().to_string().yellow(), clap::crate_version!().to_string().yellow(),
clap::crate_authors!().to_string().green(), clap::crate_authors!().to_string().green(),
"Enter your brainfuck code and press enter to run it.".italic().blue(), "Enter your brainfuck code and press enter to run it."
(COMMAND_PREFIX.to_string() + "fuck").bold().red(), .italic()
(COMMAND_PREFIX.to_string() + "help").bold().green(), .blue(),
(COMMAND_PREFIX.to_string() + "fuck").bold().red(),
(COMMAND_PREFIX.to_string() + "help").bold().green(),
); );
match Repl::new(interpreter).run() { match Repl::new(interpreter).run() {
@ -249,10 +281,7 @@ mod tests {
#[test] #[test]
fn nested_loop_level_1() { fn nested_loop_level_1() {
let interpreter = Interpreter::new( let interpreter = Interpreter::new(4, vec![]);
4,
vec![],
);
let mut repl = Repl::new(interpreter); let mut repl = Repl::new(interpreter);
@ -270,10 +299,7 @@ mod tests {
#[test] #[test]
fn nested_loop_level_2() { fn nested_loop_level_2() {
let interpreter = Interpreter::new( let interpreter = Interpreter::new(4, vec![]);
4,
vec![],
);
let mut repl = Repl::new(interpreter); let mut repl = Repl::new(interpreter);
@ -294,10 +320,7 @@ mod tests {
#[test] #[test]
fn print_my_first_name() { fn print_my_first_name() {
let interpreter = Interpreter::new( let interpreter = Interpreter::new(10, vec![]);
10,
vec![],
);
let mut repl = Repl::new(interpreter); let mut repl = Repl::new(interpreter);
@ -348,7 +371,11 @@ mod tests {
>>+++ >>+++
<<- <<-
] ]
>>. Print s".to_string().split("\n").map(|s| s.to_string()).collect::<Vec<String>>(); >>. Print s"
.to_string()
.split("\n")
.map(|s| s.to_string())
.collect::<Vec<String>>();
for line in code { for line in code {
repl.process(line); repl.process(line);
@ -357,25 +384,20 @@ mod tests {
#[test] #[test]
fn print_my_first_name_in_one_command() { fn print_my_first_name_in_one_command() {
let interpreter = Interpreter::new( let interpreter = Interpreter::new(10, vec![]);
10,
vec![],
);
let mut repl = Repl::new(interpreter); let mut repl = Repl::new(interpreter);
let code = "++++++++[>++++[>++<-]>>>>>>++[<<<->>>-]<<<<<<<-]>>+.<<++++[>+++ let code = "++++++++[>++++[>++<-]>>>>>>++[<<<->>>-]<<<<<<<-]>>+.<<++++[>+++
[>+++<-]>++<<-]>>+.<<+++[>+++[>-<-]>-<<-]>>-.<<++++++[>>+++<<-]>>.".to_string(); [>+++<-]>++<<-]>>+.<<+++[>+++[>-<-]>-<<-]>>-.<<++++++[>>+++<<-]>>."
.to_string();
repl.process(code); repl.process(code);
} }
#[test] #[test]
fn print_hello_world() { fn print_hello_world() {
let interpreter = Interpreter::new( let interpreter = Interpreter::new(10, vec![]);
10,
vec![],
);
let mut repl = Repl::new(interpreter); let mut repl = Repl::new(interpreter);
@ -415,6 +437,9 @@ mod tests {
+++.------.--------. Cell #3 for 'rl' and 'd' +++.------.--------. Cell #3 for 'rl' and 'd'
>>+. Add 1 to Cell #5 gives us an exclamation point >>+. Add 1 to Cell #5 gives us an exclamation point
>++. And finally a newline from Cell #6 >++. And finally a newline from Cell #6
".to_string().split("\n").for_each(|s| repl.process(s.to_string())); "
.to_string()
.split("\n")
.for_each(|s| repl.process(s.to_string()));
} }
} }