Is there a "standard" file suffix for modern Fortran code?

Here is the problem with this kind of approach. Do a google search for some well known fortran file. There are probably thousands of such files to choose from, but dgels.f is an example from the lapack library. This is a driver routine to solve various types of linear equations. It is, of course, fixed form fortran.

So imagine a “new user” who does such a search, finds and downloads the source code, and then attempts to compile it with the above conventions. The compile step will result in various errors because he is trying to compile a fixed form file with free form conventions. What kind of experience will that be for that new user?

My point is that one cannot simply change what is now a de facto standard, one that has existed for several decades, without consequences. No matter what you do locally with Makefile conventions, and compiler defaults, all of those fixed source *.f files still exist, and they will forever be in conflict with anyone trying to simply redefine what the .f extension means.

An experienced programmer can do this. He would know the difference in the source code forms, he knows how to configure his build system appropriately, and there is no problem at any step of the process. But this discussion keeps going back to “new users”, trying to simplify and make their life easier with less confusion. Ignoring that the .f extension is a de facto standard for fixed source form does not make things easier for this proverbial “new user”.

Regarding the .f90 extension, it is also a de facto standard for free form source file. Again, nothing can be done about the past three decades of code that have used that convention, so it should not be ignored either. However, that does not mean that a better convention could not be adopted in the future. Others have suggested .fx and .FX for this. One problem I see with this is that .fx could be thought of as “fortran extended” or it could be thought of as “fixed”, so it appears somewhat ambiguous. Maybe that ambiguity is insignificant? I don’t know. Of course, it is unfortunate in the first place that both “free” and “fixed” start with the same letter.

I understand your concerns, but I think the analogy with F was not exactly the best argument ever. F failed because it completely eliminated legacy code. Not supporting a compiler flag to at least allow legacy code to exist in some files (co-existing with F code in the same project but compiled with different FFLAGS) was a big mistake. I was an advocate of F and I must say the F compiler I used for some time was excellent (it issued warnings that you explicitly used something with only but never actually used it in the code, for example.) However I was really annoyed by the fact it didn’t let me use legacy code at all. If a language manages to annoy even its advocates with such an obvious flaw in design, it is sentenced to die.

Nobody said we should do what F tried to do, definitely not me. What I said is do something so that the compiler encourages modern Fortran in new projects, instead of doing the exact opposite with its default settings. Because that’s exactly what all compilers do now. And that’s one of the reasons people think Fortran is “obsolete”, a relic of the past that should not exist anymore. I’m tired telling students Fortran is not FORTRAN 77 anymore, only because the compiler is pretty happy accepting legacy style by default. Even in this Discourse I see mixed code very often, especially by new users asking for help.
We start to get dwarfed by languages that are blatantly not made for scientific programming, only because we refuse the slightest change, not even a change in the default compiler settings.

Again, the “new user” starts to sound proverbial only because we refuse any change. I’m not sure what’s worse, letting new users mix legacy with modern right away or forcing them to use modern Fortran and learn something useful: “There is excellent legacy code out there, it has the .f or .for filename suffix, traditionally. You can use it if you need it, just add this compiler flag when compiling it”. Which is harder to learn? This compiler flag or re-learn the language when you are already used to mixing legacy with new code in the same program entity, just because the compiler lets you do so by default?

Last but probably not least, I’m not sure quoting W. Churchill is a good idea in general, even when he said something smart (and he certainly did a few times.) He was at the right side of History, but he sent thousands of his boys to die in controversial missions ignoring his generals’ advice, and he is personally responsible for unnecessary deaths even in WW1 - say nothing about WW2, for which he was openly fascinated.

May I compiler try to compile a file first with free form and if it fails try with fixed form?
May exist a program that compiles correctly in free and fixed form but with a very different behaviour?

I know that you can write a program that can be compiled in free form and in fixed form. The point is to have a program that differ when compiled in the two way.

Ok a simple one will be to put additional instructions beyond 73 character, are there other ways?
May it be relevant for legacy codes?

May exist a legacy code that can be compiled in fixed and free form and have a different behaviour when compiled in the two ways?

