A Fortran formatter written in Fortran

Behold: fformat – A Fortran formatter written in Fortran. Another vibe-coded experiment, using Claude Opus 5.5, to create a quite useful tool that would not traditionally be written in Fortran. The results are just amazing.

Here is a speed test using fortranpack (38 libraries, 276 files, 183,666 lines of code):

Tool Written in Version Time (s) Lines/s Relative time
fformat Fortran 0.1.0 0.555 330,667 :green_circle: 1.0x
fprettier Rust 0.5.0 0.701 261,840 :yellow_circle: 1.3x
fprettify Python 0.3.7 20.978 8,755 :red_circle: 37.8x

Obviously, there are some disclaimers here (the different tools maybe aren’t quite doing the same thing, etc. I can try and update the test to try and use consistent settings for each as best that can be achieved). But as a first cut, this is amazing! The Fortran version is slightly faster than Rust, and of course the Python one is incredibly slow.

Honestly, what is the advantage any more of using Python for tools like this? Why would anyone choose a slower tool over a faster one that does the same thing? A Fortran formatter doesn’t need to be dynamic in any way. The “batteries included” argument for Python also is almost irrelevant now. I’m using a couple of existing Fortran packages via FPM, and for this project also created a brand new regex library on top of that (see fregex). And why introduce a newfangled esoteric programming language like Rust when it’s not even faster and we can do everything we need in good ole Fortran? (Don’t come after me Rust bros!)

This is all very preliminary and experimental. I’ve spent almost no time on this at all. But it seems like really getting this up to production use wouldn’t take that much effort.

17 Likes

Amazing! You are single handedly translating everything into Fortran :grin:

And why not. It shall be the first and the last, alpha and the omega, of the programming languages.

I remember reading about a report (against fortran) in DOE or somewhere that argued Fortran be stopped mainly because there are not enough developers. I guess that argument is obsolete now?

5 Likes

@jacobwilliams , which compiler you used for the test?

gfortran 15.3.0 on my mac laptop.

1 Like

The funny thing is I always viewed the “let’s convert everything to language X” as a little silly in some cases, and a massive waste of resources in others. AI changes that equation a little…

Historically, Fortran tooling was just terrible. But, with all the amazing work that has been done recently, it’s actually great now! Just look at the components I slopped together in Fortran Package Manager GUI. But we’re not as fast as we could be… What if we had instant linting, instant syntax highlighting, instant language server integrations, etc. I think we can have all that now…

2 Likes

With ai assistant apps and how these tools are advancing, what will be the advantage or need of any computer language at all, let alone assembly language, not even getting to “FORTRAN”?

Is not the entire business or use case by the IBM team and the “infamous” project that got kicked off with Backus et al. early 1950s now defunct?

It appears the only real challenge now is ACCESS, to energy and data, with vast percentage of humanity having neither of such access now with the great risk even their progress towards such access may be fraught with increasing difficulties.

Does language X or Y (say Python) vs language B (say “FORTRAN”) matter at all now in the larger scheme of things? ai assistant apps shall be able to process and execute at the base level, bypassing all the middle layers.

5 Likes

Yes, I agree in principle. But there are two camps: 1. Abstraction, 2. Low-level. Some of this discussion can be found in this other thread Modern language design and the battle for AI dominance

First camp thinks there should be an “orthogonal basis” of constraints and semantics and efficient tooling that lowers the intent to low level that leads to efficient , and most importantly, correct code.

The second camp thinks that the abstraction lives inside the AI brain. It leads to what you are describing.

I think we have still way too inefficient and primitive AI for the 2nd camp. But I believe AI could potentially design a new language that could optimize everything.

2 Likes

With some more benchmarking and code optimization, it’s now even faster:

Tool Written in Version Time (s) Lines/s Relative time
fformat Fortran 0.2.0 0.381 482,298 :green_circle: 1.0x
fprettier Rust 0.5.0 0.683 268,758 :yellow_circle: 1.8x
fprettify Python 0.3.7 20.729 8,861 :red_circle: 54.4x
2 Likes

I use fprettify in all my projects as part of the my CI, I’d love to get better speeds! I’ll take a look

Good job.

For the sake of completeness you can add the Codee formatter to your benchmark.

Just a thought, but, if your formatter could work as a dynamic library, I could use it as a plugin in fpx to return formatted string after preprocessing. At first sight, all it takes on your end is a function that takes the string and the current indent and return the pretty string.

1 Like

Thanks also for the regex library. Looks nice and battle tested.

Just a side note, but fregex was already taken (twice at least)

Changing the name would make it easier for the fpm repo, i guess.

2 Likes

Nearly 500k LOC vs ~9k in fprettify (Python)??! This comes across as a bit much.

What’s the explanation?

Send me a ticket or even a MR. This is all highly experimental and changing fast, but if we think this will actually be useful I’m happy to add whatever anybody wants!

1 Like

Naming things is hard! I can try to come up with a better name!

No idea! Python is just slow, but maybe fprettify is doing something inefficiently? i’m not a developer of fprettify or fprettier.

Jacob, any chance of adding some minimal F77 to F90 conversion capability. If you can just do the following mimimum requirement set it would be a big help.

  1. Convert continuations to F90 format
  2. Convert comments to F90
  3. Convert upper case to lower (adding a user option to keep reserved keywords and intrinsic function names UPPER would be useful)
  4. Change label DO loops/CONTINUATION etc to DO/ENDO.
  5. Changed fixed column 7 formats to user prescribed indentation patterns.
  6. If the code has explicit typing (REAL, REAL*4) etc. Convert to real(wp) :: somevalue (or something similar).

Edit.

Also convert Hollerith data in FORMAT statements to character strings.

Trying to refactor IF constructs and getting rid of GO TO are things that should be probably done at the compiler ASR/IR level.

1 Like

This is maybe scope creep from what I originally intended… but AI-fueled scope creep is now my middle name!!!

Where are some good F77 monstrosities that would be good test cases for this?

I would start with the ones I think you have already converted. SLATEC, NSWC LIB, and NBS CMLIB. However, if I remember correctly there is a lot of duplication (same codes) between all three of these.

Also, I suggested the limiting feature set above because I think they fit into the concept of a “formatter”.

2 Likes

fpt is also written in Fortran and automatically reformats code. It will do all of the things which you have listed. Also, because it does a complete static semantic analysis, it will recognise the difference between an intrinsic function, a keyword or a variable with the same name and apply the appropriate formatting rules for the name. Please see Formatting Fortran Code

3 Likes

I remember seeing this convention (keywords and intrinsic names in upper case) some in the 1980s. I think it was a carryover from pascal. But I’ve never really seen experienced fortran programmers do this. A much more common convention for fortran programmers is to define cpp macros in upper case, and then have the rest of the program in some combination of lower case, capital case, or camel case. So I think a more popular option regarding case conversions would be to ignore anything in all upper case and then act only on the remaining tokens.

Another option would be to add “_wp” kind values (or some other convention) to all floating point constants. I have in the past posted a small perl script here that does this, but there are some corner cases that it misses, so it is not fully automatic and it requires the programmer to double-check the changes.

I think this is a very good convention to adopt when working with large numbers of programmers, all of whom have their own preferences for indentation levels, upper/lower case conventions, and so on. When one programmer works on a code and makes these types of changes, it renders many of the diff-based source code comparisons and status queries almost useless for the other programmers in the project. So enforcing a standard source code style for the shared repository code solves part of that problem.