Chapter 2. Fortran Concepts and Terms

Terms are used in a precise way to describe a programming language, so this chapter introduces the fundamental terms needed to understand Fortran. You can consult the glossary in this manual for definitions of terms.

One of the major concepts involves the organization of a Fortran program. This topic is introduced in this chapter by presenting the high-level syntax rules for a Fortran program, which includes the principal constructs and statements that form a program. This chapter also describes the order in which constructs and statements must appear in a program and concludes with an example of a short Fortran program.

Scope and Association

In examining the basic concepts in Fortran, it helps to trace some of the important steps in its evolution. The results of the first few steps are familiar to Fortran programmers, but the later ones become relevant only when the new features of Fortran are used.

The first version of Fortran produced in the late 1950s did not have user-defined subroutines or functions, but it did contain intrinsic functions.

Programmers soon realized the benefits of isolating definitive chunks of code into separate units known as function and subroutine subprograms. This not only provided a mechanism for structuring a program but permitted subprograms to be written once and then be called many times by the same program (or even be used by more than one program). Equally important, subprograms could be compiled separately.

With this powerful tool came complications. For example, if both the main program and a subprogram use the variable named X, what is the connection between them? The answer is that, in general, there is no connection between X in the main program and X in a subprogram. Subprograms are separately compilable; an X in a different subprogram is not even known at compile time, so the simplest thing to do is have no connection between variables with the same name in different program units. Thus, if two different programmers work on different program units, neither one needs to worry about names picked by the other. This idea is described by saying that the two Xs have different scope.

A subroutine could be written to do a summation of the first hundred integers and print the results. For example:

  SUBROUTINE TOTAL
  M = 0
  DO I = 1, 100
     M = M + I
  END DO
  WRITE(6, 9) M
9 FORMAT(I10)
  RETURN
  END

With this subroutine available, the main program could be written as follows:

CALL TOTAL
STOP
END

Suppose you decide that the subroutine would be more generally useful if it computed the sum but did not print it, as follows:

SUBROUTINE TOTAL
M = 0
DO I = 1, 100
   M = M + I
END DO
RETURN
END

A first attempt to use this subroutine might produce the following erroneous program:

  CALL TOTAL
  WRITE(6, 9) M
9 FORMAT(I10)
  STOP
  END

This does not work because the variable M in the subroutine has nothing to do with variable M in the main program. A connection between the two values should exist, so when subroutines and functions were introduced, two schemes were provided to communicate values between them and other program units: procedure arguments and common blocks.

The following two complete programs communicate values in two ways. The first, program ARGSUM, uses a subroutine argument, and the second, program COMSUM, uses a common block to communicate values. The names in the different program units identify completely separate variables, yet their values are communicated from one to the other by using either arguments or common blocks, so the name of the variable holding the sum in the subroutine need not be the same as the corresponding variable in the calling program.

  PROGRAM ARGSUM
  CALL TOTAL(M)
  WRITE(6, 9) M
9 FORMAT(I10)
  END

  SUBROUTINE TOTAL(ITOTAL)
  ITOTAL = 0
  DO I = 1, 100
     ITOTAL = ITOTAL + I
  END DO
  END

Program COMSUM, which follows, performs the same computation as program ARGSUM:

  PROGRAM COMSUM
  COMMON /CB/ M
  CALL TOTAL
  WRITE(6, 9) M
9 FORMAT(I10)
  END

  SUBROUTINE TOTAL
  COMMON /CB/ ITOTAL
  ITOTAL = 0
  DO I = 1, 100
     ITOTAL = ITOTAL + I
  END DO
  END

To describe even these simple cases and appreciate how they work already requires the introduction of some terms and concepts. To precisely describe the phenomenon that the subroutine variable ITOTAL is not known outside the subroutine, the concept of scope is used. Because the scope of a variable in a common block is local, the scope of ITOTAL includes only the subroutine -- not the main program.

The scope of ITOTAL is the subroutine; the scope of the variable M is the main program. However, the scope of the common block name CB is global. association is used to describe the connection between M in the main program and ITOTAL in the subroutine. In the first example it is argument association, and in the second it is storage association.

To summarize, the scope of a variable is that part of the program in which it is known and can be used. Two variables may have the same name and nonoverlapping scopes; for example, there may be two completely different variables named X in two different subprograms. Association of variables means that there may be two different names for the same object; this permits sharing values under certain conditions.

With arguments available, it is natural to generalize the computation somewhat to allow the upper limit of the sum (100 in the example) to vary. Also, a function is more natural in this case than a subroutine, because the object of the computation is to return a single value. These changes produce the following program:

PROGRAM PTOTAL
INTEGER TOTAL
PRINT *, TOTAL(100)
END

FUNCTION TOTAL(N)
INTEGER TOTAL
TOTAL = 0
DO I = 1, N
   TOTAL = TOTAL + I
END DO
END

In this example, the scope of N is function TOTAL, but when function TOTAL is called from the main program in the PRINT statement, the value of N, through argument association, becomes 100. The scope of variable I is function TOTAL. The scope of function TOTAL is the whole program, but its type must be declared in the main program because by the implicit typing rules, TOTAL is not of type integer. Also note that there is a function named TOTAL, with global scope, and a variable named TOTAL is local to the function. The use of identifier TOTAL determines whether it is the local variable TOTAL or the global function name TOTAL. When TOTAL is used with an argument list, it is the function name; when used inside the function subprogram defining the function TOTAL, it is the local variable. Variable TOTAL computes and stores the value that is returned as the value of the function TOTAL.

It is possible to rewrite the example using internal procedures:

PROGRAM DO_TOTAL
  PRINT *, TOTAL(100)
  CONTAINS

  FUNCTION TOTAL(N)
     INTEGER TOTAL
     TOTAL = 0
     DO I = 1, N
        TOTAL = TOTAL + I
     END DO
  END FUNCTION TOTAL

END PROGRAM DO_TOTAL

This is similar to the previous example, but the function is placed prior to the END statement of the main program and the CONTAINS statement is inserted to mark the beginning of any internal functions or subroutines. In this case, the function TOTAL is not global but is local to the program DO_TOTAL. Also, the FUNCTION statement for TOTAL and the specifications that follow it specify TOTAL as a function of type integer with one integer argument N. The type of TOTAL must not be declared in the specification part of the program DO_TOTAL; to do so would create a duplicate declaration of TOTAL. The information about the type of the function and type of the argument is called the interface to the internal function.

To illustrate some other rules about scoping and association related to internal procedures, the example can be changed back to one that uses a subroutine, but one that is now internal.

PROGRAM DO_TOTAL
  INTEGER TOTAL
  CALL ADD_EM_UP(100)
  PRINT *, TOTAL
  CONTAINS

   SUBROUTINE ADD_EM_UP(N)
   TOTAL = 0
   DO I = 1, N
      TOTAL = TOTAL + I
   END DO
   END SUBROUTINE ADD_EM_UP

END PROGRAM DO_TOTAL

The preceding example shows that TOTAL in the internal subroutine and TOTAL in the main program are, indeed, the same variable. It does not need to be declared type integer in the subroutine. This is the result of host association, wherein internal procedures inherit information about variables from their host, which is the main program in this case. Variable I does not appear in the main program, so its scope is the internal subroutine.

Data declarations and procedures can be placed in a module. Then they can be used by other parts of the program. This scheme is illustrated using the summation function example again, as follows:

MODULE TOTAL_STUFF
CONTAINS
   FUNCTION TOTAL(N)
   INTEGER TOTAL, N, I
   TOTAL = 0
   DO I = 1, N
      TOTAL = TOTAL + I
   END DO
   END FUNCTION TOTAL
END MODULE TOTAL_STUFF

PROGRAM DO_TOTAL
USE TOTAL_STUFF
PRINT *, TOTAL(100)
END PROGRAM DO_TOTAL

The module and the program could be in different files. They can be compiled like subroutines, but unlike subroutines, the module must be available to the compiler when program DO_TOTAL is compiled.

The scope of variables N and I is function TOTAL; N gets its value 100 by argument association. The module name TOTAL_STUFF is global and any program can use the module, which causes the type and definition of function TOTAL to become available within that program. This is called use association.

When more extensive examples are constructed using such features as internal procedures within a procedure in a module, there is a need to have a deeper understanding of scope and association. These topics are introduced briefly in the following section and discussed in more detail in the Fortran Language Reference Manual, Volume 2.

Scoping Units

The scope of a program entity is that part of the entire executable program in which that entity is known, is available, and can be used. Some of the parts of a program that constitute the scope of entities are called scoping units. Scoping units range in extent of inclusiveness from parts of a statement to an entire program unit.

Some entities have scopes that are something other than a scoping unit. For example, the scope of a name, such as a variable name, can be global to an executing program. For more information on name scope and scoping units, see the Fortran Language Reference Manual, Volume 2.

Association

The term association describes how different entities in the same program unit or different program units can share values and other properties. It is also a mechanism by which the scope of an entity is made larger. For example, argument association allows values to be shared between a procedure and the program that calls it. Storage association, set up by the use of EQUIVALENCE and COMMON statements, for example, allows two or more variables to share storage, therefore values, under certain circumstances. Use association and host association both allow entities described in one part of a program to be used in another part of the program. Use association makes entities defined in modules accessible, and host association makes entities in the containing environment available to an internal or module procedure. The complete description of all categories of association are described in the Fortran Language Reference Manual, Volume 2.

Program Organization

A collection of program units constitutes an executable program. Program units can contain other smaller units.

Program Units

A Fortran program unit is one of the following:

  • Main program

  • External subprogram (subroutine or function)

  • Module

  • Block data

A Fortran program must contain one main program and can contain any number of the other types of program units. Program units define data environments and the steps necessary to perform calculations. Each program unit has an END statement to terminate the program unit. Each program unit also has an identifying initial statement, but the identifying statement for a main program is optional.

An external subprogram (a function or a subroutine) performs a task or calculation on entities available to the external subprogram. These entities can be the arguments to the subprogram that are provided in the reference, entities defined in the subprogram, or entities made accessible by other means, such as common blocks. A CALL statement invokes a subroutine. A function is invoked when its value is needed in an expression. The computational process that is specified by a function or subroutine subprogram is called a procedure. It may be invoked from other program units of the Fortran program. Neither module nor block data program units are executable, so they are not considered to be procedures. A main program also contains executable constructs, but it is not classified as a procedure.

A block data program unit contains only data definitions. It specifies initial values for a restricted set of data objects.

A module contains public definitions that can be made accessible to other program units and subprograms. It also contains private definitions that are accessible only within the module. These definitions include data definitions, type definitions, definitions of subprograms known as module subprograms, and specifications of procedure interfaces. Module subprograms can be either subroutine or function subprograms. The procedures they define are called module procedures. Module subprograms can be invoked by other module subprograms in the module or by other program units that access the module.

A main program, external subprograms, and module subprograms may contain internal subprograms, which can be either subroutines or functions. The procedures they define are called internal procedures. Internal subprograms must not themselves contain internal subprograms, however. The main program, external subprogram, or module subprogram that contains an internal subprogram is referred to as the internal subprogram's host. Internal subprograms may be invoked by their host or by other internal subprograms in the same host.

A statement function also defines a procedure. Executable program units, module subprograms, and internal subprograms can all contain statement functions.

Figure 2-1, illustrates the organization of a sample Fortran program. Large arrows represent use association with the USE statement at the arrow tip. Small arrows represent subprogram references with the call at the arrow base.

Figure 2-1. Program packaging example

Program packaging example

Program units and subprograms are described more fully in the Fortran Language Reference Manual, Volume 2.

Packaging

The packaging of a program is an important design consideration when planning a new Fortran application.

The most important benefit of packaging is the capability to hide information. Entities can be kept inaccessible except where they are actually needed. This provides some protection against inadvertent misuse or corruption, thereby improving program reliability. Packaging can make the logical structure of a program more apparent by hiding complex details at lower levels. Programs are therefore easier to comprehend and less costly to maintain. The Fortran features that provide these benefits are internal procedures and modules.

As previously noted, internal procedures can appear in a main program, external subroutines, external functions, and module subprograms. They are known only within their host. The name of an internal procedure must not be passed as an argument, and an internal procedure must not itself be the host of another internal procedure. However, a statement function can appear within an internal procedure. Thus, in some ways, internal procedures are like external procedures and in other ways they are like statement functions.

Modules provide the most comprehensive opportunities to apply packaging concepts, as illustrated in Figure 2-1. In addition to several levels of organization and hiding, the entities specified in a module (types, data objects, procedures, interfaces, and so on) can be kept private to the module or made available to other scoping units by use association.

Data Environment

Before a calculation can be performed, its data environment must be developed. The data environment consists of data objects that possess certain properties, attributes, and values. The steps in a computational process generally specify operations that are performed on operands (or objects) to create desired results or values. Operands can be constants, variables, constructors, or function references; each has a data type and (if defined) a value. In some cases the type can be assumed by the processor; in other cases it may be declared. A data object has attributes other than type. Chapter 4, “Data Types”, discusses data type in detail; Chapter 5, “Declarations”, discusses the other attributes of program entities; and Chapter 6, “Using Data”, and Chapter 7, “Expressions and Assignments”, describe how data objects are used.

Data Type

The Fortran language provides five intrinsic data types: real, integer, complex, logical, and character, and it lets you define additional types. Sometimes it is natural to organize data in combinations consisting of more than one type. For example, assume that a program is written to monitor the patients in a hospital. For each patient, certain information must be maintained, such as the patient's name, room number, temperature, pulse rate, medication, and prognosis for recovery. Because all of this data describes one object (a particular patient), it would be convenient to have a means to refer to the aggregation of data by a single name. In Fortran, an aggregation of data values of different types is called a structure. To use a structure, a programmer must first define the type of the structure. After the new type is defined, any number of structures of that type can be declared. This mechanism might seem slightly cumbersome if only one such structure is needed in a program, but usually several are needed. The following is an example of a user-defined type with three components:

TYPE PATIENT
   INTEGER              PULSE_RATE
   REAL                 TEMPERATURE
   CHARACTER(LEN = 300) PROGNOSIS
END TYPE PATIENT

After type PATIENT is defined, objects (structures) of the type can be declared. For example:

TYPE(PATIENT) JOHN_JONES, SALLY_SMITH

Kind

Some intrinsic types have more than one representation (or kind). Fortran provides both single- and double-precision representations of the real and complex types; chapter 4 describes these data representations in detail. Fortran permits more than one representation for the integer, logical, and character types. The CF90 and MIPSpro 7 Fortran 90 compilers support more than one representation for the integer and logical types, but they support only a single character type (ASCII). Alternative representations for the integer type permit different ranges of integers.

Dimensionality

Single objects, whether intrinsic or user-defined, are scalar. Even though a structure has components, it is considered to be a scalar. A set of scalar objects, all of the same type, may be arranged in patterns involving columns, rows, planes, and higher-dimensioned configurations to form arrays. It is possible to have arrays of structures. An array may have a maximum of seven dimensions. The number of dimensions is called the rank of the array. It is declared when the array is declared and cannot change. The size of the array is the total number of elements and is equal to the product of the extents in each dimension. The shape of an array is determined by its rank and its extents in each dimension. Two arrays that have the same shape are said to be conformable. The following are examples of array declarations:

REAL COORDINATES(100, 100)
INTEGER DISTANCES(50)
TYPE(PATIENT) MATERNITY_WARD(20)

In Fortran, an array is treated as an object and is allowed to appear in an expression or be returned as a function result. Intrinsic operations involving arrays of the same shape are performed element-by-element to produce an array result of the same shape. There is no implied order in which the element-by-element operations are performed.

A portion of an array, such as an element or section, can be referenced as a data object. An array element is a single element of the array and is scalar. An array section is a subset of the elements of the array and is itself an array.

Dynamic Data

There are three sorts of dynamic data objects in Fortran: pointers, allocatable arrays, and automatic data objects.

Data objects in Fortran can be declared to have the POINTER attribute. Pointer objects must be associated with a target before they can be used in any calculation. This is accomplished by allocation of the space for the target or by assignment of the pointer to an existing target. The association of a pointer with a target can change dynamically as a program is executed. If the pointer object is an array, its size and shape could change dynamically, but its rank is fixed by its declaration. The following is an example of pointer array declaration and allocation:

REAL, POINTER :: LENGTHS(:)
ALLOCATE(LENGTHS (200))

Following execution of an ALLOCATE statement, LENGTHS points at (is associated with) an array with 200 elements. The elements as yet have no values.

An array can be declared to have the ALLOCATABLE attribute. Space must be allocated for the array before it can be used in any calculation. The array can be deallocated and reallocated with a different size as the program executes. The size and shape can change at each allocation, but the rank is fixed by the declaration. The following is an example of allocatable array declaration and allocation:

REAL, ALLOCATABLE :: LENGTHS(:)
ALLOCATE (LENGTHS(200))

The similarities of these examples reflect the similarity of some of the uses of allocatable arrays and pointers, but pointers have more functionality. Pointers can be used to create dynamic data structures, such as linked lists and trees. The target of a pointer can be changed by reallocation or pointer assignment. The extents of an allocatable array can be changed only by deallocating and reallocating the array. If the values of the elements of an allocatable array are to be preserved, a new array must be allocated and the values moved to the new array before the old array is deallocated.

An automatic data object can be an array or a character string. Automatic objects can be declared in a subprogram. These local data objects are created on entry to the subprogram and disappear when the execution of the subprogram completes. They are useful in subprograms for temporary arrays and characters strings whose sizes are different for each reference to the subprogram. The following is an example of a subprogram unit with automatic array TEMP:

SUBROUTINE SWAP_ARRAYS(A, B)
   REAL, DIMENSION(:) :: A, B
   REAL, DIMENSION(SIZE(A)) :: TEMP

   TEMP = A
   A = B
   B = TEMP
END SUBROUTINE SWAP_ARRAYS

A and B are assumed-shape array arguments; that is, they take on the shape of the actual argument. TEMP is an automatic array that is created the same size as A on entry to subroutine SWAP_ARRAYS. SIZE(3i) is an intrinsic function that is permitted in a declaration statement.

Program Execution

During program execution, constructs and statements are executed in a prescribed order. Variables become defined with values and can be redefined later in the execution sequence. Procedures are invoked, perhaps recursively. Space can be allocated and later deallocated. Pointers can change their targets.

Execution Sequence

Program execution begins with the first executable construct in the main program. An executable construct is an instruction to perform one or more of the computational actions that determine the behavior of the program or control the flow of the execution of the program. It can perform arithmetic, compare values, branch to another construct or statement in the program, invoke a procedure, or read from or write to a file or device. When a procedure is invoked, its execution begins with the first executable construct after the entry point in the procedure. On normal return from a procedure invocation, execution continues where it left off. The following are examples of executable statements:

     READ(5, *) Z, Y
     X = (4.0 * Z) + BASE
     IF (X > Y) GO TO 100
     CALL CALCULATE(X)
100  Y = Y + 1

