Sometimes it is desirable to have more than one possible end-point
of a serial clause. This often happens when a loop needs to be
prematurely terminated so that a surrounding serial clause can yield a
value which is unexpected. A completer is
so-called because it provides a completion point for a serial
clause. A completer can be placed wherever a
semicolon (the go-on symbol) can appear except in
enquiry clauses (whether BOOL enquiry clauses or INT enquiry clauses).
It consists of the construct EXIT followed
by a label and a colon (:
). A
label is formed with the same rules as for an identifier and should
not be the same as any identifier in the current
range. Here is an example of a completer:
EXIT label:
The label must be referenced by a GOTO clause within the same serial clause in which the completer occurs, or in an inner clause (not necessarily serial). Here is an example of such a completer:
a:=(INT i; read((i,newline)); IF i < 0 THEN GOTO negative FI; sqrt(i) EXIT negative: sqrt(-i) )
The example is artificial, but serves to illustrate the use of a completer.
A completer can sometimes save the declaration of a boolean name. For example, here is a procedure without a completer:
PROC is in str = (STRING t, CHAR c)BOOL: ( BOOL found := FALSE; FOR n FROM LWB t TO UPB t WHILE ~found DO found:=c = t[n] OD; found );
Here is the procedure with a completer:
PROC is in str = (STRING t,CHAR c)BOOL: ( FOR n FROM LWB t TO UPB t DO IF c = t[n] THEN GOTO found OD; FALSE EXIT found: TRUE )
In fact, GOTO
clauses are valid almost anywhere in
Algol 68. They are particularly useful when it is required to
jump out of nested clauses. Let us reconsider the program
echo
in
section 9.5.1 with a
GOTO
clause:
PROGRAM echo CONTEXT VOID USE standard BEGIN FILE args; IF open(args,"",arg channel)/=0 THEN put(stand error, ("Cannot access the arguments", newline)); stop ELSE FILE ff:=args; on logical file end( ff, (REF FILE f)BOOL: close(f); GOTO end; FALSE)); DO STRING arg; get(ff,(skip terminators,arg)); print((arg,newline)) OD; end: print(("End of arguments",newline)) FI END FINISH
Use of GOTO
clauses should be confined to exceptions because
otherwise they can destroy the natural structure of your programs
making them much more difficult to understand and maintain.