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 sigwhere sig is a signature specification, which has the form:
(formal_1; ...; formal_n): R RAISES Swhere
A formal parameter declaration has the form
Mode Name: Type := Defaultwhere
When a series of parameters share the same mode, type, and default, name_i 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 := 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") = 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 {}