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:
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.
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.
C = PROC(C)C
Sian Mountbatten 2012-01-19