Routines as Parameters [ HP Pascal/iX Programmer's Guide ] MPE/iX 5.0 Documentation
HP Pascal/iX Programmer's Guide
Routines as Parameters
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 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 | Parameter is defined in formal |
| | routine. | parameter list of routine, but its |
| | | type is defined first in a type |
| | | declaration section. |
| | | |
----------------------------------------------------------------------------------------------
| | | |
| Corresponding Actual | User-defined routine. | addr applied to user-defined routine, |
| Parameter | | 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;
(Example is continued on next page.)
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 nil.
* 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 nil.
* 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.
MPE/iX 5.0 Documentation