Skip to content

Instantly share code, notes, and snippets.

@eliascotto
Last active January 23, 2024 03:40
Show Gist options
  • Save eliascotto/a99225ff71a81ec31219fc3a834872e2 to your computer and use it in GitHub Desktop.
Save eliascotto/a99225ff71a81ec31219fc3a834872e2 to your computer and use it in GitHub Desktop.
Brainfuck interpreter in Rust
use std::io::{self, Write};
struct Memory {
cells: Vec<i32>,
pointer: usize,
}
fn bf_runtime(m: &mut Memory, s: String) {
let instructions: &[u8] = s.as_bytes();
let mut idx: usize = 0;
let mut with_output = false;
loop {
if idx > instructions.len() - 1 {
break;
}
// String is transformed to byte, than indexed, and then transformed into char
// UTF-8
let c: char = instructions[idx] as char;
match c {
'>' => {
if m.pointer >= m.cells.len() {
m.cells.extend_from_slice(&[0, 1000]);
}
m.pointer += 1;
},
'<' => {
m.pointer -= 1;
},
'+' => {
m.cells[m.pointer] += 1;
},
'-' => {
m.cells[m.pointer] -= 1;
},
'.' => {
with_output = true;
let n = char::from_u32(m.cells[m.pointer] as u32).unwrap();
print!("{}", n);
io::stdout().flush().unwrap();
},
',' => {
print!("input: ");
io::stdout().flush().unwrap();
let mut input_str = String::new();
let n_bytes = io::stdin()
.read_line(&mut input_str)
.unwrap();
if n_bytes > 0 {
let bytes = input_str.as_bytes();
m.cells[m.pointer] = bytes[0] as i32;
}
},
'[' => {
if m.cells[m.pointer] == 0 {
let mut lvl = 0;
let mut counter = 1;
loop {
let nc: char = instructions[idx + counter] as char;
match nc {
'[' => lvl += 1,
']' => {
if lvl > 0 {
lvl -= 1;
} else {
break;
}
},
_ => {},
}
counter += 1
}
idx += counter + 1;
continue;
}
},
']' => {
if m.cells[m.pointer] != 0 {
let mut lvl = 0;
let mut counter = 1;
loop {
let nc: char = instructions[idx - counter] as char;
match nc {
']' => lvl += 1,
'[' => {
if lvl > 0 {
lvl -= 1;
} else {
break;
}
},
_ => {},
}
counter += 1
}
idx -= counter;
continue;
}
},
_ => {},
}
idx += 1;
}
if with_output {
println!()
}
}
fn main() {
println!("BrainFuck REPL 1.0");
let mut m = Memory { cells: vec![0; 1000], pointer: 0 };
loop {
let mut s: String = String::new();
print!("> ");
io::stdout().flush().unwrap();
let num_bytes = io::stdin().read_line(&mut s).expect("Did not enter a correct string");
if num_bytes == 0 {
break;
} else {
bf_runtime(&mut m, s);
m = Memory { cells: vec![0; 1000], pointer: 0 };
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment