Compilation, Bug Squashing & a Treasure Trove of Games
Saturday, 12th October 2019
Development of the Tiny BASIC compiler has been that much of a whirlwind affair that I forgot about blogging over the past couple of weeks. The code generation proved to be easy enough, once I decided to use C as a target language. Many of the BASIC statements map 1-to-1 onto C equivalents. The only complications were dealing with computed GOTOs and GOSUBs, and providing a numeric input routine more robust than C's own scanf().
Once working, I did a time trial test. On my underpowered laptop, an interpreted BASIC program can count from 1 to 100 million in about 30 seconds. The compiled program did it in about half a second, a 60x speed increase! It's difficult to think of a program one could write in TinyBASIC that could significantly benefit from such a speed. I suppose, given the lack of arrays, that game with a sizeable procedurally-generated world would benefit; since TinyBASIC lacks arrays such a game would have to regenerate a large part of the world continually as the player moves through it.
I'd intended to leave "compilation" at C code generation, and let the BASIC programmer take care of turning that C code into an executable. But standard ANSI C allows access to environment variables, so I decided to be a bit more helpful. If the BASIC programmer can provide, through a TBEXE environment variable, the command to compile a C program into an executable, then TinyBASIC can happily use it to turn a .bas file into an executable in one command.
Testing the compiler by compiling all of the sample programs revealed some nasty fatal memory errors. Squashing these bugs looked impossible till I discovered a debugging tool called "valgrind", which can run through the program and spit out some extra data about where thing are going wrong. The fatal errors were soon fixed after that.
Valgrind also uncovered a ton of memory leaks. It's not magic: valgrind will tell you where lost memory was reserved, and the path that got there, but not where the memory should have been released. Some of the errors were easily tracked. But most concerned tokens created by the tokeniser, and their path through the parser can be long and meandering as it tries to figure out which language constructs they belong to. Several hours, a night's sleep and some lateral thinking helped to track enough of them down that the six sample programs will now compile to valgrind's satisfaction.
The compiler section has been written slightly differently to the other parts of the project. It uses a more "object oriented" style of programming, though still in C. I used pointers to functions and added them to the relevant data structures so they look and act a bit more like methods in a proper object-oriented language. I tried to refactor existing parts of the project to work like this, but the resulting seg faults caused me to beat a hasty retreat. Now I know about valgrind I can probably make another attempt at that.
The project feels like it's nearing a releasable state. It just needs a bit more testing, possibly some more tidying up, and the preparation of some pre-packaged versions before I make the github repo public.
That out of the way, what about this treasure trove of games? I found that one of the people involved in the creation of Tiny BASIC, Bob Albrecht, also published a book called What to Do After you Hit Return, a collection of BASIC games in source code form. These predate Tiny BASIC and are for more advanced BASIC variants, but there are some interesting gems here ripe for conversion.