1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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;
}
|