<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ahineya</title>
    <description>The latest articles on DEV Community by Ahineya (@ahineya).</description>
    <link>https://dev.to/ahineya</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3465831%2F716320e6-12e9-4cb9-8c02-16c41eec27a5.jpg</url>
      <title>DEV Community: Ahineya</title>
      <link>https://dev.to/ahineya</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ahineya"/>
    <language>en</language>
    <item>
      <title>I made a professional-grade Brainfuck IDE. And used it to come closer than ever to running Doom in Brainfuck.</title>
      <dc:creator>Ahineya</dc:creator>
      <pubDate>Thu, 28 Aug 2025 17:33:07 +0000</pubDate>
      <link>https://dev.to/ahineya/i-made-a-professional-grade-brainfuck-ide-and-used-it-to-come-closer-than-ever-to-running-doom-in-4k7i</link>
      <guid>https://dev.to/ahineya/i-made-a-professional-grade-brainfuck-ide-and-used-it-to-come-closer-than-ever-to-running-doom-in-4k7i</guid>
      <description>&lt;p&gt;TL;DR: I made a Brainfuck IDE, macro language, RISC-like virtual machine in it, assembler for the VM, buggy C compiler, macro assembler, and used all of it to display Doom's titlepic — technically still in Brainfuck (and memory-mapped Brainfuck tape for IO). The IDE is live here &lt;a href="https://braintease.dev" rel="noopener noreferrer"&gt;https://braintease.dev&lt;/a&gt; with a bunch of Brainfuck, IDE, and macro language tutorials inside. And assembler.&lt;/p&gt;




&lt;p&gt;So recently I saw a video — someone made a snake in Brainfuck. It was fun, buggy, and for some reason turned the "can I do better" crank inside me. And I think I did.&lt;/p&gt;

&lt;p&gt;First, I wanted to remember how to even code in Brainfuck. I looked at currently available tooling — and was kinda disappointed. Being a professional developer and designer for the past ~20 years, I got used to nice IDEs, with debuggers, modern tooling, thought-through UI... Nothing of it existed for the Brainfuck. For some reason, companies like JetBrains do not see Brainfuck as a language worth investing into. So I did what every sane person would do in that case — I started writing my own code editor. Not the IDE — the code editor component for web, to build the IDE on top of it. Of course, I could have used Monaco, but after working with it for some time in the past, I wasn't sure that it would be easy to display a green rectangle over currently executed Brainfuck command in it.&lt;/p&gt;

&lt;p&gt;After making the editor, and tokenizer to highlight Brainfuck code in it, I added the tape visualization — to actually see what all my &lt;code&gt;+&amp;lt;[]&amp;gt;-&lt;/code&gt; do, and quickly made an interpreter v1, so I could finally execute some code. I played around, remembered how to actually use my &lt;code&gt;&amp;gt;&lt;/code&gt;, wrote some simple algos, and made a 70-line prototype of how the "fetch - decode - execute - memory - write back" pipeline may even look in Brainfuck.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2dk0ziw83j59nujtjtky.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2dk0ziw83j59nujtjtky.png" alt="Braintease IDE" width="800" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then I looked at that 70-line prototype on the next day, and understood that I have no idea how it works anymore. It was time to add some ✨abstractions✨&lt;/p&gt;

&lt;p&gt;So I extended my code editor to support a second language, and started to build this second language — basically, a macro expander on steroids, properly AST'd and parsed to support code analysis, refactoring, and non-regex code highlighting. And wrote my first &lt;code&gt;#define right(n) {repeat(n, &amp;gt;)}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As it turned out, the power to name series of &lt;code&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/code&gt; characters makes wonders on one’s ability to understand the code. Suddenly, the VM started to get shape. I still needed to solve a lot of things, like how exactly do I layout everything on a Brainfuck tape, or how the hell do I do binary operations in it. Or even “how do I emulate a random memory access in a language that is inherently sequential”. Pointers in Brainfuck, baby. And then it hit me.&lt;/p&gt;

&lt;p&gt;Lanes! I could abstract the tape itself to make it easier to work with! I believe, this technique was used previously, at least I saw it before in @dcristofani Sierpinski triangle demo. The basic idea is not to think about BF tape as about one lane, but as &lt;code&gt;[[0, 1, 2], [3, 4, 5], [6, 7, 8]]&lt;/code&gt; a bunch of grouped values. Each first value in these groups forms the first lane, each second — the second lane, and so on. While still being on the same tape, just thinking about it differently helped a lot. I dedicated one lane to registers, one lane to opcodes, two lanes as scratch lanes for ALU ops, etc. And, I was able to use a whole dedicated lane to build the trails of ones to quickly get me to the place I need to be. The pointers were solved. I quickly added the lanes visualization mode to my tape.&lt;/p&gt;

