Brainfuck to C translator written in Lua
16 May 2015Lua code translating Brainfuck to C:
local brainfuckToC_map = {
['>'] = '++ptr;',
['<'] = '--ptr;',
['+'] = '++*ptr;',
['-'] = '--*ptr;',
['.'] = 'putchar(*ptr);',
[','] = '*ptr=getchar();',
['['] = 'while (*ptr) {',
[']'] = '}',
}
local function brainfuckToC(bf_code)
local c_code = bf_code:gsub('.', function(op)
return brainfuckToC_map[op] or ''
end)
return c_code
end
local PROLOGUE = [[
#include <stdio.h>
int main() {
#define TAPE_SIZE 30000
char array[TAPE_SIZE] = {0};
char *ptr=array;
]]
local EPILOGUE = [[
return 0;
}
]]
print(PROLOGUE)
for line in io.lines() do
print(brainfuckToC(line))
end
print(EPILOGUE)
This script reads Brainfuck code from stdin and writes corresponding C code to stdout.
Let us compare the performance of code generated by the script with Brainfuck interpreter beef and Brainfsck JIT compiler from DynASM tutorial.
Download a mandelbrot set fractal viewer in Brainfuck written by Erik Bosman.
Brainfuck to C translator
Translate Brainfuck code to C using the translator:
$ lua brainfuck-to-c.lua < mandelbrot.bf > mandelbrot.c
Compile generated C code:
$ gcc mandelbrot.c -o mandelbrot.exe
Run the program:
$ time ./mandelbrot.exe
<mandelbrot set fractal here>
real 0m23.183s
user 0m23.141s
sys 0m0.004s
Add option -O3
to enable more optimizations:
$ time gcc -O3 mandelbrot.c -o mandelbrot.exe
real 0m4.796s
user 0m4.728s
sys 0m0.048s
$ time ./mandelbrot.exe
<mandelbrot set fractal here>
real 0m1.599s
user 0m1.596s
sys 0m0.000s
Brainfuck interpreter beef
$ time beef mandelbrot.bf
<mandelbrot set fractal here>
real 0m28.981s
user 0m28.886s
sys 0m0.044s
Brainfuck JIT compiler
The Brainfuck JIT compiler can be found in the DynASM tutorial.
Build the Brainfuck JIT compiler:
$ git clone https://github.com/corsix/dynasm-doc.git
$ cd dynasm-doc
$ git submodule update --init
$ gcc -o minilua luajit-2.0/src/host/minilua.c
$ ./minilua luajit-2.0/dynasm/dynasm.lua -o bf_dynasm_c.c -D X64 bf_dynasm.c
$ gcc bf_dynasm_c.c -o bf_dynasm_c.exe
Run the program:
$ time ./bf_dynasm_c.exe mandelbrot.bf
<mandelbrot set fractal here>
real 0m2.750s
user 0m2.740s
sys 0m0.004s
Conclusions
The JIT compiler’s performance of Brainfuck code execution
is comparable to the performance of C code generated from
Brainfuck code with -O3
optimizations enabled. The time of
execution of gcc -O3
(4.7 seconds) added to the time of
execution of compiled C code (1.6 seconds) exceeds the time of
execution of JIT compiler (2.7 seconds).
Obvious advantage of JIT compiler is that it doesn’t require C compiler to execute Brainfuck code. Same JIT compiler binary can execute any Brainfuck code while C compiler is needed each time to compile a C code translated from a Brainfuck code using the translator.
DynASM project is great!
Time of execution was measured on Intel(R) Core(TM) i5-3317U CPU @ 1.70GHz.