enum Op {
Inc(v),
Move(v),
Loop(ops),
Input,
Print,
}
struct Tape {
pos,
tape,
}
impl Tape {
fn new() {
Tape { pos: 0, tape: [0] }
}
fn get(self) {
self.tape[self.pos]
}
fn inc(self, x) {
self.tape[self.pos] = (self.tape[self.pos] + x) % 256;
if self.tape[self.pos] < 0 {
self.tape[self.pos] = self.tape[self.pos] + 256;
}
}
fn mov(self, x) {
self.pos += x;
while self.pos >= self.tape.len() {
self.tape.push(0);
}
}
fn set(self, v) {
self.tape[self.pos] = v;
}
}
fn run(program, tape, inputs) {
for op in program {
match op {
Op::Inc(x) => tape.inc(x),
Op::Move(x) => tape.mov(x),
Op::Loop(program) => while tape.get() != 0 {
run(program, tape, inputs);
},
Op::Print => {
let c = char::from_i64(tape.get()).expect("A valid char");
print!("{c}");
}
Op::Input => {
tape.set(0)
}
}
}
}
fn parse(it) {
let buf = Vec::new();
while let Some(c) = it.next() {
let op = match c {
'+' => Op::Inc(1),
'-' => Op::Inc(-1),
'>' => Op::Move(1),
'<' => Op::Move(-1),
'.' => Op::Print,
'[' => Op::Loop(parse(it)),
',' => Op::Input,
']' => break,
_ => continue,
};
buf.push(op);
}
buf
}
struct Program {
ops,
inputs,
}
impl Program {
fn new(code, inputs) {
Program { ops: parse(code), inputs }
}
fn run(self) {
let tape = Tape::new();
run(self.ops, tape, self.inputs);
}
}
fn bf(s, i) {
let program = Program::new(s.chars(), i);
program.run();
}
#[bench]
pub fn bf_hello_world(b) {
b.iter(
|| {
bf(
"++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.",
0,
)
},
)
}