Skip to content

Commit

Permalink
#924 fix all tests following refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
arporter committed Jan 8, 2024
1 parent e3b2c2e commit 908aac8
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 169 deletions.
10 changes: 5 additions & 5 deletions src/psyclone/psyir/nodes/call.py
Original file line number Diff line number Diff line change
Expand Up @@ -551,11 +551,11 @@ def _location_txt(node):
f"{rsym.datatype.declaration}\n"
f"Cannot currently module inline such a routine.")

# TODO #924 - need to allow for interface to multiple routines here.
# pylint: disable=import-outside-toplevel
routine = container.get_routine_definition(rsym.name)
if routine:
return [routine]
if isinstance(container, Container):
# TODO #924 - need to allow for interface to multiple routines here.
routine = container.get_routine_definition(rsym.name)
if routine:
return [routine]
#for routine in root_node.walk(Routine, stop_type=Routine):
# if routine.name.lower() == rsym.name.lower():
# kernel_schedule = routine
Expand Down
10 changes: 8 additions & 2 deletions src/psyclone/psyir/transformations/inline_trans.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ def apply(self, node, options=None):
# The table associated with the scoping region holding the Call.
table = node.scope.symbol_table
# Find the routine to be inlined.
orig_routine = self._find_routine(node)
orig_routine = node.get_callees()[0]

if not orig_routine.children or isinstance(orig_routine.children[0],
Return):
Expand Down Expand Up @@ -622,7 +622,13 @@ def validate(self, node, options=None):
# pass

# Check that we can find the source of the routine being inlined.
routine = self._find_routine(node)
# TODO #924 allow for multiple routines (interfaces).
try:
routine = node.get_callees()[0]
except (NotImplementedError, SymbolError) as err:
raise TransformationError(
f"Cannot inline routine '{name}' because its source cannot be "
f"found: {err}") from err

if not routine.children or isinstance(routine.children[0], Return):
# An empty routine is fine.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -742,9 +742,9 @@ def test_psyir_mod_inline_fail_to_get_psyir(fortran_reader):
call = psyir.walk(Call)[0]
with pytest.raises(TransformationError) as err:
intrans.validate(call)
assert ("failed to retrieve PSyIR for routine 'my_sub' due to: "
"RoutineSymbol 'my_sub' is unresolved and searching for its "
"implementation is not yet supported" in str(err.value))
assert ("failed to retrieve PSyIR for routine 'my_sub' due to: Failed "
"to find the source code of the unresolved routine 'my_sub' "
"after trying" in str(err.value))