Easy to give an example of that.

      program xyz
      integer i, j, k,ij
      i = 2
      j = 3
      ij = i*j
      k = i                                                                 &
     +j
      print *,i,j,k
      end

Make two copies of this source file, name one with a .f suffix and the other with a .f90 suffix. Compile and run, compare the results. They will be different.

1 Like

And how much time will take for a compiler to compile a file with both free and fixed form, not the full compilation, but just to get the abstract syntax tree and then compare the two (if the compilations succeed of course). If the abstract syntax trees are the same nothing to bother, otherwise emit a warning (or an error) and assume the free form is the correct one.

I imagine, most of the time, the failure will happen quite soon for legacy codes.

But it was just an idea, cheers.

Some time ago, I found myself thinking along similar lines. What if the compiler kept count of the number of syntax errors as it processed a source file as fixed format and, when the count exceeded a limit such as 100 after 50 non-comment source lines, aborted the compilation and retried assuming free form? If the number of errors after 100 lines were found to be less than the count in the aborted attempt, the compiler could issue a warning that it was re-compiling the file as a free form source file because …

The drawback again is that this idea penalizes experienced users who do not face this problem while helping beginners who may have never come across fixed form Fortran source and do not know about the presence of two source forms.

The discussion is circling around concepts and issues that I have proposed to solve with fpm a couple of years ago with this issue (where reclaiming the .f extension was one of the elements proposed, generating the relevant issue). Some of you might want to have a look.

To contextualise, I decided to put this proposal forward exactly because I’ve faced considerations and situations like

and

3 Likes

The example with dgels is also not at all a good one either.

DGELS has an involved dependency map and as such, it is downloaded as part of an entire (*PACK) library or consumed as part of a compiler package installation (e.g., Intel). Either way, there is very little practical overlap with the discussion on hand with the compiler default on source form:

  • with the latter where DGELS can be consumed from the vendor package, there is no relevance,
  • with the former, the build toolchain for the numerical library can be separate that can include specific options such as informing the compiler of the source form (e;g., -ffixed-form) which is unaffected by the defaults that the consumer might prefer on one’s own codes.

The arguments, again and again, for retaining the defaults based on legacy work practices such as fixed-form source for .f and .for are so worn out and illogical and irrelevant any longer.

1 Like

You did say regarding mixing modern and legacy fortran, “That’s exactly what we need to avoid. The “something in between” is what makes newcomers frustrated,” which is what prompted my reply. If someone wants or needs to use legacy code, then they must be able to understand it. Yes, that can be challenging, and even frustrating.

As a practical matter, here is how I use legacy code. I expect everyone else does something similar. If the old code compiles and works correctly, and I do not anticipate needing to modify it, I just use it as is, or perhaps make some minor changes in order to incorporate the code into a module. That sometimes involves adding the subroutine name to end statements and eliminating external statements for routines that are now module procedures. If I need to modify the code and adapt it somehow, then I do other things too, such as adding implicit none and declaring all variables explicitly. At this point, everything is still likely fixed form source, the same as it was when I downloaded it. The next thing might be to change argument lists, perhaps adding or combining argument into derived types. This typically involves adding USE statements and other modern features. This is about the time I consider converting to free form source. But this conversion is simply for my own convenience, the language does not require it. Everything that can be done in modern fortran with free form source can also be done with fixed form source, so I expect different people do this step at different times, but in any case, it is just a personal preference. This is about the same time that I would consider removing common blocks and replacing them with shared module data, eliminating all of the double precision declarations and replacing them with KIND values, adding KIND extensions to all floating point constants, and those kinds of things.

The other factor in this is how the code is archived in a repository. If I, or other programmers, want to track the gradual changes, then that also affects when the fixed-to-free source code changes occur. If one does that conversion early, then it makes it impossible to track the gradual changes. One commit is fixed form, and the next commit is free form, and every single line will show up in a difference listing, obscuring the noncosmetic essential changes that one really wants to track, and making source code comparisons with the original code more difficult.

