10. Procedure declarations

A procedure declaration consists of a procedure heading and a procedure body. The heading specifies the procedure identifier and the formal parameters. For type-bound procedures it also specifies the receiver parameter. The body contains declarations and statements. The procedure identifier is repeated at the end of the procedure declaration.

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].
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).

10.1 Formal parameters

Formal parameters are identifiers declared in the formal parameter list of a procedure. They correspond to actual parameters specified in the procedure call. The correspondence between formal and actual parameters is established when the procedure is called. There are two kinds of parameters, value and variable parameters, indicated in the formal parameter list by the absence or presence of the keyword VAR. Value parameters are local variables to which the value of the corresponding actual parameter is assigned as an initial value. Variable parameters correspond to actual parameters that are variables, and they stand for these variables. The scope of a formal parameter extends from its declaration to the end of the procedure block in which it is declared. A function procedure without parameters must have an empty parameter list. It must be called by a function designator whose actual parameter list is empty too. The result type of a procedure can be neither a record nor an array.
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

10.2 Type-bound procedures

Globally declared procedures may be associated with a record type declared in the same module. The procedures are said to be bound to the record type. The binding is expressed by the type of the receiver in the heading of a procedure declaration. The receiver may be either a variable parameter of record type T or a value parameter of type POINTER TO T (where T is a record type). The procedure is bound to the type T and is considered local to it.
ProcedureHeading=PROCEDURE [Receiver] IdentDef [FormalParameters].
Receiver="(" [VAR] ident ":" ident ")".
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.

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;

10.3 Predeclared procedures

The following table lists the predeclared procedures. Some are generic procedures, i.e. they apply to several types of operands. v stands for a variable, x and n for expressions, and T for a type.

NameArgument typeResult typeFunction
ABS(x)numeric typetype of xabsolute value
ASH(x, n)x, n: integer typeLONGINTarithmetic shift (x * 2^n)
CAP(x)CHARCHARx is letter: corresponding capital letter
CHR(x)integer typeCHARcharacter with ordinal number x
ENTIER(x)real typeLONGINTlargest integer not greater than x
LEN(v, n)v: array; n: integer const.LONGINTlength of v in dimension n (first dimension = 0)
LEN(v)v: arrayLONGINTequivalent 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 typeBOOLEANx MOD 2 = 1
ORD(x)CHARINTEGERordinal number of x
SHORT(x)LONGINT
INTEGER
LONGREAL
INTEGER
SHORTINT
REAL
identity
identity
identity (truncation possible)
SIZE(T)any typeinteger typenumber of bytes required by T
Function procedures
NameArgument typesFunction
ASSERT(x)x: Boolean expressionterminate 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 typev := v - 1
DEC(v, n)v, n: integer typev := v - n
EXCL(v, x)v: SET; x: integer typev := v - {x}
HALT(n)integer constantterminate program execution
INC(v)integer typev := v + 1
INC(v, n)v, n: integer typev := v + n
INCL(v, x)v: SET; x: integer typev := v + {x}
NEW(v)pointer to record or fixed arrayallocate v^
NEW(v, x0, ..., xn)v: pointer to open array; xi: integer type allocate v^ with lengths x0.. xn
Proper procedures
COPY 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.
Previous Section, Next Section, Contents
Adapted to HTML by Jürgen Geßwein; 8. Juni 1995