38 '''This module contains PSyclone Algorithm-layer-specific PSyIR classes.
46 Routine, Container, FileContainer)
51 '''An invoke call in a PSyclone Algorithm layer.
53 :param invoke_routine_symbol: the routine that this call calls.
54 :type invoke_routine_symbol: \
55 py:class:`psyclone.psyir.symbols.RoutineSymbol`
56 :param int index: the position of this invoke call relative to \
57 other invokes in the algorithm layer.
58 :param parent: optional parent of this node in the PSyIR. Defaults \
60 :type parent: sub-class of :py:class:`psyclone.psyir.nodes.Node` \
62 :param Optional[str] name: an optional name, describing the \
63 AlgorithmInvokeCall. Defaults to None.
65 :raises TypeError: if the index argument is not an integer.
66 :raises ValueError: if the index argument is negative.
67 :raises ValueError: if an invalid name is supplied.
70 _children_valid_format =
"Reference, [KernelFunctor]*"
71 _text_name =
"AlgorithmInvokeCall"
74 def __init__(self, invoke_routine_symbol, index, parent=None, name=None):
75 super().__init__(parent=parent)
76 self.addchild(Reference(invoke_routine_symbol))
78 if not isinstance(index, int):
80 f
"AlgorithmInvokeCall index argument should be an int but "
81 f
"found '{type(index).__name__}'.")
84 f
"AlgorithmInvokeCall index argument should be a non-negative "
85 f
"integer but found {index}.")
88 FortranReader.validate_name(name)
89 except (TypeError, ValueError)
as err:
91 f
"Error with AlgorithmInvokeCall name argument: "
102 self.
_name_name = name
105 def create(cls, routine, arguments, index, name=None):
107 '''Create an instance of the calling class given valid instances of a
108 routine symbol, a list of child nodes for its arguments, an
109 index and an optional name.
111 :param routine: the routine that the calling class calls.
112 :type routine: py:class:`psyclone.psyir.symbols.RoutineSymbol`
113 :param arguments: the arguments to this routine. These are \
114 added as child nodes.
115 :type arguments: list of :py:class:`psyclone.psyir.nodes.DataNode`
116 :param int index: the position of this invoke call relative to \
117 other invokes in the algorithm layer.
118 :param Optional[str] name: a string naming/describing the invoke
119 or None if one is not provided. This is converted to lower case
120 and used to create the name of the routine that replaces the
121 invoke. It must be a valid Fortran name. Defaults to None.
123 :raises GenerationError: if the arguments argument is not a \
126 :returns: an instance of the calling class.
127 :rtype: :py:class:`psyclone.psyir.nodes.AlgorithmInvokeCall` \
128 or a subclass thereof.
131 if not isinstance(arguments, list):
133 f
"AlgorithmInvokeCall create arguments argument should be a "
134 f
"list but found '{type(arguments).__name__}'.")
140 FortranReader.validate_name(name)
141 lwr_name = name.lower()
144 call = cls(routine, index, name=lwr_name)
145 call.children.extend(arguments)
149 def _validate_child(position, child):
151 :param int position: the position to be validated.
152 :param child: a child to be validated.
153 :type child: :py:class:`psyclone.psyir.nodes.Node`
155 :returns: whether the given child and position are valid for this node.
160 return isinstance(child, Reference)
161 return isinstance(child, KernelFunctor)
164 '''Construct a text representation of this node, optionally
165 containing colour control codes. Specialise as this node has
166 an additional name argument.
168 :param bool colour: whether or not to include colour control \
169 codes. Optional argument that defaults to True.
171 :returns: description of this PSyIR node.
175 return f
"{self.coloured_name(colour)}[name=\"{self._name}\"]"
177 def _def_routine_root_name(self):
178 '''Internal method that returns the proposed language-level routine
181 :returns: the proposed processed routine name for this invoke.
184 :raises TypeError: if the name provided in the invoke call is invalid.
188 routine_root_name = self.
_name_name.lower().strip()
189 if routine_root_name[0] ==
'"' and routine_root_name[-1] ==
'"' \
191 routine_root_name[0] ==
"'" and routine_root_name[-1] ==
"'":
194 routine_root_name = routine_root_name[1:-1].strip()
195 routine_root_name = routine_root_name.replace(
" ",
"_")
197 pattern = re.compile(
r"^[a-zA-Z]\w*$", re.ASCII)
198 if not pattern.match(routine_root_name):
200 f
"AlgorithmInvokeCall:_def_routine_root_name() the "
201 f
"(optional) name of an invoke must be a string "
202 f
"containing a valid name (with any spaces replaced by "
203 f
"underscores) but found '{routine_root_name}'.")
204 if not routine_root_name.startswith(
"invoke"):
205 routine_root_name = f
"invoke_{routine_root_name}"
207 routine_root_name = f
"invoke_{self._index}"
208 if len(self.arguments) == 1:
210 routine_root_name +=
"_" + self.arguments[0].name
211 return routine_root_name
214 '''If the PSy-layer routine and container root names have not been
215 created, then create them. The invoke root name is based on
216 the position of this node (compared to other nodes of the same
217 type) in the PSyIR tree. Note, we do not create and store
218 symbols, as the container name needs to be consistent between
219 different invoke calls and we have no way of knowing whether
220 one has already been created without the symbol being stored
221 in the symbol table, and we don't want to add anything related
222 to the lower level PSyIR to the symbol table before lowering.
224 :raises InternalError: if no Routine or Container is found in \
225 the PSyIR tree containing this node.
238 for node
in self.root.walk((Routine, Container)):
239 if not isinstance(node, FileContainer):
246 def _def_container_root_name(node):
248 :returns: the root name to use for the container.
251 return f
"psy_{node.name}"
255 '''Object containing a kernel call, a description of its required
256 interface and the arguments to be passed to it.
258 :param symbol: the functor symbol.
259 :type symbol: :py:class:`psyclone.psyir.symbols.Symbol`
260 :param parent: the parent node of this functor instance.
261 :type parent: :py:class:`psyclone.psyir.nodes.Node` or NoneType
264 _children_valid_format =
"[DataNode]*"
265 _text_name =
"KernelFunctor"
267 def __init__(self, symbol, parent=None):
268 super().__init__(symbol, parent=parent)
270 if not isinstance(symbol, DataTypeSymbol):
272 f
"KernelFunctor symbol argument should be a DataTypeSymbol "
273 f
"but found '{type(symbol).__name__}'.")
277 '''Create an instance of the calling class given valid instances of a
278 DataTypeSymbol and a list of child nodes for its arguments.
280 :param symbol: the name of the kernel type that this object \
282 :type symbol: py:class:`psyclone.psyir.symbols.DataTypeSymbol`
283 :param arguments: the arguments to this routine. These are \
284 added as child nodes.
285 :type arguments: list of :py:class:`psyclone.psyir.nodes.DataNode`
287 :returns: an instance of the calling class.
288 :rtype: :py:class:`psyclone.psyir.nodes.Call` or subclass thereof.
291 if not isinstance(symbol, DataTypeSymbol):
293 f
"KernelFunctor create() symbol argument should be a "
294 f
"DataTypeSymbol but found '{type(symbol).__name__}'.")
295 if not isinstance(arguments, list):
297 f
"KernelFunctor create() arguments argument should be a list "
298 f
"but found '{type(arguments).__name__}'.")
301 call.children = arguments
305 def _validate_child(position, child):
307 :param int position: the position to be validated.
308 :param child: a child to be validated.
309 :type child: :py:class:`psyclone.psyir.nodes.Node`
311 :return: whether the given child and position are valid for this node.
315 return isinstance(child, DataNode)
319 'AlgorithmInvokeCall',
def _def_container_root_name(node)
def create_psylayer_symbol_root_names(self)
psylayer_routine_root_name
def create(cls, routine, arguments, index, name=None)
def _def_routine_root_name(self)
def node_str(self, colour=True)
psylayer_container_root_name
def create(cls, symbol, arguments)