diff options
Diffstat (limited to 'rust')
-rw-r--r-- | rust/bf/.gitignore | 2 | ||||
-rw-r--r-- | rust/bf/.vscode/launch.json | 15 | ||||
-rw-r--r-- | rust/bf/Cargo.lock | 7 | ||||
-rw-r--r-- | rust/bf/Cargo.toml | 6 | ||||
-rw-r--r-- | rust/bf/src/hw.bf | 1 | ||||
-rw-r--r-- | rust/bf/src/main.rs | 91 |
6 files changed, 122 insertions, 0 deletions
diff --git a/rust/bf/.gitignore b/rust/bf/.gitignore new file mode 100644 index 0000000..64aadb8 --- /dev/null +++ b/rust/bf/.gitignore @@ -0,0 +1,2 @@ +target +target/* \ No newline at end of file diff --git a/rust/bf/.vscode/launch.json b/rust/bf/.vscode/launch.json new file mode 100644 index 0000000..33bcb32 --- /dev/null +++ b/rust/bf/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "type": "lldb", + "request": "launch", + "name": "Debug executable", + "cargo": { + "args": ["build"] + }, + "args": ["src/hw.bf"], + "cwd": "${workspaceFolder}" + } + ] +} \ No newline at end of file diff --git a/rust/bf/Cargo.lock b/rust/bf/Cargo.lock new file mode 100644 index 0000000..f1798f9 --- /dev/null +++ b/rust/bf/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "bf" +version = "0.1.0" diff --git a/rust/bf/Cargo.toml b/rust/bf/Cargo.toml new file mode 100644 index 0000000..eb4b810 --- /dev/null +++ b/rust/bf/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "bf" +version = "0.1.0" +edition = "2021" + +[dependencies] 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..e511e69 --- /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 (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<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); +} |