Skip to content

Instantly share code, notes, and snippets.

@emberian
Forked from tiffany352/bf.rs
Last active December 20, 2015 21:08
Show Gist options
  • Save emberian/6194862 to your computer and use it in GitHub Desktop.
Save emberian/6194862 to your computer and use it in GitHub Desktop.
use std::uint;
use std::io;
use std::str;
enum Token {
Add,
Sub,
Inc,
Dec,
Out,
In,
Begin (uint),
End (uint),
Nil
}
struct Context {
program: ~[Token],
pc: uint,
cell: int,
stack: ~[uint],
sp: uint,
heap_forward: ~[u8],
heap_backward: ~[u8]
}
fn heap_get(ctx: &Context, addr: int) -> u8 {
let flen = ctx.heap_forward.len() as int;
let blen = ctx.heap_backward.len() as int;
match addr {
i if i >= 0 && i < flen => ctx.heap_forward[i],
i if i > -blen && i < 0 => ctx.heap_backward[-i-1],
_ => 0
}
}
fn append_zeros_and_set(arr: &mut ~[u8], numzeros: uint, val: u8) {
for _ in range(0, numzeros) {
arr.push(0);
}
arr.push(val);
}
fn heap_set(ctx: &mut Context, addr: int, val: u8) {
let flen = ctx.heap_forward.len() as int;
let blen = ctx.heap_backward.len() as int;
match addr {
i if i >= 0 && i < flen => ctx.heap_forward[i] = val,
i if i >= flen => append_zeros_and_set(&mut ctx.heap_forward, (i - flen) as uint, val),
_ => ()
}
match addr {
i if i < 0 && i > -blen => ctx.heap_backward[-i - blen] = val,
i if i <= -blen => append_zeros_and_set(&mut ctx.heap_backward, (blen - i) as uint, val),
_ => ()
}
}
fn push(ctx: &mut Context, start: uint) -> uint {
ctx.stack.push(start);
0
}
fn pop(ctx: &mut Context, end: uint) -> uint {
let start = ctx.stack.pop();
match ctx.program[start] {
Begin(_) => ctx.program[start] = Begin(end),
_ => ()
}
start
}
fn parse_token(ctx: &mut Context, symbol: char) -> Token {
match symbol {
'+' => Add,
'-' => Sub,
'>' => Inc,
'<' => Dec,
'.' => Out,
',' => In,
'[' => Begin(push(ctx, ctx.pc)),
']' => End(pop(ctx, ctx.pc)),
_ => Nil
}
}
fn parse_program(ctx: &mut Context, source: &str) {
for ch in source.iter() {
let tok = parse_token(ctx, ch);
ctx.program.push(tok);
ctx.pc += 1;
}
}
fn exec_program(ctx: &mut Context) {
ctx.pc = 0;
loop {
if ctx.pc >= ctx.program.len() {
break;
}
let tok = ctx.program[ctx.pc];
//println(fmt!("pc: %u, cl: %i, sp: %u, in: %?", ctx.pc, ctx.cell, ctx.sp, tok));
match tok {
Add => {
let val = heap_get(ctx, ctx.cell) + 1;
heap_set(ctx, ctx.cell, val)
},
Sub => {
let val = heap_get(ctx, ctx.cell) - 1;
heap_set(ctx, ctx.cell, val)
},
Inc => ctx.cell += 1,
Dec => ctx.cell -= 1,
Out => io::stdout().write_u8(heap_get(ctx, ctx.cell)),
In => heap_set(ctx, ctx.cell, io::stdin().read_u8()),
Begin(x) => if heap_get(ctx, ctx.cell) == 0 {ctx.pc = x;},
End(x) => if heap_get(ctx, ctx.cell) != 0 {ctx.pc = x;},
_ => ()
}
ctx.pc += 1;
}
}
fn main() {
let prog = str::from_bytes(io::stdin().read_whole_stream());
let mut ctx = Context {program: ~[], pc: 0, cell: 0, stack: ~[], sp: 0, heap_forward: ~[], heap_backward: ~[]};
parse_program(&mut ctx, prog);
exec_program(&mut ctx);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment