Quaternaries are assignments, routine denotations, identity
relations and SKIP
. Of the four, the
assignment is the most common. An assignment
consists of three parts. The left-hand side must be a
tertiary. It is usually an applied
identifier or, less commonly, an enclosed
clause. Its value must be a
name. Its context is soft, so
no dereferencing is allowed unless a cast is used
(see the next chapter), but deproceduring is
allowed. The second part is the assignment token.
The right-hand side (the third part) can be any quaternary (including,
of course, another assignment). Its context is
strong so any coercion is permitted. The mode of
its value must contain one less REF
than the mode of the
left-hand side.
The right-hand side of an assignment is, most commonly, a formula which is a tertiary (all tertiaries are quaternaries, but not vice-versa). The left-hand side can also be a formula provided that the value yielded is a name (which is the case with the assigning operators--see section 5.1.2). If an assignment is to be used as a primary, a secondary or a tertiary, then it must be enclosed in parentheses(or BEGIN and END). The value of an assignment is the value of the left-hand side: that is, it is a name. Assignments were discussed in chapter 5.
Routine denotations were discussed in chapter 6.
SKIP yields an undefined value of any mode and can only occur in a strong context. It is particularly useful in the following case. Consider the procedure
PROC p=(REAL a,b)REAL: IF b=0 THEN print(("Division by zero",newline)): stop; SKIP ELSE a/b FI
Because the yield has mode REAL
, and the
ELSE
part of the conditional clause yields a value of
mode REAL
, by the principle of
balancing (see below) the THEN
part
also must yield a value of mode REAL
. Now the construct
stop
yields a value of mode VOID
which
cannot be coerced to REAL
in any context. If the
procedure is going to compile successfully, the THEN
part
must yield REAL
(or, at least, a value which can be
coerced to REAL
in the context of the body of the
procedure which is strong) even though the value yielded will never be
used (because the stop
will terminate the program). The
SKIP
will yield an undefined value of mode
REAL
. Although SKIP
must occur in a strong
context, it cannot be coerced.
Another use for SKIP
is in row- or
structure-displays where not all the units are
known at the time of a declaration. For example:
[3]INT ii:=(4,?,5)
Before the multiple ii
is used, the second element
should be given a value. If no such value is assigned, and you try to
print the value of ii[2]
the a68toc
compiler will generate code which will print whatever value was there
at the time the multiple was generated, which may well be rubbish.
The identity relation is discussed in the next chapter, but its grammar has important consequences. The identity relation consists of two tertiaries separated by an identity relator (one of :=: or :/=:). Since a formula is a tertiary, it can safely be included in an identity relation. For example, given the declarations
INT x:=3, y:=1; PROC x or y = (REAL r)REF INT: (r<0.5|x|y)
the identity relation
x or y(random) :=: x
is legal. However, if you want to include an identity relation in a formula then you must surround it with parentheses to make it into a tertiary, as in
IF (x or y(random) :=: x) AND x*y > 0 THEN
Since one side of an identity relation is in a soft
context while the other is in a strong
context, only one side of an identity relation can
be strongly-dereferenced. The soft side can be weakly-dereferenced
which means that one REF
will always be left on that
side. Balancing applies to identity
relations (see the discussion in
section 11.6).
This completes the general discussion of units.
3.5 * (a - 2 * x)
p OR q AND a = 4
sin(x)
a[3,2:4]
x:=(c<"e"|2.4|-y)
(i|x,y,z):=(p|2|-4)
PAR(x:=1.2,y:=3.6)
Sian Mountbatten 2012-01-19