namespace; include rt, run; // 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; void emit(s) { let i = 0; while (s[i]) { out[n] = s[i]; n++; i++; } return; } void emitn(int v) { if (v >= 10) emitn(v / 10); out[n] = '0' + v % 10; n++; return; } // 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("rt.put_c(t[p]);\n"); case ',': emit("t[p] = rt.eof() ? 0 : rt.get_c() & 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 (!rt.eof() && k < 19999) { let c = rt.get_c(); if (c != 10) { prog[k] = c; k++; } } prog[k] = 0; if (k) src = prog; if (translate(src)) { rt.put_s("unbalanced brackets\n"); return 1; } while (out[i]) { if (out[i] == 10) lines++; i++; } rt.put_s("compiled to "); rt.put_n(lines); rt.put_s(" lines of zc, running it:\n"); run.evals(out); return 0; }