Subsections

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


Sian Mountbatten 2012-01-19