This is what I currently do, and have done for some 30 years, and I have found it to be widely supported and reasonably portable. However, the C preprocessor is not really part of the fortran standard, so we would also need to add that to the top five list.
I have a few files where I have #if 0 ... #endif blocks that are a few hundred lines long. They are basically a small paper describing the algorithm and the argument conventions that are built right into the fortran file itself. That way, I know the fortran code and the documentation will not be separated or out of sync.
At the moment, I’m in favor of looking at F202y (hopefully out in 2028 for the 70th anniversary) as a chance to make a limited number of non-backwards compatible changes as well as add important new features. So my list of 5 (well, 6) things probably looks like
generic programming (I’m worried about the power of our typing system, though)
better rank-agnostic programming (maybe a subset of the generics or maybe like Mathematics of Arrays where we treat array indexes as function transformations)
standardize minimal preprocessor support (cpp-like, presumably)
minor language convenience features: +=, -=, …, non-SAVE initializations, multi-ASSOCIATE instead of nesting, etc.
An area that I can’t speak to, but that seems important is enhanced support for parallel computing and hybrid computing (DO CONCURRENT and beyond). It seems it’s what Fortran is for, these years.
I only wrote it a few weeks ago, but without the comment I would already be confused about what it does. I’d like the ability to annotate actual arguments with intents in procedure calls, so that one could write
If this proposal were adopted and implemented in compilers, projects could require that all intent(out) and intent(in out) arguments in callers be so annotated, which would increase clarity. The reader could assume that non-annotated actual arguments correspond to intent(in) dummy arguments.
An FYI for prep(1) preprocessor users is that IF directives by default must be logical expressions so “#if 0” will not work by default with “–prefix ‘#’”; you must use the “-fpp” switch. I very much prefer keeping documentation and/or references to documentation with the source as well so prep(1) has a lot of options for that, including changing blocks of text to comments and/or writing them to separate files; so I do not use this method of embedding text any more myself, but I see that usage in others’ files.
Because of variations in cpp and fpp when I used something similiar I found “#ifdef DOCUMENTATION” a little more portable, as some other preprocessors also enforced the arguments to a #if to be a logical expression.
Many preprocessors also support /* … */ C-like comment blocks as well, but I also found that was not true of all default processors, at least in the past.
One of the tests for the prep(1) -fpp switch tests that “#if 0” syntax …
fpp mode tests
#if defined(_CRAYFTN) || defined(__NVCOMPILER)
BAD: ONE DEFINED
#else
GOOD: NONE DEFINED
#endif
#define _CRAYFTN
#if defined(_CRAYFTN) || defined(__NVCOMPILER)
GOOD: ONE SHOULD BE DEFINED
#else
BAD: NONE DEFINED
#endif
#define __NVCOMPILER
#if defined(_CRAYFTN) || defined(__NVCOMPILER)
GOOD: BOTH DEFINED
#else
BAD: BOTH NOT DEFINED
#endif
#if NOTDEFINED
BAD: "#if NAME" NOT treated like #ifdef NAME
#else
GOOD: "#if NAME" treated like #ifdef NAME like cpp and intel fpp
#endif
#if !NOTDEFINED
GOOD: "#if NAME" treated like #ifdef NAME like cpp and intel fpp
#else
BAD: "#if NAME" NOT treated like #ifdef NAME
#endif
#if 0
BAD: should not appear
#else
GOOD: should appear
#endif
#if 1
GOOD: should appear
#else
BAD: should not appear
#endif
EOF
fpp mode tests
GOOD: NONE DEFINED
GOOD: ONE SHOULD BE DEFINED
GOOD: BOTH DEFINED
GOOD: "#if NAME" treated like #ifdef NAME like cpp and intel fpp
GOOD: "#if NAME" treated like #ifdef NAME like cpp and intel fpp
GOOD: should appear
GOOD: should appear
In the C preprocessor, 0 is false and 1 is true. So #if 0 is indeed a logical test. That 0 is a character string, not a numeric value. The C preprocessor only works with character strings, there are no other data types.
GOOD: "#if NAME" treated like #ifdef NAME like cpp and intel fpp
This is at least a little confusing. Those two tests do not have the same meaning. Here is an example that demonstrates the difference.
A block of free-format text would be allowed for a write statement, or be used to generate an external document or define a CHARACTER array or be available as help, not just comments. This is allowed with the $BLOCK directive in the prep(1) preprocessor and greatly simplifies code development and documentation if you desire documentation and source to be contained in a single file; as an example.
At least a subset of this is available in many languages, such as the ``` strings in python.