Reformat the code yo 🥰🦀
This commit is contained in:
parent
ade4438ce4
commit
c4f35dd63c
5 changed files with 180 additions and 155 deletions
|
@ -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();
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
pub mod error;
|
||||
pub mod interpreter;
|
||||
pub mod error;
|
34
src/main.rs
34
src/main.rs
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
135
src/repl.rs
135
src/repl.rs
|
@ -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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue