7.2. Formation of Expressions

An expression is formed from operands, operators, and parentheses. The simplest form of an expression is a constant or a variable.

Expression 

Meaning

3.1416 

A real constant

.TRUE. 

A logical constant

X 

A scalar variable

Y 

An array variable

Y(K) 

A variable that is an array element of Y

Y(2:10:2) 

A variable that is an array subsection of Y

M%N 

A variable that is a component of a structure M

Y(K)(I:I+3) 

A variable that is a substring of array element Y(K)

The values of these simple expressions are the constant value 3.1416, the constant value .TRUE., the value of the variable X, the value of the array Y, the value of the array element Y(K), the value of the array subsection Y(2:10:2), the value of the component N of structure M, and the value of a substring of an array element Y(K), respectively.

7.2.1. Operands

An operand in an expression can be one of the following items:

The following examples show operands:

A              ! scalar or an array
B(1)           ! array element or function
C(3:5)         ! array section or a substring
(A + COS(X))   ! expression in parentheses
(/ 1.2, 2.41 /)! array constructor
RATIONAL(1,2)  ! structure constructor or function
I_PTR          ! pointer to an integer target

7.2.2. Binary and Unary Operations

There are two forms that operations can take in an expression. One is an operation involving two operands, such as multiplying two numbers together. The other is an operation on one operand, such as making a number negative. These forms are called binary and unary operations, respectively.

Table 7-1 lists the intrinsic operators. You can use function subprograms to define additional operators. User-defined operators are either binary or unary operators.

Table 7-1. Intrinsic Operators and the Allowed Types of their Operands

Operator category

Intrinsic operator

Operand types

Arithmetic

**, *, /, +, -, unary +, unary -

Numeric of any combination of numeric types and kind type parameters or Cray pointer. Cray pointers are only allowed with the + or - operators.

Character

//

Character of any length.

Relational

.EQ., .NE., ==, /=

Both of any numeric type and any kind type parameter or Cray pointer, or both of type character with any character length parameter.

Relational

.GT., .GE., .LT., .LE., >, >=, <, <=

Both of any numeric type (except complex) and any kind type parameter or Cray pointer, or both of type character with any character length parameter.

Logical

.NOT., .AND., .OR., .XOR., .EQV., .NEQV.

Both of type logical with any combination of kind type parameters.

Bitwise masking (Boolean) expressions (EXT)

.NOT., .AND., .OR., .XOR., .EQV., .NEQV.

Integer, real, typeless, or Cray pointer.

Note: The Fortran standard does not specify the bitwise masking (Boolean) expressions, nor does it specify the .XOR. operator as a logical operator.

A binary operator combines two operands, as in the following:

x1 operator x2

Examples:

A + B
2 * C

The examples show an addition between two operands A and B, and a multiplication of two operands, the constant 2 and the operand C.

A unary operation acts on one operand, as in the following:

operator x1

Examples:

- C
.NOT. L

The first example results in the value minus C. The second example produces a value that is the logical complement of L; the operator .NOT. is the only intrinsic operator that is a unary operator and is never a binary operator.

7.2.3. Intrinsic and Defined Operations

Intrinsic operations are those whose definitions are known to the compiler. They are built into Fortran and are always available for use in expressions. Table 7-1, lists the operators built into Fortran as specified by the standard.

The relational operator symbols ==, /=, >, >=, <, and <= are synonyms for the operators .EQ., .NE., .GT., .GE., .LT., and .LE., respectively.

The less than or greater than operation is represented by the <> operator and the .LG. keyword. This operation is suggested by the IEEE standard for floating-point arithmetic, and the Cray Fortran Compiler supports this operator. Only values of type real can appear on either side of the <> or .LG. operators. If the operands are not of the same kind type value, the compiler converts them to equivalent kind types. The <> and .LG. operators perform a less-than-or-greater-than operation as specified in the IEEE standard for floating-point arithmetic.

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

The Cray Fortran Compiler allows abbreviations for the logical and masking operators. The abbreviations .A., .O., .N., and .X. are synonyms for .AND., .OR., .NOT., and .XOR., respectively. If you define the abbreviated operator for any type, the abbreviated form of the intrinsic operator cannot be used in any scope in which the defined operator is accessible.

Note: The Fortran standard does not specify abbreviations for the logical and masking operators.

In addition to the Fortran operators that are intrinsic (built in), there may be user-defined operators in expressions.

