One of the courses I’m taking this term is CS241 (Foundations of Sequential Programs). This course begins with MIPS assembly, then moves on to lexing and parsing, and eventually cumulates in writing a compiler for a subset of C down to MIPS assembly.
As I wrote my compiler, tediously coding one typechecking rule after another, my mind wandered. There used to be a time when things were simpler, the time when I tried to create my own programming language.
I was 14 back then, still in middle school, having just learned how to program in Java. Rather than going outside and kicking a ball like other kids my age, I, being a true nerd, stayed at home and tinkered with programming languages. The name of the language was BALL, short for “BaiSoft All-purpose List-oriented Language”. It was my first ever “major” programming project.
As you can imagine, my attempt was not quite the next GCC-killer. I knew nothing about compilers, none of the theory of using finite state automatons to scan input into tokens and so on. I used the little I did know, but in the end I was pleased with my efforts.
The BALL Language
One of the first oddities you notice is the GUI. Yes, a graphical user interface — I decided that running programs from the command line wasn’t very cool. To run a program, you would open ball.jar and paste your program into a textbox, then hit the Run button.
When you hit the Run button, your output would appear on a console window which conveniently pops up on the right:
The language itself was essentially a glorified form of assembly. A program consisted of a list of “instructions”, each of which was one line. My language supported two types of variables: string and integer. The only form of control flow was an unconditional jump and a conditional jump.
You are allowed 200 string variables and 300 integer variables. Whenever you use a variable, you have to tell the interpreter what type it is: you write #x if x is a number and &x if x is a string.
String literals were not enclosed by double quotations, rather, they are placed directly into the code. If you want a space character, you write *s.
Some other oddities (questionable design decisions?):
- A keyword to redefine other keywords. Done primarily to obfuscate code and confuse readers.
- A keyword to delay the program by n milliseconds. I still remember debugging a bug where the whole UI became unresponsive when a delay was used (you aren’t allowed to sleep on the UI thread in Java). That was my first taste of multithreaded programming.
- A keyword to emit a beep. I have no idea.
A typical program looks like this:
new number rep 0 write Input *s A *s Number. *n input #rep new number counter 0 hereis repeat set #counter #counter + 1 write #counter *n delay 30 if #counter < #rep repeat
This program asks the user for a number, then counts up to that number.
Examples of BALL
Here is the original manual for BALL, written in 2008. It contains a number of example programs, here are a few:
Prime number generator:
Double buffered animation:
Surprisingly the original website itself is still up. I wonder how long it will remain so.
Just from running the executable, it seems that the program, although quirky, mostly works. Only when digging through the old source code do I realize what a mess the whole thing was.
The string syntax for example. The first step in decoding an instruction was to tokenize it by the space character, so print “Hello World” would tokenize to [print,”Hello,World”]. Of course, this loses all the whitespace characters in the string literal. My solution? Use *s for space, so the tokenized list is [print,Hello,*s,World] and everything works out.
It’s often said that a programmer should always hate his old code, as that’s a sign that he’s improving. I still haven’t mastered programming, but I’ve definitely improved since I started back in eighth grade.