Unless a branching statement or control construct is encountered, executable statements are executed in the order in which they appear in a program unit until a STOP, RETURN, or END statement is executed. Branch statements specify a change in the execution sequence and consist of the various forms of GO TO statements, a procedure reference with alternative return specifiers, and input/output (I/O) statements with branch label specifiers such as ERR=, END=, and EOR= specifiers. The control constructs (IF, CASE, and DO) can cause internal branching implicitly within the structure of the construct. Chapter 8, “Controlling Execution”, discusses control flow within a program in detail.

Definition and Undefinition

Most variables have no value when execution begins; they are considered to be undefined. Exceptions are variables that are initialized in DATA statements, type declaration statements, or variables whose type is a structure for which full default initialization is specified in the structure definition (all components must be fully initialized); these are considered to be defined. A variable can acquire a value or change its current value, typically by the execution of an assignment statement or an input statement. Thus it can assume different values at different times, and under some circumstances it can become undefined. Defined and undefined are the Fortran terms that are used to specify the definition status of a variable. The Fortran Language Reference Manual, Volume 2, describes the events that cause variables to become defined and undefined.

A variable is considered to be defined only if all parts of it are defined. For example, all elements of an array, all components of a structure, or all characters of a character string must be defined; otherwise, the array, structure, or string is undefined. Fortran permits zero-sized arrays and zero-length strings; these are always considered to be defined.

Pointers have both a definition status and an association status. When execution begins, the association status of all pointers is undefined unless one of the following conditions is present:

  • The pointers are initialized with a NULL(3i) intrinsic procedure in a type declaration statement.

  • The pointers are initialized in a DATA statement.

  • The pointer is a component with default initialization specified.

During execution a pointer can become nullified by the execution of a NULLIFY statement, in which case its association status becomes disassociated, or it may become associated with a target by the execution of an ALLOCATE or pointer assignment statement, in which case its association status becomes associated. Even when the association status of a pointer is defined, the pointer is not considered to be defined unless the target with which it is associated is defined. Pointer targets become defined in the same way that other variables becomes defined, typically by the execution of an assignment or input statement. When an allocatable array is allocated by the execution of an ALLOCATE statement, it is undefined until some other action occurs that causes it to become defined with values for all array elements.

Dynamic Behavior

Fortran supports the following types of dynamic behavior:

  • Recursion

  • Allocation and deallocation

  • Pointer assignment

Many algorithms can be expressed with the use of recursion, which occurs when a subroutine or function references itself, either directly or indirectly. The keyword RECURSIVE must be present in the SUBROUTINE or FUNCTION statement if the procedure is referenced recursively. Recursive subroutines and functions are described in the Fortran Language Reference Manual, Volume 2.

No space exists for a pointer until the pointer is allocated or associated with an existing target. No space exists for an allocatable array until the array is allocated. The rank of array pointers and allocatable arrays is fixed by declaration, but the extents in each dimension (and thus the size of the arrays) is determined during execution by calculation or from input values.

The ALLOCATE and DEALLOCATE statements give Fortran programmers mechanisms to configure objects to the appropriate shape. Only pointers and allocatable arrays can be allocated. It is not possible to deallocate an object unless it was previously allocated, and it is not possible to deallocate a part of an object unless it is a pointer component of a structure. It is possible to inquire whether a pointer is currently associated and whether an allocatable array is currently allocated. Chapter 5, “Declarations”, describes the declaration of pointers and allocatable arrays. Chapter 6, “Using Data”, describes the ALLOCATE and DEALLOCATE statements. The Fortran Language Reference Manual, Volume 2, describes the ASSOCIATED(3i) intrinsic inquiry function for pointers and the ALLOCATED(3i) intrinsic inquiry function for allocatable arrays.

Pointers are more flexible than allocatable arrays, but they are also more complicated and less efficient. A pointer need not be an array; it can be a scalar of any type. A pointer need not be associated with allocated space; any object with the TARGET attribute can become a pointer target. A pointer assignment statement is provided to associate a pointer with a target (declared or allocated). It makes use of the symbol => rather than the single character =. In all other respects, pointer assignment statements are executed in the same way that ordinary assignment statements are executed, except that instead of assigning a value they associate a pointer with a target, as is shown in the following example:

REAL, TARGET :: VECTOR(100)
REAL, POINTER :: ODDS(:)
   . . .
ODDS => VECTOR(1:100:2)

The pointer assignment statement associates ODDS with the odd elements of VECTOR. The following assignment statement defines each odd element of VECTOR with the value 1.5:

ODDS = 1.5

Later in the execution sequence, pointer ODDS could become associated with a different target by pointer assignment or allocation, as long as the target is a one-dimensional, real array. Chapter 7, “Expressions and Assignments”, describes the pointer assignment statement.

Summary of Forms

