Skip to content

Instantly share code, notes, and snippets.

@DuoSRX
Created May 26, 2014 19:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DuoSRX/a25bb71dc9dc955822f5 to your computer and use it in GitHub Desktop.
Save DuoSRX/a25bb71dc9dc955822f5 to your computer and use it in GitHub Desktop.
Brainfuck in Rust
use std::char::from_u32;
use std::str::from_char;
#[deriving(Eq, Show)]
pub enum Command {
Add(int),
Move(int),
Output,
LoopIn,
LoopOut,
Loop(Vec<Command>),
Nop
}
pub struct BF {
code: Vec<Command>,
size: uint,
memory: Vec<int>,
cp: uint,
mp: uint
}
pub fn new(code: &str) -> BF {
let program = parse(code);
let memory = Vec::new();
memory.grow(30000, box 0);
BF {
size: program.len(),
code: program,
memory: memory,
cp: 0,
mp: 0
}
}
fn parse(code: &str) -> Vec<Command> {
let mut result: Vec<Command> = Vec::new();
let mut count = 1;
let mut last = ' ';
let mut prev = code.char_at(0);
let mut chars = code.slice_from(1).chars();
loop {
let c = match chars.next() {
Some(c) => c,
None => break,
};
if c != prev || c == '[' || c == ']' || c == '.' {
result.push(char_to_command(prev, count));
count = 1;
prev = c;
} else {
count += 1;
}
last = c;
}
result.push(char_to_command(last, count));
result
}
fn char_to_command(c: char, count: int) -> Command {
match c {
'>' => Move(count),
'<' => Move(-count),
'+' => Add(count),
'-' => Add(-count),
'.' => Output,
'[' => LoopIn,
']' => LoopOut,
_ => Nop
}
}
impl BF {
pub fn run(&mut self) {
while self.cp < self.size {
match *self.get_command() {
Move(n) => self.mp = self.mp + n as uint,
Add(n) => {
let mem = self.get_memory() + n;
// self.memory[self.mp] = mem;
self.memory.get(self.mp) = box mem;
}
Output => self.print_char(),
LoopIn => self.handle_open_bracket(),
LoopOut => self.handle_close_bracket(),
_ => println!("wat?"),
}
self.cp += 1;
}
}
#[allow(dead_code)]
pub fn reset(&mut self) {
let memory = Vec::new();
memory.grow(30000, box 0);
self.memory = memory;
self.cp = 0;
self.mp = 0;
}
fn get_memory(&self) -> int {
self.memory.get(self.mp)
}
fn get_command<'a>(&'a self) -> &'a Command {
self.code.get(self.cp)
}
fn print_char(&self) {
match from_u32(self.get_memory() as u32) {
Some(c) => print!("{}", from_char(c)),
None => (),
}
}
fn handle_open_bracket(&mut self) {
if self.get_memory() == 0 {
let mut level = 1;
while self.cp < self.size && level != 0 {
self.cp += 1;
match *self.get_command() {
LoopIn => level += 1,
LoopOut => level -= 1,
_ => ()
}
}
}
}
fn handle_close_bracket(&mut self) {
if self.get_memory() != 0 {
let mut level = 1;
while self.cp > 0 && level != 0 {
self.cp -= 1;
match *self.get_command() {
LoopIn => level -= 1,
LoopOut => level += 1,
_ => ()
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment