Previous | Table of Contents | Next |
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
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
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
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).
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
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
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 ....
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 |