On 4/16/19 9:06 AM,
ga...@u.washington.edu wrote:
> On Sunday, April 14, 2019 at 3:04:05 PM UTC-7, Ron Shepard wrote:
[...]
> Early Fortran compilers used only static storage. Without recursion,
> there isn't a big advantage for automatic storage.
For computers with limited memory, a few hundred or a few thousands
words total, it was very useful to allocate local variables on a stack.
That memory could then be reused by other subroutines upon return with
no effort on the programmers part. The alternative was to put local
array in static storage and then require the programmer to overlay the
routines in memory outside of the language, or to access those variables
in common blocks, again leaving up to the programmer to keep track of
what subroutine was using which variable at any time.
> Fortran 77 added the SAVE statement to request static storage,
Not exactly the same way as in other languages or in assembler. In other
languages, the loc() of the variable would be the same. Fortran 77 did
not guarantee that, and modern fortran also does not guarantee that.
Fortran only requires that the value, referenced through the variable,
remains the same. The underlying memory could, in principle, be swapped
out, reused any number of times, and then later swapped back in when
necessary, possibly at a new memory location. The C interop stuff might
affect some of this behavior.
> but there is no way to request non-static (usually automatic)
> storage.
This is correct, at least in standard fortran, and that is still true in
modern fortran. Also there is no REGISTER type of declaration that
requests, or requires, that specific variables be associated with
hardware registers. This is supported, at least to some extent, in other
languages and also as extensions in some fortran compilers.
Not so unusual in older Fortran programs:
>
> DATA PI/0./
> IF(PI.EQ.0.) PI=4.*ATAN(1.0)
>
> note that this works, though less efficiently, if PI gets
> initialized each time, but most compilers still used static
> storage and initialized it once.
If the variable was not in common, then I think this was always
undefined behavior in fortran, even after f77 unless the variable was SAVED.
> With Fortran 77, you were
> supposed to use SAVE to request only initializing once.
The initialization by a DATA statement was never required to be done
more than once, regardless of whether the variable was SAVED or not. The
language only required that it kept its value as long as it was not
changed. If it was changed, then it had to be in common, or later in f77
it had to be SAVEd, in order for its value to be defined.
> (Either SAVE by itself, to give all variables the SAVE attribute,
> or specifying the specific variables.) Fortran 77 was carefully
> written to allow, but not require, static storage for everything.
Yes.
>
> Fortran 90 added recursion, which requires (pretty much) automatic
> allocation, such that each iteration has its own local storage.
> As well as I know, since many programs used DATA in the static
> allocation sense (though most to initialize data that never changes),
> it was decided that DATA variables are always SAVEd.
I thought this change was in f2003, not f90. In any case, this is what I
think was the mistake in the language, I think the explicit SAVE should
have been required, and I think the compiler should have been required
to tell you when it wasn't there.
>
> (Note that there are some complications when using overlays,
> but that is a lost art by now.)
As computer memories grew from bytes to kbytes to mbytes to gbytes, the
need for overlays evaporated. It was always an agreement with a wink and
a nod between the compiler and the overlay linker how things worked. It
was possible, maybe all too easy, to use a linker to make a standard
conforming program behave in a nonstandard way. I once used a linker
that allowed me to have two different copies of a common block, and I
could force one set of routines to access one copy and another set of
routines to access the other copy.
> Many would use a LOGICAL variable for this, but INTEGER is fine, too.
Sometimes you need to save more than two state values, or you anticipate
that you might do so in the future.
> I suspect that enough programs depended on it working, and people
> didn't want to go change all of them.
Yes, some small minority of nonconforming programs, and now everyone
gets to be confused forever because of that hack to the language.
> But yes, many languages have the ability to initialize automatic
> variables, which then happens each time.
In every language that does this, it is redundant with a simple
assignment. It might save a few keystrokes, but it is, and will remain,
confusing, especially to people who program in multiple languages with
different semantics.
Saving keystrokes might be important in an interpreted language where
you type the code once and have it executed immediately, but it is less
important in a compiled language that runs on code saved in files.
> So, yes, it would be nice to be able to use initializers with
> automatic variables in Fortran, at least scalar, and maybe arrays.
It is exactly equivalent to an assignment, and the assignment offers no
chance of confusion. There is no practical difference, no efficiency
difference, no difference at all.
> For now, as well as I know, the only way to create automatic
> variables in Fortran is to give the procedure the RECURSIVE
> attribute, and not use them in a DATA statement, or with an
> initializer on the declaration statement.
Even this does not enforce it, the language only requires that it
behaves "as if" it works that way. For example, it could also work by
swapping in and out the local variables into the same memory locations.
If compilers were still working in kbyte address spaces, that is
probably how it would be implemented. But with gbyte address spaces,
they will be allocated from a stack in memory that never gets swapped.
$.02 -Ron Shepard