[an error occurred while processing this directive]
HP OpenVMS Systems Documentation |
HP Pascal for OpenVMS
|
Previous | Contents | Index |
A routine call executes all statements in the body of the declared routine. You must declare a routine before you can call it. Syntactically, procedure calls are statements, and function calls, which return a single value, are expressions. You can call a function anywhere that an expression of the declared result type is legal. If the result of a function is irrelevant, you can call the function as a statement in the same way that you call a procedure. You can call routines in the executable section of a program or in the body of another routine. Routine calls have the following forms:
[%IMMED ] [%REF ] procedure-identifier [[({ [%DESCR ] actual-parameter},...)]] [ ] [%STDESCR ] [%IMMED ] [%REF ] function-identifier [[({ [%DESCR ] actual-parameter},...)]] [ ] [%STDESCR ] |
procedure-identifier
function-identifier
The declared routine identifier. The scope of a routine identifier is the block in which it is declared, excluding any nested blocks that redeclare the same identifier.actual-parameter
The actual parameter whose data type matches the type of the corresponding formal parameter. Optionally, you can specify a passing mechanism for each parameter. When a mechanism specifier appears in a call, it overrides the type, semantics, mechanism specified, and even the number of parameters in the formal parameter declaration. Thus, type checking is suspended for the parameter association to which the specifier applies.
Consider the following example, which includes a procedure that takes no parameters and a function used as an expression:
VAR a, b, c, z : REAL; PROCEDURE Introduction; BEGIN WRITELN( 'This is the Inventory Program Version 5.6.' ); WRITELN; WRITELN( ' Press Ctrl/H for help. Press Return to continue.' ); END; FUNCTION Adder( Op1, Op2, Op3 : REAL ) : REAL; BEGIN Adder := Op1 + Op2 + Op3; {Assign a function return value} END; {In the executable section:} Introduction; {No parameters necessary in the call} a := 3.14; b := 14.78; c := 112.456; z := Adder( a, b, c ); {Function used as an expression evaluating to a REAL value} |
If a function returns a value of an array, record, or pointer type, you can index, select, or dereference the object at the time of the function call, without first assigning the function result to a variable, as shown in this example:
TYPE Player_Rec = RECORD Wins : INTEGER; Losses : INTEGER; Percentage : REAL; END; VAR Number : INTEGER; FUNCTION Return_Player_Info( Player_Num : INTEGER ) : Player_Rec; {In the function body:} Return_Player_Info := Player_Rec[Wins: 3; Losses: 18; Percentage: 21/3]; {In the executable section:} WRITELN( Return_Player_Info( Number ).Losses, 'losses is poor!'); |
In HP Pascal, there are two types of parameters: formal and actual parameters. A formal parameter (also called an argument) is located in the header of the routine declaration. You cannot redeclare a formal parameter in a routine's declaration section, but you can redeclare it in nested routines within the routine's declaration section.
The formal parameter establishes the semantics, the data type, and the required passing mechanism of the parameter. The general format of the formal parameter list is as follows.
{value-parameter-spec } {variable-parameter-spec } [[({ {routine-parameter-spec } };...)]] {foreign-parameter-spec } |
The specific format of a formal parameter specification depends on the semantics (value, variable, routine, foreign) of the formal parameter you are declaring (conformant parameters also have a unique syntax).
Table 6-1 presents the HP Pascal semantics for formal parameters.
Parameter Type | Description |
---|---|
Value | Used only to provide input to the routine. After calling the routine, the value of the actual parameter remains unchanged. |
Variable | Used to allow access to the actual parameter. If the rou- tine makes changes to the value of the formal parameter, the value of the actual parameter changes accordingly. |
Routine | Used to call another routine. |
Foreign | Used to call a routine written in another language. |
At run time, the formal parameter receives a value from the corresponding actual parameter, which is located in the routine call. The passing mechanism is the way in which the compiler passes the actual parameter value to the corresponding formal parameter. Table 6-2 presents the parameter-passing mechanisms supported by HP Pascal.
Mechanism | Description |
---|---|
By immediate value | The information passed to the formal parameter is the data. |
By reference | The information passed to the formal parameter is the address of the data. |
By descriptor | The information passed to the formal parameter is the address of a descriptor of the data. |
Depending on the environment in which you are programming, not all passing mechanisms may be supported on your system. |
The actual parameter must be of the same data type and passing mechanism as the corresponding formal parameter. HP Pascal uses the default passing mechanism for each actual parameter depending on its data type and formal definition. If the called routine is external to HP Pascal, you can specify an explicit passing mechanism on the actual parameter that overrides the type and number of formal parameters.
By the rules of value semantics defined by the Pascal standard, a formal value parameter represents a local variable within the called routine. When you specify value semantics, the address of the actual parameter is passed to the called routine, which then copies the value from the specified address to its own local storage. The routine then uses this copy. The copy is not retained when control returns to the calling block. Therefore, if the called routine assigns a new value to the formal parameter, the change is not reflected in the value of the actual parameter.
When you do not include a reserved word before the name of a formal parameter, you automatically cause HP Pascal to use value semantics to pass data to that parameter. A formal value parameter has the following form:
{type-identifier } {identifier},... : [[attribute-list]] {undiscriminated-schema-name } {conformant-parameter-syntax } [[:= [[mechanism-specifier]] default-value]] |
identifier
The name of the formal parameter. Multiple identifiers must be separated with commas.attribute-list
One or more identifiers that provide additional information about the formal parameter.type-identifier
The type identifier of the parameters in this section.undiscriminated-schema-name
The name of an undiscriminated schema type.conformant-parameter-syntax
The type syntax of a conformant array or a conformant VARYINGmechanism-specifier
The mechanism by which a default value is to be associated with the formal parameter.default-value
A compile-time expression representing the default value for the formal parameter.
Any attributes associated with a formal parameter become attributes of the local variable. They do not affect the values that can be passed to the parameter; they affect the behavior of the formal parameter only within the routine block. When a formal parameter has the UNSAFE attribute, the types of the actual parameters passed to it are not checked for compatibility.
An actual value parameter must be an expression whose type is assignment compatible with the type of the corresponding formal parameter. Because there is no assignment compatibility for file variables, undiscriminated schema sets, and undiscriminated schema subranges, they can never be passed as value parameters. Also, the names of routines are not allowed as value parameters.
If necessary, the type of an actual parameter is converted to the type of the formal parameter to which it is being passed. In this case, HP Pascal follows the same type conversion rules that it uses to perform any other assignment. You may, for example, pass an integer expression to a formal parameter of a real type. If an actual parameter has the UNSAFE attribute, no conversion occurs.
If you have a user-defined, formal parameter of an undiscriminated schema type, the corresponding actual parameter must be discriminated from the same schema type as that of the formal parameter.
When you pass a string expression to a formal value parameter of type
STRING, the actual parameter's current length (not its declared maximum
length) becomes both the maximum length and the current length of the
formal parameter.
You can also use the attributes [CLASS_S], [CLASS_A], and [CLASS_NCA]
on value parameters if a routine requires a specific type of descriptor
for HP Pascal to build. A [CLASS_A], [CLASS_NCA] or [CLASS_S]
formal value parameter requires the actual value parameters to be
passed with the by descriptor mechanism.
The following examples show the use of value parameters:
VAR Old_Number, x, y : INTEGER; FUNCTION Random( Seed : INTEGER ): INTEGER; {Function body...} PROCEDURE Alpha( a, b : INTEGER; c : CHAR ); {Procedure body...} {In the executable section:} New_Number := Random( Old_Number ); Alpha ( x+y, 11, 'G' ); {Actual parameters are integer and character expressions} |
By the rules of variable semantics defined by the Pascal standard, a formal variable parameter represents another name for a variable in the calling block. It is preceded by the reserved word VAR. When you specify variable semantics, the address of the actual parameter is passed to the called routine. In contrast to value semantics, the called routine directly accesses the actual parameter. Thus, the routine can assign a new value to the formal parameter during execution and the changed value is reflected immediately in the calling block (the value of the actual parameter changes).
HP Pascal uses variable semantics to pass data to a formal parameter, often called a formal VAR parameter, and has the following form:
{type-identifier } VAR {identifier},... : [[attribute-list]] {undiscriminated-schema-name } {conformant-parameter-syntax } [[:= [[mechanism-specifier]] default-value]] |
identifier
The name of the formal parameter. Multiple identifiers must be separated with commas.attribute-list
One or more identifiers that provide additional information about the formal parameter.type-identifier
The type identifier of the parameters in this parameter section.undiscriminated-schema-name
The name of an undiscriminated schema type.conformant-parameter-syntax
The type syntax of a conformant array or a conformant VARYING parameter.mechanism-specifier
The mechanism by which a default value is to be associated with the formal parameter. A mechanism specifier can be used only on a declaration for an external routine.default-value
A compile-time expression representing the default value for the parameter. A default value can be used only on an external routine.
When you use variable semantics, the actual parameter must be a variable or a component of an unpacked structured variable (you can pass an entire packed structure); no expressions are allowed unless the formal parameter has the READONLY attribute. The type of a variable passed to a routine must be structurally compatible with the type of the corresponding formal parameter, except for schema parameters. For a formal parameter that is an undiscriminated schema type, the type of the variable must be discriminated from the same type as that of the formal parameter (they must be of the same schema type family). For a formal parameter that is a discriminated schema type, the type of the variable must be of the same type family and must have equivalent actual discriminants.
The names of routines are never allowed as variable parameters. In addition, you must use variable semantics when passing a file variable as an actual parameter. Also, you cannot pass the tag field of a variant record to a formal VAR parameter.
Consider the following example:
VAR My_String : VARYING [20] OF CHAR PROCEDURE Name( VAR A_String : VARYING [String_Size] OF CHAR {Body} {In the executable section:} Name( My_String ); WRITELN( 'The new name is ', My_String ); |
This example declares a procedure, Name, which returns a new name
through the formal parameter A_String. Procedure Name modifies the
value of A_String; since My_String is passed by variable semantics,
upon completion of the routine the modified value is reflected in the
variable My_String.
In HP Pascal, certain attributes in a routine declaration or a
routine call affect the rules of compatibility between actual and
formal VAR parameters. These rules also apply to the corresponding
components of structured types and to the base types of pointer types
used as formal parameters. The attributes that result in rule changes
are the alignment, POS, READONLY, size, UNSAFE, VOLATILE, and WRITEONLY
attributes.
You can also use the attributes [CLASS_S], [CLASS_A], and [CLASS_NCA]
on variable parameters if a routine requires a specific type of
descriptor for HP Pascal to build. A [CLASS_A], [CLASS_NCA] or
[CLASS_S] formal variable parameter requires the actual variable
parameters to be passed with the by descriptor mechanism.
To write a routine that invokes another routine whose effect is not determined until the program is executed, use routine parameters. To declare a procedure or a function as a formal parameter to another routine, you must include a complete routine heading in the formal parameter list. You can also associate a foreign mechanism specifier and a default value with a formal procedure or function parameter.
The following examples show formal routine parameter sections in procedure and function declarations:
PROCEDURE Apply( FUNCTION Operation( Left, Right : REAL ) : REAL; VAR Result : REAL ); FUNCTION Copy( PROCEDURE Get_Char( VAR c : CHAR ); PROCEDURE Put_Char( i : CHAR ) ) : BOOLEAN; |
The identifiers listed as formal parameters to a formal procedure or function parameter are not accessible outside the routine declaration; they indicate the number and kind of actual parameters necessary. You refer to these identifiers only when you use nonpositional syntax to call a routine parameter.
In the previous example, the formal parameter list of Get_Char informs the compiler that Copy must pass one character parameter to Get_Char using variable semantics. Copy does not refer explicitly to the formal parameter c unless it calls Get_Char using nonpositional syntax.
To pass a routine as an actual parameter, the formal parameter list of the routine being passed and the routine specified as the formal parameter must be congruent. Two formal parameter lists are congruent if they have the same number of sections and if the sections in corresponding positions meet any of the following conditions:
The following example shows a function declaration that includes two functions as formal parameters:
VAR Costs, Pay, Fedtax, Food : REAL; Housing : INTEGER; FUNCTION Income( Salary, Tax : REAL ) : REAL; {Function body...} FUNCTION Expenses( Rent : INTEGER; Grocery : REAL ) : REAL; {Function body...} FUNCTION Budget( FUNCTION Credit( Earnings, UStax : REAL ) : REAL; FUNCTION Debit( Housing : INTEGER; Eat : REAL ) : REAL ) : REAL; VAR Deduct : REAL; BEGIN {FUNCTION Budget} Deduct := Debit( Eat := Food, Housing := Housing Budget := Credit( Pay, Fedtax ) - Deduct; END; {In the executable section:} Costs := Budget( Income, Expenses ); |
When the function Budget is called, the function Income is passed to
the formal function parameter Credit, and the function Expenses is
passed to the formal function parameter Debit. When Credit is called,
the program-level variables Pay and Fedtax are substituted for Credit's
formal parameters, Earnings and UStax.
In the call to Debit, nonpositional syntax is used to associate Debit's
formal parameters Housing and Eat with the program-level variables
Housing and Food.
The names of program-level variables do not conflict with formal
parameters of routine parameters.
The presence of the ASYNCHRONOUS and UNBOUND attributes in routine
declarations causes additional requirements to be imposed on the
routines that can legally be passed as actual parameters.
Previous | Next | Contents | Index |