Defined operations are those that you define in the Fortran program and are made available to each program unit that uses them. The computation performed by a defined operation is described explicitly in a function that must appear as a subprogram in the Fortran program where it is used. The operator used in a defined operation is called a defined operator. In this way, you extend the repertoire of operations so that computations can be expressed in a natural way using operator notation. Function subprograms that define operators are explained in detail in the Fortran Language Reference Manual, Volume 2.

A defined operator uses a symbol that is either the symbol for an intrinsic operator or is a new operator symbol. The synonyms described above for the relational operators remain synonyms in all contexts, even when there are defined operators. For example, if the operator < is defined for a new type, say STRING, the same definition applies to the operator .LT. for the type STRING; if the operator .LT. is specified as private, the operator < is also private.

A distinction is made between a defined (or new) operator and an extended intrinsic operator. An extended intrinsic operator is one that uses the same symbol as an intrinsically defined Fortran operator, like plus + or multiply *. It also causes the operations to be combined in the same order as is specified for the intrinsic operator. A defined operator is one where the operator symbol is not the same as an intrinsic operator but is new, such as the .INVERSE. operator. Defined operators, however, have a fixed precedence; defined unary operators have the highest precedence of all operators, and defined binary operators have the lowest precedence of all operators. The precedences of all operators are described in more detail in Section 7.2.5.

A defined elemental operation is a defined operation for which the function is elemental.

Note: The masking or Boolean operators and their abbreviations, which are extensions to Fortran, can be redefined as defined operators. If you redefine a masking operator, your definition overrides the intrinsic masking operator definition. See Table 7-1, for a list of the operators.

7.2.4. Rules for Forming Expressions

Expressions are formed by combining operands. Operands can be constants, variables (scalars, array elements, arrays, array sections, structures, structure components, and pointers), array constructors, structure constructors, functions, and parenthesized expressions with intrinsic and defined operators.

The method used to specify the expression formation rules is a collection of syntax rules that determine the forms of expressions. The order of evaluation of the operations in an expression is determined by the usual semantics for the operations, and the syntax rules are designed to be consistent with these semantics. In fact, the order of evaluation defines a precedence order for operators that is summarized in Table 7-2.

Table 7-2. The Hierarchy of Expressions Through Forms

Term

Definition

expression

[ expression defined_operator ] equivalence_expression

equivalence_expression

[ equivalence_expression .EQV. ] disjunct_expression equivalence_expression .NEQV. disjunct_expression

Exclusive OR (extension)

[ disjunct_expression .XOR. ] conjunct_expression

disjunct_expression

[ disjunct_expression .OR. ] conjunct_expression

conjunct_expression

[ conjunct_expression .AND. ] not_expression

not_expression

[ .NOT. ] comparison_expression

comparison_expression

[ concatenation_expression relational_operator ] concatenation_expression

concatenation_expression

