about summary refs log tree commit diff stats
path: root/rust
diff options
context:
space:
mode:
Diffstat (limited to 'rust')
-rw-r--r--rust/bf/.gitignore2
-rw-r--r--rust/bf/.vscode/launch.json15
-rw-r--r--rust/bf/Cargo.lock7
-rw-r--r--rust/bf/Cargo.toml6
-rw-r--r--rust/bf/src/hw.bf1
-rw-r--r--rust/bf/src/main.rs91
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);
+}