Skip to content

Commit

Permalink
#924 add new Node.get_container_defintion() and delete unused code
Browse files Browse the repository at this point in the history
  • Loading branch information
arporter committed Jan 8, 2024
1 parent 9038cb4 commit b588404
Show file tree
Hide file tree
Showing 7 changed files with 168 additions and 543 deletions.
38 changes: 10 additions & 28 deletions src/psyclone/psyir/nodes/call.py
Original file line number Diff line number Diff line change
Expand Up @@ -455,8 +455,6 @@ def _location_txt(node):
last_line = out_lines[idx]
return f"code:\n'{out_lines[0]}\n...\n{last_line}'"

#import pdb; pdb.set_trace()
local_containers = self.root.walk(Container, stop_type=Routine)
rsym = self.routine
if rsym.is_unresolved:

Expand All @@ -478,20 +476,10 @@ def _location_txt(node):
for container_symbol in current_table.containersymbols:
if container_symbol.wildcard_import:
wildcard_names.append(container_symbol.name)
for local in local_containers:
if container_symbol.name == local.name:
container = local
break
else:
# The Container isn't defined locally.
try:
container = container_symbol.container
except SymbolError:
# Failed to find the container source.
# TODO #924 this would be much better as a
# FileNotFoundError.
continue
# TODO this needs to support returning multiple routines
container = self.get_container_definition(
container_symbol)
if not container:
continue
routine = container.get_routine_definition(rsym.name)
if routine:
return [routine]
Expand All @@ -513,14 +501,12 @@ def _location_txt(node):
cursor = rsym
while cursor.is_import:
csym = cursor.interface.container_symbol
for local in local_containers:
if local.name == csym.name:
container = local
break
else:
# If necessary, this will search for and process the source
# file defining the container.
container = csym.container
container = self.get_container_definition(csym)
if not container:
raise NotImplementedError(

Check warning on line 506 in src/psyclone/psyir/nodes/call.py

View check run for this annotation

Codecov / codecov/patch

src/psyclone/psyir/nodes/call.py#L506

Added line #L506 was not covered by tests
f"RoutineSymbol '{rsym.name}' is imported from "
f"Container '{csym.name}' but the source defining "
f"that container could not be found.")
imported_sym = container.symbol_table.lookup(cursor.name)
if imported_sym.visibility != Symbol.Visibility.PUBLIC:
# The required Symbol must be shadowed with a PRIVATE
Expand Down Expand Up @@ -556,10 +542,6 @@ def _location_txt(node):
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
# return [kernel_schedule]

raise SymbolError(
f"Failed to find a Routine named '{rsym.name}' in "
Expand Down
10 changes: 8 additions & 2 deletions src/psyclone/psyir/nodes/container.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,14 +191,20 @@ def get_routine_definition(self, name):
routine_sym = table.lookup(rname)
if routine_sym.is_import:
child_cntr_sym = routine_sym.interface.container_symbol
return child_cntr_sym.get_routine_definition(rname)
# Find the definition of the container.
container = self.get_container_definition(child_cntr_sym)
if not container:
return None

Check warning on line 197 in src/psyclone/psyir/nodes/container.py

View check run for this annotation

Codecov / codecov/patch

src/psyclone/psyir/nodes/container.py#L197

Added line #L197 was not covered by tests
return container.get_routine_definition(rname)
except KeyError:
pass

# Look in any wildcard imports.
for child_cntr_sym in table.containersymbols:
if child_cntr_sym.wildcard_import:
result = child_cntr_sym.get_routine_definition(rname)
# Find the definition of the container.
container = self.get_container_definition(child_cntr_sym)
result = container.get_routine_definition(rname)
if result:
return result
# The required Routine was not found in the Container.
Expand Down
27 changes: 27 additions & 0 deletions src/psyclone/psyir/nodes/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -1698,6 +1698,33 @@ def path_from(self, ancestor):
result_list.reverse()
return result_list

def get_container_definition(self, csym):
'''
:param csym: the container to search for.
:type csym: :py:class:`psyclone.psyir.symbols.ContainerSymbol`
:returns: the PSyIR of the specified Container or None if not found.
:rtype: :py:class:`psyclone.psyir.nodes.Container` | NoneType
'''
# TODO should this be replaced by the ModuleManager?
lowered_name = csym.name.lower()
from psyclone.psyir.nodes.container import Container
from psyclone.psyir.nodes.routine import Routine
local_containers = self.root.walk(Container, stop_type=Routine)
for local in local_containers:
if lowered_name == local.name.lower():
return local

# The Container isn't defined locally.
try:
return csym.container
except SymbolError:
# Failed to find the container source.
# TODO #924 this would be much better as a
# FileNotFoundError.
return None


# For automatic documentation generation
# TODO #913 the 'colored' routine shouldn't be in this module.
Expand Down
35 changes: 0 additions & 35 deletions src/psyclone/psyir/symbols/containersymbol.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,41 +163,6 @@ def wildcard_import(self, value):
f"'{type(value).__name__}'")
self._has_wildcard_import = value

