BOOL or Bust

This is part five of a series celebrating the passing of BOOL, the “ship in a bottle” computer language I’ve been tinkering with for three decades. It’s a design dream, and I’ve decided to wake up.

Last time I talked about how BOOL handles data and why that was such an issue. This time I’ll ramble on about some of the other snarls that ultimately made things more complicated than I wanted. Simplicity and elegance were key design goals. I intended the run-time environment, especially, to be utterly straightforward.

Unfortunately, the behavioral design goals — the way BOOL should to act at run-time — ended up in direct conflict with that.

A great deal of that came from being stubborn about an early design goal: that core BOOL should be able to implement the rest of BOOL. Specifically, that BOOL needed to implement the @if-@elseif-@else construct in BOOL.

There is a similar problematic use case with the @switch-@case-@default construct. Let me explain…

§ §

One of the key characteristics that make a programming language a programming language is something that is formally called selection and commonly the conditional. It’s the ability, at run-time, to select among multiple paths through the code (depending on conditions at the time).

The simplest example is the IF statement:

IF x=0 THEN print "Zero!"

Which prints “Zero!” only if x equals zero; otherwise it skips it.

In some languages, the syntactical THEN is implicit and some form of punctuation or keyword structure tells the computer what the parts of the statement are:

IF (x=0) {
    print "Zero!";
    print "One!";
    print "Two!";
}

Such constructs also allow for multiple things to do in the IF block. (A lot of language syntax has to do with scope and especially block scope — lines of code that group together.)

There is the more verbose:

IF x=0
BEGIN
    print "Zero!"
    print "One!"
    print "Two!"
END

The important part is the basic construct:

IF <something-is-true> (THEN) <do stuff>

As it turns out, this simple version is all a programming language needs to qualify as having selection. All other (more sophisticated) forms of selection can be implemented with just the basic IF construct.

Conversely, every programming language must have some form of IF to qualify as a programming language. (HTML, for instance, doesn’t and isn’t. (This may have changed under HTML5; I haven’t looked into it, yet.))

§

As I showed you on the first day, core BOOL has an IF construct:

=? <expression>
.   <stuff-to-do-if-expression-is-true>
.   <more-stuff-to-do-if-true>
.   <even-more-stuff-to-do-if-true>

It’s all BOOL really has to have.

Which is exactly why it’s the only logical construct in core BOOL. In a sense, it’s a BOOL “atom.”

The construct is called a gated list. You may recall that, in BOOL, an equals sign explicitly begins a list. The question mark and expression make this a gated list.

BOOL has the core ability to define new Actions (procedures). This allows for the (usually as if) definition of standard BOOL logical constructs, such as @if:

@@if
>> *one expression
>> *any statements
<< *bool flag =t:expression;
=? flag
.  statements

That defines an Action, called @if, that acts just like an IF statement. It takes two parameters, a single object (*one) and any object or list (*any).

The body of the Action uses a gated list to do the actual work. Note that the Action returns the value of the expression (the t: (true) message evaluates its target and returns TRUE or FALSE).

So far it doesn’t seem like much of an improvement. All we’ve done is change the gated list example above to:

@if <expression>
.   <stuff-to-do-if-expression-is-true>
.   <etc>

Which does seem pretty much like a wash. (It does have a formal return value now. Gated lists don’t.) It’s a little cleaner and in line with general BOOL syntax, so it’s more elegant and expressive.

The value — and the problem — is in the extensions of the IF.

§

IF <something> THEN <something> is a simple construct, and most languages go at least one step further and allow an optional ELSE clause:

IF <expression>
  THEN <stuff-done-if-true>
ELSE <stuff-done-if-false>

This provides an alternate code path for when the test expression is false.

Many languages go one more step and add a repeatable, optional ELSE-IF clause:

IF <expression1>
  THEN <stuff-done-if-expression1-is-true>
ELSEIF <expression2>
  THEN <stuff-done-if-expression2-is-true>
ELSEIF <expression3>
  THEN <stuff-done-if-expression3-is-true>
ELSE <stuff-done-if-all-are-false>

And that’s where my troubles began.

§ §

One problem is that the ELSE clause is optional. So is the ELSE-IF clause, plus it adds the additional issue of being repeatable. How does one define an Action with optional and repeatable inputs?

Note that usually this is a syntactical issue handled by the compiler. The way BOOL maps source to run-time objects requires a function-based approach.

A tactic some languages use is function overloading, where it’s possible to have multiple functions with the same name, but which take different parameters. The computer figures out which function to invoke based on what the caller sends it.

I decided long ago not to use function overloading in BOOL. It requires too much of either the compiler or the run-time environment. So overloading was out. What I needed what a syntactical way to express optional and, especially, repeatable clauses.

Here’s my solution:

@@if
>>  *one if_expr
>>  *any if_list
@@elseif %optional %repeatable
>>  *one elif_expr
>>  *any elif_list
@else %optional
>>  *any else_list
<<  *bool swx = t:if_expr;
[if]
=?  swx
.   if_list
[elseif]
=?  not:swx;
.   set:swx t:elif_expr;
.   =?  swx
.   .   elif_list
[else]
=?  not:swx;
.   else_list

This obviously needs some explaining.

§

First, BOOL allows multiple clauses in an Action definition. Each clause is followed by one or more inputs for that clause. As discussed earlier, there can be only one return parameter; it follows the clause definitions.

Second, a multi-clause Action implies a section for each clause. Labels in square brackets identify clause sections in the body of the Action. Those sections bind with the input parameters for those clauses.

Third, if a clause is flagged as %optional inputs may not exist, in which case BOOL skips that clause section.

