[an error occurred while processing this directive]

HP OpenVMS Systems Documentation

Content starts here

HP Pascal for OpenVMS
Language Reference Manual


Previous Contents Index

4.2.5 Set Operators

A set operator forms the union, intersection, difference, or exclusive-OR of two sets, compares two sets, or tests an ordinal value for inclusion in a set. Its result is either a set or a Boolean value. Table 4-7 lists the set operators.

Table 4-7 Set Operators
Operator Example Result
+ A+B Set that is the union of sets A and B
* A*B Set that is the intersection of sets A and B
- A-B Set of those elements of set A that are not also in set B
= A=B TRUE if set A is equal to set B
<> A<>B TRUE if set A is not equal to set B
<= A<=B TRUE if set A is a subset of set B
>= A>=B TRUE if set B is a subset of set A
IN C IN B TRUE if C is an element of set B
NOT IN C NOT IN B TRUE if C is not an element of B

Most set operators require both operands to be set expressions. The IN and NOT IN operators, however, require an ordinal expression as the first operand and a set expression as the second operand. The ordinal expression must be of the same type as the set's base type. For example:


2*3 IN [1..10]

5*3 NOT IN [1..10]

The result of this IN operation is TRUE because 2 * 3 evaluates to 6, which is a member of the set [1..10], and the NOT IN operation also returns TRUE because 5 * 3 evaluates to 15, which is not a member of the set [1..10].

The XOR predeclared routine can return the set of elements that do not appear in both sets.

For More Information:

4.2.6 Type Cast Operator

Normally, HP Pascal associates each variable with one type: the type with which the variable was declared. In some systems' programming applications, you can perform operations more efficiently by relaxing HP Pascal's strict type-checking rules. HP Pascal provides the type cast operator for this purpose.

The type cast operator changes the context in which you can use a variable or an expression of a certain data type. The actual representation of the object being cast is not altered by the type cast operator. HP Pascal overrides the type only for the duration of one operation. It has one of the following forms:


         {variable-identifier  }
         {(expression)         } :: type-identifier

The type cast operator (::) separates the name of a variable or an expression in parentheses from its target type, the type to which it is being cast. The operator alters the type of the cast object at that point only.

Once you cast a variable or an expression, the object has all the properties of its target type during the execution of the operation in which the type cast operator appears. A variable and its target type must have the same allocation size. Therefore, you cannot cast a conformant-array parameter, but you can cast a fixed-size component of a conformant-array parameter. A schema variable or parameter cannot be type cast since it does not have a size that is known at compile time.

When you cast an expression in parentheses, the value of that expression can be either truncated on the left or padded on the left with zeros, so that the allocation size of the expression's value and its target type become the same. The type of a cast expression cannot be VARYING OF CHAR, a conformant-array parameter, or a discriminated schema. In addition, the target type of a cast expression cannot be VARYING OF CHAR or a discriminated schema.

Consider the following example:



TYPE
   F_float = PACKED RECORD
             Frac1 : 0..127;
             Expo  : 0..255;
             Sign  : BOOLEAN;
             Frac2 : 0..65535;
             END;
VAR
   A : REAL;
{In the executable section:}
A::F_float.Expo := A::F_float.Expo + 1;

In this example, the record type F_float shows the layout of an F_floating real number. The real variable A is cast as a record of this type, allowing you to access the fields containing the mantissa, exponent, sign, and fraction of A. Adding 1 to the field containing the exponent gives the same result as multiplying A by 2.0.

For More Information:

4.2.7 Precedence of Operators

The operators in an expression establish the order in which HP Pascal combines the operands. The compiler performs operations with higher-precedence operators before operations with lower-precedence operators. Table 4-8 lists the order of operator precedence, from highest to lowest (operators on the same line are of equal precedence).

Table 4-8 Precedence of Operators
Operators Precedence
:: Highest
NOT  
**  
*, /, DIV, REM, MOD, AND, AND_THEN  
+, -, OR, OR_ELSE, unary +, unary -  
=, <>, <, <=, >, >=, IN Lowest

In Pascal, operators of equal precedence (such as plus and minus) are combined from left to right within the expression.

You must use parentheses for correct evaluation of an expression that combines relational operators. Consider the following expression:


a<=x AND b<=y

Without parentheses, this expression is interpreted as A<= (X AND B) <=Y. The logical operator AND requires its operands X and B to be Boolean expressions and returns a Boolean result, which is then used as an operand in evaluating one of the relational operators (<=). This operation causes an error because you cannot use relational operators with Boolean operands. You can modify the expression with parentheses as follows:


( a<=x ) AND ( b<=y )

In the rewritten expression, the compiler combines the Boolean values of the two relational expressions with the AND operator.

You can use parentheses in an expression to force a particular order for combining the operands. For example:

Expression Result
8 * 5 DIV 2-4 16
8 * 5 DIV (2-4) -20

The compiler evaluates the first expression according to normal precedence rules.

First, 8 is multiplied by 5 and the result (40) is divided by 2. Then 4 is subtracted to get 16. The parentheses in the second expression, however, force the subtraction of 4 from 2 (yielding -2) to be performed before the division of 40 by -2. The result is -20.

Parentheses can help to clarify an expression. For instance, you could write the first example as follows:


( ( 8 * 5 ) DIV 2 ) -4

The parentheses eliminate any confusion about how the compiler associates the operands in the expression.

The desired results of your program should not depend on the order of subexpression evaluation. Unless you use the AND_THEN or
OR_ELSE operators, the compiler does not guarantee the order in which subexpressions and complex expressions are evaluated. In fact, if the result of an expression can be determined without complete evaluation, HP Pascal can partially evaluate some logical operations.

Usually the order of evaluation does not prevent the correct result from being produced. However, order of evaluation is very important when you write logical operations involving function designators that have side effects. (A side effect is an assignment to a nonlocal variable or to a variable parameter within a function block.)

For example, the following IF statement contains two function designators for function f:


IF f( a ) AND f( b ) THEN {Statement...}

The compiler can evaluate these two function designators in any order. Regardless of which function designator the compiler evaluates first, if the result is FALSE the other function designator does not have to be evaluated.

Suppose that function f assigns the value of its parameter to a nonlocal variable. Because you cannot know which function designator was evaluated first, you cannot be sure of the value of the nonlocal variable after the IF statement is performed.

For More Information:

  • On expressions ( Section 4.1)
  • On the AND_THEN or OR_ELSE logical operators ( Section 4.2.3)
  • On user-defined functions (Chapter 6)
  • On optimization, compiler switches, and order of evaluation (HP Pascal for OpenVMS User Manual)

4.3 Structured Function-Return Values

Syntactically, a function call is an expression since it returns a value. If a function returns a pointer, an array, or a record, you can directly dereference, index, or select the returned value. For example:


WRITELN( Make_Node( 10 )^.Data[1] );
WRITELN( Make_Vector( 15 )[2] );
Make_Node( 10 )^.Data[1] := 42;

4.4 Type Conversions

Because HP Pascal is a strongly typed language, you cannot normally treat a value of one type as though it were of a different type, as you can in many languages. For example, you cannot assign the character '1' to a variable of type INTEGER, because '1' is not an integer constant but a character constant. However, there are times when it makes sense to combine values of two different types because the values have some aspect in common. For example, suppose you wish to add a value of type REAL to a value of type INTEGER. This operation is legal because the value of type INTEGER is converted to its equivalent value of type REAL before the operation is performed. The result of the operation is of type REAL.

In HP Pascal, values are converted from one type to another when the conversion is required for an operation, an assignment, or a formal/actual parameter association. Before any type conversion, the arithmetic types are ranked as follows, from lowest to highest:

  • INTEGER
  • UNSIGNED
  • INTEGER64
  • UNSIGNED64
  • REAL or SINGLE
  • DOUBLE
  • QUADRUPLE

Similarly, the character types are also ranked as follows, from lowest to highest:

  • CHAR
  • PACKED ARRAY OF CHAR
  • STRING or VARYING OF CHAR strings

When values of two different arithmetic or character types are combined in an expression, the lower-ranked operand is converted to its equivalent in the higher-ranked type. The result of an operation in which conversion occurs is always of the higher-ranked type.

All conversions or assignments to values of type UNSIGNED or UNSIGNED64 are never checked for overflow. When combined with other unsigned values, negative integer values are converted to large unsigned values by the calculation of the modulus with respect to 2**32 or 2**64.

Conversions or assignments to values of type INTEGER or INTEGER64 can overflow. Overflow will be detected at run time if overflow checking is enabled. Overflow will occur if the value is outside the range -MAXINT to MAXINT for converting to INTEGER, or outside the range -MAXINT64 to MAXINT64 for converting to INTEGER64.

A special case of conversion can occur when you attempt to assign an expression of type VARYING OF CHAR STRING strings to a variable of type PACKED ARRAY OF CHAR or if you try to pass a string expression to a formal value parameter of type PACKED ARRAY OF CHAR. If the varying-length string has less than or exactly the same number of components as the packed array, the varying-length string is converted to a packed array of characters before the assignment is made and padded with blanks as necessary. If you attempt to perform this assignment with a varying-length string that has more components than the packed array, a run-time error occurs.

For More Information:


Chapter 5
Statements

HP Pascal statements specify actions to be performed and appear in executable sections. This chapter discusses the following statements:

When coding, separate statements with a semicolon (;). The semicolon is not syntactically part of a statement, so it is not included in the syntax examples in this chapter.

5.1 Assignment Statement

The assignment statement uses an assignment operator (:=) to assign a value to a variable or to a function identifier. An assignment statement has the following form:


variable-access := expression

variable-access

An identifier, array component, record component, pointer dereference, pointer-function dereference, or file buffer.

expression

A run-time expression whose type is assignment compatible with the type of the variable. The value of the expression is the value assigned to the variable.

You cannot assign values to a variable of a record type with variants if you allocated this variable using the NEW procedure. You can assign values to a field of such a record variable.

Consider the following example:


VAR
   x     : INTEGER;
   y, z  : RECORD
      f1 : real;
      f2 : integer
      END;
{In the executable section:}
x := 1;  {type of expression is same type as the variable}
y := z;  {variables are assignment compatible}
Func_Return_Ptr_To_Integer( 3 )^ := 19;

For More Information:

5.2 BREAK Statement

The BREAK statement immediately transfers control to the first statement past the end of the FOR, WHILE, or REPEAT statement that contains the BREAK statement. The BREAK statement appears as a single word:



BREAK

BREAK is equivalent to a GOTO to a label placed just past the end of the closest FOR, WHILE, or REPEAT statement. The following example shows the usage of the BREAK statement:



REPEAT
  name := GetInput('Your name?');
  IF ExitKeyPressed THEN BREAK;
  address := GetInput('Your address?');
  IF ExitKeyPressed THEN BREAK;
  Person[Num].Name := name;
  Person[Num].Addr := address;
  Num := SUCC(Num);
UNTIL Num > 50;

In the example, a user-defined function GetInput interacts with the user and sets a global Boolean variable ExitKeyPressed if the user presses an Exit key. The BREAK statement exits the loop here, without storing data in the array.

Use caution when using the BREAK statement because future additions to the code can result in the BREAK statement leaving a different loop than was originally intended.

5.3 CASE Statement

The CASE statement causes one of several statements to be executed. Execution depends on the value of an ordinal expression called the case selector. A CASE statement has the following form:


         CASE case-selector OF
            [[{{case-label-list};...: statement};...]]
            [[ [[;]] OTHERWISE {statement};... ]]
            [[;]]
         END

case-selector

An expression of an ordinal type.

case-label-list

One or more case labels of the same ordinal type as the case selector, separated by commas. A case label can be a single constant expression, such as 1, or a range of expressions, such as 5..10.

statement

Any statement to be executed depending on the values of both the case-selector and the case-label.

You can specify case labels in any order within the case-label-list. Each case label can appear only once within a given CASE statement.

At run time, the system evaluates the case selector expression and chooses which statement to execute. If the value of the case selector does not appear in the case-label-list, the system executes the statement in the OTHERWISE clause. If you omit the OTHERWISE clause, the value of the case selector must be equal to one of the case labels. If the value is not equal to a label, the CASE statement result is undefined.

Consider the following example:


CASE Age OF
   1..4   : School := 'preschool';   {Subranges}
   5..8   : School := 'elementary';
   9..13  : School := 'middle';
   14..18 : BEGIN
            School := 'high';
            WRITELN( 'Difficult years!' );
            END;                     {Compound statements}
   19     : School := 'reform';      {Single ordinal value}
   OTHERWISE  School := 'graduated'; {If 1 > Age > 18 ...}
   END;

For More Information:

5.4 Compound Statement

A compound statement groups a series of statements so that they can appear anywhere that language syntax calls for a single statement. A compound statement has the following form:


    BEGIN
        {statement};...
    END

statement

Any Pascal statement, including other compound statements.

The statements that make up the compound statement must be separated with semicolons (;), although the semicolon before the END delimiter is optional.

Consider the following example:


IF a < 10 THEN
   BEGIN        {A compound statement}
   x := 10;
   y := 20;
   z := x + y;
   END          {No semicolon in THEN clause before an ELSE}
ELSE z := 29;   {A single statement}

For More Information:

5.5 CONTINUE Statement

The body of a FOR, WHILE, or REPEAT loop can include the CONTINUE statement. The CONTINUE statement is equivalent to a GOTO to a label placed at the end of the statements in the body of the FOR, WHILE, or REPEAT statement. The CONTINUE statement appears as a single word:


CONTINUE

In a loop that processes a series of data items, you can use the CONTINUE statement to indicate that the rest of the loop does not apply to the current item, and that the program should continue to the next statement.

Use caution when using the CONTINUE statement because future additions to the code can result in the CONTINUE statement continuing with a different loop than was originally intended.


Previous Next Contents Index