summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkdx <kikoodx@paranoici.org>2023-06-18 20:57:59 +0200
committerkdx <kikoodx@paranoici.org>2023-06-18 20:57:59 +0200
commitdd513a4fbee3c04f4b0a825198b9fe1e43dda767 (patch)
tree78dc066d1a358fba9f86c1e9fcc8b3124846282e
parent8a1646b915c7322daea5a1b74cde60e565121cfe (diff)
downloadgolem-dd513a4fbee3c04f4b0a825198b9fe1e43dda767.tar.gz
brainfuck interpreter
-rw-r--r--samples/brainfuck.golem86
1 files changed, 86 insertions, 0 deletions
diff --git a/samples/brainfuck.golem b/samples/brainfuck.golem
new file mode 100644
index 0000000..c9e5e95
--- /dev/null
+++ b/samples/brainfuck.golem
@@ -0,0 +1,86 @@
+define EOF = 0xffff;
+define BUF_SIZE = 0x4000;
+define MEM_SIZE = 0x8000; // has to be 2^x
+define MEM_MAX_PTR = MEM_SIZE - 1;
+
+global buf[BUF_SIZE] = 0;
+global pc = 0;
+
+global mem[MEM_SIZE] = 0;
+global mem_ptr = 0;
+
+main() {
+ if drain() |> ensure_match()
+ return error("[] don't match");
+ loop {
+ if ([buf + pc] == 0)
+ return;
+ getop() |> exec();
+ }
+}
+
+drain() {
+ local p = buf;
+ loop {
+ red p;
+ if ([p] == EOF | [p] == '\n') {
+ [p] = 0;
+ return buf;
+ }
+ p++;
+ }
+}
+
+ensure_match(p) {
+ local matching = 0;
+ loop {
+ if ([p] == 0)
+ return matching;
+ if ([p] == ']' & matching == 0)
+ return 1;
+ matching = matching + ([p] == '[') - ([p] == ']');
+ p++;
+ }
+}
+
+error(msg) {
+ loop {
+ if ([msg] == 0) {
+ wrt '\n';
+ return;
+ }
+ wrt [msg++];
+ }
+}
+
+getop() => [buf + pc++];
+
+exec(op)
+ if (op == '<') mem_ptr = (mem_ptr - 1) & MEM_MAX_PTR;
+ else if (op == '>') mem_ptr = (mem_ptr + 1) & MEM_MAX_PTR;
+ else if (op == '+') [mem + mem_ptr] = ([mem + mem_ptr] + 1) & 0xff;
+ else if (op == '-') [mem + mem_ptr] = ([mem + mem_ptr] - 1) & 0xff;
+ else if (op == '.') wrt [mem + mem_ptr];
+ else if (op == ',') red mem + mem_ptr;
+ else if (op == '[') => zjmpfwd();
+ else if (op == ']') => nzjmpbckwd();
+
+zjmpfwd() {
+ local matching = 1;
+ if ([mem + mem_ptr] == 0) loop {
+ matching = matching + ([buf + pc] == '[') - ([buf + pc] == ']');
+ pc++;
+ if (matching == 0)
+ return;
+ }
+}
+
+nzjmpbckwd() {
+ local matching = 0;
+ if ([mem + mem_ptr] != 0) loop {
+ pc--;
+ matching = matching + ([buf + pc] == ']') - ([buf + pc] == '[');
+ if (matching == 0)
+ return pc++;
+ }
+}