Somewhere around 1990 I started designing a programming language I named BOOL (Beginner’s Object-Oriented Language). It was always a personal “ship in a bottle” project — something more for aesthetic expression than utility. Like that guy constantly working on an old car in his garage, I’ve dabbled with it ever since.
I’ve decided to, at long last, take BOOL off life support and let it die (another dead dream). But enough of dreams. I’m tired of the weight of dreams; time to shed a pointless burden. I’ve carried it for 30 years, and I think it’s time to chalk this one up to experience.
So this is a eulogy and a memorial.
[The wake lasts all week. Attendance is not required (or even particularly suggested, but fellow mourners are welcome (bring beer)). I almost posted these to my programming blog, but decided I wanted to commemorate such a notable piece of my life here.]
BOOL was never meant to be fast, elegant, graceful, expressive, powerful, or even particularly useful. It was meant to be strange. It was meant to make people wonder “Who wrote this? And why?”
It owes to both crazy “because I can” languages like Brainfuck and Malbolge and to really cool languages like Forth, Smalltalk, and Lisp. It’s basically a compost heap of favorite bits and pieces from other languages. Along with some strange contraptions from my own fevered imagination.
Back in 2013 I created a blog, Book of BOOL, as a better way to create documentation. Over the years I’d gone from Windows Write and Paint to MS Word and MS Visio, but never liked being trapped on vendor-specific (and expensive) platforms. (I did generate PDF files of the docs.) The blog seemed an ideal way to have a living document.
But WordPress upped the ad bloat on blogs without the premium plan, and three posts in 2018, three in 2016,… my mind seems to have finally tired of BOOL, so I think I’ll take down the blog soon (probably when the domain name comes up for renewal).
If I’m honest, it’s in large part because my design goals turned out to be just too much of a pain in the ass to implement. It was doable, but… complex and messy. Since one of the design goals was a simple code base, the conflict between what I wanted and what was required to accomplish it was just too great.
It’s certainly not the first time a project turned out to be untenable (or just too much of a pain to be worth the bother (having learned what there was to learn during design)).
Long ago, when I was enamored with relay-based telephone systems, I designed and began building a relay-based eight-line PBX. I had to buy boxes of 12-volt relays (still got a bunch). The individual subsystems all worked great, but my power supply wasn’t up to driving the whole system.
Ultimately it got thrown in a box, and I abandoned the project. I was already way over budget (my projects tend to expand) and didn’t really want to get into making a super beefy power supply.
I’d learned a lot and demonstrated the pieces all worked, so the design was good. Actually building it was really just work at that point. (Besides, what was I gonna do with an eight-line PBX?)
The flip side is walking away from a such large investment of self. I spent uncounted hours fiddling with BOOL over the decades. Not completely getting across the finish line is a little disappointing.
(Sadly, one of my deeper personal flaws is being a dreamer and thinker rather than a doer and go-getter. I’m one of those idea types who needed a motivated partner. Unfortunately, I never found anyone who could put up with me for any length of time.)
Anyway, about BOOL…
The main thing, as its name implies, is that it was a object-oriented language, and a primary design goal was that everything — and I mean everything (to absurd lengths) — is an object. Even program statements are objects in BOOL.
For non-programmers, object-oriented is an approach to programming that is mainly in contrast to the procedural approach (although there are many ways to approach a programming language). The programmer always writes essentially the same code to solve a given task, but how that code is structured varies depending on the approach.
The way I think of it is that object-oriented code places nouns at the highest level whereas procedural code places the verbs at the highest level. (For those with more experience, the former elevates data, the latter elevates subroutines.)
In BOOL, that noun view extends to the code itself. An IF statement (“if X do Y”) in BOOL is an object, which is taking object-orientation to the extreme. This mainly is a borrowing from Lisp.
A major goal was that statements such as IF or WHILE are not only objects, but constructable objects within the language. Out of the box, the core of BOOL offers mostly just potential and some very basic language constructs.
The idea is that, around this is a required set of objects that one could construct using the language core. Most implementations would actually implement these objects natively for speed, but they must act as if they were built using BOOL itself.
These required objects would be the language constructs such as IF and WHILE statements.
The underlying goal was that BOOL should be as minimal as possible at its core, with a wrapper of native functionality that could be expressed in BOOL. (One interesting property of a language is the extent to which it can implement itself.)
Core BOOL has only one logic construct (called a gated list) that syntactically looks like this:
=? expression . statement1 . statement2
The equals sign signifies a list. The question mark and expression indicate a gated list. (Without them, it’s just a list.) If expression evaluates to true (or non-zero), then BOOL preforms the “dotted” statements.
This is the only truly native construct. The reference implementation builds on this with various required constructs that, as mentioned, can either be natively implemented or not (the latter being inefficient and slow).
One of the required constructs is the @if action, which implements a more reasonable IF construct. It includes not only an @else clause, but also a repeatable @elseif clause, which allows compound statements.
Designing a language capable of doing that turned out to be one of the bigger hurdles. Providing the ability to implement the loop construct, such as @while, was trivial. But @if-@elseif-@else, with multiple @elseif clauses, was a real challenge.
Returning to the programming approaches, there are many terms used for the nouns (data) and verbs (code) a programmer creates.
A common term for data in object-oriented programming (OOP) is class — as in all data of a given type are instances of the same class. (In non-OOP languages data is just called data.)
In BOOL, a class is called a Model. All data are instances of some Model. The Model handles all operations on data of its type. Client code can never directly access data. (A key feature of OOP is data hiding and encapsulation.)
There is even more variation in what languages call code objects: sub-routines, procedures, functions, GOSUBs, or calls, to name a handful. In object-oriented programming, verbs are secondary and the common term is method — a class has methods that act on the instance data.
In BOOL, code objects are called Actions.
BOOL supports both generic standalone Actions (functions) and Actions that are part of a Model (methods).
For example, the @ (at-sign) means an Action, and an * (asterisk) means a Model. There are a number of others. Two of a punctuation symbol mean a definition (or declaration) where as a single means a reference to the defined thing.
For example, an *int object is an instance of a Model object named **int, and an @if object (an Actor object) invokes an Action named @@if. (Note that, in writing about BOOL, it’s rare to use the double version unless required to disambiguate meaning. For instance, normally the integer data Model is referred to as just *int.)
Which I think brings me to the point where I can show you the canonical “Hello, World!” program in BOOL. In its simplest form it looks like this:
@@main . print: "Hello, World!";
The first line defines an Action, named @main (which takes no parameters and returns nothing). This action has a single statement that consists of a print: message (the colon means message) and its target, the string “Hello, World!”
This statement sends the print: message (which is an object) to the string object, which sees it as a request to print itself.
This is one of the smallest possible viable BOOL programs. There must be an Action named @main for BOOL to run. It’s what starts things off. (Blame C for that, I think. Maybe it was one of its predecessors.)
As I said, this is a wake, and I have a week-long eulogy planned (and written, so there’s no avoiding it).
I realize none of you knew the deceased and have no reason for the slightest interest. (No need to send flowers.) I just don’t care to let it go without marking its passing, so it’s kinda of a big deal to me.
Stay boolean, my friends!