Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
:raises InternalError: if the arguments are of the wrong type.
:raises InternalError: if there's no symbol table associated with \
`psyir_literal_parent` or one of its ancestors.
'''
if not isinstance(fparser2_node,
(Fortran2003.Real_Literal_Constant,
Fortran2003.Logical_Literal_Constant,
Fortran2003.Char_Literal_Constant,
Fortran2003.Int_Literal_Constant)):
raise InternalError(
"Unsupported literal type '{0}' found in get_literal_precision."
"".format(type(fparser2_node).__name__))
if not isinstance(psyir_literal_parent, Node):
raise InternalError(
"Expecting argument psyir_literal_parent to be a PSyIR Node but "
"found '{0}' in get_literal_precision."
"".format(type(psyir_literal_parent).__name__))
precision_name = fparser2_node.items[1]
if not precision_name:
# Precision may still be specified by the exponent in a real literal
if isinstance(fparser2_node, Fortran2003.Real_Literal_Constant):
precision_value = fparser2_node.items[0]
if "d" in precision_value.lower():
return ScalarType.Precision.DOUBLE
if "e" in precision_value.lower():
return ScalarType.Precision.SINGLE
# Return the default precision
try:
data_name = CONSTANT_TYPE_MAP[type(fparser2_node)]
except KeyError:
import six
import io
if six.PY2:
# In Python 2 a plain string must be encoded as unicode for the call
# to write() below. unicode() does not exist in Python 3 since all
# strings are unicode.
# pylint: disable=undefined-variable
if not isinstance(contents, unicode):
contents = unicode(contents, 'utf-8')
# pylint: enable=undefined-variable
encoding = {}
elif six.PY3:
encoding = {'encoding': 'utf-8'}
else:
raise InternalError("Unrecognised Python version!")
with io.open(filename, mode='w', **encoding) as file_object:
file_object.write(contents)
:raises ParseError: if the 3rd argument is not a valid function space.
:raises ParseError: if the optional 4th argument is not a stencil \
specification or a mesh identifier (for \
inter-grid kernels).
:raises ParseError: if a field on a discontinuous function space \
has 'gh_inc' access.
:raises ParseError: if a field on a continuous function space has \
'gh_readwrite' access.
:raises ParseError: if a field on 'any_space' function space has \
'gh_readwrite' access.
:raises ParseError: if a field with a stencil access is not read only.
'''
# Check whether something other than a field is passed in
if self._type not in LFRicArgDescriptor.VALID_FIELD_NAMES:
raise InternalError(
"LFRicArgDescriptor._validate_field(): expecting a field "
"argument but got an argument of type '{0}'.".
format(arg_type.args[0]))
# There must be at least 3 arguments
if len(arg_type.args) < 3:
raise ParseError(
"In the LFRic API each 'meta_arg' entry must have at "
"least 3 arguments if its first argument is of {0} type, "
"but found {1} in '{2}'.".
format(LFRicArgDescriptor.VALID_FIELD_NAMES,
len(arg_type.args), arg_type))
# There must be at most 4 arguments
if len(arg_type.args) > 4:
raise ParseError(
"In the LFRic API each 'meta_arg' entry must have at "
format(name))
bname = statement.bname.lower()
else:
bname = statement.name.lower()
break
if bname is None:
# If no type-bound procedure found, search for an explicit
# interface that has module procedures.
bname, subnames = get_kernel_interface(name, modast)
if bname is None:
# no interface found either
raise ParseError(
"Kernel type {0} does not bind a specific procedure or \
provide an explicit interface".format(name))
elif bname == '':
raise InternalError(
"Empty Kernel name returned for Kernel type {0}.".format(name))
# add the name of the tbp to the list of strings to search for.
else:
subnames = [bname]
# walk the AST to check the subroutine names exist.
procedure_count = 0
for subname in subnames:
for statement, _ in fpapi.walk(modast):
if isinstance(statement,
fparser1.block_statements.Subroutine) \
and statement.name.lower() \
== subname:
procedure_count = procedure_count + 1
if procedure_count == 1:
# set code to statement if there is one procedure.
code = statement
var_accesses.add_access(basis_name, AccessType.READ,
self._kern)
elif shape in VALID_EVALUATOR_SHAPES:
# Need a basis array for each target space upon which the basis
# functions have been evaluated. _kern.eval_targets is a dict
# where the values are 2-tuples of (FunctionSpace, argument).
for _, target in self._kern.eval_targets.items():
basis_name = \
function_space.get_basis_name(on_space=target[0])
self.append(basis_name)
if var_accesses is not None:
var_accesses.add_access(basis_name, AccessType.READ,
self._kern)
else:
raise InternalError(
"Unrecognised evaluator shape ('{0}'). Expected one of: "
"{1}".format(shape, VALID_EVALUATOR_SHAPES))
:returns: mangled name of this function space.
:rtype: str
:raises InternalError: if a function space to create the mangled \
name for is not one of 'any_space' or \
'any_discontinuous_space' spaces.
:raises FieldNotFoundError: if no kernel argument was found on \
the specified function space.
'''
# First check that the the function space is one of any_*_space
# spaces and then proceed with name-mangling.
if self._orig_name not in FunctionSpace.VALID_ANY_SPACE_NAMES + \
FunctionSpace.VALID_ANY_DISCONTINUOUS_SPACE_NAMES:
raise InternalError(
"_mangle_fs_name: function space '{0}' is not one of "
"{1} or {2} spaces.".
format(self._orig_name, FunctionSpace.VALID_ANY_SPACE_NAMES,
FunctionSpace.VALID_ANY_DISCONTINUOUS_SPACE_NAMES))
# List kernel arguments
args = self._kernel_args.args
# Mangle the function space name for any_*_space
for arg in args:
for fspace in arg.function_spaces:
if (fspace and fspace.orig_name.lower() ==
self._orig_name.lower()):
mngl_name = self._short_name + "_" + arg.name
return mngl_name
# Raise an error if there are no kernel arguments on this
# function space
:returns: the PSyIR Precision of this literal value.
:rtype: :py:class:`psyclone.psyir.symbols.DataSymbol`, int or \
:py:class:`psyclone.psyir.symbols.ScalarType.Precision`
:raises InternalError: if the arguments are of the wrong type.
:raises InternalError: if there's no symbol table associated with \
`psyir_literal_parent` or one of its ancestors.
'''
if not isinstance(fparser2_node,
(Fortran2003.Real_Literal_Constant,
Fortran2003.Logical_Literal_Constant,
Fortran2003.Char_Literal_Constant,
Fortran2003.Int_Literal_Constant)):
raise InternalError(
"Unsupported literal type '{0}' found in get_literal_precision."
"".format(type(fparser2_node).__name__))
if not isinstance(psyir_literal_parent, Node):
raise InternalError(
"Expecting argument psyir_literal_parent to be a PSyIR Node but "
"found '{0}' in get_literal_precision."
"".format(type(psyir_literal_parent).__name__))
precision_name = fparser2_node.items[1]
if not precision_name:
# Precision may still be specified by the exponent in a real literal
if isinstance(fparser2_node, Fortran2003.Real_Literal_Constant):
precision_value = fparser2_node.items[0]
if "d" in precision_value.lower():
return ScalarType.Precision.DOUBLE
if "e" in precision_value.lower():
return ScalarType.Precision.SINGLE
# to be the same as the name computed for the first region in the
# first gen_code call (which indeed implies that the name of the
# first profile region is different the second time it is computed).
# So in order to guarantee that the computed module and region names
# are unique when gen_code is called more than once, we
# cannot store a computed name in module_name and region_name.
self._region_identifier = ("", "")
name = options.get("region_name", None)
if name:
# pylint: disable=too-many-boolean-expressions
if not isinstance(name, tuple) or not len(name) == 2 or \
not name[0] or not isinstance(name[0], str) or \
not name[1] or not isinstance(name[1], str):
raise InternalError(
"Error in PSyDataNode. The name must be a "
"tuple containing two non-empty strings.")
# pylint: enable=too-many-boolean-expressions
# Valid PSyData names have been provided by the user.
self._module_name = name[0]
self._region_name = name[1]
self.set_region_identifier(self._module_name, self._region_name)
if statement.bname:
if statement.name.lower() != "code":
raise ParseError(
"Kernel type {0} binds to a specific procedure but"
" does not use 'code' as the generic name.".
format(name))
bname = statement.bname
else:
bname = statement.name
break
if bname is None:
raise ParseError(
"Kernel type {0} does not bind a specific procedure".
format(name))
if bname == '':
raise InternalError(
"Empty Kernel name returned for Kernel type {0}.".format(name))
code = None
for statement, _ in fpapi.walk(modast, -1):
if isinstance(statement, fparser1.block_statements.Subroutine) \
and statement.name == bname:
code = statement
break
if not code:
raise ParseError(
"kernel.py:KernelProcedure:get_procedure: Kernel subroutine "
"'{0}' not found.".format(bname))
return code, bname
def rhs(self):
'''
:returns: the child node representing the Right-Hand Side of the \
assignment.
:rtype: :py:class:`psyclone.psyir.nodes.Node`
:raises InternalError: Node has fewer children than expected.
'''
if len(self._children) < 2:
raise InternalError(
"Assignment '{0}' malformed or incomplete. It "
"needs at least 2 children to have a rhs.".format(repr(self)))
return self._children[1]