Subsections

- Deproceduring
- Dereferencing
- Weakly-dereferencing
- Uniting
- Widening
- Rowing
- Voiding
- Legal coercions
- Exercises

# Coercions

There are seven coercions in the language, namely

- voiding
- rowing
- widening
- uniting,
- deproceduring
- dereferencing
- weakly-dereferencing

Roughly speaking, the coercions can be arranged in a hierarchy within the hierarchy of contexts thus:

- Strong context
  - deproceduring
  - rowing
  - voiding
  - widening
- Firm context
  - uniting
- Meek context
  - dereferencing
- Weak context
  - weakly-dereferencing
- Soft context
  - deproceduring

The only coercion not yet met is weakly-dereferencing. However, it is useful to describe all the coercions here. Before we do so, it should be noted that one of the limitations of the language is that you cannot specify the kind of context. Thus if you have a weak context and you would like a firm context, you cannot specify it. However, in any context, you can use a cast (see the section on primaries below) which will always make a context strong and because all coercions are available in a strong context, you can use the cast to specify the mode you require.

## Deproceduring

This coercion is available in all contexts. Deproceduring is the process by which a parameterless procedure is called. For example, the procedure `random`, declared in the standard prelude as having mode `PROC REAL`, when called yields a `REAL`. We can represent the coercion by

`PROC REAL` ⇒ `REAL`

The `PROC` is “removed”, which is why it is called deproceduring.

There are occasions when the identifier of a procedure can be written without the procedure being called. In the program fragment

       PROC REAL rnd:=random

the right-hand side of the assignment requires the mode `PROC REAL` because the mode of the name identified by `rnd` is `REF` `PROC` `REAL`. Clearly, `random` is not called here.

The only possible ambiguities with deproceduring are those of assignments and casts. For example, having declared `rnd` above, the subsequent assignment

       rnd:=random;

yields a value of mode `REF PROC REAL`, because the value of an assignment is the value of the left-hand side (see section 10.8). However, the following “go-on symbol” indicates that the assignment should now be voided. It is a rule of the language that voiding takes place before deproceduring if the unit being voided is an assignment. If, however, `rnd` had been used on its own, as in

       rnd;

then it would have been dereferenced, then deprocedured and the resulting `REAL` value voided. This would ensure that any side-effects (see sections 6.1.6 and 6.2.3) would take effect.

Similarly, in the unit

       PROC REAL(rnd);

`rnd` (with mode `REF PROC REAL`) will be dereferenced, but the resulting value of mode `PROC REAL` will be voided immediately since it is clear that a `REAL` value is not required. Note that all the code examples using a go-on symbol could have been written with `END` or `FI` etc, provided that the resulting context would have resulted in voiding.

When writing a program, it is common to make mistakes11.1, and one mistake is to write the identifier of a procedure without its parameters (the primary of a call). This is not, strictly speaking, an error. At least, not a grammatical error. However, in such a case, the a68toc compiler will issue a warning:

       Proc with parameters voided,
       parameters of call forgotten perhaps

in which case the mistake should be obvious. Suppose you write the identifier of a procedure in a formula without its parameters, as in

       PROC p1 = (INT n)INT:  n**2+3;
       INT a:=4;  a:=4+p1;

then the a68toc compiler will issue the message

       op + not declared for INT and PROC (INT)INT

The error message for a procedure identifier on the right-hand side of an assignment is

       PROC (INT)INT cannot be coerced to INT

Deproceduring only occurs with parameterless procedures.

## Dereferencing

This is the process of moving from a name to the value to which it refers (which could also be a name--see chapter 11). For example, if `x` has mode `REF REAL`, then in the formula

       x * 3.5

the name `x` will be dereferenced to yield a new instance of the `REAL` referred to by `x`. The coercion can be represented by

`REF REAL` ⇒ `REAL`

If `rx` has mode `REF REF REAL` (that is, `rx` can refer to a name of mode `REF REAL`), then the formula

       rx * 3.5

will result in `rx` being dereferenced twice. In this case, the coercion could be represented as

`REF REF REAL` ⇒ `REAL`

Dereferencing is available in all contexts except soft.

When a name, such as `rx`, is dereferenced twice, new instances of both the values referred to (in the case of `rx`, the `REF REAL` and the `REAL` values) are created. However, the new instance of the `REF REAL` value is discarded after the creation of the `REAL` value. This has no effect on the elaboration of the program.

## Weakly-dereferencing

This is a variant of the dereferencing coercion in which any number of `REF`s can be removed except the last. Thus, in the case of `rx` above, weakly-dereferencing would yield a mode of `REF REAL` and could be represented by

`REF REF REAL` ⇒ `REF REAL`

This coercion is only available in weak contexts. It is particularly useful in the selection of secondaries of structure modes which contain fields whose mode starts with `REF` (see section 10.6 and chapter 11).

## Uniting

In this coercion, the mode of a value becomes a united-mode. For example, if `OO` is an operator both of whose operands are `UNION(INT,REAL)`, then in the formula

       3.0 OO -2

both operands will be united to `UNION(INT,REAL)` before the operator is elaborated. These coercions can be represented by

INT | }
REAL
| ⇒ | UNION(INT,REAL)

Uniting is available in firm and strong contexts and must precede rowing.

## Widening

In a strong context, an integer can be replaced by a real number and a real number replaced by a complex number, depending on the mode required. This can be represented by

INT | ⇒ | REAL
REAL | ⇒ | COMPL

Widening is not available in formulæ (firm contexts).

## Rowing

If, in a strong context, a multiple is required and a value is provided whose mode is the base mode of the multiple, then the value will be rowed to provide the required multiple. There are two cases to consider:

1. If the mode required is not a name and the base-mode of the multiple is the mode of the value given, then the value will be rowed to give `[]base-mode`. For example, if the required mode is `[]INT`, then the base-mode is `INT`. In the identity declaration

          []INT i = 3

   the value yielded by the right-hand side (an integer) will be rowed and the coercion can be expressed as
   `INT` ⇒ `[]INT`

   If the value given is a row mode, such as `[]INT`, then there are two possible rowings that can occur.

   1. In the identity declaration

             [,]INT a = i

      where `i` was declared above with mode `[]INT`, the coercion can be expressed as

      `[]INT` ⇒ `[,]INT`

      In this case, an extra dimension is added to the multiple.

   2. If the required mode is `[][]INT` as in

             [][]INT r = i

      then the value on the right-hand side is rowed to yield a one-dimensional multiple whose base-mode is `[]INT`. This coercion can be represented as

      `[]INT` ⇒ `[][]INT`
2. If the multiple required is a name, then a name of a non-multiple can be supplied. For example, if the value supplied is a name with mode `REF INT`, then a name with mode `REF[]INT` will be created. In this identity declaration

          REF[]INT ni = LOC INT

   the local generator yields a name with mode `REF INT` and the rowing coercion yields a name with mode `REF[]INT` and bounds `[1:1]`. The coercion can be represented by
   `REF INT` ⇒ `REF[]INT`
   The first kind of rowing could also occur. The identity-declaration

          []REF INT rri = LOC INT

   produces the coercion represented by
   `REF INT` ⇒ `[]REF INT`
   Likewise, a name of mode `REF[]INT` can be rowed to a name with mode `REF[,]INT` or a non-name with mode `[]REF[]INT`, depending on the mode required. Although `INT` has been taken as an example, any mode could have been used.

## Voiding

In a strong context, a value can be thrown away, either because the mode `VOID` is explicitly stated, as in a procedure yielding `VOID`, or because the context demands it, as in the case of a semicolon (the go-on symbol). In this case, there are two exceptions to the rule that the value yielded depends only on the context. Casts and assignments are voided after the elaboration of the unit, but all other units are subjected to the usual coercions in a strong context. The following program illustrates this:

       PROGRAM tproc CONTEXT VOID
       USE standard
       BEGIN
          PROC INT p;
          PROC pp = INT:
          (
             INT i=random int(6);
             print(i);
             i
          );
          p:=pp;
          print((" p:=pp",newline));
          pp;
          print((" pp",newline));
          p;
          print((" p",newline));
          PROC INT(p);
          print((" PROC INT(p)",newline))
       END
       FINISH

The output is

        p:=pp
                +6 pp
                +1 p
        PROC INT(p)

In the assignment `p:=pp`, the mode required on the right-hand side is `PROC INT` so `pp` is not deprocedured, and `p` is neither dereferenced nor deprocedured after the assignment has been elaborated. The cast `PROC INT(p)` is elaborated (that is, `p` is dereferenced) and then voided without the procedure `p` (or `pp`) being called.

## Legal coercions

In any context, you have a unit which has, or yields, a value of some mode; and in that context you have a mode which you need. If the value of the mode you have can be coerced to a value of the mode you need (assuming that the two modes differ), then the coercion is legal.

For example, suppose you have a value of mode `PROC` `REF` `INT` in a strong context and the mode you want is `[]COMPL`. The required mode can be got via

- deproceduring to mode `REF INT`
- dereferencing to mode `INT`
- widening to mode `REAL`
- widening to mode `COMPL`
- rowing to mode `[]COMPL`

In practice, coercions are not usually as complicated as this.

Notice that deproceduring can take place before or after dereferencing, that widening must occur before rowing and that voiding can only take place after all other coercions. For example, you cannot coerce `[]INT` to `[]REAL`.

## Exercises

10.1
  Which coercions are available in a meek context? Ans
10.2
  Which coercions are not available in a strong context? Ans
10.3
  For each of the following, state whether the given mode can be coerced to the mode to the right of the arrow: Ans
  (a)
    Weak context: `REF REF BOOL` ⇒ `REF BOOL`
  (b)
    `PROC INT` ⇒ `UNION(REAL,COMPL)`
  (c)
    Soft context: `REF PROC CHAR` ⇒ `CHAR`
  (d)
    Meek context: `PROC REF REAL` ⇒ `[]REAL`
  (e)
    Weak context: `PROC REF BOOL` ⇒ `BOOL`
  (f)
    `PROC INT` ⇒ `UNION([]INT,[]REAL)`