Modula-3: Unsafe operations

# Unsafe operations

> There are some cases that no law can be framed to cover. ---Aristotle

The features defined in this section can potentially cause unchecked runtime errors and are thus forbidden in safe interfaces and modules.

An unchecked type transfer operation has the form:

        LOOPHOLE(e, T)

where `e` is an expression whose type is not an open array type and `T` is a type. It denotes `e`'s bit pattern interpreted as a variable or value of type `T`. It is a designator if `e` is, and is writable if `e` is. An unchecked runtime error can occur if `e`'s bit pattern is not a legal `T`, or if `e` is a designator and some legal bit pattern for `T` is not legal for `e`.

If `T` is not an open array type, `BITSIZE(e)` must equal `BITSIZE(T)`. If `T` is an open array type, its element type must not be an open array type, and `e`'s bit pattern is interpreted as an array whose length is `BITSIZE(e)` divided by `BITSIZE(`the element type of `T)`. The division must come out even.

The following operations are primarily used for address arithmetic:

                   ADR  (VAR x: Any)            : ADDRESS

         infix     +    (x: ADDRESS, y:INTEGER) : ADDRESS
         infix     -    (x: ADDRESS, y:INTEGER) : ADDRESS
         infix     -    (x,y: ADDRESS)          : INTEGER

`ADR(x)` is the address of the variable `x`. The actual argument must be a designator but need not be writable. The operations `+` and `-` treat addresses as integers. The validity of the addresses produced by these operations is implementation-dependent. For example, the address of a variable in a local procedure frame is probably valid only for the duration of the call. The address of the referent of a traced reference is probably valid only as long as traced references prevent it from being collected (and not even that long if the implementation uses a compacting collector).

In unsafe modules the `INC` and `DEC` statements apply to addresses as well as ordinals:

                   INC  (VAR x: ADDRESS; n: INTEGER := 1)
                   DEC  (VAR x: ADDRESS; n: INTEGER := 1)

These are short for `x := x + n` and `x := x - n`, except that `x` is evaluated only once.

A `DISPOSE` statement has the form:

                   DISPOSE (v)

where `v` is a writable designator whose type is not `REFANY`, `ADDRESS`, or `NULL`. If `v` is untraced, the statement frees the storage for `v`'s referent and sets `v` to `NIL`. Freeing storage to which active references remain is an unchecked runtime error. If `v` is traced, the statement is equivalent to `v := NIL`. If `v` is `NIL`, the statement is a no-op.

In unsafe interfaces and modules the definition of "assignable" for types is extended: two reference types `T` and `U` are assignable if `T <: U` or `U <: T`. The only effect of this change is to allow a value of type `ADDRESS` to be assigned to a variable of type `UNTRACED REF T`. It is an unchecked runtime error if the value does not address a variable of type `T`.

In unsafe interfaces and modules the type constructor `UNTRACED REF T` is allowed for traced as well as untraced `T`, and the fields of untraced objects can be traced. If `u` is an untraced reference to a traced variable `t`, then the validity of the traced references in `t` is implementation-dependent, since the garbage collector probably will not trace them through `u`.

    Last modified on Wed Apr  3 09:38:52 PST 1996 by heydon
         modified on Tue Jul 12 08:05:48 PDT 1994 by kalsow