Modula-3: Assignment statements

## Assignment

To specify the typechecking of assignment statements we need to define "assignable", which is a relation between types and types, between expressions and variables, and between expressions and types.

A type `T` is assignable to a type `U` if:

- `T <: U`, or
- `U <: T` and `T` is an array or a reference type other than `ADDRESS` (This restriction is lifted in unsafe modules.), or
- `T` and `U` are ordinal types with at least one member in common.

An expression `e` is assignable to a variable `v` if:

- the type of `e` is assignable to the type of `v`, and
- the value of `e` is a member of the type of `v`, is not a local procedure, and if it is an array, then it has the same shape as `v`.

The first point can be checked statically; the others generally require runtime checks. Since there is no way to determine statically whether the value of a procedure parameter is local or global, assigning a local procedure is a runtime rather than a static error.

An expression `e` is assignable to a type `T` if `e` is assignable to some variable of type `T`. (If `T` is not an open array type, this is the same as saying that `e` is assignable to any variable of type `T`.)

An assignment statement has the form:

        v := e

where `v` is a writable designator and `e` is an expression assignable to the variable designated by `v`. The statement sets `v` to the value of `e`. The order of evaluation of `v` and `e` is undefined, but `e` will be evaluated before `v` is updated. In particular, if `v` and `e` are overlapping subarrays, the assignment is performed in such a way that no element is used as a target before it is used as a source.

Examples of assignments:

        VAR
          x: REFANY;
          a: REF INTEGER;
          b: REF BOOLEAN;

        a := b;  (* static error *)
        x := a;  (* no possible error *)
        a := x   (* possible checked runtime error *)

The same comments would apply if `x` had an ordinal type with non-overlapping subranges `a` and `b`, or if `x` had an object type and `a` and `b` had incompatible subtypes. The type `ADDRESS` is treated differently from other reference types, since a runtime check cannot be performed on the assignment of raw addresses. For example:

        VAR
          x: ADDRESS;
          a: UNTRACED REF INTEGER;
          b: UNTRACED REF BOOLEAN;

        a := b;  (* static error *)
        x := a;  (* no possible error *)
        a := x   (* static error in safe modules *)

    Last modified on Wed Apr  3 09:39:12 PST 1996 by heydon
         modified on Mon Apr 18 14:00:50 PDT 1994 by kalsow