Join the discussion
Write your take first — we'll ask for email only when you're ready to publish.
- Hacker News
- Crazy work
- I'm kind of disappointed nobody writes this kind of stuff in Whitespace.by laughing_man
- Thanks for posting something interesting without uttering LLM, AI, agents, etc. I thought you're going to explain your experience doing it in CMake but then it's true to the title.by legends2k
- This is interesting. But the generated code has some weaknesses typical of projects that generate brainfuck algorithmically (whether done by humans or LLM agents).
-You're generating brainfuck through layers of abstractions. This doesn't work well, or at least nobody has done it well yet to my knowledge.
-You're also trying to define most of these abstractions in a position-agnostic way. To that end you maintain a relation where no command in your program is executed at more than one data pointer location.
-(You mention Turing-completeness, but this restriction reduces brainfuck to the power of a finite automaton)
-(It also makes massive code duplication at the brainfuck level almost inevitable)
-One consequence is that you need to move or copy values whenever you use them for anything. You've also gone a step further (also typical of these projects), and tend to give values a primary location, so they end up where they started after each operation, which means when you want to use values you're mostly making a copy, restoring the original, then using the copy and discarding it during or after. So the program spends most of its time and code moving values, copying values, zeroing copies, zeroing zeroes...
-(The pattern of zeroing cells before use is also a red flag. What was in that space before? Presumably nothing valuable, since you're comfortable zeroing it; then was it junk data left from some earlier calculation? That implies your compiler is leaving junk data scattered through the array in its wake, and doesn't remember what it left where? A bad sign. The efficient thing to do is usually, when you're using a value, save a copy if you're going to need that value again, or let it get wiped naturally during use the last time it's needed. Zero-after-use means much less explicit zeroing needed.)
I should acknowledge that many of your details look well conceived; it's just that the whole approach is (as far as I can tell) not capable of producing concise or efficient brainfuck code.
Good luck; -Daniel Cristofani
- Calling this "written in brainfuck" is like calling anything in C "written in machine code"by blanchebiche
- There have been some other attempts to build compilers that output brainfuck.
This one supports some LLVM IR instructions: https://github.com/caozhanhao/llvm-brainfuck
There's a list of others here, with asm2bf seeming the most complete: https://esolangs.org/wiki/Brainfuck_code_generation
- brainfuck is unpleasant to write directly - e.g. the language doesn't have variables, so you need to manually do the bookkeeping of which memory offset is storing what 'variable'. & if you need to refactor your program slightly, in a way that changes the memory layout, maybe you need to manually rework the absolute & relative offsets. So I can appreciate why the author didn't roll up their sleeves to directly write BF - that's neither a productive nor interesting exercise.
Interesting to see how the author decomposed the problem:
- C raytracer https://github.com/mTvare6/rayfuck/blob/master/ray.c
~~ LLM refactor of the C code ~~>
- SSA-style C raytracer code https://github.com/mTvare6/rayfuck/blob/master/ray_ssa.c
~~ c2dsl.py helper script (compiler) ~~>
- DSL raytracer https://github.com/mTvare6/rayfuck/blob/master/ray.dsl
~~ dsl2bf.py helper script (another compiler) ~~>
BF raytracer https://github.com/mTvare6/rayfuck/blob/master/ray.bf (~22 mb of unreadable nonsense)
The dsl2bf compiler has a bunch of examples of implementing slightly higher level abstractions atop BF primitives. E.g. "go" to move the pointer to a different offset, destructive & non-destructive copies, all the way up to things like division -- BF only natively offers unary addition/subtraction.
If we have a read of the code of the final compiler, dsl2bf.py, the abstractions used in that code are relatively simple: global variables, local variables, lists, dicts, for loops, function definitions & function calls. It is feasible to implement a simple compiler like dsl2bf in BF itself, with sufficient head scratching. Again, quite unpleasant to try it directly in BF, but a next step could be to implement the dsl2bf compiler in the DSL itself - extending it if necessary, then compiling it with itself to produce a dsl2bf compiler implemented in BF.
by shoo - Isn't this just a ray tracer in python/c that spits out brainfuck? By this logic gcc writes all my programs in assembly lol