Skip to content

Inconsistent matching of inline calls and derived type member references #384

@reuterbal

Description

@reuterbal

Yet another edge case, which is most likely not possible to resolve without having procedures in the symbol table. However, I felt it might be useful to document it:

Function calls in expressions and derived type member references are represented inconsistently. One distinction seems to be made based on whether named arguments are used or not.
A little example:

fcode = """
module inline_call_mod
    implicit none

    type mytype
        integer :: val
        integer :: arr(3)
    contains
        procedure :: some_func
    end type mytype

contains

    function check(val, thr) result(is_bad)
        integer, intent(in) :: val
        integer, intent(in), optional :: thr
        integer :: eff_thr
        logical :: is_bad
        if (present(thr)) then
            eff_thr = thr
        else
            eff_thr = 10
        end if
        is_bad = val > thr
    end function check

    function some_func(this) result(is_bad)
        class(mytype), intent(in) :: this
        logical :: is_bad

        is_bad = check(this%val, thr=10) &
            &   .or. check(this%arr(1)) .or. check(val=this%arr(2)) .or. check(this%arr(3))
    end function some_func
end module inline_call_mod
""".strip()

from fparser.common.readfortran import FortranStringReader
from fparser.two.parser import ParserFactory
reader = FortranStringReader(fcode)
parser = ParserFactory().create(std='f2003')
ast = parser(reader)
ast

The four calls to check in the is_bad = ... expression are represented as:

  • check(this%val, thr=10):
Structure_Constructor(Type_Name('check'), Component_Spec_List(',', (Proc_Component_Ref(Name('this'), '%', Name('val')), Component_Spec(Name('thr'), Int_Literal_Constant('10', None))))
  • check(this%arr(1)):
Part_Ref(Name('check'), Section_Subscript_List(',', (Data_Ref('%', (Name('this'), Part_Ref(Name('arr'), Section_Subscript_List(',', (Int_Literal_Constant('1', None),))))),)))
  • check(val=this%arr(2)):
Structure_Constructor(Type_Name('check'), Component_Spec_List(',', (Component_Spec(Name('val'), Data_Ref('%', (Name('this'), Part_Ref(Name('arr'), Section_Subscript_List(',', (Int_Literal_Constant('2', None),)))))),)))
  • check(this%arr(3)):
Part_Ref(Name('check'), Section_Subscript_List(',', (Data_Ref('%', (Name('this'), Part_Ref(Name('arr'), Section_Subscript_List(',', (Int_Literal_Constant('3', None),))))),)))

What should, to my understanding, be a Function_Reference, is either represented as Structure_Constructor (named argument present) or Part_Ref (no named argument present).
Additionally, the reference to this%val is represented as a Proc_Component_Ref in the first case, but (correctly?) identified as a Data_Ref in all others.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions