[top] [prev] [next]

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:

An expression e is assignable to a variable v if:

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 *)

[top] [prev] [next]