7.3. Interpretation of Expressions

The interpretation of an expression specifies the value of the expression when it is evaluated. As with the rules for forming an expression, the rules for interpreting an expression are described from the bottom up, from the interpretation of constants, variables, constructors, and functions to the interpretation of each subexpression to the interpretation of the entire expression.

When an expression is interpreted, the value of each constant and variable is determined. After these are determined, the operations for which the variables and constants are interpreted in precedence order, and a value for the operation is determined by the interpretation rules for each operator. This repeats recursively until the entire expression is interpreted and a value is determined.

The interpretation rules for operations are of two sorts: rules for the intrinsic operations (intrinsic operators with operands of the intrinsic types specified by Table 7-17) and rules for the defined operations (provided by the programmer using function subprograms). Except for integer division, the intrinsic operations are interpreted by the usual mathematical method, subject to representation limitations imposed by a computer (for example, a finite range of integers, or finite precision of real numbers). The defined operations are interpreted by a function program that is specified in an interface block with a generic specifier of the form OPERATOR(defined_operator).

The interpretation rules for an intrinsic or a defined operation are independent of the context in which the expression occurs. That is, the type, type parameters, and interpretation of any expression do not depend on any part of a larger expression in which it occurs.

7.3.1. Interpretation of the Intrinsic Operations

When the arguments of the intrinsic operators satisfy the requirements of Table 7-17, the operations are intrinsic and are interpreted in the usual mathematical way as described in Table 7-21, except for integer division. For example, the binary operator * is interpreted as the mathematical operation multiplication and the unary operator - is interpreted as negation.

Table 7-21. Interpretation of the Intrinsic Operations

Use of operator

Interpretation

x1 ** x2

Raise x1 to the power x2

x1 / x2

Divide x1 by x2

x1 * x2

Multiply x1 by x2

x1 - x2

Subtract x2 from x1

- x2

Negate x2

x1 + x2

Add x1 and x2

+ x2

Same as x2

x1 // x2

Concatenate x1 with x2

x1 .LT. x2

x1 less than x2

x1 < x2

x1 less than x2

x1 .LE. x2

x1 less than or equal to x2

x1 <= x2

x1 less than or equal to x2

x1 .GT. x2

x1 greater than x2

x1 > x2

x1 greater than x2

x1 .GE. x2

x1 greater than or equal to x2

x1 >= x2

x1 greater than or equal to x2

x1 .EQ. x2

x1 equal to x2

x1 == x2

x1 equal to x2

x1 .NE. x2

x1 not equal to x2

x1 /= x2

x1 not equal to x2

x1 .LG. x2

x1 less than or greater than x2

x1 <> x2

x1 less than or greater than x2

.NOT. x2

True if x2 is false

x1 .AND. x2

True if x1 and x2 are both true

x1 .OR. x2

True if x1 and/or x2 is true

x1 .NEQV. x2

True if either x1 or x2 is true, but not both

x1 .XOR. x2

1 if corresponding bits differ; 0 otherwise (bitwise exclusive .OR.)

x1 .EQV. x2

True if both x1 or x2 are true or both are false

7.3.1.1. Interpretation of Numeric Intrinsic Operations

Except for exponentiation to an integer power, when an operand for a numeric intrinsic operation does not have the same type or type parameters as the result of the operation, the operand is converted to the type, type parameter, and shape of the result and the operation is then performed. For exponentiation to an integer power, the operation can be performed without the conversion of the integer power, say, by developing binary powers of the first operand and multiplying them together to obtain an efficient computation of the result.

For integer division, when both operands are of type integer, the result is of type integer, but the mathematical quotient is often not an integer. In this case, the result is specified to be the integer value closest to the quotient and between zero and the quotient inclusively.

For exponentiation, there are three cases that need to be further described. When both operands are of type integer, the result is of type integer; when x2 is negative, the operation x1 ** x2 is interpreted as the quotient 1/(x1**ABS(x2)). Note that it is subject to the rules for integer division. For example, 4**(-2) is 0.

The second case occurs when the first operand is a negative value of type integer or real and the second operand is of type real. A program is invalid if it causes a reference to the exponentiation operator with such operands. For example, a program that contains the expression (-1.0)**0.5 is an invalid program.

The third case occurs when the second operand is of type real or of type complex. In this case, the result returned is the principal value of the mathematical power function.

7.3.1.2. Interpretation of Standard Nonnumeric Intrinsic Operations

There is only one intrinsic character operation: concatenation. For this operation, the operands must be of type character. The length parameter values can be different. The result is of type character with a character length parameter value equal to the sum of the lengths of the operands. The result consists of the characters of the first operand in order followed by those of the second operand in order. For example, 'Fortran' // '95' yields the result 'Fortran95'.

The intrinsic relational operations perform comparison operations for character and most numeric operands. For these operations, the operands must both be of numeric type or both be of character type. The kind type parameter values of the operands of the numeric types can be different and the lengths of character operands can be different. Complex operands must only be compared for equality and inequality; the reason is that complex numbers are not totally ordered. The result in all cases is of type default logical.

When the operands of an intrinsic relational operation are both numeric, but of different types or type parameters, each operand is converted to the type and type parameters they would have if the two operands were being added. Then, the operands are compared according to the usual mathematical interpretation of the particular relational operator.

When the operands are both of type character, the shorter one is padded on the right with blank padding characters until the operands are of equal length. Then, the operands are compared one character at a time in order, starting from the left-most character of each operand until the corresponding characters differ. The first operand is less than or greater than the second operand according to whether the characters in the first position where they differ are less than or greater than each other. The operands are equal if both are of zero length or all corresponding characters are equal, including the padding characters.

