Sometimes it is desirable that a name of mode REF
REF
whatever
should not refer to a definite
name (see, for example, the discussion of queues below). This can be
arranged by making it refer to NIL which
is the only denotation of a name. The mode of NIL
is
REF whatever
. For example, consider
REF[]CHAR rc=NIL; REF INT ri=NIL
The first NIL
has the mode REF[]CHAR
and the second has
the mode REF INT
.
Given the declaration
REF INT xx:=NIL
the mode of NIL
is REF INT
. However, although
NIL
is a name, you cannot assign to it. That is, the
assignment
REF INT(xx):=4
would cause the run-time error
Segmentation fault
and, possibly, a memory dump, when using the a68toc compiler.
Nor can you use NIL
in a formula if that would involve
dereferencing. The only use of NIL
is for determining,
by using an identity relation, that a name refers to it. However, we
shall see in the sections on queues and trees that this is a vital
function.
Now consider the declaration
REF REF INT rrri;
where the mode of rrri
is REF REF REF INT
. We could make
rrri
refer to NIL
directly using the
assignment
rrri:=NIL
whence the mode of NIL
is REF REF INT
. Or
we could use a NIL
of mode REF INT
by using
an anonymous name:
rrri:=LOC REF INT:=NIL
whence the mode of the anonymous name is REF REF INT
.
In the identity relation
rrri IS NIL
how can we tell which NIL
is in use? Of course, we
could use a cast for rrri
, but there is a simpler and
more useful way. Firstly we declare
REF INT nil ri = NIL
then balancing will ensure that the identity relation
rrri IS nil ri
gives the required answer with rrri
being dereferenced
twice. Alternatively, with the declaration
REF REF INT nil rri = NIL
we can ensure that the identity relation
rrri IS nil rri
will also be elaborated correctly. We shall see in the sections on
queues and trees that the declaration of nil ri
is more
useful.
Now consider the declarations
INT x:=ENTIER(random * 6), y; REF INT xx,yy; PROC x or y = REF INT: (random>0.8|x|y)
and the identity relation
CASE randint(3) IN xx,x or y, NIL ESAC IS CASE y IN x, SKIP, yy ESAC
The balancing of the identity relation includes balancing of the case clauses. The modes yielded are
xx |
REF REF INT |
|
x or y |
PROC REF INT |
|
NIL |
REF whatever |
|
x |
REF INT |
|
SKIP |
who knows? | |
yy |
REF REF INT
|
REF REF INT |
|
REF INT |
|
REF whatever |
|
REF INT |
|
who knows? | |
REF REF INT
|
Thus the left-hand side is the soft context and the right-hand side
(of the identity relation) is the strong context (remember that
SKIP
is only allowed in a strong context), and the final
modes are all REF INT
. In practice, it is rare that
identity relations are so complicated.
FILE f1:=stand in, f2; REF FILE cur file:=f2; PROC p = REF FILE: (cur file IS f1|f1|f2)what is the value of Ans
cur file:=f2
cur file :/=: stand in
p:=f1
p:=:f1
NIL
in Anscur file:=NIL
REF REF FILE ff:=NIL
Sian Mountbatten 2012-01-19