There are two kinds of procedures: proper procedures and function procedures. The latter are activated by a function designator as a constituent of an expression and yield a result that is an operand of the expression. Proper procedures are activated by a procedure call. A procedure is a function procedure if its formal parameters specify a result type. The body of a function procedure must contain a return statement which defines its result.
All constants, variables, types, and procedures declared within a procedure body are local to the procedure. Since procedures may be declared as local objects too, procedure declarations may be nested. The call of a procedure within its declaration implies recursive activation.
Objects declared in the environment of the procedure are also visible in those parts of the procedure in which they are not concealed by a locally declared object with the same name.
ProcedureDeclaration = ProcedureHeading ";" ProcedureBody ident.If a procedure declaration specifies a receiver parameter, the procedure is considered to be bound to a type (see 10.2). A forward declaration serves to allow forward references to a procedure whose actual declaration appears later in the text. The formal parameter lists of the forward declaration and the actual declaration must match (see App. A).
ProcedureHeading = PROCEDURE [Receiver] IdentDef [FormalParameters].
ProcedureBody = DeclarationSequence [BEGIN StatementSequence] END.
DeclarationSequence = {CONST {ConstantDeclaration ";"}
| TYPE {TypeDeclaration ";"}
| VAR {VariableDeclaration ";"} }
{ProcedureDeclaration ";" | ForwardDeclaration ";"}.
ForwardDeclaration = PROCEDURE " ^ " [Receiver] IdentDef [FormalParameters].
FormalParameters = "(" [FPSection {";" FPSection}] ")" [":" Qualident].
FPSection = [VAR] ident {"," ident} ":" Type.
Let Tf be the type of a formal parameter f (not an open array)
and Ta the type of the corresponding actual parameter a. For
variable parameters, Ta must be the same as Tf, or Tf
must be a record type and Ta an extension of Tf. For value
parameters, a must be assignment compatible with f (see App. A).
If Tf is an open array, then a must be array compatible with f (see App. A). The lengths of f are taken from a.
Examples of procedure declarations:
PROCEDURE ReadInt(VAR x: INTEGER);
VAR i: INTEGER; ch: CHAR;
BEGIN i := 0; Read(ch);
WHILE ("0" <= ch) & (ch <= "9") DO
i := 10*i + (ORD(ch)-ORD("0")); Read(ch)
END;
x := i
END ReadInt
PROCEDURE WriteInt(x: INTEGER); (*0 <= x <100000*)
VAR i: INTEGER; buf: ARRAY 5 OF INTEGER;
BEGIN i := 0;
REPEAT buf[i] := x MOD 10; x := x DIV 10; INC(i) UNTIL x = 0;
REPEAT DEC(i); Write(CHR(buf[i] + ORD("0"))) UNTIL i = 0
END WriteInt
PROCEDURE WriteString(s: ARRAY OF CHAR);
VAR i: INTEGER;
BEGIN i := 0;
WHILE (i < LEN(s)) & (s[i] # 0X) DO Write(s[i]); INC(i) END
END WriteString;
PROCEDURE log2(x: INTEGER): INTEGER;
VAR y: INTEGER; (*assume x>0*)
BEGIN
y := 0; WHILE x > 1 DO x := x DIV 2; INC(y) END;
RETURN y
END log2
ProcedureHeading = PROCEDURE [Receiver] IdentDef [FormalParameters].If a procedure P is bound to a type T0, it is implicitly also bound to any type T1 which is an extension of T0. However, a procedure P' (with the same name as P) may be explicitly bound to T1 in which case it overrides the binding of P. P' is considered a redefinition of P for T1. The formal parameters of P and P' must match (see App. A). If P and T1 are exported (see Chapter 4) P' must be exported too.
Receiver = "(" [VAR] ident ":" ident ")".
If v is a designator and P is a type-bound procedure, then v.P denotes that procedure P which is bound to the dynamic type of v. Note, that this may be a different procedure than the one bound to the static type of v. v is passed to P 's receiver according to the parameter passing rules specified in Chapter 10.1.
If r is a receiver parameter declared with type T, r.P^ denotes the (redefined) procedure P bound to the base type of T. In a forward declaration of a type-bound procedure the receiver parameter must be of the same type as in the actual procedure declaration. The formal parameter lists of both declarations must match (App. A).
Examples:
PROCEDURE (t: Tree) Insert (node: Tree);
VAR p, father: Tree;
BEGIN p := t;
REPEAT father := p;
IF node.key = p.key THEN RETURN END;
IF node.key < p.key THEN
p := p.left
ELSE
p := p.right
END
UNTIL p = NIL;
IF node.key < father.key THEN
father.left := node
ELSE
father.right := node
END;
node.left := NIL; node.right := NIL
END Insert;
PROCEDURE (t: CenterTree) Insert (node: Tree); (*redefinition*)
BEGIN
WriteInt(node(CenterTree).width);
t.Insert^ (node) (* calls the Insert procedure bound to Tree *)
END Insert;
Function Procedures
Name Argument type Result type Function
ABS(x) numeric type type of x absolute value
ASH(x, n) x, n: integer type LONGINT arithmetic shift (x * 2^n)
CAP(x) CHAR CHAR x is letter: corresponding
capital letter
CHR(x) integer type CHAR character with ordinal
number x
ENTIER(x) real type LONGINT largest integer not greater
than x
LEN(v, n) v: array; LONGINT length of v in dimension n
n: integer const. (first dimension = 0)
LEN(v) v: array LONGINT equivalent to LEN(v, 0)
LONG(x) SHORTINT INTEGER identity
INTEGER LONGINT
REAL LONGREAL
MAX(T) T = basic type T maximum value of type T
T = SET INTEGER maximum element of a set
MIN(T) T = basic type T minimum value of type T
T = SET INTEGER 0
ODD(x) integer type BOOLEAN x MOD 2 = 1
ORD(x) CHAR INTEGER ordinal number of x
SHORT(x) LONGINT INTEGER identity
INTEGER SHORTINT identity
LONGREAL REAL identity (truncation possible)
SIZE(T) any type integer type number of bytes required by T
Proper proceduresCOPY allows the assignment of a string or a character array containing a terminating 0X to another character array. If necessary, the assigned value is truncated to the target length minus one. The target will always contain 0X as a terminator. In ASSERT(x, n) and HALT(n), the interpretation of n is left to the underlying system implementation.
Name Argument types Function
ASSERT(x) x: Boolean expression terminate program execution
if not x
ASSERT(x, n) x: Boolean expression; terminate program execution
n: integer constant if not x
COPY(x, v) x: character array, string; v := x
v: character array
DEC(v) integer type v := v - 1
DEC(v, n) v, n: integer type v := v - n
EXCL(v, x) v: SET; x: integer type v := v - {x}
HALT(n) integer constant terminate program execution
INC(v) integer type v := v + 1
INC(v, n) v, n: integer type v := v + n
INCL(v, x) v: SET; x: integer type v := v + {x}
NEW(v) pointer to record or allocate v^
fixed array
NEW(v,x0,...,xn) v: pointer to open array; allocate v^ with lengths
xi: integer type x0..xn