Subsections

Coercions

There are seven coercions in the language, namely

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

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 REFs 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

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)

Sian Mountbatten 2012-01-19