As is usual in modern programming languages Algol 68 supports an infinity of user defined modes, which are derived from the primitive modes *. There are two ways a programmer could shoot herself in the foot while defining modes:
The first problem arises in modes that somehow include themselves. This can happen both directly, when a structure mode has a field of its own mode, or indirectly like in the following example:
mode thunk = struct (int content, thunk_extra extra); mode thunk_extra = struct (char ext code, thunk extra thunk);
The second problem is more difficult to find in practice. The following rather artificial example is taken from II:
mode itself = ref itself; ref itself who = loc itself;
If some particular mode is free of these problems, it is said that the mode is well formed.
Note how the root cause of non-well formed modes is in all cases some
sort of recursion. Structural recursion can be avoided by what is
known as shielding: a ref
or a proc
“shields” the referred or procedured mode that follows from causing
recursion. For example, the following mode is well formed and
actually quite useful:
mode tree node = struct (int data, ref tree node left, right);
The well-formedness of modes can always be detected at compile-time using a method known as the ying-yang algorithm that is specified in the Revised Report as a predicate grammar (see below).
[RR 7.1.1.A]:
A) PREF :: procedure yielding ; REF to.
[RR 7.4.1.a:d]:
a) WHETHER (NOTION) shields SAFE to SAFE: where (NOTION) is (PLAIN) or (NOTION) is (FLEXETY ROWS of) or (NOTION) is (union of) or (NOTION) is (void), WHETHER true. b) WHETHER (PREF) shields SAFE to yin SAFE: WHETHER true. c) WHETHER (structured with) sheilds SAFE to yang SAFE: WHETHER true. d) WHETHER (procedure with) shields SAFE to ying yang SAFE: WHETHER true.