Correct program?

I don’t have MFE handy right now, so I’m curious what exactly that sentence means. Does it mean, practically speaking, that a module must be compiled before it is USEd?

If modules are placed in separate files, then that statement is typically true. That is why Makefiles, or other ways of specifying compilation order, are necessary when modules occur in this case. If several modules are placed in a single file, then it is a fairly standard requirement that a module must appear within that file before it is used by a subsequent module in that file. Is that the context in which that statement applies?

This is in contrast to, for example, external functions or common blocks. These entities can be referenced in one file before they are compiled in another file, or if they are defined in a single file, they can be referenced early in the file before they are defined later in that file. Matching of interfaces or of common block lengths is the responsibility of the programmer, and this is a common source of errors. Compilation order is irrelevant in these cases.

That’s true for pretty much all explicit interfaces —i.e., procedures and interface blocks.

But interface blocks (i.e., procedure signatures) must precede its use in other interface blocks, especially when procedure prefixes are involved.

Here, both ifort/ifx and flang (v21) complain if the max_len_trim signature is placed after the do_something signature, but gfortran (v14) doesn’t seem to care:

module mod1
    implicit none

    interface
        module pure function max_len_trim(array) result(ml)
            integer :: ml
            character(*), intent(in) :: array(:)
        end function

        module pure function do_something(array) result(res)
            character(*), intent(in) :: array(:)
            character(max_len_trim(array)) :: res
        end function
    end interface
end module mod1

3 cases arise. (1) Module and its user in the same file, (2) module and
its user in different files compiled together, (3) module and its user
compiled separately.

The whole paragraph of MFE that I should have quoted (sorry I didn’t) is
“A module may contain use statements that access other modules. It
must not access itself directly or indirectly theough a chain of use
statements, for example a accessing b and b accessing
a. No overall ordering of modules is required by the standard, but
no module may precede a module that it uses.”

I therefore think that in case (1) if the module called mymod, say, and
its user (either another module or a main program) is called myuser then
the file should be

module mymod
  ...
end mymod

program myuser ! or module myuser
   use mymod
   ...
end program myuser ! or end module myuser

If the module and its user are in separate files mymod.f90 and
myuser.f90 then MFE seem to be recommending in case (2)

lfortran mymod.f90  myuser.f90

but not

lfortran myuser.f90 mymod.f90

In case (3) compile mymod.f90 first.

– John Harper, School of Mathematics and Statistics
Victoria Univ. of Wellington, PO Box 600, Wellington 6140, New Zealand.
e-mail john.harper@vuw.ac.nz

1 Like

This restriction seems unnecessary. The Fortran standard assumes the existence of a compiler (or interpreter?). Why can’t it assume the existence of a makefile generator?

In the simple case of one module used by one program unit I don’t use a makefile.

The fortran standard would then need to fully specify the behavior of that utility. Another option is to specify somehow the build process itself within the standard. One way to do that would be to incorporate the behavior of a utility, such as make, into the fortran standard. The make utility is already a posix standard, so that might not be an unreasonable approach. If only make were not such a quirky utility to begin with (e.g. with leading spaces and tabs having entirely different behavior), and if it were easily configurable to different fortran compilers, loaders, library archives, operating systems, and so on. I think something like this should have been done with f90, as soon as modules were introduced and as soon as compilation order became important.

The Standard would need to specify a required set of features for a make utility. It does not fully specify the behavior of compilers and make need not be any better. I strongly agree that the syntax of make is dreadful. Do any alternatives exist?

14.2.2 The USE statement and use association
… At the time a USE statement is processed, the public portions of the specified module shall be available…

That is all that the Standard requires. It does not need to be implemented via .mod files. It could be done, for instance, with a text config file listing, for each name of a module, the file and line number where its definition source can be found. Doing it that way would eliminate order-of-compilation issues. There is no such issue inherent in the Standard.

1 Like

I remember using a fortran compiler in the 1990s that did not use mod files. It might have been a DEC or an intel compiler, my memory fails me with the details.

In any case, the fortran standard has always refrained from specifying exactly how the source code is processed into a program. There is no mention in the standard of details such as file names, or file name extensions, or compiler options, or linkers/loaders, or libraries, and so on. I’m not sure that was a good choice – lots of things could have been simpler over the last few decades if the standard had done that and then if all compilers worked the same way.

My point is that USE statements need to be detected, but do not need to be processed for modules to be sorted in a legal order for processing. fpt accepts a list of Fortran files and sorts them into a legal order for processing (if any exists). What it doesn’t do is to find legal orders when USE ONLY constructs pick Fortran parameters from one module to satisfy dependencies in another. That may be a bridge too far for a compiler! I see no reason for the standard to require ordering of modules, or for ordering of declarations. The only necessary restriction is the avoidance of circular dependencies - deadly embraces.

is not only a feature of make. It’s also a feature of Fortran compilers!

It could be argued that the concept of forward referencing is tolerated in the Fortran standard. With acceptance that multi-pass compilers are the norm, why can’t forward referencing be more generally used ?
Surely, @ashe’s test case is not a big ask, such as considering the total of the declaration section.