[an error occurred while processing this directive]

HP OpenVMS Systems Documentation

Content starts here

HP Pascal for OpenVMS
Language Reference Manual


Previous Contents Index


Chapter 4
Expressions and Operators

This chapter discusses the following topics:

4.1 Expressions

Pascal expressions consist of one or more operands that result in a single value. If the expression contains more than one operand, the operands are separated by operators. Operands include numbers, strings, constants, variables, and function designators. Operators include arithmetic, relational, logical, string, set, and typecast operators.

Pascal recognizes two forms of expressions: constant expressions and run-time expressions. Constant expressions result in a value at the time you compile your program. These expressions can contain constants, constant identifiers, operators, and some predeclared functions. Constant expressions cannot contain the following:

  • Variable references
  • Schema discriminants
  • Bound identifiers from conformant parameters
  • Calls to user-defined functions
  • Calls to EOF and EOLN predeclared functions
  • Constructors of schema types or of types containing schema components

Run-time expressions result in a value at the time you execute your program. These expressions can contain variables, predeclared functions, user-declared functions, and everything that a constant expression cannot contain.

When you form an expression, the operands must be of the same data type. Under some circumstances, the compiler performs data type conversions and allows you to form an expression with operands of different types.

Pascal does not evaluate expressions contained within a single statement in a predictable order. Also, the compiler does not always evaluate all expressions in a single statement if the correct execution of the statement can be determined by evaluation of fewer expressions. For example, some IF statement conditions can be determined TRUE or FALSE by only evaluating one of the Boolean expressions in the condition. Do not write code that depends on the evaluation order of expressions, and, in some cases, on the evaluation of all expressions in a single statement. If you require a predictable order of evaluation, you can use the AND_THEN and OR_ELSE operators.

For More Information:

4.2 Operators

Pascal provides several classes of operators. You can form complex expressions by using operators to combine constants, constant identifiers, variables, and function designators.

Pascal also provides the assignment operator (:=) for use in assignment statements.

For More Information:

4.2.1 Arithmetic Operators

An arithmetic operator provides a formula for calculating a value.

Table 4-1 lists the arithmetic operators that you can use, in combination with numeric operands, to perform an arithmetic operation.

Table 4-1 Arithmetic Operators
Operator Example Result
+ A+B Sum of A and B
- A-B B subtracted from A
* A*B Product of A and B
** A**B A raised to the power of B
/ A/B A divided by B
DIV A DIV B Result of A divided by B
truncated toward zero
REM A REM B Remainder of A divided by B
MOD A MOD B MOD function of A with respect to B

The +, -, *, ** Operators

You can use addition, subtraction, multiplication, and exponentiation operators on integer, unsigned, real, DOUBLE, and QUADRUPLE operands. These operators produce a result of the same type as the values. In exponentiation operations, if the data types of the operands are not the same, the operand of the less precise type is converted and the result is of the more precise type.

When you use a negative integer as an exponent, the exponentiation operation can yield unexpected results. Table 4-2 shows the defined results of integers raised to the power of negative integers.

Table 4-2 Results of Negative Exponents
Base Exponent Result
0 Negative or 0 Error
1 Negative 1
-1 Negative and odd -1
-1 Negative and even 1
Any other integer Negative 0

For example, the expression 1(-3) equals 1; (-1)(-3) equals -1; (-1)(-4) equals 1; and 3(-3) equals 0.

The / Operator

You can use the division operator (/) on integer, unsigned, real, DOUBLE, and QUADRUPLE operands. The division operator always produces a real result. This result can reflect in some loss of precision as the compiler converts integer and unsigned to their real equivalents. With one or more operands of higher precision, the result is of the higher-precision type.

DIV, REM, MOD Operators

You can use the DIV, REM, and MOD operators only on integer and unsigned operands. DIV divides one integer or unsigned operand by the other, producing an integer or unsigned result. DIV truncates toward zero any remaining fraction and does not round the result. For example, the expression 23 DIV 12 equals 1, and (-5) DIV 3 equals -1.

REM returns the remainder after dividing the first operand by the second. Thus, 5 REM 3 evaluates to 2. Similarly, 3 REM 3 evaluates to 0 and (-4) REM 3 evaluates to -1.

MOD returns the remainder of A MODULO B. The result of the operation
A MOD B is defined only when B is a positive integer. This result is always an integer between 0 and B-1. The modulus of A with respect to B is computed as follows:

  • If A is greater than B, then B is subtracted repeatedly from A until the result is a nonnegative integer less than B.
  • If A is less than B and not negative, the result is A.
  • If A is less than zero, B is added repeatedly to A until the result is a nonnegative integer less than B.

