In section 6.1, it was
pointed out that the context of a routine
denotation is passed on to the last unit in the
denotation. In the example given, the body of the routine denotation
was a closed clause. The yield
of the routine was a value of mode INT
, but the yield of
the last unit was a name with mode REF INT
. Since the
context of the body of a routine denotation is strong, the name is
dereferenced to get an INT
. This principle is applicable
to all enclosed clauses.
Now conditional clauses, case clauses and conformity clauses can yield one of a number of units, and so it is quite possible for the units to yield different values of different modes. The principle of balancing allows the context of all these units, except one, to be promoted to strong whatever the context of the enclosed clause. Balancing is also invoked for identity relations which are dealt with in the next chapter.
Considering, for example, the formula
x * (a > 0|3.0|2)
the context of the conditional clause is firm which means that widening
is not allowed. Without balancing, the conditional clause could yield a
REAL
or an INT
. In this example, the principle of
balancing would promote the context of the INT
to strong and
widen it to REAL
. Balancing thus means “making the modes the
same”.
In a balanced clause, one of the yielded units is in the context of the whole clause and all the others are in a strong context, irrespective of the actual context of the clause. Here is an example of a balanced case clause
INT i:=3,j:=4,a:=2; PROC ij = REF INT: (random < 0.5|i|j); print(2 + (a|i,ij|random))
where the a
yields an INT
in a meek
context (that of the enquiry clause). In this
example, the modes of the values that can be yielded by the case
clause are REF INT
(i
), PROC REF
INT
(ij
) and PROC REAL
(random
). In a firm context, the modes become
INT
, INT
and REAL
. Thus the
context of random
is taken to be firm, and the context of
i
and ij
is promoted to strong and they are
both dereferenced and widened to REAL
. The result is
that the case clause will yield a REAL
value even though
the clause as a whole is in a firm context (it is an operand of the
operator +
).
If instead, we had
PROC REAL r:=random; (a|i,ij|j):=ENTIER r
using the declaration of ij
in the previous example,
then balancing would not be needed to produce the required mode. The
modes of the yielded units are REF INT
, PROC
REF
INT
and REF INT
respectively. In a soft context, these modes would
yield REF INT
(no dereferencing allowed), REF
INT
(deproceduring is allowed) and REF INT
. Thus
the case clause would yield REF INT
on the left-hand side
of the assignment.
Here is an example of a conditional clause which cannot be balanced:
INT i:=2, REAL a:=3.0; (random > 0.5|i|r):=random
In this case, the two parts of the conditional clause yield
REF INT
and REF REAL
. There is no coercion
which will convert a REF INT
into a REF
REAL
. When you try to compile this, the
a68toc compiler gives the following error
message:
lhs of assignment must be a reference
The balancing means that one of the yields is in a strong context and so is dereferenced which yields a value which is not a name.
The method of determining whether balancing is possible is as follows:
INT i,j, REAL a,b:=random; PROC ij = REF INT: (b>0.5|i|j); PROC r = REAL: random * random; UNION(INT,REAL) ri:=(random>0.6|i|b)Ans
a:=2.0*(random<0.3|i|b)
(j<2|ij|b):=r
a:=((ri|(INT r):r,(REAL r):r)<1|2|3)
b:=2.0*(j>3|4|SKIP)
Sian Mountbatten 2012-01-19