[an error occurred while processing this directive]
HP OpenVMS Systems Documentation |
HP Pascal for OpenVMS
|
Previous | Contents | Index |
This chapter discusses the following topics:
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:
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.
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.
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.
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 |
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.
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.
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.
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:
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.
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. |
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.
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.
A logical operator evaluates one or more Boolean expressions and returns a Boolean value. The logical operators are listed in Table 4-5.
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} |
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 ... |
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.
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.
Previous | Next | Contents | Index |