[ concatenation_expression // ] summation_expression

summation_expression

[ summation_expression + ] multiplication_expression summation_expression - multiplication_expression

+ multiplication_expression

- multiplication_expression

multiplication_expression

[ multiplication_expression * ] exponentiation_expression multiplication_expression / exponentiation_expression

exponentiation_expression

defined_unary_expression [ ** exponentiation_expression ]

defined_unary_expression

[ defined_operator ] primary

primary

constant

constant_subobject

variable

array_constructor

structure_constructor

function_reference

(expression)

The set of syntax rules defines an expression at the highest level in terms of operators and operands, which are themselves expressions. As a result, the formal set of rules is recursive. The basic or lowest level of an expression is a primary, which, for example, can be a variable, a constant, or a function, or recursively an expression enclosed in parentheses. The rules for forming expressions are described from the lowest or most primitive level to the highest or most complex level; that is, the rules are stated from a primary up to an expression.

7.2.4.1. Primary

A primary is defined as follows:

Table 7-3.

 

primary

is

constant

 

 

or

constant_subobject

 

 

or

variable

 

 

or

array_constructor

 

 

or

structure_constructor

 

 

or

function_reference

 

 

or

(expr)

 

constant_subobject

is

subobject

A variable that is a primary must not be a whole assumed-size array or a section of an assumed-size array name, unless the last subscript position of the array is specified with a scalar subscript or a section subscript in which the upper bound is specified.

The following examples show primaries:

Primary 

Meaning

3.2 

A real constant

ONE 

A named constant

'ABCS'(I:I) 

A constant subobject

A 

A variable (scalar, array, structure, or pointer)

B(:,1:N) 

An assumed-size array with an upper bound in the last dimension

C(I) 

An array element

CH(I:J) 

A substring

(/ 1, J, 7 /) 

An array constructor

RATIONAL(I, J) 

A structure constructor

FCN(A) 

A function reference

(A * B) 

A parenthesized expression

In the previous examples, ONE is a named constant if it has the PARAMETER attribute or appears in a PARAMETER statement. 'ABCS'(I:I) is a constant subobject even though I may be a variable because its parent ('ABCS') is a constant; the reference 'ABCS'(I:I) is a constant subobject because it cannot be defined like a variable can be defined. RATIONAL is a derived type and FCN is a user-defined function.

When an array variable is a primary, the whole array is used, except in a masked assignment statement. In a masked assignment statement, only that part of the array specified by the mask is used.

When a pointer is a primary, the target associated with (pointed to by) the pointer is used, except possibly when the pointer is an actual argument of a procedure, or is an operand of a defined operation or a defined assignment. Whether the pointer or the target is used in these exceptional cases is determined by the procedure invoked by the reference.

Recall that an assumed-size array is a dummy argument whose shape is not completely specified in the subprogram in that the extent in the last dimension is determined by its corresponding actual argument. The implementation model is that the extent in the last dimension is never known to the subprogram but is specified by the use of a subscript, section subscript, or vector subscript expression that defines an upper bound in the last dimension. Unless the extent is specified in this way, such an object must not be used as a primary in an expression. On the other hand, if a subscript, section subscript with an extent for the upper bound, or a vector subscript is specified for the last dimension, the array value has a well-defined shape and hence can be used as a primary in any expression. For example, if A is declared as REAL A(3,*), array A(:,3) has a well-defined shape and can be used as a primary in an expression.

Expressions can be used as actual arguments in procedure references (function references or subroutine calls). Because actual arguments can be expressions involving operations, actual arguments must not contain assumed-size arrays, unless their shape is well-defined, as described above. An actual argument, however, can be just a variable, which then allows the actual argument to be the name of an assumed-size array. This implies that such actual arguments can be assumed-size arrays, unless the procedure requires the shape of the argument to be specified by the actual argument. Most of the intrinsic procedures that allow array arguments require the shape to be specified for the actual array arguments, and therefore assumed-size arrays cannot be used as actual arguments for most intrinsic functions. The exceptions are all references to the intrinsic function LBOUND(3i), and certain references to the intrinsic functions UBOUND(3i) and SIZE(3i).

7.2.4.2. Defined Unary Expression

Defined unary expressions have the highest operator precedence. A defined unary expression is a defined operator followed by a primary. These are defined as follows:

Table 7-4.

 

defined_unary_expr

is

[ defined_operator ] primary

 

defined_operator

is

. letter [ letter ] ... .

A defined operator must not contain more than 31 letters.

A defined operator must not be the same as any intrinsic operator (.NOT., .AND., .OR., .EQV., .NEQV., .EQ., .NE., .GT., .GE., .LT., .LE., or .LG.) or any logical literal constant (.FALSE. or .TRUE.).

Note: The Fortran standard does not describe the .LG. operator.

A defined operator can be the same as one of the masking or Boolean operators supported by the Cray Fortran Compiler as an extension to the Fortran standard. The corresponding Cray Fortran operator loses its intrinsic properties. Note that the abbreviations .T., .F., .A., .O., .N., and .X. are synonyms for .TRUE., .FALSE., .AND., .OR., .NOT., and .XOR., respectively. If you define the abbreviated operator for any type, the abbreviated form of the intrinsic operator also cannot be used in any scope in which the defined operator is accessible, and the redefined abbreviated logical constants can no longer be used as logical constants.

The following examples show defined unary expressions:

Expression 

Meaning

.INVERSE. B 

A defined unary expression (where .INVERSE. is a defined operator)

A 

A primary is also a defined unary expression

7.2.4.3. Exponentiation Expression

An exponentiation expression is an expression in which the operator is the exponentiation operator **. This is defined as follows:

Table 7-5.

 

exponentiation_expr

is

defined_unary_expr [ ** exponentiation_expr  ]

Note that the definition is right recursive (that is, the defined term appears to the right of the operator **) which indicates that the precedence of the ** operator in contexts of equal precedence is right-to-left. Thus, the interpretation of the expression A ** B ** C is A ** ( B ** C ).

The following examples show exponentiation expressions:

Expression 

Meaning

A ** B 

An exponentiation expression

A ** B ** C 

An exponentiation expression with right-to-left precedence

.INVERSE. B 

A defined unary expression is also an exponentiation expression

A 

A primary is also an exponentiation expression

7.2.4.4. Multiplication Expression

A multiplication expression is an expression in which the operator is either * or /. It is defined as follows:

Table 7-6.

 

multiplication_expr

is

[ multiplication_expr * ] exponentiation_expr 

 

 

or

[ multiplication_expr / ]  exponentiation_expr

Note that the definition is left recursive (that is, the defined term appears to the left of the operator * or /) which indicates that the precedence of the * and / operators in contexts of equal precedence is left-to-right. Thus, the interpretation of the expression A * B * C is (A * B) * C, or A / B * C is (A / B) * C. This left-to-right precedence rule applies to the remaining binary operators except the relational operators.

The following examples show multiplication expressions:

Expression 

Meaning

A * B 

A multiplication expression

A * B * C 

A multiplication expression with left-to-right precedence

A / B 

A multiplication expression

A / B / C 

A multiplication expression with left-to-right precedence

A ** B 

An exponentiation expression is also a multiplication expression

.INVERSE. B 

A defined unary expression is also a multiplication expression

A 

A primary is also a multiplication expression

7.2.4.5. Summation Expression

A summation expression is an expression in which the operator is either + or -. It is defined as follows:

Table 7-7.

 

summation_expr

is

[[ summation_expr ] + ]  multiplication_expr

 

 

or

[ [ summation_expr ] - ]  multiplication_expr

The following examples show summation expressions:

Expression 

Meaning

A + B 

A summation expression

A + B - C 

A summation expression with left-to-right precedence

- A - B - C 

A summation expression with left-to-right precedence

+ A 

A summation expression using unary +

- A 

A summation expression using unary -

A * B 

A multiplication expression is also a summation expression

A ** B 

An exponentiation expression is also a summation expression

.INVERSE. B 

A defined unary expression is also a summation expression

A 

A primary is also a summation expression

7.2.4.6. Concatenation Expression

A concatenation expression is an expression in which the operator is //. It is defined as follows:

Table 7-8.

 

concatenation_expr

is

[ concatenation_expr // ]  summation_expr

The following examples show concatenation expressions:

Expression 

Meaning

A // B 

A concatenation expression

A // B // C 

A concatenation expression with left-to-right precedence

A - B 

A summation expression is also a concatenation expression

- A 

A summation expression is also a concatenation expression

A * B 

A multiplication expression is also a concatenation expression

A ** B 

An exponentiation expression is also a concatenation expression

.INVERSE. B 

A defined unary expression is also a concatenation expression

A 

A primary is also a concatenation expression

7.2.4.7. Comparison Expression

A comparison expression is an expression in which the operator is a relational operator. It is defined as follows:

Table 7-9.

 

comparison_expr

is

[ concatenation_expr rel_op ]  concatenation_expr

 

rel_op

is

.EQ.

 

 

or

.NE.

 

 

or

.LT.

 

 

or

.LE.

 

 

or

.GT.

 

 

or

.GE.

EXT

 

or

.LG.

 

 

or

==

 

 

or

/=

 

 

or

<

 

 

or

<=

 

 

or

>

 

 

or

>=

EXT

 

or

<>

The operators ==, /=, <, <=, >, >=, and <> are synonyms in all contexts for the operators .EQ., .NE., .LT., .LE., .GT., .GE., and .LG., respectively.

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

Note that the definition of a comparison expression is not recursive, and therefore comparison expressions cannot contain relational operators in contexts of equal precedence.

The following examples show comparison expressions:

Expression 

Meaning

A .EQ. B 

A comparison expression

A < B 

A comparison expression

A // B 

A concatenation expression is also a comparison expression

A - B 

A summation expression is also a comparison expression

- A 

A summation expression is also a comparison expression

A * B 

A multiplication expression is also a comparison expression

A ** B 

An exponentiation expression is also a comparison expression

.INVERSE. B 

A defined unary expression is also a comparison expression

A 

A primary is also a comparison expression

7.2.4.8. Not Expression

A not expression is an expression in which the operator is .NOT.. It is defined as follows:

Table 7-10.

 

not_expr

is

[ .NOT. ] comparison_expr

Note that the definition of a not expression is not recursive, and therefore not expressions cannot contain adjacent .NOT. operators.

The following examples show not expressions:

Expression 

Meaning

.NOT. A 

A not expression

A .EQ. B 

A comparison expression is also a not expression

A // B 

A concatenation expression is also a not expression

A - B 

A summation expression is also a not expression

- A 

A summation expression is also a not expression

A * B 

A multiplication expression is also a not expression

A ** B 

An exponentiation expression is also a not expression

.INVERSE. B 

A defined unary expression is also a not expression

A 

A primary is also a not expression

7.2.4.9. Conjunct Expression

A conjunct expression is an expression in which the operator is .AND.. It is defined as follows:

Table 7-11.

 

conjunct_expr

is

[ conjunct_expr .AND. ]  not_expr

Note that the definition of a conjunct expression is left recursive, and therefore the precedence of the .AND. operator in contexts of equal precedence is left-to-right. Thus, the interpretation of the expression A .AND. B .AND. C is (A .AND. B) .AND. C.

The following examples show conjunct expressions:

Expression 

Meaning

A .AND. B 

A conjunct expression

A .AND. B .AND. C 

A conjunct expression with left-to-right precedence

.NOT. A 

A not expression is also a conjunct expression

A .EQ. B 

A comparison expression is also a conjunct expression

A // B 

A concatenation expression is also a conjunct expression

A - B 

A summation expression is also a conjunct expression

- A 

A summation expression is also a conjunct expression

A * B 

A multiplication expression is also a conjunct expression

A ** B 

An exponentiation expression is also a conjunct expression

.INVERSE. B 

A defined unary expression is also a conjunct expression

A 

A primary is also a conjunct expression

7.2.4.10. Inclusive Disjunct Expression

An inclusive disjunct expression is an expression in which the operator is .OR.. It is defined as follows:

Table 7-12.

 

inclusive_disjunct_expr

is

[ inclusive_disjunct_expr .OR. ]  conjunct_expr

Note that the definition of an inclusive disjunct expression is left recursive, and therefore the precedence of the .OR. operator in contexts of equal precedence is left-to-right. Thus, the interpretation of the expression A .OR. B .OR. C is (A .OR. B) .OR. C.

The following examples show inclusive disjunct expressions:

Expression 

Meaning

A .OR. B 

An inclusive disjunct expression

A .OR. B .OR. C 

An inclusive disjunct expression with left-to-right precedence

A .AND. B 

A conjunct expression is also an inclusive disjunct expression

.NOT. A 

A not expression is also an inclusive disjunct expression

A .EQ. B 

A comparison expression is also an inclusive disjunct expression

A // B 

A concatenation expression is also an inclusive disjunct expression

A - B 

A summation expression is also an inclusive disjunct expression

- A 

A summation expression is also an inclusive disjunct expression

A * B 

A multiplication expression is also an inclusive disjunct expression

A ** B 

An exponentiation expression is also an inclusive disjunct expression

.INVERSE. B 

A defined unary expression is also an inclusive disjunct expression

A 

A primary is also an inclusive disjunct expression

7.2.4.11. Equivalence Expressions and Exclusive Disjunct Expressions

An equivalence expression is an expression in which the operator is either .EQV. or .NEQV.. It is defined as follows:

Table 7-13.

 

equivalence_expr

is

[ equivalence_expr .EQV. ] inclusive_disjunct_expr 

 

 

or

[ equivalence_expr .NEQV. ]  inclusive_disjunct_expr

An exclusive disjunct expression is an expression in which the operator is .XOR.. It is defined as follows:

Table 7-14.

EXT

exclusive_disjunct_expr

is

[ exclusive_disjunct_expr .XOR. ]  inclusive_disjunct_expr

Note: The Fortran standard does not specify the .XOR. operator.

Note the following:

  • In the following discussion, equivalence expression means either equivalence expression or exclusive disjunct expression.

  • The definition of an equivalence expression is left recursive, and therefore the precedence of the .EQV. or .NEQV. operators in contexts of equal precedence is left-to-right. Thus, the interpretation of the expression A .EQV. B .NEQV. C is (A .EQV. B) .NEQV. C.

The following examples show equivalence expressions:

Expression 

Meaning

A .EQV. B 

An equivalence expression

A .XOR. B 

An equivalence exclusive disjunct expression

A .NEQV. B .XOR. C 

An equivalence expression with left-to-right precedence

A .OR. B 

An inclusive disjunct expression is also an equivalence expression

A .AND. B 

A conjunct expression is also an equivalence expression

.NOT. A 

A not expression is also an equivalence expression

A .EQ. B 

A comparison expression is also an equivalence expression

A // B 

A concatenation expression is also an equivalence expression

A - B 

A summation expression is also an equivalence expression

- A 

A summation expression is also an equivalence expression

A * B 

A multiplication expression is also an equivalence expression

A ** B 

An exponentiation expression is also an equivalence expression

.INVERSE. B 

A defined unary expression is also an equivalence expression

A 

A primary is also an equivalence expression

7.2.4.12. Expression

The most general form of an expression is defined as follows:

Table 7-15.

 

expr

is

[ expr defined_binary_op ]  equivalence_expr

 

defined_binary_op

is

.letter [ letter  ] ....

Note that the definition of an expression is left recursive, and therefore the precedence of the binary defined operator in contexts of equal precedence is left-to-right. The interpretation of the expression A .PLUS. B .MINUS. C is thus (A .PLUS. B) .MINUS. C (where .MINUS. is a defined operator).

The following examples show expressions:

Expression 

Meaning

A .PLUS. B 

An expression (where .PLUS. is a defined operator)

A .CROSS. B .CROSS. C 

An expression with left-to-right precedence (where .CROSS. is a defined operator)

A .EQV. B 

An equivalence expression is also an expression

A .OR. B 

An inclusive disjunct expression is also an expression

A .AND. B 

A conjunct expression is also an expression

.NOT. A 

A not expression is also an expression

A .EQ. B 

A comparison expression is also an expression

A // B 

A concatenation expression is also an expression

A - B 

A summation expression is also an expression

- A 

A summation expression is also an expression

A * B 

A multiplication expression is also an expression

A ** B 

An exponentiation expression is also an expression

.INVERSE. B 

A defined unary expression is also an expression

A 

A primary is also an expression

7.2.4.13. Summary of the Forms and Hierarchy for Expressions

The previous sections have described in detail the sorts of expressions that can be formed. These expressions form a hierarchy that can best be illustrated by a figure. Figure 7-1, describes the hierarchy by placing the simplest form of an expression, a variable, at the center of a set of nested rectangles. The more general forms of an expression are the enclosing rectangles, from a primary to an exponentiation expression, to a summation expression, and finally to a general expression using a defined binary operator .CROSS.. Figure 7-1 demonstrates that an expression is all of these special case forms, including the simplest form, a primary.

Figure 7-1. The Hierarchy of Expressions by Examples

Table 7-2, illustrates the relationship between the different sorts of expressions by summarizing the definitional forms in one table. The simplest form of an expression is at the bottom and is the primary, as in Figure 7-1. The next, more general, form is second from the bottom and is the defined unary expression; it uses the primary in its definition. At the top of the table is the most general form of an expression.

7.2.5. Precedence of Operators

Table 7-16 summarizes the relative precedence of operators, including the precedence when operators of equal precedence are adjacent. An entry of N/A in the rightmost column indicates that the operator cannot appear in such contexts. The left-most column classifies the operators as defined, numeric, character, relational, and logical operators. Note that these operators are not intrinsic operators unless the types of the operands are those specified in Table 7-17.

Table 7-16. Categories of Operations and Relative Precedences

Category of operator

Operator

Precedence

In context of equal precedence

Defined

Unary defined-operator

Highest

N/A

Numeric

**

.

Right-to-left

Numeric

* or /

.

Left-to-right

Numeric

Unary + or -

.

N/A

Numeric

Binary + or -

.

Left-to-right

Character

//

.

Left-to-right

Relational

.EQ., .NE., .LT., .LE., .GT., .GE., .LG., ==, /=, <, <=, >, >=, <>

.

N/A

Logical or Boolean

.NOT.

.

N/A

Logical or Boolean

.AND.

.

Left-to-right

Logical or Boolean

.OR.

.

Left-to-right

Logical

.EQV. or .NEQV.

.

Left-to-right

Logical or Boolean

.XOR.

.

Left-to-right

Defined

Binary defined-operator

Lowest

Left-to-right

For example, consider the following expression:

A .AND. B .AND. C .OR. D

Table 7-2, indicates that the .AND. operator is of higher precedence than the .OR. operator, and the .AND. operators are combined left-to-right when in contexts of equal precedence; thus, A and B are combined by the .AND. operator, the result A .AND. B is combined with C using the .AND. operator, and that result is combined with D using the .OR. operator. Thus, this expression is interpreted the same way as the following fully parenthesized expression:

(((A .AND. B) .AND. C) .OR. D)

Notice that the defined operators have fixed precedences; defined unary operators have the highest precedence of all operators and are all of equal precedence; defined binary operators have the lowest precedence, are all of equal precedence, and are combined left-to-right when in contexts of equal precedence. Both kinds of defined operators may have multiple definitions in the program unit and therefore may be generic just as intrinsic operators and intrinsic procedures are generic.

As a consequence of the expression formation rules, unary operators cannot appear in a context of equal precedence; the precedence must be specified by parentheses. There is thus no left-to-right or right-to-left rule for any unary operators. Similarly, the relational operators cannot appear in a context of equal precedence; consequently, there is no left-to-right or right-to-left rule for the relational operators. Use of some of the operators as Boolean or masking operators is an extension to the Fortran standard that is supported by the Cray Fortran Compiler.

Note: The Fortran standard does not specify the use of operators as Boolean or masking operators.

7.2.6. Intrinsic Operations

Intrinsic operations are those known to the processor. For an operation to be intrinsic, an intrinsic operator symbol must be used, and the operands must be of the intrinsic types specified in Table 7-17.

Note: In the following table, the symbols I, R, Z, C, L, B, and P stand for the types integer, real, complex, character, logical, Boolean, and Cray pointer, respectively. Where more than one type for x2 is given, the type of the result of the operation is given in the same relative position in the next column. Boolean and Cray pointer types are extensions of the Fortran standard.

Table 7-17. Operand Types and Results for Intrinsic Operations

Intrinsic operator

Type of x1

Type of x2

Type of result

Unary +, -

 

I, R, Z, B, P

I, R, Z, I, P

Binary +, -, *, /, **

I

I, R, Z, B, P

I, R, Z, I, P

 

R

I, R, Z, B

R, R, Z, R

 

Z

I, R, Z

Z, Z, Z

 

B

I, R, B, P

I, R, B, P

 

P

I, B, P

P, P, P

 

(For Cray pointer, only + and - are allowed.)

 

 

//

C

C

C

.EQ., ==, .NE., /=

I

I, R, Z, B, P

L, L, L, L, L

 

R

I, R, Z, B, P

L, L, L, L, L

 

Z

I, R, Z, B, P

L, L, L, L, L

 

B

I, R, Z, B, P

L, L, L, L, L

 

P

I, R, Z, B, P

L, L, L, L, L

 

C

C

L

.GT., >, .GE., >=, .LT., <, .LE., <=

I

I, R, B, P

L, L, L, L

 

R

I, R, B

L, L, L

 

C

C

L

 

P

I, P

L, L

.LG., <>

R

R

L

.NOT.

 

L

L

 

 

I, R, B

B

.AND., .OR., .EQV., .NEQV., .XOR.

L

L

L

 

I, R, B

I, R, B

B

Note: The Fortran standard does not specify the use of type Boolean or the use of type Boolean in masking expressions, nor does it describe the .LG. and <> operators.

The intrinsic operations are either binary or unary. The binary operations use the binary intrinsic operator symbols +, -, *, /, **, //, .EQ., .NE., .LT., .GT., .LE., .GE., and .LG.(and their synonyms ==, /=, <>, <, >=, and <>), .AND., .OR., .XOR., .EQV., and .NEQV.. The unary operations use the unary intrinsic operator symbols +, -, and .NOT..

Note that the intrinsic operators .AND., .OR., .NOT., and .XOR. can be abbreviated as .A., .O., .N., or .X.. If a user-defined operator with the same name as the abbreviated name is accessible in a scope, the abbreviated forms of these operators may not be used as synonyms for .AND., .OR., .NOT., or .XOR..

The intrinsic operations are divided into five classes with different rules and restrictions for the types of the operands. The five classes are numeric intrinsic, character intrinsic, logical intrinsic, relational intrinsic operations, and bitwise masking expressions.

The numeric intrinsic operations use the intrinsic operators +, -, *, /, and **. The operands can be of any numeric type and with any kind type parameters. The result of the operation is of a type specified by Table 7-17, and has type parameters as specified in Section 7.2.8.2.

For example, the following expressions, in which I, R, D, and Z are declared to be of types integer, real, double-precision real, and complex, have the types and type parameters of the variables R, I, D, and Z, respectively:

I + R
I * I
I - D
I / Z

There is only one character intrinsic operation; it uses the intrinsic operator //. The result of a character intrinsic operation is type character.

The logical intrinsic operations use the intrinsic operators .AND., .OR., .NOT., .EQV., and .NEQV., respectively. The result of a logical intrinsic operation is type logical and has type parameters as specified in Section 7.2.8.2.

The relational intrinsic operations use the intrinsic operators .EQ., .NE., .GT., .GE., .LT., .LE., or .LG. or their symbolic synonyms. A relational intrinsic operation is a numeric relational intrinsic operation if its operands are of type integer, real, or complex. A relational intrinsic operation is a character relational intrinsic operation if its operands are of type character. The result of either kind of relational operation is type logical and has type parameters as specified in Section 7.2.8.2.

Note: The Fortran standard does not describe the .LG. operator.

The operators .NOT., .AND., .OR., .EQV., and .XOR. can also be used in the Cray Fortran Compiler's bitwise masking expressions; these are extensions to the Fortran standard. The result is Boolean (or typeless) and has no kind type parameters.

7.2.7. Defined Operations

A defined operation is any nonintrinsic operation that is interpreted and evaluated by a function subprogram specified by an interface block with a generic specifier of the following form:

OPERATOR (defined_operator)

A defined elemental operation is a defined operation for which the function is elemental.

A defined operation uses either a defined operator or an intrinsic operator symbol, and it is either unary or binary. Its forms are as follows:

intrinsic_unary_op x2

defined_operator x2

x1 intrinsic_binary_op x2

x1 defined_operator x2

The terms intrinsic_unary_op and intrinsic_binary_op include all intrinsically defined operators; these terms are not specifically defined in any syntax rules.

x1 and x2 are operands. When an intrinsic operator symbol is used, the type of x2 (for a unary operator) and types of x1 and x2 (for a binary operator) must not be the same as the types of the operands specified in Table 7-17, for the particular intrinsic operator symbol. Thus, you cannot redefine intrinsic operations on intrinsic types.

When a defined operation uses an intrinsic operator symbol, the generic properties of that operator are extended to the new types specified by the interface block. When a defined operation uses a defined operator, the defined operation is called an extension operation, and the operator is called an extension operator. An extension operator can have generic properties by specifying more than one function subprogram in an interface block with a generic specifier of the form OPERATOR (defined_operator).

7.2.8. Data Type, Type Parameters, and Shape of an Expression

The data type, type parameters, and shape of a complete expression are determined by the data type, type parameters, and shape of each constant, variable, constructor, and function reference appearing in the expression. The determination is inside-out in the sense that the properties are determined first for the primaries. These properties are then determined repeatedly for the operations in precedence order, resulting eventually in the properties for the expression.

For example, consider the expression A + B * C, where A, B, and C are of numeric type. First, the data types, type parameter values, and shapes of the three variables A, B, and C are determined. Because * has a higher precedence than +, the operation B * C is performed first. The type, type parameters, and shape of the expression B * C are determined next, and then these properties for the entire expression are determined from those of A and B * C.

A defined elemental operation is a defined operation for which the function is elemental.

7.2.8.1. Data Type and Type Parameters of a Primary

The type, type parameters, and shape of a primary that is a nonpointer variable or constant are straightforward because these properties are determined by specification statements for the variable or named constant, or by the form of the constant. For example, if A is a variable, its declaration in a specification statement such as the following determines it as an explicit-shaped array of type real with a default kind parameter:

REAL A(10, 10)

For a constant such as the following, the form of the constant indicates that it is a scalar constant of type complex and of default kind:

(1.3, 2.9)

For a pointer variable, the type, type parameters, and rank are determined by the declaration of the pointer variable. However, if the pointer is of deferred shape, the shape (in particular, the extents in each dimension) is determined by the target of the pointer. Consider the following declarations and assume that pointer A is associated with the target B:

REAL, POINTER :: A(:, :)
REAL, TARGET  :: B(10, 20)

The shape of A is (10, 20).

The type and type parameters of an array constructor are determined by the contents of the constructor. Unless the element is of type Boolean (or typeless), its type and type parameters are those of any element of the constructor because they must all be of the same type and type parameters. If the element is of type Boolean, the type and kind type of the array constructor are the same as the default integer type. Therefore, the type and type parameters of the following array constructor are integer and kind value 1:

(/ 1_1, 123_1, -10_1 /)

Its shape is always of rank one and of size equal to the number of elements.

The type of a structure constructor is the derived type or type alias used as the name of the constructor. A structure has no type parameters. So, the type of the following structure constructor is the derived type PERSON:

PERSON(56, 'Father')

(See Section 4.8, for the type definition PERSON.)

A structure constructor is always a scalar.

The type, type parameters, and shape of a function are determined by one of the following:

  • An implicit type declaration for the function within the program unit referencing the function

  • An explicit type declaration for the function within the program unit referencing the function (just like a variable)

  • An explicit interface to the function. (When the interface is not explicit, the function is either an external function or a statement function.)

If the interface is explicit, the type, type parameter, and shape are determined by one of the following:

  • The type and other specification statements for the function in an interface block within the program unit referencing the function

  • The type and other specification statements for the internal or module procedure specifying the function

  • The description of the particular intrinsic function being referenced

Note, however, that because intrinsic functions and functions with interface blocks can be generic, these properties are determined by the type, type parameters, and shapes of the actual arguments of the particular function reference.

For example, consider the following statements as part of the program unit specifying an internal function FCN:

REAL FUNCTION FCN(X)
DIMENSION FCN(10, 15)

A reference to FCN(3.3) is of type default real with shape (10,15). As a second example, consider the following: