Skip to content

Commit

Permalink
#2422 update to preserve module-procedure information.
Browse files Browse the repository at this point in the history
  • Loading branch information
arporter committed Jan 22, 2024
1 parent c854646 commit fae0056
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 30 deletions.
22 changes: 12 additions & 10 deletions src/psyclone/psyir/symbols/generic_interface_symbol.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class GenericInterfaceSymbol(RoutineSymbol):
:type kwargs: unwrapped dict.
'''
RoutineInfo = namedtuple("RoutineInfo", ["symbol", "is_module"])
RoutineInfo = namedtuple("RoutineInfo", ["symbol", "from_container"])

def __init__(self, name, routines, **kwargs):
super().__init__(name, **kwargs)
Expand Down Expand Up @@ -91,17 +91,19 @@ def routines(self, values):
raise TypeError(f"A GenericInterfaceSymbol requires a list of "
f"tuples describing its member routines but got: "
f"'{values}'")
self._routines = []
for item in values:
if not isinstance(item, tuple) or len(item) != 2:
if not isinstance(item, tuple):
raise TypeError(
f"A GenericInterfaceSymbol requires a list of 2-tuples but"
f" got: {[type(rt).__name__ for rt in values]}")
if (not isinstance(item[0], RoutineSymbol) or
f"A GenericInterfaceSymbol ('{self.name}') requires a "
f"list of tuples but got: '{type(item).__name__}'")
if (len(item) != 2 or not isinstance(item[0], RoutineSymbol) or
not isinstance(item[1], bool)):
raise TypeError(
f"A 2-tuple used to define a routine within the "
f"Each tuple used to define a routine within the "
f"GenericInterfaceSymbol '{self.name}' must consist of a "
f"RoutineSymbol and a bool but got: {item}")
f"RoutineSymbol and a bool but got: "
f"{[type(rt).__name__ for rt in item]}")
self._routines.append(self.RoutineInfo(item[0], item[1]))

@property
Expand All @@ -112,7 +114,7 @@ def module_routines(self):
'''
result = []
for value in self._routines:
if value.is_module:
if value.from_container:
result.append(value.symbol)
return result

Expand All @@ -124,13 +126,13 @@ def external_routines(self):
'''
result = []
for value in self._routines:
if not value.is_module:
if not value.from_container:
result.append(value.symbol)
return result

def __str__(self):
return (f"{self.name}: {type(self).__name__}<{self.datatype}, "
f"routines={[rt.name for rt in self.routines]}>")
f"routines={[rt.symbol.name for rt in self.routines]}>")

def copy(self):
'''Create and return a copy of this object. Any references to the
Expand Down
11 changes: 6 additions & 5 deletions src/psyclone/psyir/symbols/symbol_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,10 +295,11 @@ def deep_copy(self):
for symbol in new_st.symbols:
if not isinstance(symbol, GenericInterfaceSymbol):
continue
new_syms = []
for rsym in symbol.routines:
new_syms.append(new_st.lookup(rsym.name))
symbol.routines = new_syms
new_routines = []
for routine in symbol.routines:
new_routines.append((new_st.lookup(routine.symbol.name),
routine.from_container))
symbol.routines = new_routines