&lt;p&gt;I continued working on the VM implementation, and hit another wall — I really, really needed to stop the execution at a particular point in code, and manually step through the Brainfuck commands to make sure that I got, let’s say, a division algorithm right. So I added an ability to set breakpoints in Brainfuck code like you usually do in other programming languages — by clicking on a line number. Also, I shoved the “&lt;code&gt;$&lt;/code&gt;” symbol to be recognized by my interpreter as a code breakpoint (is this the place where I lose all the interest from Brainfuck purists, or I already lost you at “macro language”? 😁)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftm43yv6ixpc1kvwuxiq9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftm43yv6ixpc1kvwuxiq9.png" alt="Lanes View" width="800" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After this, the rest was actually easy — if you find making virtual machines easy. After all, it is just moving some numbers here and there — and Brainfuck is good at it.&lt;/p&gt;

&lt;p&gt;So I got the whole virtual machine working: I was able to execute arbitrary machine code on it by setting up tape cells to those opcodes (the story of How I Made a Turing Tarpit Less Tarpit-y). It took only around 900k Brainfuck commands! &lt;/p&gt;

&lt;p&gt;_But you know, programming in machine codes is like... Coding in Brainfuck. Hard to understand, easy to make a mistake. _&lt;/p&gt;

&lt;p&gt;And once again, I did what every sane person would do on my place — I wrote assembler and linker, so they could spit me the exact Brainfuck code, that would set those machine codes somewhere on Brainfuck tape before the virtual machine starts executing those.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;But you know, programming in assembly is like... Coding in Brainfuck. Hard to understand, easy to make a mistake.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So of course I wrote a C compiler. It actually got me into a whole bunch of another fun mini projects, like writing a test suite TUI for it. Then, when I was getting to around 50 tests, waiting for them to run on Brainfuck virtual machine was excruciating, so I wrote the same virtual machine, but in Rust, so I could debug my C compiler on it, while still being able to compile everything down to Brainfuck...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgex2utuh3g39m8loj1qq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgex2utuh3g39m8loj1qq.png" alt="TUI Debugger" width="800" height="476"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I added memory-mapped I/O to the VM, so I could not only spit ASCII, but also emulate work with the game controller, keyboard,  40x25 terminal, then RGB565-based double-buffered screen, and a tiny persistent storage r/w driver...&lt;/p&gt;

&lt;p&gt;Wrote a whole bunch of demos for all of it, starting with FizzBuzz, and Brainfuck interpreter, and ending with a working Tetris game, and Forth machine...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnhlub1gvsz9242tcbgqg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnhlub1gvsz9242tcbgqg.png" alt="Tetris in Ripple VM" width="800" height="824"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just to find out that somewhere in my C compiler lies a bug which corrupts memory, but only when the program size exceeds some particular value. And that particular value was the exact one I needed to go over to actually write a Doom .wad files parser — so I just adapted my already powerful macro language to be able to spit out assembly, and wrote the parser in macro assembly.&lt;/p&gt;

&lt;p&gt;Seeing Doom titlepic showing up in my VM was like writing some complex algorithm in Brainfuck and succeeding.&lt;/p&gt;

&lt;p&gt;And the beauty? All the programs that do not require memory-mapped IO still work in your regular Brainfuck interpreter like &lt;a href="https://copy.sh/brainfuck/" rel="noopener noreferrer"&gt;https://copy.sh/brainfuck/&lt;/a&gt; — just make sure to set cell size to 16 bits, memory size to at least a million, and memory overflow behavior to wrap.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbtkp6ok09chwgph4gjxp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbtkp6ok09chwgph4gjxp.png" alt="Full-blown IDE" width="800" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So yeah, that was a very fun ride. To give something back to the community, I put the IDE on &lt;a href="https://braintease.dev" rel="noopener noreferrer"&gt;https://braintease.dev&lt;/a&gt;, and dumped all the code on Github. Just be aware — a lot of it, and I mean A LOT of it except the VM, brainfuck, macro, and assembly code, and the code editor itself was made with a different degree of help from Claude Code, and I didn’t even care about looking in it if it was doing what I need. It allowed me to finish this in a month instead of like four that would take me to build everything by hand. And took off the boredom of writing lexer/parser/ast/transforms in like twentieth time in my life, and instead allowed me to have fun with designing the macro language and ISA, implementing the VM, and writing a whole bunch of brainfuck, macro assembly, C, and Rust.  You have been warned &lt;a href="https://github.com/ahineya/braintease" rel="noopener noreferrer"&gt;https://github.com/ahineya/braintease&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cheers everyone!&lt;/p&gt;

</description>
      <category>programming</category>
      <category>computerscience</category>
      <category>jokes</category>
      <category>architecture</category>
    </item>
  </channel>
</rss>