My point is that for many of those intermediate steps, the code is indeed in a mixed state with legacy remnants mixed with some modern features. Fortran has been designed, carefully and purposely, to allow that kind of gradual evolution to be done. It does place more burden on the programmer, including new programmers, to understand how all of those old and new things work together, but if they are going to use legacy code, that is necessary in any case.

If within a programming project, the convention is to not allow legacy code at all, then that eliminates one of the major advantages of using fortran. As you say, that is why the F and ELF dialects failed. No modern programming language, such as python, julia, etc., have that kind of legacy simply because they are not old enough.

Regarding the history quote, yes I know that both the philosopher Santayana and the statesman Churchill made the same point. Santayana was a white supremacist and a eugenics advocate, while Churchill was the prime minister of his country during war where many lives were lost. I think one is allowed to quote either of them to make a point without advocating for every other decision or every other belief that they held.

I also want to point out that this discussion about using legacy code is a tangent to the discussion title about fortran file extensions. This part of the discussion is independent of compiler defaults and how to use and modify existing Makefiles and other build systems.

1 Like

To recap:

@Pap, as the original author of this thread, expressed interest in “reclaiming.f as the file suffix for “modern Fortran” code which is expected to be in free-form source. But that is currently rather problematic as several of the compilers treat files with .f suffix and also .for as fixed-form source code by default.

And the existing compilers who do so are unwilling to change the default. This is an issue for anyone wanting to proceed with .f as their preferred file suffix.

This issue is at the crux of the discussion, the unwillingness to change even as others such as @epagone et al. agree with @Pap re: wanting to be able to proceed with .f as the preferred suffix. And if given the choice, many more practitioners are likely to drop .f90 and move to .f for their codes that use current standard with free-form source i.e., modern Fortran.

Using .fx might make the people who think .f90 is only for Fortran 90 believe that .fx is only for programs that must be compiled with ifx and not with ifort, gfortran, NAG etc. Why not follow the example of many US states’ 2-letter abbreviations and use .fo or .FO ?

Nowadays file extensions are not limited to just 1-3 letters. How about using the file extension .fortran for all modern, free format Fortran source files? Would this make any sense?

4 Likes

I have a really wild idea. Preprocessing is on the table for the next standard. What if it included directives to signal to a processor whether the following source was free or fixed? Then you could even mix and match in the same file, and the compiler is free to determine the source form by other means if they are omitted (i.e. file extension). We could even include signals about version of the standard to use and start actually removing old features!

NOTE: This is just a preliminary idea, so it may have holes

3 Likes

I have wanted to do that many times in the past when mixing new and legacy code, for example, to put everything into a single module. One workaround is to convert everything to free form, but as I said previously, that sometimes gets in the way of making small incremental changes to a repository code. The other is to put things into two modules and then combine them with USE statements, but then you have two *.o files to worry about instead of just one.

This seems about as clear and explicit as it can get. I’d extend it to apply to all Fortran source files.

The Fortran Standard and the vendors of mature compilers won’t do anything about this, so the only way forward is for a new compiler like LFortran to establish a convention and lead with it.

3 Likes

The only minor downside to this I can see is typing 7 characters instead of 1, 2, or 3. Would that make fortran look even clunkier than it already does? The upside is that it is backwards compatible with past conventions (i.e. it leaves *.f and *.f90 as is).

Another possibility is something like .free. But then we will have the gnu folks wondering if it is free as in freedom or free as in beer.

I’m not sure the fortran standard should say anything about this? As for mature compilers, if it is backwards compatible (and .fortran would be, I think), then I doubt there would be opposition. It is mostly just the proposed features that break backwards compatibility that see strong opposition from the community (users and compiler vendors).

Oh, of course not, just pointing it out. :slightly_smiling_face:

RonShepard’s objection to .fortran does not apply to .fo , which shares the upside he pointed out.

I vote for either .ftn and .FTN or .for and .FOR. I think Cray supports .ftn (or did at one time). Keep .f and .F for those still tied to F77. Personally, I think its time to move on from tying anything in Fortran to a particular iteration of the standard. The compiler developers can implement compiler switches to force compliance with a particular version if they want. The default should be the most recent version implemented by the compiler.

1 Like