Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A brainfuck interpreter in rust. Takes input from stdin.
use std::env::args;
use std::io::{stdin, Read, BufRead};
use std::u8;
use std::fmt::{self, Display};
struct BFVM {
data: Box<u8>,
instr_data: Vec<u8>,
loop_stack: u32,
data_ptr: usize,
instr_ptr: usize,
run: bool,
}
impl fmt::Display for BFVM {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "data: {:#?}\ndata ptr: {}\ninstruction ptr: {}\nloop stack: {}", &self.data[..10], self.data_ptr, self.instr_ptr, self.loop_stack)
}
}
impl BFVM {
pub fn new(program: String) -> Self {
BFVM {
data: box![0u8 ; 0x1000],
instr_data: program.into_bytes(),
data_ptr: 0,
instr_ptr: 0,
loop_stack: 0,
run: true,
}
}
pub fn step(&mut self, input: &mut std::io::StdinLock) {
if self.instr_ptr == self.instr_data.len() - 1 {
println!("\nreached end of program.");
self.run = false;
return;
}
match self.instr_data[self.instr_ptr] as char {
'>' => {
self.data_ptr = (self.data_ptr + 1) % self.data.len();
},
'<' => {
if self.data_ptr > 0 {
self.data_ptr -= 1;
} else {
self.data_ptr = self.data.len() - 1;
}
},
'+' => {
self.data[self.data_ptr] = self.data[self.data_ptr].overflowing_add(1).0;
},
'-' => {
self.data[self.data_ptr] = self.data[self.data_ptr].overflowing_sub(1).0;
},
'.' => {
if self.data[self.data_ptr].is_ascii_whitespace() || !self.data[self.data_ptr].is_ascii_control() {
print!("{}", self.data[self.data_ptr] as char);
} else {
println!("{}", self.data[self.data_ptr]);
}//
},
',' => {
match input.read_exact(&mut self.data[self.data_ptr..self.data_ptr + 1]) {
Ok(_) => {},
Err(w) => println!("{:#?}", w)
}
},
'[' => {
self.loop_stack += 1;
if self.data[self.data_ptr] == 0 {
let curr_stack = self.loop_stack;
while self.instr_ptr < self.instr_data.len() && self.loop_stack >= curr_stack {
self.instr_ptr += 1;
match self.instr_data[self.instr_ptr] as char {
'[' => {
self.loop_stack += 1;
},
']' => {
self.loop_stack -= 1
},
'\0' => panic!(),
_ => {}
};
}
}
},
']' => {
if self.data[self.data_ptr] > 0 {
let curr_stack = self.loop_stack;
while self.instr_ptr > 0 && self.loop_stack >= curr_stack {
self.instr_ptr -= 1;
match self.instr_data[self.instr_ptr] as char {
'[' => {
self.loop_stack -= 1;
},
']' => {
self.loop_stack += 1
},
_ => {}
};
}
self.loop_stack += 1;
} else {
self.loop_stack -= 1;
}
},
_ => {}
};
self.instr_ptr += 1;
}
}
fn main() {
let std_in = stdin();
let mut input = std_in.lock();
let mut strng = String::new();
input.read_line(&mut strng).unwrap();
let mut vm = BFVM::new(strng);
while vm.run {
vm.step(&mut input);
}
}
// borrowed hello world
//++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
// Print 3 1's and 3 0's
// +.>+.>+.[-.<]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment