[an error occurred while processing this directive]
HP OpenVMS Systems Documentation |
HP Pascal for OpenVMS
|
Previous | Contents | Index |
The following predeclared functions can be passed directly to formal function parameters:
ABS | ARCTAN | CHR | CLOCK |
COS | DBLE | EOF | EOLN |
EXP | EXPO | INT | LN |
ODD | ORD | QUAD | ROUND |
SIN | SNGL | SQR | SQRT |
STATUS | STATUSV | TRUNC | UAND |
UFB | UINT | UNDEFINED | UNOT |
UOR | UROUND | UTRUNC | UXOR |
For example:
program math(output); procedure a( function f(r:real):real ); begin writeln(f(1.0)); end; begin a(sin); a(cos); end. |
When declaring an external routine (one written in a language other than Pascal) that is called by an HP Pascal routine, you must specify not only the correct semantics but the correct mechanism as well. To allow you to obtain these passing mechanisms, HP Pascal provides foreign mechanism specifiers and the passing mechanism attributes. Table 6-3 gives the method specifier or attribute used for each passing mechanism.
Passing Mechanism | Specifiers and Attributes |
---|---|
By immediate value | %IMMED or [IMMEDIATE] |
By reference | %REF or [REFERENCE] |
By descriptor | %DESCR or %STDESCR |
Depending on the environment in which you are programming, not all passing-mechanism specifiers may be supported on your system. |
The foreign mechanism specifier %IMMED, %REF, %DESCR or %STDESCR precedes a formal parameter in the declaration of an external routine. If the formal parameter does not represent a routine, the mechanism specifier must precede the parameter name. If the formal parameter represents a routine, the specifier must precede the reserved word PROCEDURE or FUNCTION in the parameter declaration.
In addition, it is possible to use the passing-mechanism attributes [IMMEDIATE] or [REFERENCE] in a formal parameter's attribute list to obtain the same behavior as %IMMED or %REF, respectively.
When calling an external routine, you must make sure that you pass actual parameters by the mechanism stated or implied in the routine declaration. HP Pascal allows you to use the foreign mechanism specifiers %IMMED, %REF, %DESCR, and %STDESCR before an actual parameter in a routine call. (Passing-mechanism attributes are valid only on formal parameters.) 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. Type checking is suspended for the parameter association to which the specifier applies.
The passing of an expression to a foreign mechanism parameter implies foreign value semantics: the calling block makes a copy of the actual parameter's value and passes this copy to the called routine. The copy is not retained when control returns to the calling block. Foreign value semantics differs from value semantics in that the calling block, not the called routine, makes the copy.
The passing of a variable to a foreign mechanism parameter (except a parameter with the %IMMED or [IMMEDIATE] specifier) implies foreign variable semantics: the variable itself is passed.
A compile-time warning occurs if the compiler must convert the value of an actual parameter variable to make it match the type of a foreign mechanism parameter. In that case, the compiler passes a copy of the converted value by foreign value semantics, using the specified mechanism. You can eliminate this warning by enclosing the actual parameter variable in parentheses; by doing so, you prevent the compiler from interpreting the actual parameter as a variable. The compiler takes the same action, whether or not it produces a warning message.
Mechanism specifiers on formal parameters produce the following results:
Because the semantics are implicit in the mechanism, a formal parameter cannot be declared with both the reserved word VAR and a mechanism specifier.
Also, when passing an actual parameter to a formal foreign parameter, the HP Pascal compiler checks for type compatibility when an external routine is called. However, at the time of the declaration, a formal parameter passed by immediate value that does not represent a routine is checked to ensure that it can be stored in 64 or fewer bits, or 32 or fewer bits, depending on the platform. A formal parameter passed by immediate value that does represent a routine must be declared with the UNBOUND attribute.
Special considerations arise when a function that has no formal parameters of its own (or that has defaults that are being used for all its formal parameters) is passed as a formal parameter to another routine. The appearance of the function identifier in an actual parameter list could indicate the passing of either the address of the function or the function result. In HP Pascal, the address of the function is passed by default, as shown in this example.
p( %IMMED f ); {Address of function f is passed} |
To cause the function result to be passed, you must enclose the function identifier in parentheses, as shown in this example:
p( %IMMED (f) ); {Result of function f is passed} |
HP Pascal provides a method of processing schematic arrays, records, sets, subranges, and STRINGs with potentially different actual discriminants. To do this, you can use undiscriminated schema parameters.
An undiscriminated schema formal parameter is a type name that represents a specific schema family. The actual discriminants are determined each time you pass a corresponding actual parameter. The actual discriminants are available within the routine through the formal parameter.
You can use undiscriminated schema formal parameters when declaring value and variable parameters. When you use a formal, undiscriminated schema parameter instead of a conformant parameter or a type identifier, a call to the routine provides actual parameters that are discriminated from the same schema type family. However, when using value semantics, there are two exceptions:
Consider the following example:
TYPE Array_Template( lbnd, hbnd : INTEGER ) = ARRAY[lbnd..hbnd] OF INTEGER; VAR Even_Numbers : Array_Template( 1, 30 ); Odd_Numbers : Array_Template( 1, 60 ); PROCEDURE Print_Array( Array_To_Print : Array_Template ); VAR i : INTEGER; BEGIN WRITELN( 'The maximum number of elements is ', Array_To_Print.hbnd ); WRITELN; FOR I := LOWER( Array_To_Print ) TO UPPER( Array_To_Print ) DO WRITELN( Array_To_Print[i] ); END; {In the executable section:} Print_Array( Even_Numbers ); Print_Array( Odd_Numbers ); |
All passing-mechanism specifiers and attributes (%REF, %IMMED, %DESCR, %STDSCR, [REFERENCE], [IMMEDIATE], [CLASS_S], [CLASS_A], [CLASS_NCA]) are illegal on parameters of nonstatic types.
When you specify more than one formal schema parameter of the same schema type in a single parameter section, there are additional programming considerations.
If you specify more than one formal parameter (separated by commas) of a single, user-defined undiscriminated schema type, the corresponding actual parameters must be discriminated from the same type as the formal parameter (they must be of the same schema type family), and the actual schema parameters must have equivalent actual discriminant values. Consider the following example.
TYPE Array_Template( Upper_Bound : INTEGER ) = ARRAY[1..Upper_Bound] OF INTEGER; VAR Actual_1, Actual_2 : Array_Template( 10 ); Actual_3 : Array_Template( 20 ); PROCEDURE Schema_Proc1( Only_One : Array_Template ); {Body...} PROCEDURE Schema_Proc2( One, Two : Array_Template ); {Body...} {In the executable section:} Schema_Proc1( Actual_1 ); {Legal} Schema_Proc1( Actual_3 ); {Legal} Schema_Proc2( Actual_1, Actual_2 ); {Legal} Schema_Proc2( Actual_1, Actual_3 ); {Illegal} |
When using value semantics, if you specify more than one formal parameter (separated by commas) of an undiscriminated STRING type, the corresponding actual parameters must have equivalent current lengths (not necessarily equivalent maximum lengths). Consider the following example.
VAR One_String, Two_String : STRING( 15 ); Three_String : STRING( 20 ); PROCEDURE Test_Strings( One, Two : STRING ); {Body...} {In the executable section:} Test_Strings( 'a', 'b' ); {Legal} Test_Strings( 'a', 'bb' ); {Illegal} One_String := 'Hello'; Two_String := 'Hello there'; Three_String := 'olleH'; Test_Strings( One_String, Two_String ); {Illegal} Test_Strings( One_String, Three_String ); {Legal} |
When using variable semantics, if you specify more than one formal parameter (separated by commas) of an undiscriminated STRING type, the corresponding discriminated STRING actual parameters must have an equivalent maximum length.
HP Pascal provides a method of processing arrays and character strings with potentially different maximum lengths. To do this, you can use conformant array parameters or conformant varying parameters.
A conformant parameter is a syntax that represents a set of types that are identical except for their bounds. The bounds of a conformant parameter are determined each time a corresponding actual parameter is passed. The bounds of an actual parameter are available within the routine through identifiers declared in the conformant parameter. A conformant parameter can appear only within a formal parameter list.
You can use conformant parameters when declaring value, variable, and foreign mechanism parameters. When you use a conformant parameter instead of a type identifier in a formal parameter declaration, a call to the routine can provide static and nonstatic arrays, VARYING OF CHAR strings, and discriminated strings (of the STRING schema family) of any size.
In addition, two conformant parameters are equivalent if they have
indexes of the same ordinal type and components that either are
compatible or are equivalent conformant parameters. They must also have
the same number of dimensions and both must be packed or unpacked.
6.3.7.1 Conformant Array Parameters
The syntax for a conformant array has the following form:
lower-bound-identifier
An identifier that represents the lower bound of the conformant array's index.upper-bound-identifier
An identifier that represents the upper bound of the conformant array's index.
ARRAY[{lower-bound-identifier..upper-bound-identifier : [[attribute-list]] index-type-identifier};...] OF [[attribute-list]] {type-identifier } {conformant-parameter-syntax } PACKED ARRAY[lower-bound-identifier..upper-bound-identifier : [[attribute-list]] index-type-identifier] OF [[attribute-list]] type-identifierattribute-list
One or more identifiers that provide additional information about the conformant array.index-type-identifier
The type identifier of the index, which must denote an ordinal type.type-identifier
The type identifier of the array components, which can denote any type.
To specify the range and type of the index, you must use type identifiers that represent predefined or user-defined ordinal types. The identifiers that represent the index bounds can be thought of as READONLY value parameters, implicitly declared in the procedure declaration.
Unless the conformant array is packed, the component can be either a type identifier or another conformant parameter; therefore, only the last dimension of a conformant parameter can be packed. The following example is illegal because the component of the packed array is another conformant parameter:
PACKED ARRAY[l1..u1: INTEGER; l2..u2: INTEGER] OF CHAR |
However, the following is allowed because only the last component is packed:
ARRAY[l1..u1: INTEGER] OF PACKED ARRAY[l2..u2: INTEGER] OF CHAR |
Consider the following example:
TYPE Workdays = 1..31; Feb_Days = 1..28; Mar_Days = 1..31; VAR Feb_Arr : ARRAY[Feb_Days] OF INTEGER; Mar_Arr : ARRAY[Mar_Days] OF INTEGER; Feb_Total, Mar_Total : INTEGER; FUNCTION Inventory( VAR Amt_Sold : ARRAY[First_Day..Last_Day : Workdays] OF INTEGER ) : INTEGER; {In executable section:} {Amt_Sold : ARRAY[1..28] OF INTEGER...} Feb_Total := Inventory( Feb_Arr ); {Amt_Sold : ARRAY[1..31] OF INTEGER...} Mar_Total := Inventory( Mar_Arr ); |
The formal parameter Amt_Sold can have index values from 1 to 31 to indicate the number of workdays in each month. Thus, an actual parameter passed to Amt_Sold could be an array whose index type is either Feb_Days or Mar_Days. Using a conformant parameter in this example allows you to write a general-purpose routine that sums the components of Amt_Sold and returns the monthly inventory total to the calling block.
The syntax for a conformant VARYING string has the following form:
VARYING [upper-bound-identifier] OF [[attribute-list]] CHAR |
The upper-bound-identifier specifies the maximum length of the VARYING
OF CHAR string and must denote an integer. The upper-bound-identifier
that represents the maximum length can be thought of as a READONLY
value parameter, implicitly declared in the procedure declaration.
When you pass a string expression to a value conformant varying-length
parameter, the length of the actual parameter's current value parameter
(not its declared maximum length) becomes both the current length and
the maximum length of the formal parameter. When you pass either a
conformant VARYING OF CHAR string variable or a discriminated STRING
variable to a VAR conformant varying-length parameter, the declared
maximum length of the actual parameter becomes the maximum length of
the formal parameter.
The following example shows how to declare and use a VARYING OF CHAR
conformant parameter:
One or more identifiers that provide additional information about the
conformant VARYING string.
attribute-list
upper-bound-identifier
An identifier that represents the upper bound of the conformant VARYING
OF CHAR string's index. The type of the upper-bound-identifier is
always an integer.
VAR Short_String : VARYING[40] OF CHAR := PAD( '', '-', 40 ); Long_String : VARYING[80] OF CHAR := PAD( '', '-', 80 ); PROCEDURE Dashed_Line( VAR String : VARYING[Len] OF CHAR ); {Body...} {In the executable section:} Dashed_Line( Short_String ); Dashed_Line( Long_String ); |
In this example, note that Len is not a previously declared identifier but is instead an additional implicit parameter defined by the procedure declaration. The upper bound of the conformant parameter String is established by the declared maximum length of the actual parameter passed to it when the procedure Dashed_Line is called. The first call to Dashed_Line passes a 40-character string, so Len has the value 40. The second call passes an 80-character string, so Len has the value 80.
When you specify more than one conformant parameter of the same type in a single parameter section, there are additional programming considerations.
When using value semantics, if you specify more that one formal parameter (separated by commas) of a single user-defined conformant parameter, the corresponding actual parameters must have either of the following characteristics:
Consider the following example:
VAR Actual_1, Actual_2 : ARRAY[1..10] OF INTEGER; Actual_3 : ARRAY[5..10] OF INTEGER; PROCEDURE TestArr( One, Two : ARRAY [L1..U1 : INTEGER] OF INTEGER ); {Procedure body...} PROCEDURE TestStr( One, Two : PACKED [L2..U2 : INTEGER] OF CHAR ); {Procedure body...} {In the executable section:} TestArr( Actual_1, Actual_2); {Legal} TestArr( Actual_2, Actual_3); {Illegal} TestStr( 'ABC', 'XYZ' ); {Legal} TestStr( 'HELLO', 'GOODBYE' ); {Illegal} |
When using variable semantics, if you specify more than one formal parameter (separated by commas) of a single, user-defined, conformant parameter, the corresponding actual variable parameters must be of the same type.
Previous | Next | Contents | Index |