Last active
August 29, 2015 14:22
-
-
Save davenportw15/5ae4e80c156c1dae6582 to your computer and use it in GitHub Desktop.
Partial BrainF Interpreter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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