Last Word on Lists

One of the more unusual aspects of BOOL is its List notation, which is somewhat similar to how Python uses indentation for code blocks. (In fact, the List Character can be defined as the TAB character, which makes BOOL look very similar.)

This post discusses current (and presumed final) List syntax, including Gated Lists.

The original List Syntax post explains the motivation behind BOOL “dot lists” and how they’re similar to how Python uses indentation to delineate code blocks.

But the details of implicit lists and the comma operator are different than shown and discussed there. A number of the examples are now considered incorrect.

Let’s start with the simplest BOOL program possible, good ol’ “Hello, World!”

*string hello = "Hello, World!"

.   print:hello

This defines an Action, named Main, that prints the string “Hello, World!”

(The string could also be defined inside @Main, or be used directly as a literal, rather than the variable hello, but I wanted to illustrate the implicit @Global list.)

Internally, BOOL has a @System Action, which is what the run-time engine calls to execute a program. That Action initializes the run-time environment and lastly calls the internal @Global Action.

The @Global Action is a compiler-created list of all global objects defined in user code (including any imported user code). The order of the list is guaranteed only within module boundaries.

When @System calls @Global, the latter sends an X: Message to all objects on its list (which causes those object to initialize themselves). Lastly it calls the @Main Action, thus starting the user program.

Therefore, the code sample above shows two objects, both of which the compiler adds to @Global: a global string, and the @Main Action. (Because @Main is “special” the compiler puts it at the end of the list. All other objects are appended in the order found.)

The key point is that any object that occurs at the top level is actually a member of an internal (@Global) List object. All other objects are members of some other object (which might be a List or some other object).

Dot Lists

Let’s write the @Main Action a bit differently:

.   *string hello = "Hello, World!"
.   print:hello

Here, it’s the @Main Action that has two items on its list. This is indicated by the dots. Space between the dots is optional, and the dot character may be redefined to any character that doesn’t collide with existing syntax rules.

The most formal way to write it is:

=   *string hello = "Hello, World!"
.   print:hello

The difference is the equals sign (=), which is the formal List indicator.

The compiler interprets dot level change appropriately, but the List indicator is helpful in situations where a List is expected rather than an object.

Such as with object initialization lists:

.   *int x = 21
.   *int y = 42
.   *float f = 3.1415
.   *string s = "Hi there!"

Note that what may seem like an assignment operator is really a List operator. (BOOL does not have an assignment operator, as such.)

Comma Lists

A key change involves the implicit list comma operator. It no longer forces a new list but adds to the existing list. This:

.   A, B, C

Is now the same as this:

.   A
.   B
.   C

No new list is created (as shown in the original post).

It also changes this:

.   A B C

To this:

.   A

That is, a following object reverts to the lowest dot level, rather than keeping the current dot level.

Gated Lists

The original Gated Lists post is obsolete. The more recent Gated Lists (update) post remains current.

Specifically, the full List syntax is:

{<[><label><]>} <=> {<?> <expression>} <list-items>

As has been mentioned, this is the only true flow control construct in BOOL. A typical example might look something like this:

=? lt:x 0
.   set:x 0

Which tests to see if object x is less than object 0 (zero) and, if so, sets x to 0. Here’s what a loop might look like using the basic construct:

*int max = 12
*int ix = 0
=? lt:ix max
.  {{loop statements}}
.  {{loop statements}}

Which loops twelve times.

The traditional programming constructs, such as the if-else or while-loop, are defined Actions in BOOL (although they are allowed to be native).

For example, the @if Action is defined as-if:

>>  *one if_expr
>>  *any if_list
@@elif %optional %repeats
>>  *one elif_expr
>>  *any elif_list
@@else %optional
>>  *any else_list
=   *bool flag
.   set:flag t:if_expr
[if]=? flag
.   if_list
[elif]=? f:flag
.   =? t:elif_expr
.   .   elif_list
.   .   set:flag TRUE
[else]=? f:flag
.   else_list

Which shows off BOOL Gated Lists nicely! Note that the Action has four Lists: the usual default List, and three Clause Lists.

And the common while-loop is defined as-if:

>>  *one expr
>>  *any list
=? t:expr
.   list
.   [^]

The [^] object is a jump to the list top. The mirror version, the until-loop, is defined very similarly (as @until).

Truth be told, a major design goal in BOOL is exactly this: a single flow construct on which all others are defined. Its syntax was designed around the need to implement if-elif-else, which explains its convoluted approach.

%d bloggers like this: