Allow end do loop_variable?

In an October 2020 comp.lang.fortran thread I suggested that the following syntax be allowed:

do i=1,n
   do j=1,n
      ...
   end do j
end do i

Currently, one can write

do i=1,n
   do j=1,n
      ...
   end do ! j
end do ! i

but comments are sometimes wrong and are not checked by the compiler. The currently permitted labels

do_i: do i=1,n
   do_j: do j=1,n
      ...
   end do do_j
end do do_i

are more verbose than the suggested syntax, and labels such as do_i can only be used once in a procedure, even if there are several loops over i. They could also be misleading – the above code is valid if do_i and do_j are interchanged everwhere.

What do people think? I may suggest this feature at j3-fortran/fortran_proposals. I would use it often if it were available.

In the Visual Basic for Applications (VBA) language, one can similarly write

For I = 1 To 10 
   For J = 1 To 10 
      For K = 1 To 10 
         ... 
      Next K 
   Next J 
Next I

The counters after the Next statements are optional. So there is a precedent for the suggested syntax in a widely-used language.

1 Like

So what would be the scope of I and J? Would they be implicitly implied as integers or still need declarations if “implicit none” were in effect? I like the syntax you propose, put the following also crossed my mind:

I: do 1,n
   J: do 1,n
   ...   
   enddo J
enddo I    

where the labels would also implicitly declare an INTEGER variable with scope only within the range of the DO.

Perhaps because it varied between compilers in the distant pass, I have seen code that incorrecty assumed the values of I and J were 2 instead of 3 in the output from the WRITE() in code such as

n=2
do i=1,n
   do j=1,n
   enddo
enddo
write(*,*)'I=',i,'J=',j
end

limiting the scope of the counters to the confines of the loop would eliminate that confusion, but might add the confusion of what values the variables called I and J might have after the loop if they were in scope in the code preceding the loops. I like the shorter syntax but wondering about the details.
I don’t use it anymore, but there was clarity in the old self-imposed syntax

      do 10 i10=1,n
         do 20 i20=1,n
          write(*,*)i10,i20
20        continue
10    continue

which your proposed syntax restores.

I actually like that you cannot reuse the labels in the same scope. I dislike that a label becomes a reserved name in the scoping unit. I am not as opposed to variables not being able to be the same as a label, but I sometimes find the restriction on a procedure name irritating.

SIN: do i=1,2
enddo SIN
!SIN=10                ! not allowed
!write(*,*)sin(1.0)    ! not allowed
end

but assuming using the second syntax I showed would also reserve the names for the encompassing scope, some might like it for the clarity it provides (albeit you seem to prefer being able to reuse the names, and as mentioned, I am not always happy with it). That is, the names of the labels would become variables only used in the scope of that loop, so they would not easily be confused with some other use of the name (well, BLOCK and ASSOCIATE might confuse that anyway, not sure off the cuff). You would not have to declare the counter variables, their scope would be clear, and they would be unique to the loop so you do not end up with every unnested loop using “i” as the counter (which is fine for short loops, but is confusing when there are many long loops in the same procedure in my opinion).

Note that labels are currently not declared with a type, and this would take advantage of that and implicitly imply them as INTEGER, eliminating any confusion as to whether the counter might be REAL, a commonly encountered extension required for backward compatibility with older code. Since this is a new syntax, there would be no confusion along those lines.

I also think that in the syntax

INFINITE: do
write(*,*)'TRIP COUNT=',INFINITE
read(*,*,iostat=ios) something
if(ios.ne.0)exit INFINITE
enddo INFINITE

that INFINITE should be defined and take on the trip count as a value, which I think would be nice and currently requires a increment statement in the loop of some variable. But since that is currently allowed syntax for the DO statement that might break some code, so it is probably not possible.

EDIT: On second thought, since the label is currently a reserved name in the current scope, maybe that would be OK.

Being a new syntax, it would also be worth discussing whether the label/variable name should be allowed to be changed within the loop, although this would disallow a lot of optimizations. I see that in quite a few other languages.