A procedure is either `NIL`

or a triple consisting of:

- the body, which is a statement,
- the signature, which specifies the procedure's formal arguments, result type, and raises set (the set of exceptions that the procedure can raise),
- the environment, which is the scope with respect to which variable names in the body will be interpreted.

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:

TYPE T = PROCEDURE sigwhere

`sig`

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

- Each
`formal_`

is a formal parameter declaration, as described below. `R`

is the result type, which can be any type but an open array type. The ```: R`

'' can be omitted, making the signature that of a proper procedure.`S`

is the raises set, which is either an explicit set of exceptions with the syntax`{E_1, ..., E_n}`

, or the symbol`ANY`

representing the set of all exceptions. If ```RAISES S`

'' is omitted, ```RAISES {}`

'' is assumed.

A formal parameter declaration has the form

Mode Name: Type := Defaultwhere

`Mode`

is a parameter mode, which can be`VALUE`

,`VAR`

, or`READONLY`

. If`Mode`

is omitted, it defaults to`VALUE`

.`Name`

is an identifier that names the parameter. The parameter names must be distinct.`Type`

is the type of the parameter.`Default`

is a constant expression, the default value for the parameter. If`Mode`

is`VAR`

, ```:= Default`

'' must be omitted, otherwise either ```:= Default`

'' or ```: Type`

'' can be omitted, but not both. If`Type`

is omitted, it is taken to be the type of`Default`

. If both are present, the value of`Default`

must be a member of`Type`

.

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 := Defaultis shorthand for:

Mode v_1: Type := Default; ...; Mode v_n: Type := DefaultThis 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:

- They have the same number of parameters, and corresponding parameters have the same type and mode.
- They have the same result type, or neither has a result type.
- The raises set of
`signature_1`

contains the raises set of`signature_2`

.

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") = BEGIN 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:

TYPE 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:

TYPE T = PROCEDURE (): (PROCEDURE ()) RAISES {}

m3-support@elego.de