37 '''Module providing a transformation from an Assignment node
38 containing an Array Reference node in its left-hand-side which in turn
39 has at least one PSyIR Range node specifying an access to an array
40 index (equivalent to an array assignment statement in Fortran) to the
41 equivalent loop representation using a NemoLoop node. The outermost
42 Range is chosen to be replaced as replacing any other Range node would
43 result in a reordering of the array accesses.
50 import TransformationError
53 NemoArrayRange2LoopTrans
57 '''Provides a transformation from the outermost PSyIR ArrayReference
58 Range to a PSyIR NemoLoop. For example:
60 >>> from psyclone.parse.algorithm import parse
61 >>> from psyclone.psyGen import PSyFactory
63 >>> filename = "tra_adv.F90" # examples/nemo/code
64 >>> ast, invoke_info = parse(filename, api=api)
65 >>> psy = PSyFactory(api).create(invoke_info)
66 >>> schedule = psy.invokes.invoke_list[0].schedule
68 >>> from psyclone.psyir.nodes import Assignment
69 >>> from psyclone.domain.nemo.transformations import \
70 NemoOuterArrayRange2LoopTrans
71 >>> from psyclone.transformations import TransformationError
73 >>> print(schedule.view())
74 >>> trans = NemoOuterArrayRange2LoopTrans()
75 >>> for assignment in schedule.walk(Assignment):
78 >>> trans.apply(assignment)
79 >>> except TransformationError:
81 >>> print(schedule.view())
84 def apply(self, node, options=None):
85 '''Apply the NemoOuterArrayRange2Loop transformation to the specified
86 node if the node is an Assignment and the left-hand-side of
87 the assignment is an Array Reference containing at least one
88 Range node specifying an access to an array index. If this is
89 the case then the outermost Range nodes within array
90 references within the assignment are replaced with references
91 to a loop index. A NemoLoop loop (with the same loop index) is
92 also placed around the modified assignment statement.
94 The name of the loop index is taken from the PSyclone
95 configuration file if a name exists for the particular array
96 index, otherwise a new name is generated. The bounds of the
97 loop are taken from the Range node if they are provided. If
98 not, the loop bounds are taken from the PSyclone configuration
99 file if bounds values are supplied. If not, the LBOUND or
100 UBOUND intrinsics are used as appropriate. The type of the
101 NemoLoop is also taken from the configuration file if it is
102 supplied for that index, otherwise it is specified as being
105 :param node: an Assignment node.
106 :type node: :py:class:`psyclone.psyir.nodes.Assignment`
107 :param options: a dictionary with options for \
108 transformations. No options are used in this \
109 transformation. This is an optional argument that defaults \
111 :type options: Optional[Dict[str, Any]]
112 :param bool options["allow_string"]: whether to allow the
113 transformation on a character type array range. Defaults to False.
116 self.
validatevalidate(node, options)
119 deepest_range = node.lhs.walk(Range, stop_type=Range)[-1]
120 lhs_array_ref = deepest_range.parent
121 index = lhs_array_ref.get_outer_range_index()
123 nemo_arrayrange2loop.apply(lhs_array_ref.children[index], options)
126 return (
"Convert a PSyIR assignment to the outermost ArrayReference "
127 "Range into a PSyIR NemoLoop.")
132 :returns: the name of the transformation.
136 return type(self).__name__
139 '''Perform various checks to ensure that it is valid to apply the
140 NemoOuterArrayRange2LoopTrans transformation to the supplied
143 :param node: the node that is being checked.
144 :type node: :py:class:`psyclone.psyir.nodes.Assignment`
145 :param options: a dictionary with options for \
146 transformations. No options are used in this \
147 transformation. This is an optional argument that defaults \
149 :type options: Optional[Dict[str, Any]]
151 :raises TransformationError: if the supplied node is not an \
152 Assignment node, if the Assignment node does not have an \
153 Array-type Reference node on its left hand side or if the \
154 Array-type node does not contain at least one Range \
159 if not isinstance(node, Assignment):
160 raise TransformationError(
161 f
"Error in NemoOuterArrayRange2LoopTrans transformation. The "
162 f
"supplied node argument should be a PSyIR Assignment, but "
163 f
"found '{type(node).__name__}'.")
166 if not (isinstance(node.lhs, Reference)
and node.lhs.walk(ArrayMixin)):
167 raise TransformationError(
168 f
"Error in NemoOuterArrayRange2LoopTrans transformation. The "
169 f
"LHS of the supplied assignment node should be a Reference "
170 f
"that contains an array access somewhere in the expression, "
171 f
"but found '{node.lhs}'.")
173 if not node.lhs.walk(Range):
174 raise TransformationError(
175 f
"Error in NemoOuterArrayRange2LoopTrans transformation. The "
176 f
"LHS of the supplied assignment node should be an expression "
177 f
"with an array that has a Range node, but found "
183 'NemoOuterArrayRange2LoopTrans']
def validate(self, node, options=None)
def apply(self, node, options=None)