There is no ordering defined for logical values. However, logical values can be compared for equality and inequality by using the logical equivalence and not equivalence operators .EQV. and .NEQV.. That is, L1 .EQV. L2 is true when L1 and L2 are both true or both false and is false otherwise. L1 .NEQV. L2 is true if either L1 or L2 is true (but not both true) and is false otherwise.

The intrinsic logical operations perform many of the common operations for logical computation. For these operations, the operands must both be of logical type but can have different kind type parameters. If the kind type parameter values are the same, the kind type parameter value of the result is the kind type parameter value of the operands. If the kind type parameter values are different, the kind type parameter value is the larger of the two kind type parameter values. The values of the result in all cases are specified in Table 7-22.

Table 7-22. The Values of Operations Involving Logical Operators

x1

x2

.NOT.x1

x1.AND.x2

x1.OR.x2

x1.EQV.x2

x1.NEQV.x2

True

True

False

True

True

True

False

True

False

False

False

True

False

True

False

True

True

False

True

False

True

False

False

True

False

False

True

False

7.3.1.3. Interpretation of Intrinsic Operations with Array Operands

Each of the intrinsic operations can have array operands; however, for the binary intrinsic operations, the operands must both be of the same shape, if both are arrays. When one operand is an array and the other is a scalar, the operation behaves as if the scalar operand were broadcast to an array of the result shape and the operation performed.

For both the unary and binary intrinsic operators, the operation is interpreted element-by-element; that is, the scalar operation is performed on each element of the operand or operands. For example, if A and B are arrays of the same shape, the expression A * B is interpreted by taking each element of A and the corresponding element of B and multiplying them together using the scalar intrinsic operation * to determine the corresponding element of the result. Note that this is not the same as matrix multiplication. As a second example, the expression -A is interpreted by taking each element of A and negating it to determine the corresponding element of the result.

For intrinsic operations that appear in masked assignment statements (in WHERE blocks, ELSEWHERE blocks, or in a WHERE statement), the scalar operation is performed only for those elements selected by the logical mask expression.

Note that there is no order specified for the interpretation of the scalar operations. A processor is allowed to perform them in any order, including all at the same time.

7.3.1.4. Interpretation of Intrinsic Operations with Pointer Operands

The intrinsic operations can have operands with the POINTER attribute. In such cases, each pointer must be associated with a target that is defined, and the value of the target is used as the operand. The target can be scalar or array-valued; the rules for interpretation of the operation are those appropriate for the operand being a scalar or an array, respectively.

Recall that an operand can be a structure component that is the component of a structure variable that is itself a pointer. In this case, the value used for the operand is the named component of the target structure associated with the structure variable. For example, consider the following declarations and assume that the pointer PTR is associated with T:

TYPE RATIONAL
   INTEGER :: N, D
END TYPE

TYPE(RATIONAL), POINTER :: PTR
TYPE(RATIONAL), TARGET  :: T

If PTR%N appears as an operand, its value is the component N of the target T, namely T%N.

7.3.2. Interpretation of Defined Operations

The interpretation of a defined operation is provided by a function subprogram with an OPERATOR interface (see the Fortran Language Reference Manual, Volume 2). When there is more than one function with the same OPERATOR interface, the function giving the interpretation of the operation is the one whose dummy arguments match the operands in order, types, kind type parameters, and rank. For example, for the operation A .PLUS. B, where A and B are structures of the derived type RATIONAL, the following interface specifies that the function RATIONAL_PLUS provides the interpretation of this operation.

Example:

INTERFACE OPERATOR(.PLUS.)

   FUNCTION RATIONAL_PLUS(L, R)
      USE RATIONAL_MODULE
      TYPE(RATIONAL), INTENT(IN) :: L, R
      TYPE(RATIONAL)          :: RATIONAL_PLUS
   END FUNCTION RATIONAL_PLUS

   FUNCTION LOGICAL_PLUS(L, R)
      LOGICAL, INTENT(IN) :: L, R
      LOGICAL              :: LOGICAL_PLUS
   END FUNCTION LOGICAL_PLUS

END INTERFACE

A defined operation is declared by using a function with one or two dummy arguments. (Note that the function can be an entry in an external or module function.)

The dummy arguments to the function represent the operands of the operation. If there is only one, the operation is a unary operation; otherwise it is a binary operation. For a binary operation, the first argument is the left operand and the second is the right operand.

There must be an interface block for the function with the generic specifier of the form OPERATOR (defined_operator).

The types and kind type parameters of the operands in the expression must be the same as those of the dummy arguments of the function.

The function is elemental or the rank of the operands in the expression must match the ranks of the corresponding dummy arguments of the function.

One of the following conditions must be true:

As with the intrinsic operations, the type, type parameters, and interpretation of a defined operation are independent of the context of the larger expression in which the defined operation appears. The interpretation of the same defined operation in different contexts is the same, but the results can be different because the results of the procedure being invoked may depend on values that are not operands and that are different for each invocation.

The relational operators ==, /=, >, >=, <, <, and <> are synonyms for the operators .EQ., .NE., .GT., .GE., .LT., .LE., and .LG.even when they are defined operators. It is invalid, therefore, to have an interface block for both == and .EQ., for example, for which the order, types, type parameters, and rank of the dummy arguments of two functions are the same.

Note: The Fortran standard does not describe the <> or .LG. operators.

Defined operations are either unary or binary. An existing unary operator (that is, one that has the same name as an intrinsic operator) cannot be defined as a binary operator unless it is also a binary operator. Similarly, an existing binary operator cannot be defined as a unary operator unless it is also a unary operator. However, a defined operator, .PLUS. say, (that is, one that does not have a name that is the same as an intrinsic operator) can be defined as both a unary and binary operator.