This is the mail archive of the
fortran@gcc.gnu.org
mailing list for the GNU Fortran project.
Re: F2003 Finalization -- progress and problems
Tobias Burnus wrote:
After finishing the code, I want to write some little documentation
about how finalization works and is implemented if you want so in the
future everyone has it easier to work on it (now that I still know how
it works...), if you point me where to write this.
GREAT idea! I think gfc-internals.texi is the best place, see:
http://gcc.gnu.org/onlinedocs/gfc-internals/
(An alternative would be the Wiki, but I think gfc-internals.texi is
better.)
I also like the TexInfo better, so we've agreed here ;) But this will
have to wait until the code is ready for check-in I think, then we can
discuss this again.
c) what exactly does that "specification expression in scoping unit"
mean? But otherwise, this sounds similar to b).
"If a specification expression in a scoping unit references a function,
the result is finalized before execution of the first executable
statement in the scoping unit."
"7.1.6 Specification expression"
"R729 specification-expr is scalar-int-expr"
"C710 (R729) The scalar-int-expr shall be a restricted expression."
"A *restricted expression* is an expression [...], and where any final
subroutine that is invoked is *pure*."
But then nothing needs to be finalized if the result has to be
integer... Or did I miss something?
b) results of functions and structure-constructors after they have been
used: I'm not sure how this could be done in resolution-phase (without
"rewriting" the code and introducing temporaries), but maybe in trans
this will be easier. Any ideas and tipps?
I don't quite understand what with "after they have been used" is meant
- nor can I find it in the standard. (Currently, I have no opinion
whether on should use trans*.c or resolve*.c.)
In the subsection "When finalization occurs":
...
"If an executable construct references a function, the result is
finalized after execution of the innermost executable construct
containing the reference.
"If an executable construct references a structure constructor, the
entity created by the structure constructor is finalized after execution
of the innermost executable construct containing the reference."
My problem here is that if we have something like:
x = foobar (funct (x)),
where funct returns a finalizable entity. Then we need to generate code
like that:
temp = funct (x)
x = foobar (temp)
finalize (temp)
If I did understand the code correctly. Are such nested constructs
flattened in trans like the above or is this passed down like it is to
the middle-end and converted there? In the latter case, we would need
to split it and introduce temporaries manually during either resolution
or trans to handle the finalization (in that case when both are equally
possible, I'd prefer resolution as working on the gfortran-trees is
probably easier as more information is available). Or do you have
better ideas?
I think it should not be too hard to do those splitting of expressions,
although it surely makes the code uglier, but I don't see any other way
to handle the finalization-requirements of the standard.
e) intrinsic assignment: for ordinary assignments this is handled
What do you mean by ordinary assignments? If you mean a simple
Right, I mean assignment not in WHERE/FORALL; I believe somewhere in the
code this is called "resolve_ordinary_assignment" ;)
type(t) :: x, y
y = x
then this is an intrinsic assignment unless you have "assignment(=)"
anywhere. Using
interface assignment(=)
subroutine assign_t(x,y)
the finalization happens automatically as the LHS argument matches a
INTENT(OUT) in assign_t.
Ah, yes! But I have to make sure the LHS is not finalized twice in this
case; the old patch *should* already handle this, but at the moment
there's no test for this. That will be changed of course.
WHERE (arr == 2)
arr = 5
END WHERE
Should this finalize the whole masked arr at once or each element before
it is overwritten? Can there be a similar unclarity for FORALL?
I really dislike WHERE as it is (at least to me) a bit intransparent
what happens there. Maybe something to ask at lang.comp.fortran.
I myself don't have much experience with WHERE, only looked at it
briefly once. From a programmer's point of view, it sounds nice to me
(or, better, like a neat feature that let's you express some thing in an
elegant way; but it might be something that's never really needed
anyway, I don't know). But I believe this will be some mess implementing...
I read this as follows, but now guarantees that I interpret the standard
correctly.
{
tmp = function(array)
finalize(array(mask))
array(mask) = tmp(mask)
}
That makes sense, so finalizing the masked array.
FORALL: I have not yet fully understand how this should be handled, but
note:
"C738 (R756) Any procedure referenced in a forall-body-construct,
including one referenced by a defined operation, assignment, or
*finalization*, shall be a *pure* procedure."
And for PURE procedures:
"C1273 Any procedure referenced *in a pure subprogram*, including one
referenced via a defined operation, assignment, or *finalization*, shall
be *pure*."
Do you mean I have to check on finalization if the only calls are pure
procedures and output an error otherwise? Hm... It gets even nicer...
I was more thinking about the expression "x + foobar (x)" in itself
rather than the I/O; that's because foobar (x) changes the value of x
and I wanted to know whether it was defined or not if the first x had
the earlier or later value.
In other words: The program is invalid and the compiler can do anything.
(The saying goes this includes starting WW3.)
Thanks, that's what I was looking for.
+ TYPE(yes_t), ALLOCATABLE :: alloc_vector(:)
+ ! alloc_vector is deallocated automatically here
+ ! XXX: Or not?
BTW, I was a bit surprised when I first read about this nice feature
of automatic deallocation (and automatic allocation the like)--Fortran
isn't C++ :D
That is one of the nice features of Fortran: With allocatable, one
cannot have loose memory. If one tries to allocate an already allocated
variable, one gets an error; and when the variable goes out of scope, it
is automatically deallocated.
This is implemented now, I did this other than everything else so far in
trans as I believe this automatic deallocation is added there.
How about ALLOCATABLE components? I saw in the code there that all
those are recursively deallocated during deallocation of an entity. So
this means we have to finalize those, too, before they get deallocated,
right? But maybe this isn't much effort now I've already some
experience (and code) for doing the finalization in trans.
The problem with this is just that I need the original gfc_expr for
this, as I have to have access to the derived-type structure and similar
for access to the finalizer-procedures and the like. And this lets me
reuse the existing finalization-code :D
Cheers,
Daniel
--
Done: Bar-Sam-Val-Wiz, Dwa-Elf-Hum-Orc, Cha-Law, Fem-Mal
Underway: Ran-Gno-Neu-Fem
To go: Arc-Cav-Hea-Kni-Mon-Pri-Rog-Tou