Previous Table of Contents Next


11.9. 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 because the garbage collector probably will not trace them through u.

11.10. Required Interfaces

There are several fundamental interfaces that every Modula-3 implementation must provide:

  Text provides operations on text strings.
  Thread provides synchronization primitives for multiple threads of control.
  Word provides operations on unsigned words.
  Real, LongReal, and ExtendedReal define the properties of the three floating-point types—for example, their bases and ranges.
  RealFloat, LongFloat, and ExtendedFloat provide numerical operations related to the floating-point representation—for example, extracting the exponent of a number.
  FloatMode provides operations for testing (and possibly setting) the behavior of the implementation in response to numeric conditions—for example, overflow.

Implementations are free to extend the required interfaces, provided they do not invalidate clients of the unextended interfaces.

Most Modula-3 implementations provide many other interfaces. A few that are recommended to other implementers, but not required are

  Fmt and Lex provide for textual formatting and scanning of numbers and other data.
  Pickle provides type-safe persistent storage via binary files called pickles.
  Table provides generic hash tables.

The interfaces in this section are included verbatim as a Modula-3 program in a literate-programming style. Each call in the interface is followed by a description of the call.

See http://www.research.digital.com/SRC/modula-3/html or http://www.m3.org/ for other standard interfaces.


Previous Table of Contents Next