diff options
author | elioat <{ID}+{username}@users.noreply.github.com> | 2024-09-20 17:15:11 -0400 |
---|---|---|
committer | elioat <{ID}+{username}@users.noreply.github.com> | 2024-09-20 17:15:11 -0400 |
commit | e010163faaca10c20d5301af99f1505bb361d5a9 (patch) | |
tree | 3a4aa4355743728bfe1aaf0eb31c18aeefd83b3b /rust/bf/src | |
parent | 665ad1f48ddb4513272bfecb372651a4ea96d869 (diff) | |
download | tour-e010163faaca10c20d5301af99f1505bb361d5a9.tar.gz |
*
Diffstat (limited to 'rust/bf/src')
-rw-r--r-- | rust/bf/src/hw.bf | 1 | ||||
-rw-r--r-- | rust/bf/src/main.rs | 91 |
2 files changed, 92 insertions, 0 deletions
diff --git a/rust/bf/src/hw.bf b/rust/bf/src/hw.bf new file mode 100644 index 0000000..ea2b641 --- /dev/null +++ b/rust/bf/src/hw.bf @@ -0,0 +1 @@ +++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++. \ No newline at end of file diff --git a/rust/bf/src/main.rs b/rust/bf/src/main.rs new file mode 100644 index 0000000..9257ae2 --- /dev/null +++ b/rust/bf/src/main.rs @@ -0,0 +1,91 @@ +use std::io::{self, Read}; +use std::env; +use std::process; + +fn interpret_brainfuck(code: &str) { + let mut memory = vec![0u8; 30000]; // 30,000 cells of memory initialized to 0 + let mut pointer: usize = 0; // data pointer starts at the first cell + let mut pc: usize = 0; // program counter for the Brainfuck code + let code_chars: Vec<char> = code.chars().collect(); // convert the Brainfuck code to a vector of characters + + // Stack to keep track of [ and ] for loops + let mut loop_stack: Vec<usize> = Vec::new(); + + while pc < code_chars.len() { + match code_chars[pc] { + '>' => { + pointer += 1; + if pointer >= memory.len() { + panic!("Pointer out of bounds"); + } + } + '<' => { + if pointer == 0 { + panic!("Pointer out of bounds"); + } + pointer -= 1; + } + '+' => { + memory[pointer] = memory[pointer].wrapping_add(1); // increment with wrap around + } + '-' => { + memory[pointer] = memory[pointer].wrapping_sub(1); // decrement with wrap around + } + '.' => { + print!("{}", memory[pointer] as char); + } + ',' => { + let mut input = [0u8]; + io::stdin().read_exact(&mut input).expect("Failed to read input"); + memory[pointer] = input[0]; + } + '[' => { + if memory[pointer] == 0 { + // Jump to the matching ']' if the current cell is 0 + let mut open_brackets = 1; + while open_brackets > 0 { + pc += 1; + if pc >= code_chars.len() { + panic!("Unmatched ["); + } + if code_chars[pc] == '[' { + open_brackets += 1; + } else if code_chars[pc] == ']' { + open_brackets -= 1; + } + } + } else { + // Push the current position to the stack if not jumping + loop_stack.push(pc); + } + } + ']' => { + if memory[pointer] != 0 { + // Jump back to the matching '[' if the current cell is nonzero + if let Some(loop_start) = loop_stack.last() { + pc = *loop_start; + } else { + panic!("Unmatched ]"); + } + } else { + // Pop the stack if done with the loop + loop_stack.pop(); + } + } + _ => {} // Ignore any non-Brainfuck commands + } + pc += 1; // Move to the next instruction + } +} + +fn main() { + let args: Vec<String> = env::args().collect(); + if args.len() != 2 || !args[1].ends_with(".bf") { + eprintln!("Usage: {} <filename.bf>", args[0]); + process::exit(1); + } + + let filename = &args[1]; + let code = std::fs::read_to_string(filename).expect("Failed to read the file"); + interpret_brainfuck(&code); +} |