Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

modern do loop syntax (#80) #85

Open
gronki opened this issue Nov 14, 2019 · 14 comments
Open

modern do loop syntax (#80) #85

gronki opened this issue Nov 14, 2019 · 14 comments
Labels
Clause 11 Standard Clause 11: Execution control

Comments

@gronki
Copy link

gronki commented Nov 14, 2019

originally proposed by Espen Myklebust in #80

New syntax for iterated DO loops

Proposal

Add a new syntax for declaring a DO statement loop-control that follows the pattern of modern Fortran. This syntax will be further enhanced with subsequent syntax proposals

Rationale

  1. The “regular” DO construct index/control specification has a completely different form than the modern Fortran constructs
  • A comma separated list specifying the control variable (instead of a triplet)
  • a label (legacy from non-block DO)
  • no parenthesized expression or specification
  1. It also lacks some additional features of the DO CONCURRENT and FORALL index specifications
  2. A consistent notation should be pursued
  • extremely helpful when learning the language

Proposed syntax

[do-construct-name :] DO [ ,] FOR( [type-spec ::] index-spec-list [ , scalar-mask-expr] )
:
END DO [do-construct-name]

This matches the DO CONCURRENT syntax exactly, with the obvious difference in the “DO-keyword.” However, if more than one index variable is specified there must be a rule for determining in which order the indices are incremented, in contrast to the case for a DO CONCURRENT construct where this does not matter. The following rule is suggested:
The leftmost index declared is incremented first, then the second leftmost and so on.
This is consistent with how the subscript order value increases in array element order which have a pleasant
implication when looping through arrays.

Example

The following loop

DO j=1,m
  DO i=1,n
    IF ( i.LT.n .AND. j.LT.m ) THEN
      a(i,j) = a(i,j) + a(i+1,j+1)
    END IF
  END DO
END DO

could be written much more compactly as

DO FOR( i=1:n, j=1:m, i.LT.n .AND. j.LT.m )
  a(i,j) = a(i,j) + a(i+1,j+1)
END DO

In both loops the indices are specified in the order that should(?) achieve the best performance, but whereas for the present syntax the outermost construct (usually declared first?) must have the last index and the innermost construct the first one, the proposed syntax declares the indices in the same order as they (should!) appear in the array qualifier. This is perhaps a minor detail (that some compilers automatically mend), but in the writers experience, at least beginners and those that are not aware of this, tend to declare the nested loops “in the reverse order.” Of course it would also be possible to maintain the structure of the first code block, only changing the loop-control parts to the new syntax, as shown below

DO FOR( j=1:m )
  DO FOR( i=1:n )

Comments

  1. The proposed syntax makes it easy to switch between a CONCURRENT and regular DO by just changing
    the token, as opposed to having to respecify the whole statement
  2. Compared to the present “legacy” DO construct it also adds the possibility
  • to declare multiple index/control variables,
  • their type parameter, and
  • for a mask expression
  1. The token FOR is widely used for this kind of loop
  2. In the last code block it could be possible to include the masking expression since the loop control variables would be equally well known to the program as in the middle code block.
@milancurcic
Copy link
Member

I overall like it and it would be a quality-of-life improvement.

I like the rule where the index increment order is specified left-to-right.

for seems redundant though. Why not just

do ( i=1:n, j=1:m, i < n .and. j < m )
  a(i,j) = a(i,j) + a(i+1,j+1)
end do

With this syntax, the do concurrent() would then be a special case of this more general form.

@FortranFan
Copy link
Member

FortranFan commented Nov 14, 2019

  1. It will be nice if Espen Myklebust can be acknowledged explicitly upfront in the original post.

  2. I had the same thought as @milancurcic, one of the two tokens DO/FOR appears redundant. Why not try to avoid any impact on DO construct, the most important and perhaps the most complicated block construct in the language, why not consider this a new FOR construct?

   for ( i=1,n; j=1,m; (i < n) .and. (j<m) )
      a(i,j) = a(i,j) + a(i+1,j+1)
   end for
  1. There appears an unwritten rule in the language with FORALL and DO CONCURRENT constructs that colon notation e.g., 1:n is intended to signal loop iterations in no specified order. So one might end up needing some change to the syntax, perhaps one that retains the comma as in 1,n but introduces the line separator of semi-colon to separate the loop variables.

  2. Now, making the loop variables a construct entity and thus being able to declare them with a <type-spec> is rather important. However this might be the opportunity to introduce iterators into Fortran, so the loop control needn't be using only an integer variable.

  3. Loop control schemes need to be worked out, especially with CYCLE, EXIT.

Note though the development of a good set of requirements and specifications for such a construct is the real challenge; syntax is the easy part.

@gronki
Copy link
Author

gronki commented Nov 14, 2019

Sorry I thought it was clear enough. I updated it :)

@klausler
Copy link

What problem does this proposal solve? Is this problem important enough to justify all of the work needed to define the feature precisely, implement a demonstration prototype, compile the edits needed to formalize it in the standard, implement it in all current compilers and IDEs, document it in tutorials and reference works, and maintain it forever?

Sorry if it seems like I'm picking on this particular proposal; the question that I posed is one that I think about with every proposal that arises here. In this case, the price seems higher than average, and I don't understand the payoff.

@gronki
Copy link
Author

gronki commented Nov 14, 2019 via email

@FortranFan
Copy link
Member

FortranFan commented Nov 14, 2019

@klausler wrote:

What problem does this proposal solve? Is this problem important enough to justify all of the work needed to define the feature precisely, implement a demonstration prototype, compile the edits needed to formalize it in the standard, implement it in all current compilers and IDEs, document it in tutorials and reference works, and maintain it forever?

Sorry if it seems like I'm picking on this particular proposal; the question that I posed is one that I think about with every proposal that arises here. In this case, the price seems higher than average, and I don't understand the payoff.

As I tired to suggest above, there are several problems with current DO loop that can be addressed with such a proposal:

  1. Allow the DO loop variable to be a construct entity. Coders then need not introduce the silly integer :: i, j, k, .. statements in the declaration section of a program unit only to consume these in DO loops.

  2. Allow the looping using iterators, not just integer variables

  3. Reduce verbosity with compound loops

  4. Reduce the learning curve of using DO loops efficiently, particularly for those who use Fortran as a second/third or a part-time coding language.

@klausler
Copy link

@klausler wrote:

What problem does this proposal solve? Is this problem important enough to justify all of the work needed to define the feature precisely, implement a demonstration prototype, compile the edits needed to formalize it in the standard, implement it in all current compilers and IDEs, document it in tutorials and reference works, and maintain it forever?
Sorry if it seems like I'm picking on this particular proposal; the question that I posed is one that I think about with every proposal that arises here. In this case, the price seems higher than average, and I don't understand the payoff.

As I tired to suggest above, there are several problems with current DO loop that can be addressed with such a proposal:

  1. Allow the DO loop variable to be a construct entity. Coders then need not introduce the silly integer :: i, j, k, .. statements in the declaration section of a program unit only to consume these in DO loops.
  2. Allow the looping using iterators, not just integer variables
  3. Reduce verbosity with compound loops
  4. Reduce the learning curve of using DO loops efficiently, particularly for those who use Fortran as a second/third or a part-time coding language.
  1. Index variables in DO CONCURRENT and FORALL are already construct entities (19.4.6), and an integer-type-spec is allowed in the concurrent-header (R1125).
  2. Fortran doesn't have iterators.
  3. Other alternatives exist; as a case in point, the example presented to support this feature really should be written as an array assignment A(1:N-1,1:M-1) = A(1:N-1,1:M-1) + A(2:N,2:M).
  4. If you mean "easier to learn", that claim needs to be substantiated; it's not immediately obvious to me why it would be so.

@gronki
Copy link
Author

gronki commented Nov 14, 2019 via email

@certik
Copy link
Member

certik commented Nov 14, 2019

The strongest argument for this proposal is that the do loop becomes consistent with its parallel / concurrent variant: one only adds the concurrent keyword to a loop to make it run parallel, with no other syntax changes.

@FortranFan
Copy link
Member

@certik wrote:

The strongest argument for this proposal is that the do loop becomes consistent with its parallel / concurrent variant: one only adds the concurrent keyword to a loop to make it run parallel, with no other syntax changes.

Do (!) keep in mind it can prove extremely difficult to do (!) anything with the DO construct, to make it consistent with DO CONCURRENT syntactically while not impacting adversely any of the existing semantics appears anything but simple e.g., with CYCLE, EXIT; or the definition of loop variables upon termination; or one-pass/zero-pass. This can prove to be the backward compatibility issue on steroids!

Hence a new construct e.g., FOR that can possibly help introduce other facilities also might be a safer approach.

@milancurcic
Copy link
Member

@FortranFan that's an important point regarding cycle and exit semantics.

My default assumption is that this doesn't deprecate the existing do. It only adds this general do() construct to the language. Maybe this isn't what @gronki meant.

@gronki
Copy link
Author

gronki commented Nov 15, 2019 via email

@certik
Copy link
Member

certik commented Nov 15, 2019

@FortranFan good point, I haven't thought about it that way. I just don't like 2 different ways of doing the same thing, but maybe we have to in this case.

@gronki
Copy link
Author

gronki commented Nov 15, 2019 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Clause 11 Standard Clause 11: Execution control
Projects
None yet
Development

No branches or pull requests

5 participants