Does Fortran need a block text capability?

Wondering if anyone thinks proposing a block text feature for
Fortran would be as useful as I think it would be.

Most of my own preprocessing is to allow for placing free-format
documentation in the same file as the code or for defining
a character variable using a block of free-format text (see
prep).

But there is no standard Fortran preprocessor that might support the
feature and it would be preferable in my mind for Fortran to support
something like docstrings and “”" in Python as part of the language
anyway.

And I would strongly prefer the documentation be easily exported into
its own file for treatment as HTML, or tex, or markdown, or man-pages,
or other flat text formats in order to easily generate documentation
(short of Fortran supporting something like ford(1) or doxygen(1)).

As far as possible syntax goes I could envision something like a keyword
in a CHARACTER declaration or something like a BLOCK statement that
could only contain a block of text:

   NAME : textblock (mytext)
        This is a block of text
      that can become a character variable or
      just be treated as a comment block. 
   end textblock NAME

where if (varname) is not present it is just a block comment, but if it
is present the data is used to define the specified variable name, for
example.

Or a new descriptor on CHARACTER statements something like

   character(len=*),freeformat,parameter :: name(*)=[ character(len=80) ::&
      free-format text
      could go here
   ]

or using [[

   character(len=*),freeformat,parameter :: name(*)=[[ character(len=80) ::&
      free-format text
      could go here
   ]]

instead of

   character(len=*),parameter :: name(*)=[ character(len=80) ::&
   "   free-format text", &
   "   could go here" &
   ]

But those have several issues and potentially could be hard to parse
out of the file.

The INCLUDE directive is far more like a preprocessor directive (actually,
that is exactly what it is, come to think about it) that has a very simple
syntax and has to be on a line by itself and cannot be continued. So
it would be easy to locate and parse. So using it as a model a simple
comment would be something like

TEXT
  free-format comments
  go here
END TEXT

and a variable definition would be

character(len=80),allocatable :: myname
   :
   :
! in the body of the program, not in the declarations ...
TEXT myname
   free-format text
   could go here
END TEXT

and an optional label that could easily be parsed by an external program
could contain a suggested filename that some compilers might actually
support using for generating a filename on demand via a compiler switch:

TEXT name "myfile.tex"
   free-format text
   could go here that could be markdown, tex, HTML, flat text, ...
END TEXT

So an unquoted value would define data for a CHARACTER variable and a
quoted string could be used as a hint for a filename, or maybe a tag
for the developer like “todo”, and both could be on a single statement.

The rules that INCLUDE requires (line cannot be numbered, must be on a
single line by itself, … would make extracting the data externally
far easier.

It would be even better if the data was actually (optionall?) written
to the file, but that has other ramifications that might (or might
not?) make the feature more controversial.

3 Likes

I like the idea. I’m not sure the proposed solutions quite “nail” it, but it’s certainly worth exploring.

2 Likes

It seems that the objective here is to have a block of text be treated as if each line were a Comment (begins with !.) This is pretty common as a documentation method at the beginning of subprograms. Some text editors have commands to insert the ! character automatically at the beginning of each line in a range. Which is most likely why a separate syntax was not implemented. (Note that some compilers have an extension to allow C-style comments, in which case

/*

*/

would work.) This might be a simpler approach to an additional feature for Fortran.

I think there are a few use cases that ! comments don’t cover:

  • commenting out chunks of code up to a certain point in a line. This is useful for e.g. removing some items from an array but not others.
  • Writing long string literals. The current notation with & characters at the start and end of every line is pretty unwieldy.
  • Distinguishing between documentation and code comments (e.g. python uses '''documentation''' and #comments).

Obviously these are all ease-of-use things which can easily be worked around, but I definitely think having some kind of block text would make the language a little bit nicer to use.

Though not convenient as having /**/, ! in conjunction with & can still be used for selectively inserting comments within a statement. For example, I frequently use:

integer ::          &
   a,               & ! this is an integer
   b,               & ! this is another integer
   c                  ! a yet another one

There are two other cases beyond just “commenting out” sections of the code.

  1. Have a string literal include newlines. For example something like
character(len=*), parameter :: startup_message = """
This is my long, and nicely formatted message.
It gets displayed at program startup.
But I don't want to have to manually use concatenation,
continuation characters, and the NEW_LINE intrinsic,
because that clutters it up.
"""
  1. Have it defined by the language that some comments are to be treated as documentation. I.e. it is defined by the language that
subroutine my_cool_procedure
"""
This subroutine is super cool.
It does this, that and the other thing.
You use it like `call my_cool_procedure`.
This block of text is the documentation that goes with it
"""

I would find #1 to be the most immediately useful, but it might also be nice to have a standardized way of documenting code.

2 Likes

Literally using the python syntax presents the problem that “”" is not necessarily the beginning of a bad string in Fortran, but requiring it to end a line would probably work. My most common use is I want simply maintained blocks of text that do not require special editor modes to maintain and edit, especially since I often filter text through things like fmt and column and other commands; and sometimes that text is just a comment, sometimes it is for a variable declaration, and sometimes it is special documentation that I want to keep with the code but needs processed automatically into manpages, latex, txt2man, and might be
required to be formatted so Ford or Doxygen et. al. can process it. I do that simply now with a preprocessor, as often I want to write something once in the file as plain text and have it be used as both help text for the program and processed by documentation tools and other utilities. But I could live with two options of comment block and variable declaration as long as they supported being easily identified and extracted by other tools like Ford or Doxygen but also just simple scripts.

For example, I use a preprocessor directive like

$BLOCK  variable -varname=help_text -file doc/myprogram.1.man
NAME
     myprogram(1) - do cool stuff
SYNOPSIS
     myprogram --this --that  --the_other_thing
DESCRIPTION
    ....
OPTIONS
   ....
EXAMPLES
   ...
$BLOCK END
program myprogram
     ::
     ::
end program

and the text is easy to maintain, but it rewritten as a CHARACTER declaration in the code (or as comments if desired) but is also written to a file that is automatically converted into a man-page and HTML document and indexed. So I edit one file and can find my code and documentation, build the code and the documentation is automatically updated. Trying to do that currently with plain Fortran is painful. So that “extractability” is import to me but I do not necessarily expect Fortran to support that; but I would like it to support some labelling mechanism so I can use trivial external tools to extract the blocks I want to transfer. Long ago I used to use #cpp directives and something like
#ifdef DOC
my documenation
goes here
#elif C
C code goes here
#elif F
Fortran code goes here
#elif SHELL
#else
this file contains the Fortran code, supporting C code, documentation and system commands to process them to build such_and_such.
#endif

and then the make(1) files did things to build the documentation, compiled the Fortran and C, and so on.
Still would work.

This Pythonic multi-line string feature would be extremely nice to have in Fortran. Without it, one has to come up with complex ways of writing multi-line strings that are not quite aesthetic. Here is an example ugliness caused by the lack of this feature.

1 Like

Interesting. Looking at your example I am picturing If you had a procedure like the $SET command in prep(1) which would name a value like a “set” command in common shells (which
can be found in str(3f) and/or fmt(3f) in the M_msg(3f) module) that takes any intrinsic type
and something like the variable expansion in prep(1) you could envision something like

      :
   character(len=:),allocatable :: string(:) 
   integer :: i
   call set('var1',sqrt(3.0))
   call set('var2','another variable')
   string=form([ character(len=128) :: &
   ' this is my text where I print ${var1} and     ',&
   ' ${var2} and anything else using the same      ',&
   ' syntax as a "here" document in the POSIX shell'])
   write(*,'(a)'))trim(string(i),i=1,size(string))
       :

which could be done now using parts of M_msg(3f) and prep(1). And if
the “”" syntax were accepted and the AT descriptor available the string
declaration and WRITE() would simply be

   string=form("""
   this is my text where I print ${var1} and     
   ${var2} and anything else using the same      
   syntax as a "here" document in the POSIX shell
   """)

   write(*,'(AT)'))string

except for some question about indenting, which bash “here” documents have
too, I think that would be much nicer.