Subsections

Balancing

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:

  1. Determine the context of the choice clause.
  2. In the context found in step 1, determine the mode yielded by each unit in the choice clause.
  3. If there is a mode such that all the modes but that one can be strongly coerced to that mode, the clause can be balanced.

Exercises

10.12
In each of the following clauses, state whether balancing is possible, and if so, the mode yielded by the balanced clause. These declarations are in force:
   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)
a:=2.0*(random<0.3|i|b)

(b)
(j<2|ij|b):=r

(c)
a:=((ri|(INT r):r,(REAL r):r)<1|2|3)

(d)
b:=2.0*(j>3|4|SKIP)


Sian Mountbatten 2012-01-19