I don’t think it’s possible, but let’s try: Zen of Fortran
I see: “block myblock” should be “end block myblock”.
But j is not an implicit variable - “integer :: j”. I tried a complete version (which had a judiciously placed implict none statement) with gfortran and got the message about j not having a type that I expected.
What am I missing?
Here is the code:
program blockj
implicit none
call mysub
contains
subroutine mysub
integer :: i
myblock: block
integer :: j
do i = 1,10
j = i * 2
if ( j > 5 ) exit myblock
enddo
write( *, * ) 'Final value: ', j
end block myblock
! j not defined here?
write(*,*) 'Value of j = ', j
end subroutine mysub
end program blockj
As I understand the block construct, the point is that variables declared within it are only available there; the block is their scope. So you would have to move the end block myblock
line below the last use of j
. This can get confusing in larger cases, as stated by @milancurcic above.
I’d say this is an argument against long program units in the first place
What I find annoying in Java, C++ or C# code where variables are declared seemingly haphazardly, is that you have to scan the code to find out where these declarations occur. It may be a matter of getting used to and I am sure we will never agree on the Only Correct Way To Program or the One True Style. If we did, programming and discussing programming might become boring.
Well, that ought to teach me to always check my code fragments , especially when demonstrating diagnostic capabilities.
Declare variables anywhere?
People already do. We found declarations after executable code (without block or associate) in WRF. WRF builds on ifort, gfortran, g95 (or it did), pathscale, fujitsu … So you can already do this with all of those. I see no reason why the standard shouldn’t reflect the behaviour of the compilers. For clarity it might be useful to specify the scope in or before the embedded declarations. That might prevent errors from cut-and-paste editing.
Best wishes, John.
Thanks, John, can you point to any specific source file? I’ve been working with WRF for 12 years and I haven’t seen such declarations.
Hi Milan,
I am away from home, but the latest WRF on the machine I have here gives me:
FPT> t
94 flux5(q_im3,q_im2,q_im1,q_i,q_ip1,q_ip2,ua) = &
95 flux6(q_im3,q_im2,q_im1,q_i,q_ip1,q_ip2,ua) &
96 -SIGN(1,time_step)SIGN(1.,ua)( &
97 (q_ip2-q_im3)-5.(q_ip1-q_im2)+10.(q_i-q_im1))/60.0
98 !
99 !
100 >> LOGICAL :: specified
!--------------^-------------------------------------------------------
!!! FPT - 3493 Declarations follow executable statements
!----------------------------------------------------------------------
101 !
102 specified = .FALSE.
103 IF (config_flags%specified .OR. config_flags%nested)specified = .TRUE.
104 !
105 ! set order for vertical and horzontal flux operators
106 !
FPT> show cursor
The cursor is at line: 100 in file:
wrf_re-eng/UCAR_clean_build/WRFV3/dyn_em/module_advect_em.F
At line: 91 in sub-program: module_advect_em%advect_u
Current scope is “ALL FILES”
FPT>
Now flux5 is a statement function, but that should be after the declarations. There are many like this. I will check current versions of WRF in a few days when I get back to my main machines. This was in 3.4.1 which is ancient.
John
By the way, the reply text box has completely trashed the formatting of the code. fpt is much more respectful!
John
That code is also here.
specified = .false.
if(config_flags%specified .or. config_flags%nested) specified = .true.
should be written
specified = config_flags%specified .or. config_flags%nested
and the same verbosity is present elsewhere:
degrade_xs = .true.
degrade_xe = .true.
degrade_ys = .true.
degrade_ye = .true.
IF( config_flags%periodic_x .or. &
config_flags%symmetric_xs .or. &
(its > ids+3) ) degrade_xs = .false.
IF( config_flags%periodic_x .or. &
config_flags%symmetric_xe .or. &
(ite < ide-2) ) degrade_xe = .false.
IF( config_flags%periodic_y .or. &
config_flags%symmetric_ys .or. &
(jts > jds+3) ) degrade_ys = .false.
IF( config_flags%periodic_y .or. &
config_flags%symmetric_ye .or. &
(jte < jde-4) ) degrade_ye = .false.
which should be written
degrade_xs = config_flags%periodic_x .or. config_flags%symmetric_xs .or. &
its > ids+3
etc. Are there any tools that can simplify such code? Maybe the awkward continuation syntax of Fortran should be preserved so that people are incented to write shorter code .
If that file is typical, WRF could be written better. Looking at
i_start = its
i_end = ite
IF ( config_flags%open_xs .or. specified ) i_start = MAX(ids+1,its)
IF ( config_flags%open_xe .or. specified ) i_end = MIN(ide-1,ite)
IF ( config_flags%periodic_x ) i_start = its
IF ( config_flags%periodic_x ) i_end = ite
it is not easy to see how i_start
is set. Clearer is
IF ( config_flags%periodic_x ) then
i_start = its
ELSE IF ( config_flags%open_xs .or. specified ) then
i_start = MAX(ids+1,its)
ELSE
i_start = its
END IF
or
IF ( config_flags%periodic_x ) then
i_start = its
ELSE
i_start = merge(MAX(ids+1,its),its,config_flags%open_xs .or. specified)
END IF
Statement function statements are declaration constructs. Type declaration statements (like LOGICAL :: specified
) are too. They can be mixed together. There don’t appear to be any executable statements before the declaration of specified
.
This is the key. This is very common in Fortran codes that statement functions appear anywhere in declarations. LFortran was tripped by this too and we had to rework our parser.
@Jcollins , you will be hard-pressed to find a Fortran processor that allows a specification-part
in the execution-part
of a program, some relaxation along such lines is what “declare variables anywhere” would require.
None of the processors studied alongside fpt
are likely to allow the following:
print *, "Hello World!"
integer x
end
Please note the example you give with WRF upthread suggests fpt
misconstrues stmt-function-stmt
- which is a declaration-construct
part of the specification-part
- as belonging to an execution-part
. That example is not indicative of compilers supporting “declare variables anywhere”.
I agree that we should try to rearrange assignments of values to logical variables so as to make the code more readable, but we need to be careful to keep the logic intact.
The above suggested replacement is incorrect; you need to apply .NOT.(…) to the right hand expression.
You are quite right. Under extended FORTRAN 77 (e.g. VMS) statement functions were required to lie between the last type/parameter declaration and the first data statement. This is no longer the case, and now data statements can be written anywhere and statement functions can go amongst the type declarations. I have checked the versions of WRF I have with me, and there are no type declarations after executable statements. I will amend fpt to accept statement functions within the declarations (it processes them anyway, just the error message is spurious). Apologies!
Yes, this is spelled out in Table 5.1 in clause 5.3.2 in the standard. There is a lot of apparent weirdness in that table, if I’m reading it correctly. (Like FORMAT statements can appear interspersed with IMPLICIT declarations???)
Yes, when you read it carefully as I had to do to figure out what is going on, there is all kinds of freedom that is allowed that I didn’t know about (and don’t want to know about ;).
I wish you could put implicit none
just after the program foo
or module foo
statements and before the use bar
statements. I have gotten syntax errors many times for having implicit none
in the wrong place.
I agree, would prefer to put implicit none right after the program or module.