#[std] #[memory(1024)] // // A brainfuck interpreter written in Oak // // Copy a char array fn strcpy(dst: &char, src: &char) { for (let i=0; src[i] != '\0'; i=i+1) { dst[i] = src[i]; } dst[i] = 0; } // Get the length of a char array fn strlen(str: &char) -> num { for (let i=0; str[i] != '\0'; i=i+1) {} return i } const EOF = -1; const MAX_LOOP_DEPTH = 32; const TAPE_SIZE = 128; const MACHINE = 6; struct Machine { let jmp_stack: &num, jmp_counter: num, val_ptr: num, ins_ptr: num, tape: &num, code: &char; fn new(source_code: &char) -> Machine { let jmp_stack = alloc(MAX_LOOP_DEPTH) as # let jmp_counter = 0; let val_ptr = 0; let ins_ptr = 0; let code = alloc(strlen(source_code)) as &char; strcpy(code, source_code); let tape = alloc(TAPE_SIZE) as # return [ jmp_stack, jmp_counter, val_ptr, ins_ptr, tape, code ]; } fn token(self: &Machine) -> &char { return self->code + self->ins_ptr } fn plus(self: &Machine) { self->val = self->val + 1 } fn minus(self: &Machine) { self->val = self->val - 1 } fn left(self: &Machine) { self->val_ptr = self->val_ptr - 1 } fn right(self: &Machine) { self->val_ptr = self->val_ptr + 1 } fn input(self: &Machine) { self->val = get_char() } fn out(self: &Machine) { if self->val != EOF { putchar((self->val) as char) } } fn val(self: &Machine) -> &num { return self->tape + self->val_ptr } fn loop(self: &Machine) { (self->jmp_stack)[self->jmp_counter] = self->ins_ptr; self->jmp_counter = self->jmp_counter + 1; } fn end(self: &Machine) { if self->val != 0.0 { self->jmp_counter = self->jmp_counter - 1; self->ins_ptr = (self->jmp_stack)[self->jmp_counter]; (self->jmp_stack)[self->jmp_counter] = 0; } else { self->jmp_counter = self->jmp_counter - 1; (self->jmp_stack)[self->jmp_counter] = 0; self->ins_ptr = self->ins_ptr + 1; } } fn dump(self: &Machine) { putstrln(self->code); for i in 0..self->ins_ptr { putchar(' '); } putcharln('^'); putchar('['); for i in 0..TAPE_SIZE { putchar(' '); putnum((self->tape)[i]); } putstr(" ]\n "); for i in 0..self->val_ptr { putstr(" "); } putcharln('^'); } fn run(self: &Machine) { while self->ins_ptr != strlen(self->code) { if self->token == '+' { self.plus() } if self->token == '-' { self.minus() } if self->token == '<' { self.left() } if self->token == '>' { self.right() } if self->token == ',' { self.input() } if self->token == '.' { self.out() } if self->token == '[' { self.loop() } if self->token == ']' { self.end() } else { self->ins_ptr = self->ins_ptr + 1; } } } fn drop(self: &Machine) { free self->jmp_stack: MAX_LOOP_DEPTH; free self->code: strlen(self->code); free self->tape: TAPE_SIZE; } } fn main() { let m: Machine = Machine::new( "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++." ); m.run(); m.dump(); m.drop(); }