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. |
| 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. |
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]. |
| 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;
| 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; n: integer const. | LONGINT | length of v in dimension n (first dimension = 0) |
| LEN(v) | v: array | LONGINT | equivalent to LEN(v, 0) |
| LONG(x) | SHORTINT INTEGER REAL | INTEGER LONGINT LONGREAL | identity |
| MAX(T) | T = basic type T = SET | T INTEGER | maximum
value of type T maximum element of a set |
| MIN(T) | T = basic type T = SET | T INTEGER | minimum
value of type T 0 |
| ODD(x) | integer type | BOOLEAN | x MOD 2 = 1 |
| ORD(x) | CHAR | INTEGER | ordinal number of x |
| SHORT(x) | LONGINT INTEGER LONGREAL | INTEGER SHORTINT REAL | identity identity identity (truncation possible) |
| SIZE(T) | any type | integer type | number of bytes required by T
|
| Name | Argument types | Function |
|---|---|---|
| ASSERT(x) | x: Boolean expression | terminate program execution if not x |
| ASSERT(x, n) | x: Boolean expression; n: integer constant | terminate program execution if not x |
| COPY(x, v) | x: character array, string; v: character array | v := x |
| 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 fixed array | allocate v^ |
| NEW(v, x0, ..., xn) | v: pointer to open array; xi: integer type | allocate v^ with lengths x0.. xn
|