2.2.8 Procedures

A procedure is either NIL or a triple consisting of:

A procedure that returns a result is called a function procedure; a procedure that does not return a result is called a proper procedure. A top-level procedure is a procedure declared in the outermost scope of a module. Any other procedure is a local procedure. A local procedure can be passed as a parameter but not assigned, since in a stack implementation a local procedure becomes invalid when the frame for the procedure containing it is popped.

A procedure constant is an identifier declared as a procedure. (As opposed to a procedure variable, which is a variable declared with a procedure type.)

A procedure type declaration has the form:

where sig is a signature specification, which has the form:
    (formal_1; ...; formal_n): R RAISES S

A formal parameter declaration has the form

    Mode Name: Type := Default

When a series of parameters share the same mode, type, and default, Name can be a list of identifiers separated by commas. Such a list is shorthand for a list in which the mode, type, and default are repeated for each identifier. That is:

    Mode v_1, ..., v_n: Type := Default
is shorthand for:
    Mode v_1: Type := Default; ...; Mode v_n: Type := Default
This shorthand is eliminated from the expanded definition of the type. The default values are included.

A procedure value P is a member of the type T if it is NIL or its signature is covered by the signature of T, where signature_1 covers signature_2 if:

The parameter names and defaults affect the type of a procedure, but not its value. For example, consider the declarations:

    PROCEDURE P(txt: TEXT := "P") =
        Wr.PutText(Stdio.stdout, txt)
      END P;

    VAR q: PROCEDURE(txt: TEXT := "Q") := P;
Now P = q is TRUE, yet P() prints ``P'' and q() prints ``Q''. The interpretation of defaulted parameters is determined by a procedure's type, not its value; the assignment q := P changes q's value, not its type.

Examples of procedure types:

      Integrand = PROCEDURE (x: REAL): REAL;
      Integrator = PROCEDURE(f: Integrand; lo, hi: REAL): REAL;

      TokenIterator = PROCEDURE(VAR t: Token) RAISES {TokenError};

      RenderProc = PROCEDURE(
        scene: REFANY;
        READONLY t: Transform := Identity)

In a procedure type, RAISES binds to the closest preceding PROCEDURE. That is, the parentheses are required in: