Skip to content

Instantly share code, notes, and snippets.

@bjorn3 bjorn3/brainfuck.rs
Last active Apr 16, 2016

Embed
What would you like to do?
use std::collections::VecDeque;
use std::iter::Peekable;
use std::str::Chars;
use std::mem;
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
enum Instruction{
Nop,
Next,
Prev,
Inc,
Dec,
Print,
Input,
Loop(Vec<Instruction>)
}
impl Instruction{
pub fn from_iter(iter: &mut Peekable<Chars>) -> Vec<Instruction>{
let mut instructions = Vec::new();
let mut stop = false;
loop{
let instr = match iter.peek(){
Some(instr) => instr,
None => break
}.clone();
instructions.push(match instr{
'>' => {
iter.next();
Instruction::Next
},
'<' => {
iter.next();
Instruction::Prev
},
'+' => {
iter.next();
Instruction::Inc
},
'-' => {
iter.next();
Instruction::Dec
},
'.' => {
iter.next();
Instruction::Print
},
',' => {
iter.next();
Instruction::Input
},
'[' => {
iter.next();
Instruction::Loop(Instruction::from_iter(iter))
},
']' => {
stop = true;
iter.next();
Instruction::Nop
},
char => {
println!("{}", char);
unreachable!();
}
});
if stop{
break;
}
}
instructions
}
pub fn run(&self, pc: &mut usize, mem: &mut [u8], memnum: &mut usize){
{
let mut instr = format!("{:#?}", self);
while instr.len() < 5{
instr.push(' ');
}
let mut pc = format!("{}", pc);
while pc.len() < 2{
pc.push(' ');
}
let mut mem = mem.iter().map(|num|{
let mut num = format!("{}", num);
while num.len() < 2{
num.push(' ');
}
num
}).fold("".to_owned(), |acc, num| acc + &num);
// +----uncomment this for debug information
// v
//println!("instr: {}, pc: {}, mem: {:?}, memnum: {}", instr, pc, mem.to_owned(), memnum);
}
match *self{
Instruction::Nop => {
*pc += 1;
},
Instruction::Next => {
*memnum += 1;
*pc += 1;
},
Instruction::Prev => {
*memnum -= 1;
*pc += 1;
},
Instruction::Inc => {
(*mem)[*memnum] += 1;
*pc += 1;
},
Instruction::Dec => {
(*mem)[*memnum] -= 1;
*pc += 1;
},
Instruction::Print => {
use ::std::io::Write;
let mut stdout = ::std::io::stdout();
let num = [mem[*memnum]];
stdout.write(&num).unwrap();
stdout.flush().unwrap();
*pc += 1;
},
Instruction::Loop(ref instructions) => {
let mut loop_pc = 0;
while mem[*memnum] != 0{
while loop_pc < instructions.len(){
instructions[loop_pc].run(&mut loop_pc, mem, memnum);
}
loop_pc = 0;
}
*pc += 1;
}
_ => panic!("Invalid key")
}
}
}
fn main(){
let program: &str = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.";
let program: Vec<Instruction> = Instruction::from_iter(&mut program.chars().peekable());
let mut pc = 0;
let mut mem = [0u8;30000];
let mut memnum = 0;
// +----uncomment this for debug information
// v
//println!("{:#?}", program);
loop{
program[pc].run(&mut pc, &mut mem, &mut memnum);
if pc >= program.len() {
break;
}
}
}
@bjorn3

This comment has been minimized.

Copy link
Owner Author

commented Apr 16, 2016

This is a fully functional implementation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.