stfc / fparser

This project maintains and develops a Fortran parser called fparser2 written purely in Python which supports Fortran 2003 and some Fortran 2008. A legacy parser fparser1 is also available but is not supported. The parsers were originally part of the f2py project by Pearu Peterson.
https://fparser.readthedocs.io
Other
64 stars 29 forks source link

No Support for DO CONCURRENT #403

Closed mjklemm closed 1 year ago

mjklemm commented 1 year ago

It seems like fparser does not support F08 DO CONCURRENT:

C:\PycharmProjects\fortran> python main.py
Traceback (most recent call last):
  File "C:\Users\micha\anaconda3\envs\fortran\lib\site-packages\fparser\two\Fortran2003.py", line 266, in __new__
    return Base.__new__(cls, string)
  File "C:\Users\micha\anaconda3\envs\fortran\lib\site-packages\fparser\two\utils.py", line 487, in __new__
    raise NoMatchError(errmsg)
fparser.two.utils.NoMatchError: at line 14
>>>        do concurrent (i=1:n) local_init(a)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\micha\PycharmProjects\fortran\main.py", line 7, in <module>
    parse_tree = f08_parser(reader)
  File "C:\Users\micha\anaconda3\envs\fortran\lib\site-packages\fparser\two\Fortran2003.py", line 270, in __new__
    raise FortranSyntaxError(string, "")
fparser.two.utils.FortranSyntaxError: at line 14
>>>        do concurrent (i=1:n) local_init(a)

Failing code is:

module saxpy_impl
    implicit none
contains
    subroutine saxpy(a, x, y, n)
        use iso_fortran_env
        implicit none

        integer :: n
        real(kind=real32) :: a
        real(kind=real32), dimension(n) :: x
        real(kind=real32), dimension(n) :: y
        integer :: i

        do concurrent (i=1:n) local_init(a)
            y(i) = a * x(i) + y(i)
        end do
    end subroutine saxpy
end module saxpy_impl
arporter commented 1 year ago

Thanks for the reproducer Michael and yes, you're quite right. We're adding F2008 features as and when they're needed.

mjklemm commented 1 year ago

DO CONCURRENT is one of the feature I'd badly need. Could you comment on when it might make into fparser?

rupertford commented 1 year ago

We tend to fix issues as they arise so now that you've raised it, hopefully we will have time in the near future to add support.

mjklemm commented 1 year ago

Thanks! Much appreciated. I think I can emulate things with regular DO for now and acquaint myself with fparser API in the meantime.

mjklemm commented 1 year ago

Please have a look at pull request #404. I think I have done enough to at least cover the most basic form of DO CONCURRENT, which will let me continue. I will try to find some time to work on also adding support for LOCAL, LOCAL_INIT, and SHARED.

rupertford commented 1 year ago

Thanks @mjklemm, I've commented on #404. It is up to you whether you would like to do the full implementation as suggested and go through the review process, which would need the suggested re-working, tests, documentation etc., or whether you want to keep using your local version and wait for me to do it :-)

mjklemm commented 1 year ago

I'm OK with me working with my "hack" and wait for you to make the final changes. I will abstract the tree processing on my end enough, so that I can hopefully easily absorb the new tree structure (unless you're generally OK with how I did the tree).

rupertford commented 1 year ago

OK. I'll re-use your changes where possible :-)

rupertford commented 1 year ago

Created branch 403_do_concurrent

rupertford commented 1 year ago

Reopening issue as @sergisiso has found that we are still not matching do concurrent statements.

rupertford commented 1 year ago

I'll re-use branch 403_do_concurrent.

rupertford commented 1 year ago

OK, I've found the problem. The two classes that call Loop_Control (via the rule hierarchy) are Label_Do_Stmt and Nonlabel_Do_Stmt. Both of these classes are currently Fortran2003 classes and they call Loop_Control directly so the f2003 version of Loop_Control will always be picked up. The only solution I can think of is to create f2008 subclasses of these.

rupertford commented 1 year ago

I'm surprised this has not come up (much?) before. Our previous changes must be classes that are not used directly by other classes. Anyway, I now have a working version that subclasses the 2003 classes and uses methods to provide the appropriate 2003 or 2008 class. The main issue I am currently having is that I don't know what the outer-shared-do-construct and inner-shared-do-construct rules refer to and how to trigger them. I could just skip these as the main cases are working ...

  ! Block nonlabel do
  do concurrent (i=1:n)
     a(i) = 0.0
  end do

  ! Block label do
  do 10 concurrent (i=1:n)
     a(i) = 0.0
  10 continue

  ! Action_Term_Do_Construct
  do 20 concurrent (i=1:n)
  20 a(i) = 0.0
rupertford commented 1 year ago

outer-shared-do-construct and inner-shared-do-construct should be used when there are non-block nested do loops. non-block do loops are ones which do not have enddo or <label> continue as loop terminators. For example do 10 i=1,100\n10 a(i) = 0.0\n.

However, in fparser2, the implementation of rule 835 <nonblock-do-stmt> = <action-term-do-construct>|<outer-shared-do-construct> checks for action-term-do-construct first and this returns a valid tree even if there are nested loops. Now I could re-order this rule and probably should at some point. However, the implementation of outer-shared-do-construct and inner-shared-do-construct do not restore the reader if they fail to match, which will cause parse failures. I therefore think that fixing this should be a separate issue. Created issue #422 for this.