This section shows the forms of the higher-level components of a Fortran program. The notation used in most of the forms is the same as that used to show the syntax forms in all the remaining sections of this manual. The complete Backus-Naur form (BNF), as given in the Fortran standard, is included in the Fortran Language Reference Manual, Volume 3.

Program Units

Fortran defines a program_unit as follows:

 

executable_program

is

program_unit
[program_unit]...

 

program_unit

is

main_program

 

 

or

external_subprogram

 

 

or

module

 

 

or

block_data

 

main_program

is

[program_stmt]
[specification_part]
[execution_part]
[internal_subprogram_part]
end_program_stmt

 

external_subprogram

is

functional_program

 

 

or

subroutine_subprogram

 

function_subprogram

is

function_stmt
[specification_part]
[execution_part]
[internal_subprogram_part]
end_function_stmt

 

subroutine_subprogram

is

subroutine_stmt
[specification_part]
[execution_part]
[internal_subprogram_part]
end_subroutine_stmt

 

module

is

module_stmt
[specification_part]
[module_subprogram_part]
end_subroutine_stmt

 

block_data

is

block_data_stmt
[specification_part]
end_block_data_stmt

 

specification_part

is

[use_stmt]...
[implicit_part]
[declaration_construct]...

 

implicit_part

is

[implicit_part_stmt]...
implicit_stmt

 

implicit_part_stmt

is

implicit_stmt

 

 

or

parameter_stmt

 

 

or

format_stmt

 

 

or

entry_stmt

 

declaration_construct

is

derived_type_def

 

 

or

interface_block

 

 

or

type_declaration_stmt

 

 

or

specification_stmt

 

 

or

parameter_stmt

 

 

or

format_stmt

 

 

or

entry_stmt

 

 

or

stmt_function_stmt

 

execution_part

is

executable_construct
[execution_part_construct]...

 

execution_part_construct

is

executable_construct

 

 

or

format_stmt

 

 

or

data_stmt

 

 

or

entry_stmt

 

internal_subprogram_part

is

contains_stmt
internal_subprogram
[internal_subprogram]...

 

internal_subprogram

is

function_subprogram

 

 

or

subroutine_subprogram

 

module_subprogram_part

is

contains_stmt
module_subprogram
[module_subprogram]...

 

module_subprogram

is

function_subprogram

 

 

or

subroutine_subprogram

 

specification_stmt

is

access_stmt

 

 

or

allocatable_stmt

 

 

or

common_stmt

 

 

or

data_stmt

 

 

or

dimension_stmt

 

 

or

equivalence_stmt

 

 

or

external_stmt

 

 

or

intent_stmt

 

 

or

intrinsic_stmt

 

 

or

namelist_stmt

 

 

or

optional_stmt

 

 

or

pointer_stmt

 

 

or

save_stmt

 

 

or

target_stmt

 

executable_construct

is

action_stmt

 

 

or

case_construct

 

 

or

do_construct

 

 

or

forall_construct

 

 

or

if_construct

 

 

or

where_construct

 

action_stmt

is

allocate_stmt

 

 

or

arithmetic_if_stmt

 

 

or

assign_stmt

 

 

or

assigned_goto_stmt

 

 

or

assignment_stmt

 

 

or

backspace_stmt

 

 

or

call_stmt

 

 

or

close_stmt

 

 

or

computed_goto_stmt

 

 

or

continue_stmt

 

 

or

cycle_stmt

 

 

or

deallocate_stmt

 

 

or

endfile_stmt

 

 

or

end_function_stmt

 

 

or

end_program_stmt

 

 

or

end_subroutine_stmt

 

 

or

exit_stmt

 

 

or

forall_stmt

 

 

or

goto_stmt

 

 

or

if_stmt

 

 

or

inquire_stmt

 

 

or

nullify_stmt

 

 

or

open_stmt

 

 

or

pause_stmt

 

 

or

pointer_assignment_stmt

 

 

or

print_stmt

 

 

or

read_stmt

 

 

or

return_stmt

 

 

or

rewind_stmt

 

 

or

stop_stmt

 

 

or

where_stmt

 

 

or

write_stmt


Main Program

Typically, a main program takes the following form:

[ PROGRAM program_name]
[specification_part]
[execution_part]
[ CONTAINS
internal_subprogram
[internal_subprogram] ... ]
END [ PROGRAM [program_name]]

External Subprogram

Typically, an external subprogram takes one of the following forms:

function_stmt
[specification_part]
[execution_part]
[ CONTAINS
internal_subprogram
[internal_subprogram] ... ]
end_function_stmt
subroutine_stmt
[specification_part]
[execution_part]
[ CONTAINS
internal_subprogram
[internal_subprogram] ... ]
end_subroutine stmt

Module

Typically, a module takes the following form:

MODULE module_name
[specification_part]
[ CONTAINS
module_subprogram
[module_subprogram] ... ]
END [ MODULE [module_name]]

Block Data

Typically, a block data program unit takes the following form:

