Super Prev Next

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 Type-bound procedures). 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 Definition of terms).


Super Prev Next

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 Definition of terms). If Tf is an open array, then a must be array compatible with f (see Definition of terms). 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


Super Prev Next

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 Definition of terms). If P and T1 are exported (see section Declarations and scope rules) 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 (dynamic binding). 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 section Formal parameters.

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 (Definition of terms).

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;


Super Prev Next

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.


Super Prev Next

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*2n)
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 the same as 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 number of bytes required by T


Super Prev Next

Proper procedures

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

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.