(2023-04-27) Brainfuck running in VTL-2 running in AWK. Why not? ---------------------------------------------------------------- Brainfuck is pure art. VTL-2 is pure constraint-driven engineering. Yet I couldn't find a single BF interpreter in VTL-2. Not even on the Rosetta Code. Probably because BF was created much later than VTL-2, in 1993, when almost nobody gave a damn about VTL and even about Tiny BASIC already. But now, in 2023, here it is - bf.vtl that I was able to run with lvtl.awk which in turn can run under the "busybox awk" command. I deliberately avoided using any bitwise operators in the bf.vtl code (although they might make it more efficient in some places) to make it portable to non-LVTL implementations. So, anyone who has access to any VTL-2 version should be able to pick it up from my hoi.st downloads and try it out. In case you've stumbled upon my phlog by navigating here from some unexpected place and still don't know what Brainfuck is, well, it's a programming language operating on an unbounded (although practically finite) virtual tape of integers (typically unsigned bytes from 0 to 255) that only has 8 single-character instructions and ignores any other characters as comments. In the canonical BF, these instructions are: + increment current cell - decrement current cell < move the cell pointer to the previous cell > move the cell pointer to the next cell , read a character from stdin and save its code to the current cell . write the current cell as a character to stdout [ jump past the matching ] if the cell at the pointer is 0 ] jump back to the cell after the matching [ if the cell at the pointer is non-zero That's it. These instructions (that, by the way, can be 3-bit-encoded in a straightforward manner or, for instance, remapped onto phone keypad digits, oh shit, why did I think of this...) are everything that's required to construct a Turing-complete language. Since its inception in 1993, Brainfuck gained really huge following, spawning countless variations, improvements and a whole "esoteric programming" subculture. But this very canonical variant of BF remains the most popular esolang to this very day. I think it's safe to say it's more popular now than VTL-2 itself, which is not an esolang but, as I said, a fine piece of constraint-driven engineering. Yes, I imagine that a BF interpreter for Altair machines could weigh much less than 768 bytes of VTL/VTL-2, but how useful would it be with programs that long and the RAM limit far less than the 30000 bytes of recommended minimum for BF? And that's only operating RAM (the virtual number tape size), not counting the length of the program itself. I guess, when VTL was a necessity, it was too early for something like BF to even appear on the scene. But now, when RAM is usually not a problem even for the most embedded tech, we have a perfect opportunity to explore this alternative history timeline and see how an interpreter of the most popular esoteric programming language would look when written in the tiniest non-esoteric one. That's how my first VTL-2 project began. Yes, I finally started writing something new _in_ VTL-2, not just interpreters _of_ VTL-2 in other languages. And you know what... I really like it. In fact, you get used to this weird assignment-driven syntax with strictly-LTR expressions so quickly that it might even become baffling to you how every other high-level language didn't implement this and went with more verbose expression/statement syntax modeled after BASIC. And yes, I have the guts to say VTL-2 is pretty high-level and abstracts over a lot of machine-specific stuff, although it also requires you to be precise in your line number calculations. By the way, the whole idea of using #=0 as nop is indeed very clever and provides a concise way to do all branching and loops and everything. You just need to be good at math. Now I guess that BASIC, its expression model and all its IF/ELSE/FOR/WHILE/UNTIL had been invented for those who weren't. No wonder that later BASIC generations ditched line numbering altogether. But I digress, let's go back to my BF-VTL. Just like with implementing BF in any other language, the main culprit here were the [ and ] instructions. Because, as I already had written somewhere in this phlog, I hate parentheses matching, it slows everything down, especially here where you have to do code lookahead. Because if we imagine our data as a tape, we can also imagine our BF code as another tape, and every time the corresponding condition is triggered at one of these brackets, we have to fast-forward or rewind this tape to the matching bracket, stopping at intermediate brackets to increase/decrease the tracking counter. But here, brackets and their matching are a paramount part of the language, so they had to be implemented appropriately. At first, I just wanted to use a single subroutine that would be parameterized for each of the two cases and called from the instruction subroutines. This would allow to shorten their code significantly. But then, I remembered the limitation that we only have a single ! variable that already was being used, so I had to improvise and combine these two routines into one that returned directly to the original processing loop. Nevertheless, overall bf.vtl SLOC count turned out to be under 75 lines. Not bad for such a Very Tiny Language, don't you think? Of course, when run in LVTL-W, any program in BF-VTL runs extremely slowly. Because that's a triple interpretation layer. But the point is, it runs. And runs correctly. It's a good benchmark of both AWK and VTL-2. For example, on busybox awk, I instantly got a segfault because the interpreter couldn't allocate memory for all the operations. So, with trial and error, I found out that I had to tweak the L variable in line 12 and also delete lines 13 to 18 to be able to run my Hello World. Still, on the second run, I could already see how much memory was leaking. Maybe AWK is not the right tool for the job, but it's a lot of fun. No issues on GAWK though, maybe it has proper GC. But, for some factorial code like this one... >++++++++++>>>+>+[>>>+[-[<<<<<[+<<<<<]>>[[-]>[<<+>+>-]<[>+<-]<[>+<-[>+<-[> +<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>[-]>>>>+>+<<<<<<-[>+<-]]]]]]]]]]]>[<+>- ]+>>>>>]<<<<<[<<<<<]>>>>>>>[>>>>>]++[-<<<<<]>>>>>>-]+>>>>>]<[>++<-]<<<<[<[ >+<-]<<<<]>>[->[-]++++++[<++++++++>-]>>>>]<<<<<[<[>+>+<<-]>.<<<<<]>.>>>>] ...you really want to use the compiled VTL-2 versions to run BF-VTL. By the way, from now on, all existing LVTL versions except the initial A prototype (LVTL-O, LVTL-R and LVTL-W) are distributed in a single sharball, lvtl.shar.gz, and bf.vtl is included in the examples directory of that sharball. And yes, since I already mentioned phone keypad mapping... Here's how I'd do this: + 2 - 8 < 4 > 6 , 7 . 9 [ 1 ] 3 end-of-code # run/halt 5 save *index# load 0index# One could even imagine using this for some sort of DTMF-driven programming. For now though, I want this to just remain a concept. --- Luxferre ---