diff --git a/src/misc_languages/brainf__k.md b/src/misc_languages/brainf__k.md index f00a91e..576668c 100644 --- a/src/misc_languages/brainf__k.md +++ b/src/misc_languages/brainf__k.md @@ -40,4 +40,207 @@ we currently have two implementations of the brainf##k esoteric programming lang -brainf ``` -test +### Using the Interpreter + +- We currently have a simple interpreter for brainf##k, which can be used to run brainf##k programs on the DSA architecture. +- To use the interpreter, Start the emulator binary and open the editor, then open brainf__k.dsa from the included resources/dsa/bin directory. +- The brainf##k program to run is defined as a string at the start of the file. paste the program you wish to run here, then build and load the program to use! +- Full source code for the interpreter is attached below for reference: + +```dsa +// a simple brainf##k interpreter, +// because I already wrote a compiler lol. + +include print "./lib/io/print.dsa" + +// "print hello world" +db program: "" + +db error: "Invalid Instruction!" +dw stack: 0x10000 +dw input: 0x30000 +resb data: 1024 + +// set up a stack so we can call functions +_init_stack: + ldw stack, bpr + mov bpr, spr + +start: + // load the start of the program into rg0 + lwi program, rg0 + lwi data, rg1 + + // rg0 is our instruction pointer + // rg1 is our data pointer + // rg2 is the value at the data pointer + // rg3 stores the current instruction + // rg4 is the expression nesting level. + + lli 43, rg8 // + = 43 increment + lli 45, rg9 // - = 45 decrement + lli 62, rga // > = 62 increment pointer + lli 60, rgb // < = 60 decrement pointer + lli 46, rgc // . = 46 output + lli 44, rgd // , = 44 input + lli 91, rge // [ = 91 loop start + lli 93, rgf // ] = 93 loop end + +loop_start: + // load the current instruction into rg3 + ldb rg0, rg3 + + // switch on the instruction + // all cases will return to either loop_start or loop_end + cmp rg3, rg8 + jeq increment + cmp rg3, rg9 + jeq decrement + cmp rg3, rga + jeq inc_ptr + cmp rg3, rgb + jeq dec_ptr + cmp rg3, rgc + jeq output + cmp rg3, rgd + jeq input + cmp rg3, rge + jeq expr_start + cmp rg3, rgf + jeq expr_end + cmp rg3, zero + jeq end + + // if we get here, we don't know what the instruction is + lwi error, rg2 + pusha 2 + push rg2 + call print::print + pop zero + popa 2 + +end: + hlt + +loop_end: + inc rg0 + jmp loop_start + +// ------------------------------------------ +// increment the current cell +increment: + inc rg2 + jmp loop_end + +// ------------------------------------------ +// decrement the current cell +decrement: + dec rg2 + jmp loop_end + +// ------------------------------------------ +// increment the pointer +inc_ptr: + stw rg2, rg1 + addi rg1, 4 + ldw rg1, rg2 + jmp loop_end + +// ------------------------------------------ +// decrement the pointer +dec_ptr: + stw rg2, rg1 + subi rg1, 4 + ldw rg1, rg2 + jmp loop_end + +// ------------------------------------------ +// print the byte in the current cell +output: + pusha 2 + push rg2 + call print::print_byte + pop zero + popa 2 + jmp loop_end + +// ------------------------------------------ +// read a byte into the current cell +input: + ldw input, rg2 + jmp loop_end + +// ------------------------------------------ +// handle an open bracket instruction +expr_start: + cmp rg2, zero + jne loop_end + +_traverse_right_start: + // push a register that definitely has a nonzero value + // when we pop this value from the stack + // we know we've finished traversing. + push rg8 + +_traverse_right: + inc rg0 + ldb rg0, rg3 + + cmp rg3, rge + jeq open_right + cmp rg3, rgf + jeq close_right + cmp rg3, zero + jeq end + jmp _traverse_right + +open_right: + // push zero to the stack + push zero + jmp _traverse_right + +close_right: + // check if we've reached the bottom of the stack + pop rg4 + cmp rg4, zero + jeq _traverse_right + + // go to next instruction after closing bracket + inc rg0 + jmp loop_start + +// ------------------------------------------ +// handle the close bracket instruction +expr_end: + cmp rg2, zero + jeq loop_end + +_traverse_left_start: + push rg8 +_traverse_left: + dec rg0 + ldb rg0, rg3 + + cmp rg3, rge + jeq open_left + cmp rg3, rgf + jeq close_left + cmp rg3, zero + jeq end + jmp _traverse_left + +open_left: + // check if we've reached the bottom of the stack + pop rg4 + cmp rg4, zero + jeq _traverse_left + + // go to next instruction after open bracket + inc rg0 + jmp loop_start + +close_left: + // push zero to the stack + push zero + jmp _traverse_left +```