def old_get_routine_definition(self, name):
'''
'''
rname = name.lower()
# Get the container definition. Imports it if necessary.
cntr = self.container
from psyclone.psyir.nodes.routine import Routine
for node in cntr.children:
if isinstance(node, Routine) and node.name.lower() == rname:
# Check this routine is public
routine_sym = cntr.symbol_table.lookup(node.name)
if routine_sym.visibility == Symbol.Visibility.PUBLIC:
return node
# The Container does not contain the expected Routine or the
# Routine is not public.

# Look in the import that names the routine if there is one.
table = cntr.symbol_table
try:
routine_sym = table.lookup(rname)
if routine_sym.is_import:
child_cntr_sym = routine_sym.interface.container_symbol
return child_cntr_sym.get_routine_definition(rname)
except KeyError:
pass

# Look in any wildcard imports.
for child_cntr_sym in table.containersymbols:
if child_cntr_sym.wildcard_import:
result = child_cntr_sym.get_routine_definition(rname)
if result:
return result
# The required Routine was not found in the Container.
return None


class ContainerSymbolInterface(SymbolInterface):
''' Abstract implementation of the ContainerSymbol Interface '''
Expand Down
150 changes: 0 additions & 150 deletions src/psyclone/psyir/transformations/inline_trans.py
Original file line number Diff line number Diff line change
Expand Up @@ -840,156 +840,6 @@ def validate(self, node, options=None):
f"with a non-unit stride: "
f"'{actual_arg.debug_string()}' (TODO #1646)"))

@staticmethod
def _find_routine(call_node):
'''Searches for the definition of the routine that is being called by
the supplied Call.
:param call_node: the Call that is to be inlined.
:type call_node: :py:class:`psyclone.psyir.nodes.Call`
:returns: the PSyIR for the target routine.
:rtype: :py:class:`psyclone.psyir.nodes.Routine`
:raises TransformationError: if the routine definition cannot be found.
'''
# TODO remove this routine altogether!
try:
callees = call_node.get_callees()
return callees[0]
except (NotImplementedError, SymbolError) as err:
raise TransformationError(
f"Failed to find the source code of the routine "
f"'{call_node.routine.name}': {err}") from err

name = call_node.routine.name
routine_sym = call_node.routine

if routine_sym.is_modulevar:
table = routine_sym.find_symbol_table(call_node)
for routine in table.node.walk(Routine):
if routine.name.lower() == name.lower():
return routine
raise TransformationError(
f"Failed to find the source code of the local routine "
f"'{routine_sym.name}' - it is probably in a CodeBlock.")

if routine_sym.is_unresolved:

