Gated Lists

I think I just solved a long-open issue in BOOL regarding conditional Lists. It’s something that’s been nagging me a long time. For one thing, it’s one place that’s line-sensitive, and BOOL tries to avoid that. (Actually BOOL is very line-sensitive, but not that way.)

The other thing is that it conflated two things into one, and that’s also to be avoided. Clarity is everything, and not overloading concepts is an important part of clarity. (Orthogonality is another clarity goal that BOOL considers important.)

The background for this goes back to a BOOL primary design goal and technique.

It starts with a BOOL design goal of having a rudimentary language syntax used to build complex statements. The if-else and loop statements (for-next, while and so on) are actually standard library constructs that use this basic BOOL syntax.

(For efficiency, the BOOL standard allows standard constructs to be native to an implementation and supported at a binary level. They must function “as if” they were library functions and must be real objects in BOOL space.)

The basic syntax features a primitive List object; lists are native objects in BOOL. A basic code scope mechanism in BOOL is a list of statements (a list of executable objects). An Action is a list of such lists. Statement lists are also intended as the one true flow control mechanism, so a basic syntax requirement has always been for some kind of conditional list (what BOOL calls a “Gated List”).

It’s this bit of syntax that’s always been ugly, and which I think I’ve finally resolved!

Here’s the old syntax for a Gated List:

{=}  [ label [ expression ] ] 
.   list-statement
.   list-statement
.   etc

Here’s the new syntax for a Gated List:

{=}  [ label expression ] 
.   list-statement
.   list-statement
.   etc

The expression is no longer optional. This makes parsing the list-statement(s) not dependent on the end of the first line. A Gated List could be on one line of code:

= [foobar] expression list-statement

The reason for the optional expression was to allow for labeled Lists that weren’t gated. If you wanted just a labeled List, you had to use a gate expression that was always true.

= [foobar] true
.   etc

Which is ugly. Now you create a labeled List the same way you create a labeled anything. You use a label, and the next object gets that label.

[foobar] =
.   list-statement
.   list-statement
.   etc

Simple, it follows the prefix notation goal, and it makes labeling more orthogonal. Huge wins! This implies that the gate expression in a Gated List is the labeled object, and that is exactly correct. The presence of a labeled object as the first statement of an executable List is what signifies a Gated List. (And in more complex situations, that label identifies input arguments.)

The formal semantics of a list with a gate expression are that, when a List applies an execute message (canonically, x: or exec:), if the first object has a label, that object is sent a true: message. If the object returns TRUE, the remaining objects are sent exec: messages. If the first object returns FALSE, the other objects are ignored.

This is the one and only native BOOL flow control structure!

Which means there is, in the standard library, a BOOL Action, called @if, that is referenced by any if statement in the code. When that code runs, it calls the @if Action with the if-expression and if-list as parameters. (Or at least, the code acts “as if” it called the @if Action. At a binary level, the if code can be inline.)

The code for an @if Action might look like this:

@@if
>>  *()  if-expression
>>  *list  if-statements
.   *bool  swx
.    set: swx  t: if-expression ;;
=[if] swx
.   x: if-statements ;

Briefly, the @if Action takes two parameters: an object of unknown type, called if-expression, and a list object, called if-statements. The Action has two statement lists, an implicit list followed by an explicit list. Neither list is labeled. The first list consists of two statement objects. The first defines a new object, a *bool object, named swx. The second statement sets the value of swx to the true/false evaluation of the if-expression object.

The second list illustrates the topic of this article. The [if] label applies to the expression after, in this case just the object swx. Since this list has a labeled object as its first member, that object is considered a go/no-go value for the other objects.

In this case those other objects are just the second line of the list, an x: message sent to the if-statements list object. The end result is that the list tests the swx object to see if it returns a TRUE value and then sends the execute message to the if statements depending on the result.

Long way around, but we’ve implemented an if statement using BOOL primitive syntax. And there are several fine points to make, but those are food for another meal.

Advertisements
%d bloggers like this: