 |
» |
|
|
 |
A routine can be a parameter in two ways: it can be a routine
parameter (a procedure or function parameter, as defined by ANSI
Pascal), or it can be a routine that is passed as a parameter (as
defined by the systems programming extensions of HP Pascal). Table 7-2 “Routine Parameters versus Parameters of
Routine Type ” differentiates between
routine parameters and parameters of routine types. Table 7-2 Routine Parameters versus Parameters of
Routine Type | Routine Parameter | Parameter of Routine Type |
|---|
Availability | ANSI Pascal | System programming extensions. | Where Defined | Formal parameter list of routine. | Parameter is defined in formal parameter
list of routine, but its type is defined first in a type declaration
section. | Corresponding Actual Parameter | User-defined routine. | addr applied
to user-defined routine, or variable of a routine type. | Referenced By | Name | Fcall or call
routine. |
Routine Parameters |  |
Routine parameters (procedure or functions
parameters) are parameters that are routines (procedures or functions,
respectively). They are completely defined in the formal parameter
lists of other routines, which reference them by name. A formal function parameter is a function definition. Its
actual parameter is the name of a user-defined function with a congruent
parameter list and the same result type. A formal procedure parameter is a procedure definition. Its
actual parameter is the name of a user-defined procedure with a
congruent parameter list. Predefined routines cannot be passed to routine parameters. Example PROGRAM prog; VAR s : char; PROCEDURE p (PROCEDURE procparm1 (a,b : integer); {formal procedure parameter} FUNCTION funcparm1 (c : integer) : char); VAR ch : char; BEGIN procparm1(1,2); ch := funcparm1(3); END; FUNCTION f (PROCEDURE procparm2; {formal procedure parameter} FUNCTION funcparm2 : integer); {formal function parameter} VAR i : integer; BEGIN procparm2; i := funcparm2; END; PROCEDURE actual_procparm1 (x,y : integer); {user-defined procedure} BEGIN . . END; FUNCTION actual_funcparm1 (z : integer) : char; {user-defined function} BEGIN . . END; PROCEDURE actual_procparm2; {another user-defined procedure} BEGIN . . END; FUNCTION actual_funcparm2 : integer; {another user-defined function} BEGIN . . END; BEGIN {prog} p(actual_procparm1, {actual parameter for procparm1} actual_funcparm1); {actual parameter for funcparm1} s := f(actual_procparm2, {actual parameter for procparm2} actual_funcparm2); {actual parameter for funcparm2} END. {prog} |
Parameters of Routine Types |  |
Parameters of routine types (procedure
or function types) are like parameters of other user-defined types.
They are defined in the formal parameter lists of other routines,
but their types — routine types — are defined
in type declaration sections. The types must be declared first (see
the HP Pascal/iX Reference Manual or the
HP Pascal/HP-UX Reference Manual, depending
on your implementation, for more information on declaring routine
types). The actual parameter for a formal parameter of function type
is either: The result of the function addr
when applied to the name of a user-defined function. The name of a variable of function type (in which
case the value of the variable must be a user-defined function).
In either case, the user-defined function and the formal parameter
must have congruent parameter lists and the same result type. The actual parameter for a formal parameter of procedure type
is either: The result of the function addr
when applied to the name of a user-defined procedure. The name of a variable of procedure type (in which
case the value of the variable must be a user-defined procedure).
In either case, the user-defined procedure and the formal
parameter must have congruent parameter lists. Predefined routines cannot be actual parameters for formal
parameters of routine types. For information on variables of routine
types, see "Variables of Routine Types." Example The procedure p
has a parameter of procedure type, procparm1,
and a parameter of function type, funcparm1.
The function f
has a parameter of procedure type, procparm2,
and a parameter of function type, funcparm2.
Compare this example to the example in “Routine Parameters ”. See “Congruent Parameter Lists ” for examples of congruent parameter lists.
See “Fcall Function ” and “Call Procedure ” for information on
the fcall function and call
procedure.  |
$STANDARD_LEVEL 'HP_MODCAL'$ PROGRAM prog; TYPE proctype1 = PROCEDURE (a,b : integer); functype1 = FUNCTION (c : integer) : char; proctype2 = PROCEDURE; functype2 = FUNCTION : integer; VAR s : char; PROCEDURE p (procparm1 : proctype1; funcparm1 : functype1); VAR ch : char; BEGIN call(procparm1,1,2); ch := fcall(funcparm1,3); END; FUNCTION f (procparm2 : proctype2; funcparm2 : functype2); VAR i : integer; BEGIN call(procparm2); i := fcall(funcparm2); END; PROCEDURE actual_procparm1 (x,y : integer); BEGIN . . . END; FUNCTION actual_funcparm1 (z : integer) : char; BEGIN . . . END; |
PROCEDURE actual_procparm2; BEGIN . . . END; FUNCTION actual_funcparm2 : integer; BEGIN . . . END; BEGIN {prog} p(addr(actual_procparm1), addr(actual_funcparm1)); s := f(addr(actual_procparm2), addr(actual_funcparm2)); END. {prog} |
Variables of Routine Types |  |
Variables of routine types (procedure and function types)
can be actual parameters for formal parameters of routine types
(function and procedure types, respectively). See “Parameters of Routine Types ”. The values that you can assign to a function variable are: The value returned by the predefined function addr
when you call it with the name of an appropriate function (appropriate
is defined below). The value returned by any function whose return
type is the same function type as that of the variable. Another function variable of the same type.
The values that you can assign to a procedure variable are: The value returned by the predefined function addr
when you call it with the name of an appropriate procedure (appropriate
is defined below). The value returned by any function whose return
type is the same procedure type as that of the variable. Another procedure variable.
A routine is an appropriate parameter
for addr under these conditions: The routine and the variable have
congruent parameter lists. In the case of a function and a function variable,
if they have the same result type. The routine is declared at the same or a higher
level than the variable. The routine is not predefined.
Routine variables are system programming extensions. To use
them, specify $STANDARD_LEVEL 'HP_MODCAL'$.
Refer to the HP Pascal/iX Reference Manual
or the HP Pascal/HP-UX Reference Manual,
depending on your implementation, for more information on compiler
options. Example 1 This program uses the predefined function addr
to assign appropriate functions to a variable of function type and
appropriate procedures to a variable of procedure type. $STANDARD_LEVEL 'HP_MODCAL'$ PROGRAM proc (input); TYPE proctype = PROCEDURE (x,y : integer); functype = FUNCTION (x,y : integer) : integer; VAR procvar : proctype; funcvar : functype; b : Boolean; i : integer; PROCEDURE p1 (a,b : integer); EXTERNAL; PROCEDURE p2 (a,b : integer); EXTERNAL; FUNCTION f1 (a,b : integer) : integer; EXTERNAL; FUNCTION f2 (a,b : integer) : integer; EXTERNAL; BEGIN read(b); IF b THEN BEGIN procvar := addr(p1); funcvar := addr(f1); END ELSE BEGIN procvar := addr(p2); funcvar := addr(f2); END; call(procvar,10,20); i := fcall(funcvar,10,20); END. |
Example 2 This program declares procedures and procedure variables at
different levels and assigns each procedure visible to each variable.
The comments tell you which assignments are illegal and why. $STANDARD_LEVEL 'HP_MODCAL'$ PROGRAM prog; TYPE proctype = PROCEDURE (x,y : integer); VAR procvar : proctype; PROCEDURE p1 (a,b : integer); VAR pvar1 : proctype; PROCEDURE p2 (c,d : integer); VAR pvar2 : proctype; PROCEDURE p3 (e,f : integer); VAR pvar3 : proctype; BEGIN {p3} pvar3 := addr(p1); pvar3 := addr(p2); pvar3 := addr(p3); END; {p3} BEGIN {p2} pvar2 := addr(p1); pvar2 := addr(p2); pvar2 := addr(p3); {illegal p3 is at a lower level than pvar2} END; {p2} BEGIN {p1} pvar1 := addr(p1); pvar1 := addr(p2); {illegal p2 is at a lower level than pvar1} END; {p1} BEGIN {prog} procvar := addr(p1); END. {prog} |
Example 3 This program uses functions whose return types are function
and procedure types to assign values to routine variables. The comments
tell you which assignments are illegal and why. $STANDARD_LEVEL 'HP_MODCAL'$ PROGRAM proc; TYPE proctype1 = PROCEDURE (x : integer); proctype2 = PROCEDURE (x,y : integer); functype1 = FUNCTION (y : real) : integer; functype2 = FUNCTION (y : real) : real; VAR procvar : proctype1; funcvar : functype1; FUNCTION returnproc1 (z : integer) : proctype1; EXTERNAL; FUNCTION returnproc2 (z : integer) : proctype2; EXTERNAL; FUNCTION returnfunc1 : functype1; EXTERNAL; FUNCTION returnfunc2 : functype2; EXTERNAL; BEGIN procvar := returnproc1(1); procvar := returnproc2(2); {illegal function returns wrong type} funcvar := returnfunc1; funcvar := returnfunc2; {illegal function returns wrong type} END. |
Example 4 Undefined routine variables are undetectable, and cause unpredictable
results. The following program avoids problems caused by such undefined
variables by assigning the value nil to those
variables.  |
$STANDARD_LEVEL 'EXT_MODCAL'$ PROGRAM prog (input,output); VAR i,j : integer; procvar1 : PROCEDURE (a,b : integer); procvar2 : PROCEDURE (VAR c,d : integer); PROCEDURE alpha (x,y: integer); EXTERNAL; PROCEDURE beta (x,y: integer); EXTERNAL; PROCEDURE gamma (VAR x,y: integer); EXTERNAL; PROCEDURE delta (VAR x,y: integer); EXTERNAL; BEGIN read(i,j); {initialize variables of procedure type} procvar1 := nil; procvar2 := nil; {If -100 <= i <= -1, procvar1 is alpha; if 0 <= i <= 100, procvar1 is beta} IF (i IN [-100..-1] THEN procvar1 := addr(alpha) ELSE IF i IN [0..100] THEN procvar1 := addr(beta); {If -10 <= j <= -1, procvar2 is gamma; if 0 <= j <= 10, procvar2 is delta} IF j IN [-10..-1] THEN procvar2 := addr(gamma) ELSE IF j IN [0..10] THEN procvar2 := addr(delta); {Call procvar1 and procvar2, unless they are nil} IF procvar1 = nil THEN writeln('i is out of range') ELSE call(procvar1,i,j); IF procvar2 = nil THEN writeln('j is out of range') ELSE call(procvar2,i,j); END. |
Call Procedure |  |
The predefined procedure call executes
a call to the procedure specified by a procedure variable. Its parameters
are a procedure variable and the actual parameters with which the
procedure is to be called. Just as a pointer is dereferenced with
, a procedure variable is dereferenced with call. Example $STANDARD_LEVEL 'EXT_MODCAL'$ PROGRAM prog; TYPE proctype = PROCEDURE (x,y : integer); VAR procvar : proctype; PROCEDURE p (a,b : integer); BEGIN . . . END; BEGIN procvar := addr(p); call(procvar,1000,3500); p(1000,3500); END. |
The calls to the procedures call and
p are semantically equivalent. The first parameter to call (procedure
variable) cannot have the value nil or be undefined. Fcall Function |  |
The predefined function fcall executes
a call to the function specified by a function variable. Its parameters
are a function variable (which specifies the function to be called)
and the actual parameters with which the function is to be called.
Just as a pointer is dereferenced with , a function variable is
dereferenced with fcall. Example $STANDARD_LEVEL 'EXT_MODCAL'$ PROGRAM prog; TYPE functype = FUNCTION (x,y : integer) : integer; VAR funcvar : functype; v1 : integer; FUNCTION f (a,b : integer) : integer; BEGIN f := (a+b)*(a-b); END; BEGIN new(v1); funcvar := addr(f); v1 := fcall(funcvar,27,94); v1 := f(27,94); END. |
The calls to the functions fcall and
f are semantically
equivalent. The first parameter to fcall (the function
variable) cannot have the value nil or be undefined.
|