# First check for any wildcard imports and see if they can
# be used to resolve the symbol.
wildcard_names = []
current_table = call_node.scope.symbol_table
while current_table:
for container_symbol in current_table.containersymbols:
if container_symbol.wildcard_import:
wildcard_names.append(container_symbol.name)
routine = InlineTrans._find_routine_in_container(
call_node, container_symbol)
if routine:
return routine
current_table = current_table.parent_symbol_table()

# Next check for any "raw" Routines, i.e. ones that are not
# in a Container. Such Routines would exist in the PSyIR
# as a child of a FileContainer (if the PSyIR contains a
# FileContainer). Note, if the PSyIR does contain a
# FileContainer, it will be the root node of the PSyIR.
for routine in call_node.root.children:
if (isinstance(routine, Routine) and
routine.name.lower() == name.lower()):
return routine
raise TransformationError(
f"Failed to find the source code of the unresolved "
f"routine '{name}' after trying wildcard imports from "
f"{wildcard_names} and all routines that are not in "
f"containers.")

if routine_sym.is_import:
container_symbol = routine_sym.interface.container_symbol
routine = InlineTrans._find_routine_in_container(
call_node, container_symbol)
if routine:
return routine
raise TransformationError(
f"Failed to find the source for routine '{routine_sym.name}' "
f"imported from '{container_symbol.name}' and therefore "
f"cannot inline it.")

if isinstance(routine_sym.datatype, UnknownType):
raise TransformationError(
f"Failed to find the source for routine '{routine_sym.name}' "
f"which is of type '{routine_sym.datatype}'. This indicates "
f"that it corresponds to a generic interface and inlining "
f"such a routine is not yet implemented - TODO #924")

raise InternalError(
f"Routine Symbol '{routine_sym.name}' is not local, "
f"unresolved or imported.")

@staticmethod
def _find_routine_in_container(call_node, container_symbol):
'''Searches for the definition of a routine that is being called by
the supplied Call. If present, this routine must exist within a
container specified by the supplied container symbol.
:param call_node: the Call that is to be inlined.
:type call_node: :py:class:`psyclone.psyir.nodes.Call`
:param container_symbol: the symbol of the container to search.
:type container_symbol: \
:py:class:`psyclone.psyir.symbols.ContainerSymbol`
:returns: the PSyIR for the target routine, if found.
:rtype: Optional[:py:class:`psyclone.psyir.nodes.Routine`]
'''
# The required Routine will exist within a Container and
# that Container could exist in the PSyIR as a child of a
# FileContainer (if the PSyIR contains a
# FileContainer). If the PSyIR does contain a
# FileContainer, it will be the root node of the PSyIR.
call_routine_sym = call_node.routine
for container in call_node.root.children:
if (isinstance(container, Container) and
container.name.lower() == container_symbol.name.lower()):
for routine in container.children:
if (isinstance(routine, Routine) and
routine.name.lower() ==
call_routine_sym.name.lower()):
# Check this routine is public
routine_sym = container.symbol_table.lookup(
routine.name)
if routine_sym.visibility == Symbol.Visibility.PUBLIC:
return routine
# The Container has been found but it does not contain
# the expected Routine or the Routine is not public.

# Look in the import that names the routine if there is one.
table = container.symbol_table
try:
routine_sym = table.lookup(call_routine_sym.name)
if routine_sym.is_import:
child_container_symbol = \
routine_sym.interface.container_symbol
return (InlineTrans._find_routine_in_container(
call_node, child_container_symbol))
except KeyError:
pass

# Look in any wildcard imports.
for child_container_symbol in table.containersymbols:
if child_container_symbol.wildcard_import:
result = InlineTrans._find_routine_in_container(
call_node, child_container_symbol)
if result:
return result
# The required Symbol was not found in the Container.
return None
# The specified Container was not found in the PSyIR.
return None


# For AutoAPI auto-documentation generation.
__all__ = ["InlineTrans"]
Loading

0 comments on commit b588404

Please sign in to comment.