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 = 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 = Vec::new(); while pc < code_chars.len() { match code_chars[pc] { '>' => { pointer += 1; if pointer >= memory.len() { panic!("Pointer out of bounds (positive)"); } } '<' => { if pointer == 0 { panic!("Pointer out of bounds (negative)"); } 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. Unable to read a single byte from stdin"); 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 = env::args().collect(); if args.len() != 2 || !args[1].ends_with(".bf") { eprintln!("Usage: {} ", 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); }