Fourth, importantly, if a clause is flagged as %repeatable then BOOL loops that section for each matching clause found (multiple @elseif clauses, for instance).

It allows the programmer to use many forms of the @if Action:

@if eq:x 0
.   print:"Hooray!"
.   print:"X is zero."

@if eq:x 0
.   print:"Hooray!"
.   print:"X is zero."
@else
.   print:"Oops!"
.   print:"X is not zero."

@if eq:x 0
.   print:"X is zero."
@elseif eq:x 1
.   print:"X is one."
@elseif eq:x 2
.   print:"X is two."
@else
.   print:"X isn't 0,1, or 2."

In each case, BOOL invokes the same @if Action. BOOL only does the sections of that Action that bind to clauses in the Actor. (The three examples above all compile to a single @if Actor linked to the @if Action.)

For the first example, BOOL only does the [if] section. The eq: expression binds to the if_expr object, and the list of print: statements binds to the if_list object.

For the second example, BOOL does the [if] and [else] sections. In this case the second list of print: statements binds to the else_list object.

For the third example, BOOL does all three sections, and it loops the [elseif] section twice, each time binding elif_expr and elif_list to different inputs. The first time it binds to the eq:x 1 expression and the second print: statement. The second time it binds to the eq:x 2 expression and the third print: statement.

§

At the beginning I mentioned the @switch-@case-@default construct. I won’t go into detail, but it’s another logical structure with optional sections (the last two) as well as repeatable sections (the @case clause).

Suffice to say that BOOL uses this way of writing Actions to define the @switch Action and some other intricate select constructs.

Syntactically and semantically, I was pretty happy with this. It creates a great deal of flexibility in how one defines Actions.

The problem was implementing it. That,… turned into something of a Rube Goldberg machine. Actions with repeating clauses required a complicated run-time approach.

There was also a tension between Model Actions and generic Actions, because of the way message passing works.

Model Actions pull parameters off the p-stack (parameter stack; a Forth borrowing). In contrast, generic Actions are invoked by Actor objects with links to the parameters. The bottom line is two different, not entirely compatible, approaches to using Actions.

By the time I got it all working, I wasn’t at all happy with the level of complexity. The vision of a simple elegant run-time based on a basic approach to objects… just wasn’t realistic.

Between the tripartite data implementation (and the need for GC) and the complications of the Action invoking mechanism, BOOL was proving to be much more of a challenge than I’d anticipated 30 years ago.

That said, the ability to define such complex function signatures is, as far as I know, “somewhat unique” to BOOL.

§ §

I could accept the challenge, but I wasn’t up for BOOL turning into such a complicated monster. A central point was simplicity and elegance.

The truth turned out to be that implementing the features and behaviors I wanted just wasn’t possible without creating a complicated mechanism. I could have lived with the data solution (kinda liked it, in fact), but I couldn’t live with the necessary intricacies of Actions (especially the disconnect between generic Actions and Model Actions).

That was the final straw.

It was a learning experience and an intellectual whetstone. I’ve applied some of my BOOL ideas in other more productive places, so at least it wasn’t all pure recreation.

And even if it all was just for fun, we all need time to play.

Stay boolean, my friends!

About Wyrd Smythe

The canonical fool on the hill watching the sunset and the rotation of the planet and thinking what he imagines are large thoughts. View all posts by Wyrd Smythe

7 responses to “BOOL or Bust

  • Wyrd Smythe

    As it turned out: Bust. (And not the good kind, either.)

  • Wyrd Smythe

    Thanks to those few silent mourners who apparently hung in there for the whole series. I appreciate the support!

  • SelfAwarePatterns

    Hey, at least it sounds like you learned a lot with the effort! That’s always a benefit.

    This reminds me a little of Andrew Tanenbaum’s old book, Operating Systems: Design and Implementation, which I once owned and perused, mostly as a curiosity. His OS, Minix, didn’t really go anywhere, but it inspired a guy named Linus Torvalds to take his own shot at it.

    (Tanenbaum himself eventually started one of the earliest electroral projection site, and still I think the best one.)

    • Wyrd Smythe

      Learned indeed, but mostly it was play and fun (except for the frustrations). I sure learned the difference between a design and its implementation! (I didn’t even get into the challenges the syntax presents the compiler. That was another place a cool design turned out to be an implementation monster.)

      ((It’s all a bit like how when an architect designs a cool curvy building. Builders hate those. Builders prefer building things with nice straight lines and right angles. If builders had their way, rockets would be square tubes with flat ends. 🙂 ))

      Operating Systems! That can be one of those “dark arts” sectors of programming. Torvalds is certainly one of the warlocks. The BOOL/OS is another area I didn’t get into. I actually like the architecture, although admittedly it’s not designed with speed in mind. (Altho I’m not sure it would be awful, either.)

      Like BOOL, it’s message-based. If an app wants to encrypt a document, for example, it sends a message to an encryption sub-system. That message provides access to the document. The sub-system sends back a message when its done. This way apps don’t have any access to library or OS code. All they can do is send messages and make requests.

      I think I’ll leave that for a someday (if ever) post on my programming blog, though. I only ever did one My Ideal System post, years ago, and it wasn’t anything to do with BOOL. (I still think it’s a sweet idea, though.)

  • Anonymole

    Torvalds is an amazing character. Git on its own is cause enough for celebration. Linux, on the other hand is more of a great-step-child of UNIX, BSD and MINIX. But, we all stand on the shoulders of giants don’t we.
    Creating an OS from zero? Way beyond me. A language and compiler might be fun though–if I was, like 30 years old. At 60 I’ve got maybe three neurons left that work.

And what do you think?

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: