I wanted to recreate Toadskin, this funny esolang that combined Brainfuck and Forth. I felt like it had a major flaw, besides being a Brainfuck. It was totally incompatible with standard Brainfuck! The original source tarball of Toadskin was really scuffed and I couldn’t really figure it out, so hacking on the source to kludge compatability in was out of the question. I emailed the developer of Toadskin about it, to see if he’d ever reapproached the project and had a funny little exchange. He told me that he’d banged it out over two days at a hotel during a conference. lol
So I set out to recreate it myself. I didn’t really know anything about interpreter design then, so it took a lot of research and I’d actually forgotten about what I set out to do until extremely recently, when I was feeling confident and driven to fill out my github a bit.
nutoad is a standard brainfuck with 8 operations for interacting with a memory array, but input is interpreted with a call-threaded virtual machine. Being call-threaded means that for every operation recieved there’s an associated instruction (implemented as a reference to a function in Lua) to be called. Threading has nothing to do with CPU threads but is a metaphor for keeping track of which instruction is to be executed next, all at machine level.
A brainfuck will typically read the input string and run code in a switch statement, more or less direct string interpretation. nutoad takes an input, breaks it into a table of single characters and reads that like a tape. The tape position is kept track of locally in each call to the ‘interpret’ function. Each operation is looked up in the dictionary and if it exists, it’s called. Otherwise, it ignores anything it doesn’t recognize, so you can program in literate style I suppose.
:AB+++; A [-] :B+++; A
In this example, a new procedure named ‘A’ is defined that increments the first memory address three times. New procedures in nutoad may only have single character identifiers. The letter B is ignored because it’s not in the dictionary. We call ‘A’ and the first memory address is incremented. We zero it with ‘[-]’ and then define a new procedure called ‘B’. calling ‘A’ again will increment the first memory address six times, because now ‘B’ exists in the dictionary, so it will be called.
I think this is really really funny. You could probably obfuscate the shit out of some brainfuck code with this. Or make a really cute quine.