BLOCK DATA [block_data_name][specification_part]
END [ BLOCK DATA [block_data_name]]

Internal Subprogram

Typically, an internal subprogram takes one of the following forms:

function_stmt[specification_part][execution_part]end_function_stmt
subroutine_stmt[specification_part][executable_part]end_subroutine stmt

Procedure Headings

The FUNCTION and SUBROUTINE statements are defined as follows:

[prefix] FUNCTION function_name ([dummy_argument_list])
[ RESULT (result_name) ]
[prefix] SUBROUTINE subroutine_name[ ([dummy_argument_list]) ]
[prefix] FUNCTION function_name
([dummy_argument_list])
[ RESULT (result_name) ]
[prefix] SUBROUTINE subroutine_name
[ ([dummy_argument_list]) ]

Procedure Endings

The END FUNCTION and END SUBROUTINE statements are defined as follows:

END [ FUNCTION [function_name]]
END [ SUBROUTINE [subroutine_name]]

Specification Constructs

A specification part generally can contain any of the following. Some program units or subprograms may not allow some of these specification constructs. See the descriptions for each program unit or subprogram description for restrictions.

  • USE statements

  • PARAMETER statements

  • FORMAT statements

  • ENTRY statements

  • Derived type definitions

  • Interface blocks

  • Type declaration statements

  • Other specification statements

Derived-type Definition

Typically, derived-type definitions take the following form:

TYPE [[, access_spec] :: ]type_name
[ PRIVATE ]
[ SEQUENCE ]
type_spec[[, component_attr_spec_list] :: ]component_decl_list ...
[type_spec[[, component_attr_spec_list] :: ]
component_decl_list ... ] ...
END TYPE [type_name]
TYPE [[, access_spec] :: ]type_name
[ PRIVATE ]
[ SEQUENCE ]
type_spec[[, component_attr_spec_list] :: ]
component_decl_list ...
[type_spec[[, component_attr_spec_list] :: ]
component_decl_list ... ] ...
END TYPE [type_name]

Interface Block

Typically, an interface block takes the following form:

INTERFACE [generic_spec]
[interface_body] ...
[ MODULE PROCEDURE procedure_name_list] ...
END INTERFACE

Specification Statements

This section lists the general forms for specification statements. The BNF used here is an abbreviated format and is used only in this section. The specific formats are described in later sections of this manual. The specification statements are as follows:

ALLOCATABLE [ :: ]allocatable_array_list
AUTOMATIC automatic_list ...
COMMON [ / [common_block_name] / ]common_block_object_list
DATA data_statement_object_list / data_statement_value_list
 /
DIMENSION array_dimension_list
EQUIVALENCE equivalence_set_list
EXTERNAL external_name_list
FORMAT ([format_item_list])
IMPLICIT implicit_spec
INTENT (intent_spec) [ :: ]dummy_argument_name_list
INTRINSIC intrinsic_procedure_name_list
NAMELIST / namelist_group_name / namelist_group_object_list
OPTIONAL [ :: ]optional_object_list
PARAMETER (named_constant_definition_list)
POINTER [ :: ]pointer_list
PUBLIC [[ :: ]module_entity_name_list]
PRIVATE [[ :: ]module_entity_name_list]
SAVE [[ :: ]saved_object_list]
TARGET [ :: ]target_list
USE module_name[ , rename_list]
USE module_name , ONLY : [access_list]
type_spec[[, attr_spec] ... :: ]object_declaration_list
VOLATILE entity_decl_list

Note: The Fortran standard does not specify the AUTOMATIC or VOLATILE attributes.



Note: The VOLATILE attribute is not supported on UNICOS or UNICOS/mk platforms.


Type Declaration Statements

Typically, the type declaration statements take the following form:

TYPE (type_name)
LOGICAL [ ([ KIND= ]kind_parameter) ]
CHARACTER*char_length
CHARACTER (KIND= kind_parameter[, LEN= length_parameter])
CHARACTER ([ LEN= ]length_parameter[, [KIND= ]kind_parameter])
CHARACTER [ ([ LEN= ]length_parameter) ]
COMPLEX [ ([ KIND= ]kind_parameter) ]
DOUBLE PRECISION
REAL [ ([ KIND= ]kind_parameter) ]
INTEGER [ ([ KIND= ]kind_parameter) ]

Attribute Specifications

“Specification Statements”, introduced attr_spec. Typically, attribute specifications take the following form:

ALLOCATABLE
AUTOMATIC
DIMENSION (array_spec)
EXTERNAL
INTENT (intent_spec)
INTRINSIC
OPTIONAL
PARAMETER
POINTER
PRIVATE
PUBLIC
SAVE
TARGET
VOLATILE

Note: The Fortran standard does not specify the AUTOMATIC or VOLATILE attributes.



Note: The VOLATILE attribute is not supported on UNICOS or UNICOS/mk platforms.