# Set the default visibility
new_st._default_visibility = self.default_visibility
Expand Down Expand Up @@ -1063,7 +1064,7 @@ def remove(self, symbol):
# Check for any references to it within interfaces.
for sym in self._symbols.values():
if isinstance(sym, GenericInterfaceSymbol):
if symbol in sym.routines:
if symbol in [rt.symbol for rt in sym.routines]:
raise ValueError(
f"Cannot remove RoutineSymbol '{symbol.name}' "
f"because it is referenced in interface "
Expand Down
7 changes: 4 additions & 3 deletions src/psyclone/tests/psyir/backend/fortran_gen_decls_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,10 +319,11 @@ def test_procedure_interface(fortran_reader, fortran_writer):
declaration from a GenericInterfaceSymbol.
'''
symbol_table = SymbolTable()
isub = GenericInterfaceSymbol("subx", [RoutineSymbol("sub1"),
RoutineSymbol("sub2")])
isub = GenericInterfaceSymbol("subx", [(RoutineSymbol("sub1"), False),
(RoutineSymbol("sub2"), True)])
symbol_table.add(isub)
out = fortran_writer.gen_decls(symbol_table)
assert "interface subx" in out
assert "procedure :: sub1, sub2" in out
assert "procedure :: sub1" in out
assert "module procedure :: sub2" in out
assert "end interface subx" in out
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,8 @@ def __str__(self):
container.symbol_table.add(RoutineSymbol("eos", OtherType("some code")))
with pytest.raises(InternalError) as err:
fortran_writer.gen_decls(container.symbol_table)
assert ("Symbol 'eos' is a RoutineSymbol which is not imported nor an "
"interface (UnknownFortranType). This is already implicitly "
assert ("Symbol 'eos' is a RoutineSymbol which is not imported or of "
"UnknownFortranType. This is already implicitly "
"declared by the routine itself and should not be provided "
"to 'gen_vardecl'." in str(err.value))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,8 @@ def has_cmp_interface(code):
# Check that the generic interface in in the code
assert '''interface psyclone_internal_cmp
procedure :: psyclone_cmp_int, psyclone_cmp_logical, psyclone_cmp_char
end interface psyclone_internal_cmp''' in code
end interface psyclone_internal_cmp
private psyclone_internal_cmp''' in code

# Check that the integer implementation is in the code
assert '''function psyclone_cmp_int(op1, op2)
Expand Down
26 changes: 18 additions & 8 deletions src/psyclone/tests/psyir/symbols/generic_interface_symbol_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,18 +58,27 @@ def test_gis_constructor():
acorn = RoutineSymbol("acorn")
with pytest.raises(TypeError) as err:
_ = GenericInterfaceSymbol("oak", [acorn, "sycamore"])
assert ("of RoutineSymbols but got: ['RoutineSymbol', 'str']" in
assert ("GenericInterfaceSymbol ('oak') requires a list of tuples but "
"got: 'RoutineSymbol'" in str(err.value))
with pytest.raises(TypeError) as err:
_ = GenericInterfaceSymbol("oak", [(acorn, False),
(acorn, False, False)])
assert ("Each tuple used to define a routine within the "
"GenericInterfaceSymbol 'oak' must consist of a RoutineSymbol and "
"a bool but got: ['RoutineSymbol', 'bool', 'bool']" in
str(err.value))
oak = GenericInterfaceSymbol("oak", [acorn])
assert oak.routines == [acorn]
oak = GenericInterfaceSymbol("oak", [(acorn, False)])
assert len(oak.routines) == 1
assert oak.routines[0].symbol is acorn
assert oak.routines[0].from_container is False


def test_gis_typedsymbol_keywords():
'''
Test that keyword arguments to the constructor are passed through to the
TypedSymbol constructor.
'''
walnut = GenericInterfaceSymbol("walnut", [RoutineSymbol("nut")],
walnut = GenericInterfaceSymbol("walnut", [(RoutineSymbol("nut"), True)],
datatype=INTEGER_TYPE)
assert walnut.datatype == INTEGER_TYPE

Expand All @@ -80,7 +89,7 @@ def test_gis_str():
'''
ash = RoutineSymbol("ash")
holly = RoutineSymbol("holly")
coppice = GenericInterfaceSymbol("coppice", [ash, holly])
coppice = GenericInterfaceSymbol("coppice", [(ash, True), (holly, False)])
assert str(coppice) == ("coppice: GenericInterfaceSymbol<NoType, "
"routines=['ash', 'holly']>")

Expand All @@ -91,10 +100,11 @@ def test_gis_copy():
'''
ash = RoutineSymbol("ash")
holly = RoutineSymbol("holly")
coppice = GenericInterfaceSymbol("coppice", [ash, holly])
coppice = GenericInterfaceSymbol("coppice", [(ash, True), (holly, False)])
spinney = coppice.copy()
assert isinstance(spinney, GenericInterfaceSymbol)
assert spinney is not coppice
assert len(spinney.routines) == 2
assert ash in spinney.routines
assert holly in spinney.routines
rsyms = [item.symbol for item in spinney.routines]
assert ash in rsyms
assert holly in rsyms
2 changes: 1 addition & 1 deletion src/psyclone/tests/psyir/symbols/symbol_table_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1663,7 +1663,7 @@ def test_deep_copy():
symtab.add(sym3)
symtab.specify_argument_list([sym1])
rsym = symbols.RoutineSymbol("my_sub")
gisym = symbols.GenericInterfaceSymbol("generic_sub", [rsym])
gisym = symbols.GenericInterfaceSymbol("generic_sub", [(rsym, False)])
symtab.add(rsym)
symtab.add(gisym)

Expand Down

0 comments on commit fae0056

Please sign in to comment.