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:
TYPE T = PROCEDURE sig
where sig is a signature specification, which has the form:
(formal_1; ...; formal_n): R RAISES S
where
formal_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 := Default
where
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 := 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:
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