[Patch, Fortran] PR fortran/39626: Implement Fortran 2008's BLOCK construct
Daniel Kraft
d@domob.eu
Mon Sep 28 14:46:00 GMT 2009
Hi all,
here's my revised patch to implement the BLOCK construct that will
appear in the upcoming Fortran 2008 standard. I personally believe that
this is some really nice feature that missed for a long time, and also
heard others say they'd like to have something like this in Fortran.
Especially nice is that you can have automatic variables with dynamic
array size or string length, as per the block_2.f08 test case.
Something like:
INTEGER :: n
... get n somewhere ...
BLOCK
INTEGER :: arr(n)
CHARACTER(LEN=n) :: str
... work with arr and str here ...
END BLOCK
Additionally, I believe it is sometimes helpful to keep local variable
declarations near the place they belong (especially for long routines),
but that's of course some point of preferrence and style.
In any case, what this patch does is implement BLOCK somewhat
"basically" -- see the test cases for what exactly it is supposed to do
and which errors to catch. As Richard Maine pointed out in some c.l.f
thread, there are a lot of fine points and corner cases; I do not strive
to handle them here mostly. I did target to implement the "reasonable"
semantics I would expect as user not thinking about the standard and
ugly cases, just defining lexically scoped local variables including
automatic variable length arrays and strings as mentiond above.
Regarding the draft F2008 standard, I tried to implement the section
about "The BLOCK construct" as fully as possible. However, so far I do
not care about VOLATILE and ASYNCHONOUS declarations inside the BLOCK,
did not implement the clause that a SAVE list may not target common
names and also do nothing special about locals being "construct
entities". block_7.f08 is a test case designed for some special
handling required with implicit typing because of that (as per Richard
Maine's answer on c.l.f, linked from bugzilla), but it seemed harder to
me to implement than I first thought. Because this is something I do
not think really important for real-world users, I XFAILed the test and
would like to defer this along with other points mentioned to some later
patch/"bugfix". I will document this in the PR and keep it open.
Additionally, I may add some words about BLOCK to the gfc-internals
documentation in some later patch when I find time to do so.
The patch is against today's trunk and passed both a full bootstrap and
regression test on GNU/Linux-x86-32. Ok for trunk?
Yours,
Daniel
PS: Here are some words about how I actually implemented BLOCK.
I tried to re-use most of existing handling of namespaces/program-units,
as a BLOCK is somewhat similar to a contained procedure. Internally, a
BLOCK statement is a gfc_code of type EXEC_BLOCK. It "owns" a namespace
in ext.ns, which keeps the local variable symbols. This namespace has
the containing procedure (or block in case of nested blocks) as parent
and is the gfc_current_ns for the block's body; so quite everything is
automagically handled "right" by the existing code, just as it would in
case of a contained procedure.
The proc_name symbol of the BLOCK's namespace is set to a FL_LABEL
symbol with either the block's name if it is given one or "block@" if
there is none. We need this proc_name symbol later for code generation
(because the symbol's tlink field is used there -- this seems to be not
a particular beautiful design in handling intialization/clean-up for
variables).
Parsing of a block is also done mainly with the already existing code in
parse_progunit. A block gets resolved by resolving its namespace, and
in the future we may want to add some more checks or special handling to
the resolution routine resolve_block_construct, though at the moment it
is quite small.
Finally, the code generation also "just" uses the existing code for
procedures/local variables; we generate a block, add the body and local
variables as well as their initialization/clean-up code by means of the
existing trans code, and finish it.
While this may seem a little "hackish" because of generating this symbol
as part of a statement, I really do think that it is quite a good
solution because a lot of things work just with existing code
out-of-the-box.
PPS: In block_2.f08, is there an easy way to check that the local
allocatable array gets free'ed on exit of the block? (Marked by an XXX
comment) If not, I think it won't hurt much to just get rid of the
comment and not check this, but if there is, it would be cool to add
this check.
PPPS: This patch (or a nearly finished version without some error checks
and clean-up) was already tested a little in real-world, somewhat... I
used patched gfortran and BLOCK constructs (mainly for automatic
variable-size arrays and variable-size strings as noted above) for round
2 of Google CodeJam last Saturday. Well, I did perform really, really
bad :D But the patch and gfortran were not once the reason for it ;)
--
Done: Arc-Bar-Cav-Ran-Rog-Sam-Tou-Val-Wiz
To go: Hea-Kni-Mon-Pri
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: patch.changelog
URL: <http://gcc.gnu.org/pipermail/fortran/attachments/20090928/b55f47b8/attachment.ksh>
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: patch.diff
URL: <http://gcc.gnu.org/pipermail/fortran/attachments/20090928/b55f47b8/attachment-0001.ksh>
More information about the Fortran
mailing list