def test_get_psyir_to_inline(monkeypatch):
Expand Down Expand Up @@ -836,7 +836,7 @@ def fake_get_code(node):
:returns: a fake routine name and the routine PSyIR.
:rtype: Tuple(str, :py:class:`psyclone.psyir.nodes.Routine`)
'''
code_to_inline = node.routine.get_routine(node)
code_to_inline = node.get_callees()[0]
return "broken", code_to_inline

monkeypatch.setattr(KernelModuleInlineTrans, "_get_psyir_to_inline",
Expand Down
79 changes: 75 additions & 4 deletions src/psyclone/tests/psyir/nodes/call_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@
from psyclone.configuration import Config
from psyclone.core import Signature, VariablesAccessInfo
from psyclone.psyir.nodes import (
ArrayReference, BinaryOperation, Call, Literal, Reference, Routine,
Schedule)
ArrayReference, Assignment, BinaryOperation, Call, Literal, Reference,
Routine, Schedule)
from psyclone.psyir.nodes.node import colored
from psyclone.psyir.symbols import (
ArrayType, INTEGER_TYPE, DataSymbol, NoType, RoutineSymbol, REAL_TYPE,
Expand Down Expand Up @@ -627,8 +627,10 @@ def test_call_get_callees_unresolved(fortran_reader):
call = psyir.walk(Call)[0]
with pytest.raises(NotImplementedError) as err:
_ = call.get_callees()
assert ("'bottom' is unresolved and searching for its implementation is "
"not yet supported - TODO #924" in str(err.value))
assert ("Failed to find the source code of the unresolved routine 'bottom'"
" after trying wildcard imports from [] and all routines that are "
"not in containers. Wider searching for its implementation is not "
"yet supported - TODO #924" in str(err.value))


def test_call_get_callees_unknown_type(fortran_reader):
Expand Down Expand Up @@ -666,6 +668,31 @@ def test_call_get_callees_unknown_type(fortran_reader):
"UnknownFortranType:" in str(err.value))


def test_call_get_callees_file_container(fortran_reader):
'''
Check that get_callees works if the called routine happens to be in file
scope, even when there's no Container.
'''
code = '''
subroutine top()
integer :: luggage
luggage = 0
call bottom(luggage)
end subroutine top
subroutine bottom(luggage)
integer :: luggage
luggage = luggage + 1
end subroutine bottom
'''
psyir = fortran_reader.psyir_from_source(code)
call = psyir.walk(Call)[0]
result = call.get_callees()
assert len(result) == 1
assert isinstance(result[0], Routine)
assert result[0].name == "bottom"


def test_call_get_callees_no_container(fortran_reader):
'''
Check that get_callees() raises the expected error when the Call is not
Expand Down Expand Up @@ -842,3 +869,47 @@ def test_get_callees_import_private_clash(fortran_reader, tmpdir, monkeypatch):
"but that Container defines a private Symbol of the same name. "
"Searching for the Container that defines a public Routine with "
"that name is not yet supported - TODO #924" in str(err.value))


def test_get_callees_interface_name(tmpdir, monkeypatch, fortran_reader):
'''
Test get_callees() for a subroutine that is called via an interface with a
different name.
TODO #924 - this is currently unsupported.
'''
path = str(tmpdir)
monkeypatch.setattr(Config.get(), '_include_paths', [path])

with open(os.path.join(path, "my_mod.f90"), "w") as mfile:
mfile.write('''\
module my_mod
interface manna
module procedure :: manna_sp, manna_dp
end interface manna
contains
subroutine manna_sp(arg)
real(kind=kind(1.0)) :: arg
end subroutine manna_sp
subroutine manna_dp(arg)
real(kind=kind(1.0d0)) :: arg
end subroutine manna_dp
end module my_mod
''')
code = '''\
module a_mod
use my_mod, only: manna
contains
subroutine a_sub()
real, dimension(10) :: a
call manna(a)
end subroutine a_sub
end module a_mod
'''
psyir = fortran_reader.psyir_from_source(code)
call = psyir.walk(Call)[0]
with pytest.raises(NotImplementedError) as err:
call.get_callees()
assert ("RoutineSymbol 'manna' exists in Container 'my_mod' but is of "
"UnknownFortranType:" in str(err.value))
154 changes: 0 additions & 154 deletions src/psyclone/tests/psyir/symbols/routinesymbol_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,157 +146,3 @@ def test_routinesymbol_str():
assert (str(routine_symbol) ==
"eyore: RoutineSymbol<some_type: DataTypeSymbol, pure=True, "
"elemental=False>")


def test_get_routine_recursive(fortran_reader, fortran_writer, tmpdir,
monkeypatch):
'''
Test get_routine() when the implementation of the routine is not in the
immediately-imported Container.
'''
code = '''\
module a_mod
use my_mod, only: my_sub
contains
subroutine a_sub()
real, dimension(10) :: a
call my_sub(a)
end subroutine a_sub
end module a_mod
'''
# Create the modules containing the subroutine definition, write it to
# file and set the search path so that PSyclone can find it.
path = str(tmpdir)
monkeypatch.setattr(Config.get(), '_include_paths', [path])

with open(os.path.join(path, "my_mod.f90"), "w") as mfile:
mfile.write('''\
module my_mod
use my_mod2, only: my_sub
contains
subroutine ignore_this()
end subroutine ignore_this
end module my_mod
''')
with open(os.path.join(path, "my_mod2.f90"), "w") as mfile:
mfile.write('''\
module my_mod2
contains
subroutine my_sub(arg)
real, dimension(10), intent(inout) :: arg
arg(1:10) = 1.0
end subroutine my_sub
end module my_mod2
''')
psyir = fortran_reader.psyir_from_source(code)
call = psyir.walk(nodes.Call)[0]
psyir = call.routine.get_routine()
assert isinstance(psyir, nodes.Routine)
assigns = psyir.walk(nodes.Assignment)
assert len(assigns) == 1
assert assigns[0].lhs.symbol.name == "arg"


def test_get_routine_unresolved(fortran_reader):
'''Test that get_routine() raises the expected error when the routine
being called is unresolved.'''
psyir = fortran_reader.psyir_from_source('''\
module my_mod
contains
subroutine my_sub()
call external_routine()
end subroutine my_sub
end module my_mod
''')
call = psyir.walk(nodes.Call)[0]
with pytest.raises(NotImplementedError) as err:
call.routine.get_routine()
assert ("RoutineSymbol 'external_routine' is unresolved and searching for "
"its implementation is not yet supported" in str(err.value))


def test_get_routine_missing_container(fortran_reader):
'''
Test that get_routine() raises the expected error if a RoutineSymbol is
not imported but no Container has been provided in which to search.
'''
psyir = fortran_reader.psyir_from_source('''\
module my_mod
contains
subroutine my_sub()
implicit none
end subroutine my_sub
end module my_mod
''')
ctr = psyir.walk(nodes.Container)[1]
rsym = ctr.symbol_table.lookup("my_sub")
with pytest.raises(SymbolError) as err:
rsym.get_routine()
assert ("RoutineSymbol 'my_sub' is not imported so a Container node must "
"be provided in order to search for its Schedule"
in str(err.value))


def test_get_routine_missing_implementation(fortran_reader):
'''Test that get_routine() raises the expected error if the implementation
of the Routine cannot be found in the supplied Container.'''
psyir = fortran_reader.psyir_from_source('''\
module my_mod
contains
subroutine my_sub()
implicit none
end subroutine my_sub
end module my_mod
''')
ctr = psyir.walk(nodes.Container)[1]
rsym = RoutineSymbol("missing")
ctr.symbol_table.add(rsym)
with pytest.raises(SymbolError) as err:
rsym.get_routine(ctr)
assert ("Failed to find a Routine named 'missing' in Container 'my_mod'"
in str(err.value))


def test_get_routine_interface_name(tmpdir, monkeypatch, fortran_reader):
'''
Test get_routine() for a subroutine that is called via an interface with a
different name.
TODO #924 - this is currently unsupported.
'''
path = str(tmpdir)
monkeypatch.setattr(Config.get(), '_include_paths', [path])

with open(os.path.join(path, "my_mod.f90"), "w") as mfile:
mfile.write('''\
module my_mod
interface manna
module procedure :: manna_sp, manna_dp
end interface manna
contains
subroutine manna_sp(arg)
real(kind=kind(1.0)) :: arg
end subroutine manna_sp
subroutine manna_dp(arg)
real(kind=kind(1.0d0)) :: arg
end subroutine manna_dp
end module my_mod
''')
code = '''\
module a_mod
use my_mod, only: manna
contains
subroutine a_sub()
real, dimension(10) :: a
call manna(a)
end subroutine a_sub
end module a_mod
'''
psyir = fortran_reader.psyir_from_source(code)
call = psyir.walk(nodes.Call)[0]
with pytest.raises(NotImplementedError) as err:
call.routine.get_routine()
assert ("RoutineSymbol 'manna' exists in Container 'my_mod' but is of "
"UnknownFortranType:" in str(err.value))

0 comments on commit 908aac8

Please sign in to comment.