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.

Sian Mountbatten 2012-01-19