Keywords: pame

# Completers

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.