First attempt at a dumb brainfuck interpreter
commit
4aa01762e6
|
@ -0,0 +1 @@
|
|||
/target
|
|
@ -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"
|
|
@ -0,0 +1,6 @@
|
|||
[package]
|
||||
name = "bfin"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
|
@ -0,0 +1 @@
|
|||
,[.,]
|
|
@ -0,0 +1,2 @@
|
|||
+++++++++++[>++++++>+++++++++>++++++++>++++>+++>+<<<<<<-]>+++
|
||||
+++.>++.+++++++..+++.>>.>-.<<-.<.+++.------.--------.>>>+.>-.
|
|
@ -0,0 +1 @@
|
|||
,[->+<]>++.
|
|
@ -0,0 +1 @@
|
|||
,++.
|
|
@ -0,0 +1,2 @@
|
|||
[toolchain]
|
||||
channel = "nightly"
|
|
@ -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()
|
||||
}
|
Loading…
Reference in New Issue