[an error occurred while processing this directive]

HP OpenVMS Systems Documentation

Content starts here

HP Pascal for OpenVMS
Language Reference Manual


Previous Contents Index

6.3.4 Passing Predeclared Functions to Formal Function Parameters

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.

6.3.5 Foreign Parameters

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.

Table 6-3 Specifiers and Attributes for Passing Mechanisms
Passing Mechanism Specifiers and Attributes
By immediate value %IMMED or [IMMEDIATE]
By reference %REF or [REFERENCE]
By descriptor %DESCR or %STDESCR

Note

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:

  • A %REF or [REFERENCE] formal parameter requires actual parameters to be passed by reference. %REF or [REFERENCE] implies variable semantics unless the actual parameter is an expression; in that case, it implies foreign value semantics.
  • An %IMMED or [IMMEDIATE] formal parameter requires actual parameters to be passed with the by immediate value mechanism and always implies value semantics. %IMMED or [IMMEDIATE] cannot be used on formal parameters of type VARYING, or on conformant array and conformant VARYING parameters.
  • A %DESCR formal parameter requires actual parameters to be passed with the by descriptor mechanism and interprets the semantics as %REF or [REFERENCE] does.
  • A %STDESCR formal parameter requires actual parameters to be passed with the by string descriptor mechanism. An actual parameter variable of type PACKED ARRAY OF CHAR implies variable semantics. An actual parameter expression of either type PACKED ARRAY OF CHAR or type VARYING OF CHAR implies foreign value semantics. You cannot use %STDESCR on formal procedure and function parameters.

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}

For More Information:

  • On conformant parameters ( Section 6.3.7)
  • On type conversions ( Section 4.4)
  • On attributes (Chapter 10)
  • On calling external routines (HP Pascal for OpenVMS User Manual)
  • On compiler messages (HP Pascal for OpenVMS User Manual)

6.3.6 Schema Parameters

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:

  • You cannot pass schema sets and schema subranges as value parameters, since there is no assignment compatibility for undiscriminated sets and for undiscriminated subranges.
  • You can pass a varying-length string expression to a formal STRING parameter (the actual parameter does not have to be of the STRING type).

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.

For More Information:

6.3.7 Conformant Parameters

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-identifier

attribute-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.

For More Information:

6.3.7.2 Conformant VARYING Parameter

The syntax for a conformant VARYING string has the following form:


VARYING [upper-bound-identifier] OF [[attribute-list]] CHAR

attribute-list

One or more identifiers that provide additional information about the conformant VARYING string.

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.

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:



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.

For More Information:

6.3.7.3 Conformant Parameter Sections

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:

  • Equivalent current lengths (in the case of passing a string expression to a conformant PACKED array parameter of type CHAR or to a conformant VARYING OF CHAR
  • Indexes that are equivalent and of the same ordinal type, the same number of dimensions, and components that are compatible (in the case of passing a static or nonstatic array to a conformant array parameter)

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.

For More Information:


Previous Next Contents Index