First attempt at a dumb brainfuck interpreter

master
Wynd 2024-10-20 00:40:01 +03:00
commit 4aa01762e6
9 changed files with 107 additions and 0 deletions

1
.gitignore vendored 100644
View File

@ -0,0 +1 @@
/target

7
Cargo.lock generated 100644
View File

@ -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"

6
Cargo.toml 100644
View File

@ -0,0 +1,6 @@
[package]
name = "bfin"
version = "0.1.0"
edition = "2021"
[dependencies]

1
input/cat.bf 100644
View File

@ -0,0 +1 @@
,[.,]

View File

@ -0,0 +1,2 @@
+++++++++++[>++++++>+++++++++>++++++++>++++>+++>+<<<<<<-]>+++
+++.>++.+++++++..+++.>>.>-.<<-.<.+++.------.--------.>>>+.>-.

1
input/loop.bf 100644
View File

@ -0,0 +1 @@
,[->+<]>++.

1
input/math.bf 100644
View File

@ -0,0 +1 @@
,++.

View File

@ -0,0 +1,2 @@
[toolchain]
channel = "nightly"

86
src/main.rs 100644
View File

@ -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<u8> = load_program();
let mut tape: Vec<u8> = vec![0];
let mut cell_index: usize = 0;
let mut ip: usize = 0;
let mut user_input: Vec<u8> = vec![];
let mut table: HashMap<usize, usize> = HashMap::new();
let mut stack: VecDeque<usize> = 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<u8> {
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<u8> {
let path: PathBuf = [".", "input", PROGRAM].iter().collect();
let input = fs::read_to_string(path).unwrap();
input.as_bytes().to_vec()
}