For example, 5 MOD 3 equals 2, (-4) MOD 3 equals 2, and 2 MOD 5 equals 2.

When both operands are positive, the REM and MOD operators return the same result. For example, 28 REM 5 equals 3 and 28 MOD 5 equals 3. However, when the first operand is negative, REM produces a negative or zero result, while MOD produces a positive or zero result. For example, (-42) REM 8 equals -2 and (-42) MOD 8 equals 6.

Enabling subrange checking ensures that a MOD operation is legal by verifying at run time that B is a positive integer.

Note that the use of negative integer and real number constants as operands in MOD and exponentiation operations can not produce the results you expect because the minus sign (-) is actually a negation operator. For example, the expression -2.0**2 is equivalent to the expression -(2.0**2) and produces the result -4.0. Therefore, you should enclose a negative constant in parentheses to make sure that it is interpreted as you intend. The expression (-2.0)**2 produces the result 4.0.

Table 4-3 lists the result types of arithmetic operations with operands of various types.

Table 4-3 Result Types of Arithmetic Operators
Operator Type of Operands Result Type
+
-
*
**
INTEGER, INTEGER64, UNSIGNED, UNSIGNED64
REAL, DOUBLE,
QUADRUPLE
Same as the operands if both are of the same type; otherwise, the operand of the lower-ranked type is converted and the result is of the higher-ranked type.
/ INTEGER, INTEGER64, UNSIGNED, UNSIGNED64, REAL, DOUBLE, QUADRUPLE One of the real types---REAL if the operands are of type REAL (or SINGLE) or a lower-ranked type; otherwise, the operand of the lower-ranked type is converted and the result is of the higher-ranked type.
DIV
REM
MOD
INTEGER, INTEGER64,
UNSIGNED, UNSIGNED64
Same as the operands if both are of the same type; otherwise, the operand of the lower-ranked type is converted and the result is of the higher-ranked type.

For More Information:

4.2.2 Relational Operators

A relational operator tests the relationship between two ordinal, real, DOUBLE, or QUADRUPLE expressions and returns a Boolean result. If the relationship holds, the result is TRUE; otherwise, the result is FALSE. Table 4-4 lists the relational operators that you can apply to arithmetic operands. You can also apply some of the relational operators to string operands and to set operands.

Table 4-4 Relational Operators
Operator Example Result
= A = B TRUE if A is equal to B
<> A <> B TRUE if A is not equal to B
< A < B TRUE if A is less than B
<= A <= B TRUE if A is less than or equal to B
> A > B TRUE if A is greater than B
>= A >= B TRUE if A is greater than or equal to B

Note that operators designated with two characters must appear in the order specified and cannot be separated by a space.

For More Information:

4.2.3 Logical Operators

A logical operator evaluates one or more Boolean expressions and returns a Boolean value. The logical operators are listed in Table 4-5.

Table 4-5 Logical Operators
Operator Example Result
AND A AND B TRUE if both A and B are TRUE
OR A OR B TRUE if either A or B is TRUE, or if both are TRUE
NOT NOT A TRUE if A is FALSE, and FALSE if A is TRUE
AND_THEN A AND_THEN B TRUE if both A and B are TRUE; forces left-to-right evaluation order with short circuiting
OR_ELSE A OR_ELSE B TRUE if either A or B is TRUE, or if both are TRUE; forces left-to-right evaluation order with short circuiting

The AND, AND_THEN, OR, and OR_ELSE operators combine two conditions to form a compound condition. The NOT operator reverses the value of a single condition so that if A is TRUE, NOT A is FALSE, and vice versa.

The following examples show logical expressions and their Boolean results:


   {  Expressions:                      Results: }
( 4 > 3 ) AND ( 18 = 3 * 6 )            {TRUE}
( 3 > 4 ) OR  ( 18 = 3 * 6 )            {TRUE}
NOT ( 4 <> 5 )                          {FALSE}
( i < 11 ) AND_THEN ( Array_A[i] = 0 )  {Not known}
p = NIL  OR_ELSE  p^ = 0                {Not known}
You can use Boolean variables and functions as operands in logical expressions. Consider the following example:


Flag AND ODD( i )