Execution Part

An execution part can contain the following:

  • action_statement

  • case_construct

  • do_construct

  • if_construct

  • where_construct

Action Statements

Typically, action statements take the following form:

ALLOCATE (allocation_list[ , STAT= scalar_integer_variable])
ASSIGN label TO scalar_integer_variable
BACKSPACE external_file_unit
BACKSPACE (position_spec_list)
BUFFER IN (id, mode) (start_loc, end_loc )
BUFFER OUT (id, mode) (start_loc, end_loc )
CALL subroutine_name[ ([actual_argument_spec_list]) ]
CLOSE (close_spec_list)
CONTINUE
CYCLE [do_construct_name]
DEALLOCATE (name_list[ , STAT= scalar_integer_variable])
ENDFILE external_file_unit
ENDFILE (position_spec_list)
EXIT [do_construct_name]
FORALL forall_headerforall_assignment_stmt
GO TO label
GO TO (label_list) [ , ]scalar_integer_expression
GO TO scalar_integer_variable[[ , ]
(label_list) ]
IF (scalar_logical_expression) action_statement
IF (scalar_numeric_expression) label, label, label
INQUIRE (inquire_spec_list) [output_item_list]
NULLIFY (pointer_object_list)
OPEN (connect_spec_list)
PAUSE [access_code]
PRINT format[, output_item_list]
READ (io_control_spec_list) [input_item_list]
READ format[, input_item_list]
RETURN [scalar_integer_expression]
REWIND external_file_unit
REWIND (position_spec_list)
STOP [access_code]
WHERE (array_logical_expression) array_assignment_statement
WRITE (io_control_spec_list) [output_item_list]
pointer_variable => target_expression
variable = expression

CASE Construct

Typically, CASE constructs take the following form:

SELECT CASE (case_expr)
[ CASE case_selector
block] ...
[ CASE DEFAULT
block]
END SELECT

DO Construct

Typically, DO constructs take the following form:

DO [label]
block
end_do
DO [label][ , ]do_variable = scalar_numeric_expr,
scalar_numeric_expr[,scalar_numeric_expr]
block
end_do
DO [label][ , ] WHILE (scalar_logical_expr)
block
end_do

IF Construct

Typically, IF constructs take the following form:

IF (scalar_logical_expr) THEN
block
[ ELSE IF (scalar_logical_expr) THEN
block] ...
[ ELSE
block]
END IF

FORALL Construct

Typically, FORALL constructs take the following form:

FORALL forall_header
[assignment_stmt] |
[forall_assignment_stmt] |
[forall_construct] |
[forall_stmt] |
[pointer_assignment_stmt] |
[where_construct] |
[where_stmt]
END FORALL

WHERE Construct

Typically, WHERE constructs take the following form:

[where_construct_name:] WHERE (mask_expr)
[where_body_construct] ...
[ ELSEWHERE (mask_expr) [where_construct_name]
[where_body_construct] ...]
[ ELSEWHERE
[where_body_construct] ...]
END WHERE [where_construct_name]

Ordering Requirements

Within program units and subprograms, there are ordering requirements for statements and constructs. The syntax rules in the previous section do not fully describe the ordering requirements. They are illustrated in both Figure 2-2, and Figure 2-3. Generally, data declarations and specifications must precede executable constructs and statements, although FORMAT, DATA, NAMELIST, and ENTRY statements can appear among the executable statements. USE statements, if any, must appear first. Internal or module subprograms, if any, must appear last following a CONTAINS statement.


Note: The Fortran standard does not allow NAMELIST statements to be intermixed with executable statements and constructs. The CF90 and MIPSpro 7 Fortran 90 compilers ease this restriction.

In Figure 2-2, a vertical line separates statements and constructs that can be interspersed; a horizontal line separates statements that must not be interspersed.

Figure 2-2. Requirements on statement ordering

Requirements on statement ordering

There are restrictions on the places where some statements may appear. Figure 2-3, summarizes these restrictions.


Note:: Miscellaneous declarations are PARAMETER statements, IMPLICIT statements, type declaration statements, and specification statements.


Figure 2-3. Restrictions on the appearance of statements

Restrictions on the appearance of statements

Example Fortran Program

The following simple Fortran program consists of one program unit, the main program. Three data objects are declared: H, T, and U. These become the loop indexes in a triply-nested loop structure that contains an IF statement that conditionally executes an I/O statement.

PROGRAM SUM_OF_CUBES
! This program prints all 3-digit numbers that
! equal the sum of the cubes of their digits.
INTEGER :: H, T, U
DO H = 1, 9
  DO T = 0, 9
    DO U = 0, 9
    IF (100*H + 10*T + U == H**3 + T**3 + U**3) &
      PRINT "(3I1)", H, T, U
    END DO
  END DO
END DO
END PROGRAM SUM_OF_CUBES

This Fortran program produces the following output:

153
370
371
407