Previous Table of Contents Next


11.5.9. LOOP

A statement of the form

   LOOP S END

repeatedly executes S until it raises the exit-exception. Informally, it is like

   TRY S; S; S; ... EXCEPT exit-exception => (*skip*) END

11.5.10. EXIT

The statement

   EXIT

raises the exit-exception. An EXIT statement must be textually enclosed by a LOOP, WHILE, REPEAT, or FOR statement.

We define EXIT and RETURN in terms of exceptions in order to specify their interaction with the exception-handling statements. As a pathological example, consider the following code, which is an elaborate infinite loop:

   LOOP
     TRY
     TRY EXIT FINALLY RAISE E END
     EXCEPT
       E => (*skip*)
     END
   END

11.5.11. RETURN

A RETURN statement for a proper procedure has the form

   RETURN

The statement raises the return-exception without an argument. It is allowed only in the body of a proper procedure.

A RETURN statement for a function procedure has the form

   RETURN Expr

where Expr is an expression assignable to the result type of the procedure. The statement raises the return-exception with the argument Expr. It is allowed only in the body of a function procedure.

Failure to return a value from a function procedure is a checked runtime error.

The effect of raising the return exception is to terminate the current procedure activation. To be precise, a call on a proper procedure with body B is equivalent (after binding the arguments) to

   TRY B EXCEPT return-exception => (*skip*) END

A call on a function procedure with body B is equivalent to

   TRY
     B; (error: no returned value)
   EXCEPT
     return-exception (v) => (the result becomes v)
   END

11.5.12. IF

An IF statement has the form

   IF B1 THEN S1
   ELSIF B2 THEN S2
   ...
   ELSIF Bn THEN Sn
   ELSE S0
   END

where the Bs are boolean expressions and the Ss are statements. The ELSE S0 and each ELSIF Bi THEN Si are optional.

The statement evaluates the Bs in order until some Bi evaluates to TRUE and then executes Si. If none of the expressions evaluates to TRUE and ELSE S0 is present, S0 is executed. If none of the expressions evaluates to TRUE and ELSE S0 is absent, the statement is a no-op (except for any side effects of the Bs).

11.5.13. WHILE

If B is an expression of type BOOLEAN and S is a statement:

    WHILE B DO S END

is shorthand for

   LOOP IF B THEN S ELSE EXIT END END

11.5.14. REPEAT

If B is an expression of type BOOLEAN and S is a statement:

   REPEAT S UNTIL B

is shorthand for

   LOOP S; IF B THEN EXIT END END

11.5.15. WITH

A WITH statement has the form

   WITH id = e DO S END

where id is an identifier, e an expression, and S a statement. The statement declares id with scope S as an alias for the variable e or as a read-only name for the value e. The expression e is evaluated once at entry to the WITH statement.

The statement is like the procedure call P(e), where P is declared as

   PROCEDURE P(mode id: type of e) = BEGIN S END P;

If e is a writable designator, mode is VAR; otherwise, mode is READONLY. The only difference between the WITH statement and the call P(e) is that free variables, RETURNs, and EXITs that occur in the WITH statement are inter-preted in the context of the WITH statement, not in the context of P (see Section 11.7.3).

A single WITH can contain multiple bindings, which are evaluated sequentially. That is, WITH id1 = e1, id2 = e2, ... is equivalent to WITH id1 = e1 DO WITH id2 = e2 DO ....

11.5.16. FOR

A FOR statement has the form

   FOR id := first TO last BY step DO S END

where id is an identifier, first and last are ordinal expressions with the same base type, step is an integer-valued expression, and S is a statement. BY step is optional; if omitted, step defaults to 1.

The identifier id denotes a readonly variable whose scope is S and whose type is the common basetype of first and last.

If id is an integer, the statement steps id through the values first, first+step, first+2*step, and so on, stopping when the value of id passes last. S executes once for each value; if the sequence of values is empty, S never executes. The expressions first, last, and step are evaluated once before the loop is entered. If step is negative, the loop iterates downward.

The case in which id is an element of an enumeration is similar. In either case, the semantics are defined precisely by the following rewriting, in which T is the type of id and in which i, done, and delta stand for variables that do not occur in the FOR statement:

   VAR
     i := ORD(first); done := ORD(last); delta := step;
   BEGIN
     IF delta >= 0 THEN
       WHILE i <= done DO
         WITH id = VAL(i, T) DO S END; INC(i, delta)
       END
     ELSE
       WHILE i >= done DO
         WITH id = VAL(i, T) DO S END; INC(i, delta)
       END
     END
   END

If the upper bound of the loop is LAST(INTEGER), it should be rewritten as a WHILE loop to avoid overflow.


Previous Table of Contents Next