Reference Guide  2.5.0
scoping_node.py
1 # -----------------------------------------------------------------------------
2 # BSD 3-Clause License
3 #
4 # Copyright (c) 2021-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: A. R. Porter and S. Siso, STFC Daresbury Lab
35 # -----------------------------------------------------------------------------
36 
37 ''' This module contains the ScopingNode implementation.'''
38 
39 from psyclone.psyir.nodes.node import Node
40 from psyclone.psyir.nodes.reference import Reference
41 from psyclone.psyir.symbols import SymbolTable
42 
43 
45  ''' Abstract node that has an associated Symbol Table to keep track of
46  symbols declared in its scope (symbols that can be accessed by this node
47  and any of its descendants). If a pre-existing symbol table is provided,
48  it will be attached to the node (raising an error if the symbol table
49  is already attached to another scope), otherwise a new empty Symbol Table
50  will be created.
51 
52  :param children: the PSyIR nodes that are children of this node.
53  :type children: List[:py:class:`psyclone.psyir.nodes.Node`]
54  :param parent: the parent node of this node in the PSyIR.
55  :type parent: Optional[:py:class:`psyclone.psyir.nodes.Node`]
56  :param symbol_table: attach the given symbol table to the new node.
57  :type symbol_table: \
58  Optional[:py:class:`psyclone.psyir.symbols.SymbolTable`]
59 
60  '''
61  # Polymorphic parameter to initialize the Symbol Table of the ScopingNode
62  _symbol_table_class = SymbolTable
63 
64  def __init__(self, children=None, parent=None, symbol_table=None):
65  super().__init__(children=children, parent=parent)
66  self._symbol_table_symbol_table = None
67 
68  if symbol_table is not None:
69  # Attach the provided symbol table to this scope
70  symbol_table.attach(self)
71  else:
72  # Create a new symbol table attached to this scope
73  self._symbol_table_symbol_table = self._symbol_table_class_symbol_table_class(self)
74 
75  def __eq__(self, other):
76  '''
77  Checks whether two nodes are equal. Scoping nodes are equal if their
78  symbol tables are equal.
79 
80  :param object other: the object to check equality to.
81 
82  :returns: whether other is equal to self.
83  :rtype: bool
84  '''
85  is_eq = super().__eq__(other)
86  is_eq = is_eq and self.symbol_tablesymbol_tablesymbol_table == other.symbol_table
87  return is_eq
88 
89  def _refine_copy(self, other):
90  ''' Refine the object attributes when a shallow copy is not the most
91  appropriate operation during a call to the copy() method.
92 
93  :param other: object we are copying from.
94  :type other: :py:class:`psyclone.psyir.node.Node`
95 
96  '''
97  super(ScopingNode, self)._refine_copy(other)
98  self._symbol_table_symbol_table = other.symbol_table.deep_copy()
99  # pylint: disable=protected-access
100  self._symbol_table_symbol_table._node = self # Associate to self
101 
102  # Update of children references to point to the equivalent symbols in
103  # the new symbol table attached to self.
104  # TODO #1377 Unfortunately Loop nodes currently store the associated
105  # loop variable in a `_variable` property rather than as a child so we
106  # must handle those separately. Also, in the LFRic API a Loop does not
107  # initially have the `_variable` property set which means that calling
108  # the `variable` getter causes an error (because it checks the
109  # internal-consistency of the Loop node). We therefore have to check
110  # the value of the 'private' `_variable` for now.
111  # We have to import Loop here to avoid a circular dependency.
112  # pylint: disable=import-outside-toplevel
113  from psyclone.psyir.nodes.loop import Loop
114  for node in self.walkwalk((Reference, Loop)):
115  if isinstance(node, Reference):
116  if node.symbol in other.symbol_table.symbols:
117  node.symbol = self.symbol_tablesymbol_tablesymbol_table.lookup(node.symbol.name)
118  if isinstance(node, Loop) and node._variable:
119  if node.variable in other.symbol_table.symbols:
120  node.variable = self.symbol_tablesymbol_tablesymbol_table.lookup(
121  node.variable.name)
122 
123  @property
124  def symbol_table(self):
125  '''
126  :returns: table containing symbol information for this scope.
127  :rtype: :py:class:`psyclone.psyGen.SymbolTable`
128  '''
129  return self._symbol_table_symbol_table
130 
131 
132 # For AutoAPI documentation generation
133 __all__ = ['ScopingNode']
def walk(self, my_type, stop_type=None, depth=None)
Definition: node.py:1075