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)]
pub struct InterpreterError {
@ -62,10 +62,15 @@ impl InterpreterErrorKind {
impl Display for InterpreterErrorKind {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
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::IoError(error) =>
write!(f, "Failed to read byte from stdin: no bytes available: {}", error),
InterpreterErrorKind::IoError(error) => write!(
f,
"Failed to read byte from stdin: no bytes available: {}",
error
),
InterpreterErrorKind::FlushError(e) => write!(f, "Failed to flush stdout: {}", e),
InterpreterErrorKind::UnmatchedBracket => write!(f, "Unmatched bracket"),
InterpreterErrorKind::InvalidUtf8 => write!(f, "Invalid utf8"),
@ -88,8 +93,13 @@ mod tests {
assert_eq!(error.to_string(), "Value out of bounds");
assert_eq!(error.code, 12);
let error = 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");
let error =
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);
/*let error = InterpreterErrorKind::FlushError(e).to_error();

View File

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

View File

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

View File

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

View File

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