From 4aa01762e67317d7191fd12159caa83d2ca7f128 Mon Sep 17 00:00:00 2001 From: Wynd Date: Sun, 20 Oct 2024 00:40:01 +0300 Subject: [PATCH] First attempt at a dumb brainfuck interpreter --- .gitignore | 1 + Cargo.lock | 7 ++++ Cargo.toml | 6 ++++ input/cat.bf | 1 + input/hello-world.bf | 2 ++ input/loop.bf | 1 + input/math.bf | 1 + rust-toolchain.toml | 2 ++ src/main.rs | 86 ++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 107 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 input/cat.bf create mode 100644 input/hello-world.bf create mode 100644 input/loop.bf create mode 100644 input/math.bf create mode 100644 rust-toolchain.toml create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..c3c47f3 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "bfin" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..db62cc1 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "bfin" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/input/cat.bf b/input/cat.bf new file mode 100644 index 0000000..05b49e2 --- /dev/null +++ b/input/cat.bf @@ -0,0 +1 @@ +,[.,] diff --git a/input/hello-world.bf b/input/hello-world.bf new file mode 100644 index 0000000..281a0a5 --- /dev/null +++ b/input/hello-world.bf @@ -0,0 +1,2 @@ ++++++++++++[>++++++>+++++++++>++++++++>++++>+++>+<<<<<<-]>+++ ++++.>++.+++++++..+++.>>.>-.<<-.<.+++.------.--------.>>>+.>-. diff --git a/input/loop.bf b/input/loop.bf new file mode 100644 index 0000000..dc6dbda --- /dev/null +++ b/input/loop.bf @@ -0,0 +1 @@ +,[->+<]>++. diff --git a/input/math.bf b/input/math.bf new file mode 100644 index 0000000..ad6a80d --- /dev/null +++ b/input/math.bf @@ -0,0 +1 @@ +,++. diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..5d56faf --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly" diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..f31df9f --- /dev/null +++ b/src/main.rs @@ -0,0 +1,86 @@ +use std::{ + collections::{HashMap, VecDeque}, + fs, + io::{self, Write}, + path::PathBuf, +}; + +const PROGRAM: &str = "hello-world.bf"; + +fn main() { + let program: Vec = load_program(); + + let mut tape: Vec = vec![0]; + let mut cell_index: usize = 0; + + let mut ip: usize = 0; + let mut user_input: Vec = vec![]; + + let mut table: HashMap = HashMap::new(); + let mut stack: VecDeque = VecDeque::new(); + for (ip, instruction) in program.iter().enumerate() { + if *instruction == b'[' { + stack.push_back(ip); + } else if *instruction == b']' { + let begin_index = stack.pop_front().unwrap(); + table.insert(begin_index, ip); + table.insert(ip, begin_index); + } + } + + while ip < program.len() { + let Some(instruction) = program.get(ip) else { + break; + }; + + match instruction { + b'+' => tape[cell_index] = tape[cell_index].wrapping_add(1), + b'-' => tape[cell_index] = tape[cell_index].wrapping_sub(1), + b'>' => { + cell_index = cell_index.wrapping_add(1); + if tape.len() <= cell_index { + tape.push(0); + } + } + b'<' => cell_index = cell_index.wrapping_sub(1), + b'.' => print!("{}", tape[cell_index] as char), + b',' => { + if user_input.is_empty() { + user_input = input(); + } + tape[cell_index] = user_input.remove(0); + } + b'[' => { + if tape[cell_index] == 0 { + ip = *table.get(&ip).unwrap(); + } + } + b']' => { + if tape[cell_index] != 0 { + ip = *table.get(&ip).unwrap(); + } + } + _ => {} + } + + ip += 1; + } + + println!(); +} + +fn input() -> Vec { + let mut input = String::new(); + + print!("Input: "); + let _ = io::stdout().flush(); + let _ = io::stdin().read_line(&mut input); + + input.as_bytes().to_vec() +} + +fn load_program() -> Vec { + let path: PathBuf = [".", "input", PROGRAM].iter().collect(); + let input = fs::read_to_string(path).unwrap(); + input.as_bytes().to_vec() +}