Skip to content

Instantly share code, notes, and snippets.

@davenportw15
Last active August 29, 2015 14:22
Show Gist options
  • Save davenportw15/5ae4e80c156c1dae6582 to your computer and use it in GitHub Desktop.
Save davenportw15/5ae4e80c156c1dae6582 to your computer and use it in GitHub Desktop.
Partial BrainF Interpreter
fn main() {
let program_data = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.";
let mut program = Program::from_chars(program_data);
program.step();
println!("OUTPUT:");
println!(" pointer: {}", program.pointer);
println!(" data: {:?}", program.data);
}
#[derive(Debug)]
pub enum Instruction {
// > : Move pointer forward
Forward,
// < : Move pointer backward
Backward,
// + : Increment current value by 1
Increment,
// - : Decrement current value by 1
Decrement,
// . : Output current value
Output,
// , : Input value, store at current pointer
Input,
// [ : Begin loop
Begin,
// ] : End loop; if current value is not zero, jump back to ]
End
}
impl Instruction {
fn new(c: char) -> Instruction {
match c {
'>' => Instruction::Forward,
'<' => Instruction::Backward,
'+' => Instruction::Increment,
'-' => Instruction::Decrement,
'.' => Instruction::Output,
',' => Instruction::Input,
'[' => Instruction::Begin,
']' => Instruction::End,
_ => panic!("Invalid character: {}", c)
}
}
}
struct Program {
instructions: Vec<Instruction>,
step: usize,
pointer: usize,
begin_stack: Vec<usize>,
data: Vec<i32>
}
impl Program {
fn from_chars(characters: &str) -> Program {
let instructions = characters.chars().map(Instruction::new).collect();
Program {
instructions: instructions,
step: 0 as usize,
pointer: 0 as usize,
begin_stack: Vec::new(),
data: vec![0] // reserve
}
}
fn step(&mut self) {
let step = self.step;
self.step += 1;
if step < self.instructions.len() {
match self.instructions[step] {
Instruction::Forward => self.forward(),
Instruction::Backward => self.backward(),
Instruction::Increment => self.increment(),
Instruction::Decrement => self.decrement(),
Instruction::Input => self.input(),
Instruction::Output => self.output(),
Instruction::Begin => self.begin(),
Instruction::End => self.end()
}
}
}
fn forward(&mut self) {
println!("forward");
self.pointer += 1;
println!("pointer: {}", self.pointer);
if self.pointer >= self.data.len() {
self.data.push(0);
}
println!("data: {:?}", self.data);
self.step();
}
fn backward(&mut self) {
println!("backward");
self.pointer -= 1;
println!("pointer: {}", self.pointer);
println!("data: {:?}", self.data);
self.step();
}
fn increment(&mut self) {
println!("increment");
self.data[self.pointer] += 1;
println!("{:?}", self.pointer);
println!("{:?}", self.data);
self.step();
}
fn decrement(&mut self) {
println!("decrement");
self.data[self.pointer] -= 1;
self.step();
}
fn input(&mut self) {
println!("input");
self.step();
}
fn output(&mut self) {
println!("output");
println!("{}", self.data[self.pointer]);
self.step();
}
fn begin(&mut self) {
println!("begin");
self.begin_stack.push(self.step);
self.step();
}
fn end(&mut self) {
println!("end");
println!("{:?}", self.pointer);
if (self.data[self.pointer] == 0) {
self.begin_stack.pop();
self.step();
} else {
self.step = match self.begin_stack.last() {
Some(v) => *v,
None => panic!("Unmatched loop bracket")
};
self.step();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment