Skip to content

Commit

Permalink
Merge pull request #263 from ecmwf-ifs/nabr-fix-external-module-proce…
Browse files Browse the repository at this point in the history
…dures

Scheduler: Fix handling of external module procedures
  • Loading branch information
reuterbal authored Mar 27, 2024
2 parents 023b46b + 634e516 commit 0a15267
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 7 deletions.
5 changes: 3 additions & 2 deletions loki/batch/item.py
Original file line number Diff line number Diff line change
Expand Up @@ -1123,11 +1123,12 @@ def get_or_create_item(self, item_cls, item_name, scope_name, config=None):
return self.item_cache[item_name]

item_conf = config.create_item_config(item_name) if config else None
if scope_name not in self.item_cache:
scope_item = self.item_cache.get(scope_name)
if scope_item is None or isinstance(scope_item, ExternalItem):
warning(f'Module {scope_name} not found in self.item_cache. Marking {item_name} as an external dependency')
item = ExternalItem(item_name, source=None, config=item_conf, origin_cls=item_cls)
else:
source = self.item_cache[scope_name].source
source = scope_item.source
item = item_cls(item_name, source=source, config=item_conf)
self.item_cache[item_name] = item
return item
Expand Down
4 changes: 2 additions & 2 deletions loki/frontend/regex.py
Original file line number Diff line number Diff line change
Expand Up @@ -386,8 +386,8 @@ def __init__(self):
r'^module[ \t]+(?P<name>\w+)\b.*?$'
r'(?P<spec>.*?)'
r'(?P<contains>^contains\n(?:'
r'(?:[ \t\w()]*?subroutine.*?^end[ \t]*subroutine\b(?:[ \t]\w+)?\n)|'
r'(?:[ \t\w()]*?function.*?^end[ \t]*function\b(?:[ \t]\w+)?\n)|'
r'(?:[ \t\w()=]*?subroutine.*?^end[ \t]*subroutine\b(?:[ \t]\w+)?\n)|'
r'(?:[ \t\w()=]*?function.*?^end[ \t]*function\b(?:[ \t]\w+)?\n)|'
r'(?:^#\w+.*?\n)'
r')*)?'
r'^end[ \t]*module\b(?:[ \t](?P=name))?',
Expand Down
44 changes: 44 additions & 0 deletions tests/test_batch.py
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,50 @@ def test_procedure_item_with_config2(here, disable):
assert item.targets == ('t_mod', 't', 'nt1', 'header_mod', 'arg%proc', 'arg%no%way')


@pytest.mark.parametrize('enable_imports', [False, True])
def test_procedure_item_external_item(enable_imports, default_config):
"""
Test that dependencies to external module procedures are marked as external item
"""
fcode = """
subroutine procedure_item_external_item
use external_mod, only: external_proc, unused_external_proc, external_type, external_var
implicit none
type(external_type) :: my_type
call external_proc(1)
my_type%my_val = external_var
end subroutine procedure_item_external_item
"""
workdir = gettempdir()/'test_procedure_item_external_item'
workdir.mkdir(exist_ok=True)
filepath = workdir/'procedure_item_external_item.F90'
filepath.write_text(fcode)

default_config['default']['enable_imports'] = enable_imports
scheduler_config = SchedulerConfig.from_dict(default_config)
item = get_item(
ProcedureItem, filepath, '#procedure_item_external_item',
RegexParserClass.ProgramUnitClass, scheduler_config
)
item_factory = ItemFactory()
item_factory.item_cache[item.name] = item
items = item.create_dependency_items(item_factory=item_factory, config=scheduler_config)

# NB: dependencies to imported symbols are not added as external items because it would be impossible
# to determine their type. Instead, the external module is marked as a dependency, regardless if
# imports are enabled or not.
# However, the external procedure with a call statement is recognized as an external procedure
# and therefore included in the dependency tree.
assert items == ('external_mod', 'external_mod#external_proc')
assert all(isinstance(it, ExternalItem) for it in items)
assert [it.origin_cls for it in items] == [ModuleItem, ProcedureItem]

filepath.unlink(missing_ok=True)
workdir.rmdir()


def test_typedef_item(here):
proj = here/'sources/projBatch'

Expand Down
7 changes: 4 additions & 3 deletions tests/test_frontends.py
Original file line number Diff line number Diff line change
Expand Up @@ -471,8 +471,9 @@ def test_regex_module_from_source():
"""
fcode = """
module some_module
implicit none
use foobar
implicit none
integer, parameter :: k = selected_int_kind(5)
contains
subroutine module_routine
integer m
Expand All @@ -481,9 +482,9 @@ def test_regex_module_from_source():
call routine_b(m, 6)
end subroutine module_routine
function module_function(n)
integer(kind=k) function module_function(n)
integer n
n = 3
module_function = n + 2
end function module_function
end module some_module
""".strip()
Expand Down

0 comments on commit 0a15267

Please sign in to comment.