Skip to content

Commit

Permalink
Merge pull request #141 from ecmwf-ifs/naan-enrich-calls-fix
Browse files Browse the repository at this point in the history
Fix for enrich calls bug
  • Loading branch information
reuterbal authored Sep 7, 2023
2 parents 7094446 + 5d3461e commit 6e4a4e0
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 1 deletion.
6 changes: 6 additions & 0 deletions loki/subroutine.py
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,12 @@ def enrich_calls(self, routines):
name_type.dtype.procedure is not routine # ProcedureType not linked to routine
)
if update_symbol:
# Remove existing symbol from symbol table if defined in interface block
for node in [node for intf in self.interfaces for node in intf.body]:
if getattr(node, 'name', None) == call.name:
if node.parent == self:
node.parent = None

# Need to update the call's symbol to establish link to routine
name_type = name_type.clone(dtype=routine.procedure_type)
call._update(name=call.name.clone(scope=self, type=name_type), not_active=not_active)
Expand Down
64 changes: 63 additions & 1 deletion tests/test_subroutine.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
SymbolAttributes, StringLiteral, fgen, fexprgen, VariableDeclaration,
Transformer, FindTypedSymbols, ProcedureSymbol, ProcedureType,
StatementFunction, normalize_range_indexing, DeferredTypeSymbol,
Assignment
Assignment, Interface
)


Expand Down Expand Up @@ -1992,3 +1992,65 @@ def _verify_call_enrichment(driver_, kernels_):

_verify_call_enrichment(driver, kernels)
_verify_call_enrichment(cloned_driver, cloned_kernels)


@pytest.mark.parametrize('frontend', available_frontends())
def test_enrich_calls_explicit_interface(frontend):
"""
Test enrich_calls points to the actual routine and not the symbol declared
in an explicit interface.
"""

fcode_kernel = """
subroutine kernel(a,b)
implicit none
integer, intent(inout) :: a
integer, intent(out) :: b
a = a + 1
b = a
end subroutine kernel
"""

fcode_driver = """
subroutine driver()
implicit none
interface
subroutine kernel(a,b)
integer, intent(inout) :: a
integer, intent(out) :: b
end subroutine kernel
end interface
integer :: a = 0
integer :: b
call kernel(a,b)
end subroutine driver
"""

kernel = Subroutine.from_source(fcode_kernel, frontend=frontend)
driver = Subroutine.from_source(fcode_driver, frontend=frontend)

driver.enrich_calls(routines=(kernel,))

# check if call is enriched correctly
calls = FindNodes(CallStatement).visit(driver.body)
assert calls[0].routine is kernel

# check if the procedure symbol in the interface block has been removed from
# driver's symbol table
intfs = FindNodes(Interface).visit(driver.spec)
assert not intfs[0].body[0].parent

# check that call still points to correct subroutine
_ = [sym for intf in intfs for sym in intf.symbols]
assert calls[0].routine is kernel

# confirm that rescoping symbols has no effect
driver.rescope_symbols()
assert calls[0].routine is kernel

0 comments on commit 6e4a4e0

Please sign in to comment.