Subsections

- Determination of well-formedness
- Exercises

# Well-formed modes

In chapter 6, the mode declaration was presented and it was pointed out that not all possible mode declarations are allowed. The rules for determining whether a mode declaration is well-formed are straightforward.

There are two reasons why a mode might not be well-formed:

1. the elaboration of a declaration using that mode would need an infinite amount of memory
2. the mode can be strongly coerced to a related mode

Let us look at some examples of modes which are not well-formed. Firstly, in the mode declaration

       MODE WRONG = STRUCT(CHAR c,WRONG w)

the `WRONG` within the `STRUCT` would expand to a further `STRUCT` and so on ad infinitum. Even this declaration

       MODE WRONGAGAIN = STRUCT(WRONGAGAIN wa)

will not work for the same reason. However, if the mode within the `STRUCT` is shielded by `REF` or `PROC`, then the mode declaration is legal:

       MODE ALRIGHT = STRUCT(CHAR c,REF ALRIGHT a);

In the declaration

       ALRIGHT ar = ("A",LOC ALRIGHT)

the second field of the structure is a name which is quite different from a structure. Likewise, the declaration

       MODE OKP = STRUCT(CHAR c,PROC OKP po)

is well-formed because in any declaration, the second field is a procedure (or a name referring to such a procedure) which is not the original structure and so does not require an infinite amount of storage. It should be noted, however, that a `UNION` does not shield the mode sufficiently. Thus, the mode declarations

       MODE MW1 = UNION(INT,MW1);
       MODE MW2 = STRUCT(UNION(CHAR,MW2) u,CHAR c)

are not well-formed. In fact, the mode declaration of `MW1` fails on reason 2 above.

Secondly, a mode which could be strongly coerced to a related mode would lead to ambiguity in coercions. Thus the mode declarations

       MODE WINT = PROC WINT;
       MODE WREF = REF WREF;
       MODE WROW = [5]WROW

are not well-formed.

All the above declarations have been recursive, but not mutually recursive. Is it possible to declare

       MODE WA = STRUCT(WB wb,INT i),
            WB = STRUCT(WA wa,CHAR c)

Again, the elaboration of declarations using either mode would require an infinite amount of storage, so the modes are not well-formed. The following pair of mode declarations are all right:

       MODE RA = STRUCT(REF RB rb,INT i),
            RB = STRUCT(PROC RA pra,CHAR c)

All non-recursive mode declarations are well-formed. It is only in recursive and mutually-recursive modes that we have to apply a test for well-formedness.

## Determination of well-formedness

In any mutually-recursive mode declarations, or any recursive mode declaration, to get from a particular mode on the left-hand side of a mode declaration to the same mode indicant written on the right-hand side of a mode declaration, it is necessary to traverse various mode constructors such as `REF`, `PROC` or `UNION`. Above each `STRUCT` or set of procedure parameters write “yang”. Above each `REF` or `PROC` write “yin”. Now trace the path from the mode in question on the left-hand side of the mode declaration until you arrive at the same mode indicant on the right-hand side. If you have at least one “yin” and at least one “yang”, the mode is well-formed.

Let us try this method on the recursive mode declarations given in this section. In the mode declaration for `WRONG`, write “yang” above the `STRUCT`. Thus to get from `WRONG` on the left to `WRONG` on the right, a single “yang” is traversed. Thus `WRONG` is not well-formed. Likewise, `WRONGAGAIN` is not well-formed. In mode `ALRIGHT`, you have to traverse a “yang” (`STRUCT`) and a “yin” (`REF`), so `ALRIGHT` is well-formed. Try it with the mode `OKP`.

Conversely, to get from `MW1` to `MW1` requires neither “yin” nor “yang”, so `MW1` is not well-formed. To get from `MW2` to `MW2`, only a `STRUCT` is traversed (the `UNION` does not count) so `MW2` is also not well-formed. Similar arguments hold for `WINT`, `WREF` and `WROW`.

Now consider the mutually-recursive mode declarations of `WA` and `WB`. At whichever mode we start, getting back to that mode means traversing two “yangs” (both `STRUCT`). Two “yangs” are all right, but there should be at least one “yin”, so the modes are not well-formed. On the other hand, from `RA` to `RA` traverses a `STRUCT` and a `REF` and, via `RB`, a `STRUCT` and a `PROC` giving “yang-yin-yang-yin”, so both `RA` and `RB` are well-formed.

Remember that if you want to declare modes which are mutually-recursive, the a68toc compiler requires that one of the modes should first be declared with a stub declaration.

## Exercises

10.13
  For each of the following mode declarations, determine whether the modes are well-formed: Ans
  (a)
    `MODE MA = INT`

  (b)
    `MODE MB = PROC(MB)VOID`

  (c)
    `MODE MC =[3,2]MC`

  (d)
    `MODE MD = STRUCT(BOOL p,MD m)`

  (e)
    `MODE ME = STRUCT(STRING s,REF ME m)`

  (f)

  (g)

  (h)

  (i)
    `C = PROC(C)C`