Reference Guide  2.5.0
nemo_allarrayrange2loop_trans.py
1 # -----------------------------------------------------------------------------
2 # BSD 3-Clause License
3 #
4 # Copyright (c) 2020-2024, Science and Technology Facilities Council.
5 # All rights reserved.
6 #
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions are met:
9 #
10 # * Redistributions of source code must retain the above copyright notice, this
11 # list of conditions and the following disclaimer.
12 #
13 # * Redistributions in binary form must reproduce the above copyright notice,
14 # this list of conditions and the following disclaimer in the documentation
15 # and/or other materials provided with the distribution.
16 #
17 # * Neither the name of the copyright holder nor the names of its
18 # contributors may be used to endorse or promote products derived from
19 # this software without specific prior written permission.
20 #
21 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 # POSSIBILITY OF SUCH DAMAGE.
33 # -----------------------------------------------------------------------------
34 # Authors: R. W. Ford, A. R. Porter and N. Nobre, STFC Daresbury Lab
35 # Modified: A. B. G. Chalk, STFC Daresbury Lab
36 
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 the required number of NemoLoop
42 nodes.
43 
44 '''
45 from __future__ import absolute_import
46 
47 from psyclone.psyir.nodes import Assignment
48 from psyclone.psyGen import Transformation
50  import TransformationError
52  import NemoOuterArrayRange2LoopTrans
53 
54 
56  '''Provides a transformation for all PSyIR Array Ranges in an
57  assignment to PSyIR NemoLoops. For example:
58 
59  >>> from psyclone.parse.algorithm import parse
60  >>> from psyclone.psyGen import PSyFactory
61  >>> api = "nemo"
62  >>> filename = "tra_adv.F90" # examples/nemo/code
63  >>> ast, invoke_info = parse(filename, api=api)
64  >>> psy = PSyFactory(api).create(invoke_info)
65  >>> schedule = psy.invokes.invoke_list[0].schedule
66  >>>
67  >>> from psyclone.psyir.nodes import Assignment
68  >>> from psyclone.domain.nemo.transformations import \
69  NemoAllArrayRange2LoopTrans
70  >>>
71  >>> print(schedule.view())
72  >>> trans = NemoAllArrayRange2LoopTrans()
73  >>> for assignment in schedule.walk(Assignment):
74  >>> trans.apply(assignment)
75  >>> print(schedule.view())
76 
77  '''
78  def apply(self, node, options=None):
79  '''Apply the NemoAllArrayRange2Loop transformation to the specified
80  node if the node is an Assignment and the left-hand-side of
81  the assignment is an Array Reference containing at least one
82  Range node specifying an access to an array index. If this is
83  the case then all Range nodes within array references within
84  the assignment are replaced with references to the appropriate
85  loop indices. The appropriate number of NemoLoop loops are
86  also placed around the modified assignment statement.
87 
88  The name of each loop index is taken from the PSyclone
89  configuration file if a name exists for the particular array
90  index, otherwise a new name is generated. The bounds of each
91  loop are taken from the Range node if they are provided. If
92  not, the loop bounds are taken from the PSyclone configuration
93  file if a bounds value is supplied. If not, the LBOUND or
94  UBOUND intrinsics are used as appropriate. The type of the
95  NemoLoop is also taken from the configuration file if it is
96  supplied for that index, otherwise it is specified as being
97  "unknown".
98 
99  :param node: an Assignment node.
100  :type node: :py:class:`psyclone.psyir.nodes.Assignment`
101  :param options: a dictionary with options for transformations. No
102  options are used in this transformation. This is an optional
103  argument that defaults to None.
104  :param bool options["verbose"]: whether to print out the reason
105  why the inner transformation was not applied. This is useful
106  because this transfomation succeeds even if one of the inner
107  transformations fails, and therefor the reason why the inner
108  transformation failed is not propagated.
109  :type options: Optional[Dict[str, Any]]
110  :param bool options["allow_string"]: whether to allow the
111  transformation on a character type array range. Defaults to False.
112 
113  '''
114  self.validatevalidatevalidate(node, options)
115 
116  trans = NemoOuterArrayRange2LoopTrans()
117  try:
118  while True:
119  trans.apply(node, options)
120  except TransformationError as err:
121  # TODO #11: Instead we could use proper logging
122  if options and options.get("verbose", False):
123  errmsg = str(err)
124  # Skip the errors that are obious and are generated for any
125  # statement that is not an array expression
126  if "assignment node should be an expression with an array " \
127  "that has a Range node" not in errmsg and \
128  "be a Reference that contains an array access somewhere" \
129  not in errmsg:
130  print(errmsg)
131 
132  def __str__(self):
133  return ("Convert all array ranges in a PSyIR assignment into "
134  "PSyIR NemoLoops.")
135 
136  @property
137  def name(self):
138  '''
139  :returns: the name of the transformation.
140  :rtype: str
141 
142  '''
143  return type(self).__name__
144 
145  def validate(self, node, options=None):
146  '''Perform various checks to ensure that it is valid to apply the
147  NemoArrayRange2LoopTrans transformation to the supplied PSyIR Node.
148 
149  :param node: the node that is being checked.
150  :type node: :py:class:`psyclone.psyir.nodes.Assignment`
151  :param options: a dictionary with options for \
152  transformations. No options are used in this \
153  transformation. This is an optional argument that defaults \
154  to None.
155  :type options: Optional[Dict[str, Any]]
156 
157  :raises TransformationError: if the supplied node is not an \
158  Assignment.
159 
160  '''
161  # Am I an assignment node?
162  if not isinstance(node, Assignment):
163  raise TransformationError(
164  f"Error in NemoAllArrayRange2LoopTrans transformation. The "
165  f"supplied node argument should be a PSyIR Assignment, but "
166  f"found '{type(node).__name__}'.")
167 
168 
169 # For automatic document generation
170 __all__ = [
171  'NemoAllArrayRange2LoopTrans']
def validate(self, node, options=None)
Definition: psyGen.py:2799