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:
e
is assignable to the type of v
, and
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 := ewhere
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 *)
m3-support@elego.de