Subsections

- Exercises

# The value `NIL`

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`

In a soft context, these modes become:

| `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.

## Exercises

11.14
  Given the declarations

         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
  (a)
    `cur file:=f2`

  (b)
    `cur file :/=: stand in`

  (c)
    `p:=f1`

  (d)
    `p:=:f1`

11.15
  Given the declarations of exercise 1, what is the mode of `NIL` in Ans
  (a)
    `cur file:=NIL`

  (b)
    `REF REF FILE ff:=NIL`