Clauses & Control Flow

A serial clause is declarations and units separated by ;; its value is that of the last unit:

28.1 Serial clauses

A serial clause is declarations and units separated by ;; its value is that of the last unit:

Rules: declarations and units can be interleaved, but no declaration may follow a label.

REAL hyp = BEGIN
              REAL a = 3, b = 4;
              sqrt(a * a + b * b)
           END;

28.2 Collateral clauses

Units separated by commas are collateral: their order of evaluation is unspecified (possibly interleaved):

A collateral clause in a strong context of a row or structure mode is a display: (1, 2, 3), (1.0, 2.0).

INT a := 1, b := 2;          # collateral declaration #
(a := 3, b := 4);            # collateral assignments: order unspecified #

28.3 Conditional clauses

FI is IF reversed; similarly ESAC, OD.

The enquiry clause (the condition) is itself a serial clause and may contain declarations: IF INT k = n MOD 7; k = 0 THEN ... FI.

Without an ELSE, the clause yields VOID (or SKIP if a value is required — avoid).

IF n < 0 THEN print("negative")
ELIF n = 0 THEN print("zero")
ELSE print("positive")
FI;

# brief form: ( condition | then-part | else-part ) and |: for ELIF #
STRING sign = (n < 0 | "negative" |: n = 0 | "zero" | "positive");

28.4 Case clauses

The integer selects the n-th unit (counting from 1); out-of-range values take the OUT part. Case clauses on unions (conformity clauses) are covered in Chapter 30.

CASE day IN
   print("Monday"),
   print("Tuesday"),
   print("Wednesday")
OUT
   print("another day")
ESAC;

# brief form #
STRING name = (day | "Mon", "Tue", "Wed" | "other");

# OUSE chains another CASE #
CASE i IN print("one"), print("two")
OUSE i - 2 IN print("three"), print("four")
OUT print("many")
ESAC

28.5 Loop clauses

The general form — every part is optional:

The loop variable (i) is an INT constant local to the loop; it cannot be assigned and does not exist after the loop.

FROM, BY and TO are evaluated once, before the loop starts (unlike ALGOL 60).

The WHILE part is a serial clause evaluated before each iteration; it may contain declarations: WHILE INT x; read(x); x /= 0 DO ... OD.

FOR i FROM 1 BY 1 TO 10 WHILE condition DO ... OD
BEGIN
   FOR i TO 5 DO print((whole(i, 0), " ")) OD;               # FROM 1 BY 1 by default #
   print(newline);
   FOR i FROM 10 BY -2 TO 0 DO print((whole(i, 0), " ")) OD;  # counting down #
   print(newline);
   TO 3 DO print("hip ") OD; print(("hooray", newline));      # no loop variable #
   INT n := 27, steps := 0;
   WHILE n /= 1 DO                                           # plain while loop #
      n := (ODD n | 3 * n + 1 | n OVER 2);
      steps +:= 1
   OD;
   print(("Collatz steps for 27: ", whole(steps, 0), newline));
   FOR i WHILE i * i < 50 DO SKIP OD;                         # FOR ... WHILE: unbounded count with a condition #
   INT k := 0;
   DO k +:= 1; IF k = 3 THEN GOTO done FI OD;                # infinite loop with a jump out #
done:
   print(("k = ", whole(k, 0), newline))
END

28.6 Jumps and labels

A jump may leave any number of enclosing clauses and procedures but may not enter one. Labelled units must come after all declarations of their serial clause. The completer EXIT ends a serial clause early with the value of the unit before it:

GOTO finish;          # or simply: finish  (GOTO is optional) #
   ...
finish: print("end")
INT category = BEGIN
                  IF x < 0 THEN GOTO negative FI;
                  1 EXIT
                  negative: -1
               END;

28.7 SKIP, EMPTY and NIL

SKIP yields an undefined value of whatever mode the context requires (useful as a placeholder).

EMPTY is the only value of mode VOID.

NIL is the null reference.