40 ''' This module contains the LFRic-specific SymbolTable implementation.
41 It provides convenience functions to create often used symbols.
50 ImportInterface, INTEGER_TYPE, ScalarType,
57 Sub-classes SymbolTable to provide a LFRic-specific implementation.
59 :param node: reference to the Schedule or Container to which this \
61 :type node: :py:class:`psyclone.psyir.nodes.Schedule`, \
62 :py:class:`psyclone.psyir.nodes.Container` or NoneType
63 :param default_visibility: optional default visibility value for this \
64 symbol table, if not provided it defaults to PUBLIC visibility.
65 :type default_visibillity: \
66 :py:class:`psyclone.psyir.symbols.Symbol.Visibility`
75 def __init__(self, node=None, default_visibility=Symbol.Visibility.PUBLIC):
76 super().__init__(node, default_visibility)
79 if not LFRicSymbolTable._precision_map:
81 mod_name = const.UTILITIES_MOD_MAP[
"constants"][
"module"]
82 LFRicSymbolTable._constants_mod = ContainerSymbol(mod_name)
84 api_config = Config.get().api_conf(
"dynamo0.3")
85 for precision
in api_config.precision_map:
86 LFRicSymbolTable._precision_map[precision] = \
87 DataSymbol(precision, INTEGER_TYPE,
91 '''This function returns a symbol for an integer reference. If a
92 tag is specified, it will be used to search for an existing symbol,
93 otherwise the name will be used. If the symbol should not already
94 exist in the symbol table, it will be returned, otherwise a new
95 symbol will be created.
97 :param str name: name of the integer variable to declare.
98 :param tag: optional tag of the integer variable to declare.
99 :type tag: Optional[str]
101 :returns: the symbol for the variable.
102 :rtype: :py:class:`psyclone.psyir.symbols.Symbol`
104 :raises TypeError: TypeError if the symbol exists but is not \
106 :raises TypeError: TypeError if the symbol exists and is a \
107 DataSymbol, but not an Integer.
112 sym = self.lookup_with_tag(tag)
117 sym = self.lookup(name)
121 datatype =
LFRicTypes(
"LFRicIntegerScalarDataType")()
124 sym = self.new_symbol(name, tag=tag,
125 symbol_type=DataSymbol,
129 if not isinstance(sym, DataSymbol):
130 raise TypeError(f
"Symbol '{sym.name}' already exists, but is "
131 f
"not a DataSymbol, but '{type(sym)}'.")
132 if sym.datatype != datatype:
133 raise TypeError(f
"Symbol '{sym.name}' already exists, but is "
134 f
"not an integer, but '{sym.datatype}'.")
140 '''This function returns a symbol for an ArrayReference. If the
141 symbol does not exist, it is created. If a new array symbol is
142 created, it gets the DEFERRED attribute, which in Fortran means
143 it will be declared as an allocatable array.
145 :param str array_name: the name and tag of the array.
146 :param int num_dimensions: the number of dimensions of this array.
147 :param intrinsic_type: the intrinsic type of the array.
148 :type intrinsic_type: \
149 :py:class:`psyclone.psyir.symbols.datatypes.ScalarType.Intrinsic`
150 :param tag: optional tag to be used in searching and defining.
151 :type tag: Optional[str]
153 :returns: the requested symbol
154 :rtype: :py:class:`psyclone.psyir.symbols.Symbol`
156 :raises TypeError: if the symbol exists, but is not a DataSymbol, \
157 or not an Array, or has different number of dimensions.
160 if intrinsic_type == ScalarType.Intrinsic.REAL:
161 datatype =
LFRicTypes(
"LFRicRealScalarDataType")()
162 elif intrinsic_type == ScalarType.Intrinsic.INTEGER:
163 datatype =
LFRicTypes(
"LFRicIntegerScalarDataType")()
164 elif intrinsic_type == ScalarType.Intrinsic.BOOLEAN:
165 datatype =
LFRicTypes(
"LFRicLogicalScalarDataType")()
167 raise TypeError(f
"Unsupported data type "
168 f
"'{intrinsic_type}' in "
169 f
"find_or_create_array")
173 sym = self.lookup_with_tag(tag)
175 sym = self.lookup(array_name)
179 array_type = ArrayType(datatype,
180 [ArrayType.Extent.DEFERRED]*num_dimensions)
182 sym = self.new_symbol(array_name, tag=tag,
183 symbol_type=DataSymbol,
188 if not isinstance(sym, DataSymbol):
189 raise TypeError(f
"Symbol '{sym.name}' already exists, but is "
190 f
"not a DataSymbol, but '{type(sym)}'.")
192 if not isinstance(sym.datatype, ArrayType):
193 raise TypeError(f
"Symbol '{sym.name}' already exists, but is "
194 f
"not an ArraySymbol, but "
195 f
"'{type(sym.datatype)}'.")
197 if sym.datatype.datatype != datatype:
198 raise TypeError(f
"Symbol '{sym.name}' already exists, but is "
199 f
"not of type '{intrinsic_type}', but "
200 f
"'{type(sym.datatype.datatype)}'.")
202 if len(sym.shape) != num_dimensions:
203 raise TypeError(f
"Array '{sym.name}' already exists, but has "
204 f
"{len(sym.shape)} dimensions, not "
205 f
"{num_dimensions}.")
212 If the named LFRic precision symbol is not already in the table then
213 add it. Also ensure that the Container symbol from which it is
214 imported is in the table.
216 :param str name: name of the LFRic precision symbol to add to table.
218 :returns: the specified LFRic precision symbol.
219 :rtype: :py:class:`psyclone.psyir.symbols.DataSymbol`
221 :raises ValueError: if the supplied name is not a recognised LFRic \
223 :raises ValueError: if a symbol with the same name is already in the \
224 table but is not imported from the correct container.
227 api_config = Config.get().api_conf(
"dynamo0.3")
228 if name
not in api_config.precision_map.keys():
229 raise ValueError(f
"'{name}' is not a recognised LFRic precision.")
230 sym = LFRicSymbolTable._precision_map[name]
234 existing_sym = self.lookup(name)
235 if (
not isinstance(existing_sym.interface, ImportInterface)
or
236 existing_sym.interface.container_symbol.name !=
239 f
"Precision symbol '{name}' already exists in the "
240 f
"supplied symbol table but is not imported from the "
241 f
"LFRic constants module ({self._constants_mod.name}).")
def find_or_create_integer_symbol(self, name, tag=None)
def add_lfric_precision_symbol(self, name)
def find_or_create_array(self, array_name, num_dimensions, intrinsic_type, tag=None)