wrote interpreter source code

This commit is contained in:
2026-07-08 19:29:24 +02:00
parent df38b15dd5
commit 7bab256fc8
+96 -2
View File
@@ -1,3 +1,97 @@
fn main() {
println!("Hello, world!");
use anyhow::Result;
use anyhow::anyhow;
use std::collections::HashMap;
use std::io::{self, Read, Write};
use std::fs;
fn clean_code(code: &str) -> Vec<char> {
let vec: Vec<char> = code.chars().collect();
let clean = vec
.into_iter()
.filter(|b| "+-<>,.[]".contains(*b))
.collect();
clean
}
fn precompute_jump_table(code: &[char]) -> Result<HashMap<usize, usize>> {
let mut jump_table = HashMap::new();
let mut stack = Vec::new();
for (i, &char) in code.iter().enumerate() {
if char == '[' {
stack.push(i);
} else if char == ']' {
match stack.pop() {
Some(start_index) => {
jump_table.insert(start_index, i);
jump_table.insert(i, start_index);
}
None => {
return Err(anyhow!("miss matching closing brackets at index {}", i));
}
}
}
}
if !stack.is_empty() {
return Err(anyhow!("open brackets unclosed"));
}
Ok(jump_table)
}
fn execute(raw_code: &str) -> Result<()> {
let clean = clean_code(raw_code);
let jump_table = precompute_jump_table(&clean)?;
let mut tape: [u8; 30000] = [0; 30000];
let mut data_ptr: usize = 0;
let mut exec_ptr: usize = 0;
while exec_ptr < clean.len() {
let cmd = clean[exec_ptr];
match cmd {
'+' => {
tape[data_ptr] = tape[data_ptr].wrapping_add(1);
}
'-' => {
tape[data_ptr] = tape[data_ptr].wrapping_sub(1);
}
'>' => {
data_ptr += 1;
if data_ptr > 29999 {
data_ptr = 0;
}
}
'<' => {
if data_ptr == 0 {
data_ptr = 29999;
}
else {
data_ptr -= 1;
}
}
',' => {
let mut buf = [0; 1];
if io::stdin().read_exact(&mut buf).is_ok() {
tape[data_ptr] = buf[0];
}
}
'.' => {
print!("{}", tape[data_ptr] as char);
let _ = io::stdout().flush();
}
'[' => {
if tape[data_ptr] == 0 {
exec_ptr = *jump_table.get(&exec_ptr).unwrap();
}
}
']' => {
if tape[data_ptr] != 0 {
exec_ptr = *jump_table.get(&exec_ptr).unwrap();
}
}
_ => {}
}
exec_ptr += 1;
}
Ok(())
}
fn main() -> Result<()> {
let code_path = std::env::args().nth(1).ok_or_else(|| anyhow!("Usage: bf <path to file.bf>"))?;
let code = fs::read_to_string(&code_path)?;
execute(&code)?;
Ok(())
}