aboutsummaryrefslogtreecommitdiff
path: root/docs/history/17-o3-boundaries/code/examples/bf.zc
diff options
context:
space:
mode:
Diffstat (limited to 'docs/history/17-o3-boundaries/code/examples/bf.zc')
-rw-r--r--docs/history/17-o3-boundaries/code/examples/bf.zc50
1 files changed, 50 insertions, 0 deletions
diff --git a/docs/history/17-o3-boundaries/code/examples/bf.zc b/docs/history/17-o3-boundaries/code/examples/bf.zc
new file mode 100644
index 0000000..384025a
--- /dev/null
+++ b/docs/history/17-o3-boundaries/code/examples/bf.zc
@@ -0,0 +1,50 @@
+// a brainfuck compiler. it turns a brainfuck program into zc source, hands
+// that to the compiler that's sitting in memory, and runs the result, which on
+// arm64 means native code. runs of + - < > fold into one statement each.
+// give it a program after a backtick, or it runs the hello world below.
+let out[30000], n, depth;
+fn emit(s) { let i = 0; while (s[i]) { out[n] = s[i]; n++; i++; } return 0; }
+fn emitn(int v) { if (v >= 10) emitn(v / 10); out[n] = '0' + v % 10; n++; return 0; }
+// how many times does c repeat from s[i]
+int run(s, int i, int c) { int k = 0; while (s[i + k] == c) k++; return k; }
+
+fn translate(s)
+{
+ int i = 0, k;
+ n = 0; depth = 0;
+ emit("let t[30000], p = 0;\n");
+ while (s[i]) {
+ switch (s[i]) {
+ case '+', '-':
+ k = run(s, i, s[i]);
+ emit("t[p] = (t[p] "); emit(s[i] == '+' ? "+ " : "- "); emitn(k); emit(") & 255;\n");
+ i = i + k; continue;
+ case '>', '<':
+ k = run(s, i, s[i]);
+ emit("p "); emit(s[i] == '>' ? "+= " : "-= "); emitn(k); emit(";\n");
+ i = i + k; continue;
+ case '[': emit("while (t[p]) {\n"); depth++;
+ case ']': emit("}\n"); depth--;
+ case '.': emit("putc(t[p]);\n");
+ case ',': emit("t[p] = eof() ? 0 : getc() & 255;\n");
+ }
+ i++;
+ }
+ emit("return 0;\n");
+ out[n] = 0;
+ return depth;
+}
+let hello = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.";
+let prog[20000];
+fn main()
+{
+ let src = hello, k = 0, lines = 0, i = 0;
+ while (!eof() && k < 19999) { let c = getc(); if (c != 10) { prog[k] = c; k++; } }
+ prog[k] = 0;
+ if (k) src = prog;
+ if (translate(src)) { puts("unbalanced brackets\n"); return 1; }
+ while (out[i]) { if (out[i] == 10) lines++; i++; }
+ puts("compiled to "); putn(lines); puts(" lines of zc, running it:\n");
+ evals(out);
+ return 0;
+}