Suppose that Flag is a Boolean variable and ODD( i ) is a function that returns TRUE if the value of the integer variable i is odd and FALSE if the value of i is even. Both operands, Flag and ODD( i ), must be TRUE for the expression to be TRUE.

Normally, the compiler does not guarantee the evaluation order for logical operations. The AND_THEN and OR_ELSE operators force the compiler to evaluate an expression from left to right, stopping when the overall result can be determined (also called short circuiting). The following example forces the compiler to verify that an array element is within index bounds before evaluating the element's contents:


IF ( i < 11 ) AND_THEN ( Array_A[i] = 0 ) THEN
   WRITELN( 'Index bounds are legal and element contained 0' );

The precedence of AND_THEN and OR_ELSE is the same as AND and OR, respectively. Because the Pascal language associates parameters of operands at the same precedence level from left to right, you might not get the answer you expect. For example, in this code you might expect the AND_THEN to guard all the expressions to its right:


IF (PTR <> NIL) AND_THEN (P^.DATA1 = 0) AND (P^.DATA2 = 1) THEN ...

However, AND_THEN is at the same precedence level as AND, so the previous expression is equivalent to:


IF ((PTR <> NIL) AND_THEN (P^.DATA1 = 0)) AND (P^.DATA2 = 1) THEN ...

Given this assocation and the fact that the two operands of the AND operator can be evaluated in any order, the compiler might evaluate P^.DATA2 = 1 without it being guarded by the PTR <> NIL test.

To guard both dereferences to P, you must use parentheses as shown in this example:


IF (PTR <> NIL) AND_THEN ((P^.DATA1 = 0) AND (P^.DATA2 = 1)) THEN ...

Alternatively, you can replace all the occurrences of AND and OR with AND_THEN and OR_ELSE, repectively. For example,


IF (PTR <> NIL) AND_THEN (P^.DATA1 = 0) AND_THEN (P^.DATA2 = 1) THEN ...

For More Information:

4.2.4 String Operators

A string operator concatenates or compares character-string expressions. The result of the operation is either a string or a Boolean value. Table 4-6 lists the string operators.

Table 4-6 String Operators
Operator Example Result
+ A+B String that is the concatenation of strings
A and B
= A=B TRUE if strings A and B have equal ASCII values
<> A<>B TRUE if strings A and B have unequal ASCII values
< A<B TRUE if ASCII value of string A is less than that of string B
<= A<=B TRUE if ASCII value of string A is less than or equal to that of string B
> A>B TRUE if ASCII value of string A is greater than that of string B
>= A>=B TRUE if ASCII value of string A is greater than or equal to that of string B

With the plus sign (+), you can concatenate any combination of STRING and VARYING character strings, packed arrays of characters, and single characters.

The result of a string comparison depends on the ordinal value in the ASCII character set of the corresponding characters in the strings. For example:


'motherhood' > 'cherry pie'

This relational expression is TRUE because lowercase 'm' comes after lowercase 'c' in the ASCII character set. If the first characters in the strings are the same, Pascal searches for differing characters, as in the following example:


'string1' < 'string2'

This expression is TRUE because the digit 1 precedes the digit 2 in the ASCII character set.

The relational operators are legal for testing character strings of different lengths as well as for testing character strings of the same lengths. The shorter of the two character strings is padded with blanks for the comparison. The following two strings, for instance, result in a value of TRUE:


'John' < 'Johnny'
'abc' = 'abc   '

The EQ, NE, GE, GT, LE, and LT predeclared routines make string comparisons that are similar to the relational operators, but these routines do not pad strings of unequal length with blanks. Instead, they halt string comparison when they detect unequal lengths.

If you are comparing the equality or inequality of very large strings, it is sometimes more efficient to use the EQ and NE functions instead of the = and <> operators. When using the operators, HP Pascal compares each string, character by character, until detecting either a difference or the end of one string. When you use the functions, HP Pascal sometimes detects different string lengths without comparing the strings character by character.

When trying to determine the length of a string, you can use either the LENGTH function, or the .LENGTH component of a STRING (or VARYING OF CHAR) type. The LENGTH routine and .LENGTH provide the same value. Consider the following example:


VAR
   One_String : STRING( 25 ) VALUE 'Harvey Fierstein';
{In the executable section:}
WRITELN( One_String.LENGTH, LENGTH( One_String ) );

The WRITELN call writes 16 and 16 to the predeclared file OUTPUT (by default, to your terminal).

Enabling bounds checking causes the length of all character strings to be checked at run time for illegal operations.

For More Information:


Previous Next Contents Index