Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
else:
stop = schedule.jloop_stop
# This strange line splitting was the only way I could find
# to avoid pep8 warnings: using [..._space]\ keeps on
# complaining about a white space
bounds = GOLoop._bounds_lookup[index_offset][self.field_space][
self._iteration_space][self._loop_type]
stop = bounds["stop"].format(start='2', stop=stop)
# Remove all white spaces
stop = "".join(stop.split())
# This common case is a bit of compile-time computation
# but it helps to fix all of the test cases.
if stop == "2-1":
stop = "1"
return Literal(stop, INTEGER_TYPE, self)
if self.field_space == "go_every":
# Bounds are independent of the grid-offset convention in use
# We look-up the upper bounds by enquiring about the SIZE of
# the array itself
stop = BinaryOperation(BinaryOperation.Operator.SIZE,
self)
# TODO 363 - needs to be updated once the PSyIR has support for
# Fortran derived types.
api_config = Config.get().api_conf("gocean1.0")
# Use the data property to access the member of the field that
# contains the actual grid points. The property value is a
# string with a placeholder ({0}) where the name of the field
# must go.
data = api_config.grid_properties["go_grid_data"].fortran \
# to avoid pep8 warnings: using [..._space]\ keeps on
# complaining about a white space
bounds = GOLoop._bounds_lookup[index_offset][self.field_space][
self._iteration_space][self._loop_type]
start = bounds["start"].format(start='2', stop=stop)
# Remove all white spaces
start = "".join(start.split())
# This common case is a bit of compile-time computation
# but it helps with fixing all of the test cases.
if start == "2-1":
start = "1"
return Literal(start, INTEGER_TYPE, self)
if self.field_space == "go_every":
# Bounds are independent of the grid-offset convention in use
return Literal("1", INTEGER_TYPE, self)
# Loop bounds are pulled from the field object which is more
# straightforward for us but provides the Fortran compiler
# with less information.
if self._iteration_space.lower() == "go_internal_pts":
key = "internal"
elif self._iteration_space.lower() == "go_all_pts":
key = "whole"
else:
raise GenerationError("Unrecognised iteration space, '{0}'. "
"Cannot generate loop bounds.".
format(self._iteration_space))
api_config = Config.get().api_conf("gocean1.0")
props = api_config.grid_properties
# key is 'internal' or 'whole', and _loop_type is either
# 'inner' or 'outer'. The four possible combinations are
:param node: node in fparser2 parse tree.
:type node: \
:py:class:`fparser.two.Fortran2003.Logical_Literal_Constant`
:param parent: parent node of the PSyIR node we are constructing.
:type parent: :py:class:`psyclone.psyir.nodes.Node`
:returns: PSyIR representation of node.
:rtype: :py:class:`psyclone.psyir.nodes.Literal`
'''
# pylint: disable=no-self-use
boolean_type = ScalarType(ScalarType.Intrinsic.BOOLEAN,
get_literal_precision(node, parent))
value = str(node.items[0]).lower()
if value == ".true.":
return Literal("true", boolean_type, parent=parent)
if value == ".false.":
return Literal("false", boolean_type, parent=parent)
raise GenerationError(
"Expected to find '.true.' or '.false.' as fparser2 logical "
"literal, but found '{0}' instead.".format(value))
symtab = self.scope.symbol_table
try:
data_symbol = symtab.lookup_with_tag(tag)
except KeyError:
name = symtab.new_symbol_name(suggested_name)
data_symbol = DataSymbol(name, INTEGER_TYPE)
symtab.add(data_symbol, tag=tag)
self.variable = data_symbol
# Pre-initialise the Loop children # TODO: See issue #440
self.addchild(Literal("NOT_INITIALISED", INTEGER_TYPE,
parent=self)) # start
self.addchild(Literal("NOT_INITIALISED", INTEGER_TYPE,
parent=self)) # stop
self.addchild(Literal("1", INTEGER_TYPE, parent=self)) # step
self.addchild(Schedule(parent=self)) # loop body
:param node: node in fparser2 parse tree.
:type node: :py:class:`fparser.two.utils.NumberBase`
:param parent: Parent node of the PSyIR node we are constructing.
:type parent: :py:class:`psyclone.psyir.nodes.Node`
:returns: PSyIR representation of node.
:rtype: :py:class:`psyclone.psyir.nodes.Literal`
:raises NotImplementedError: if the fparser2 node is not recognised.
'''
# pylint: disable=no-self-use
if isinstance(node, Fortran2003.Int_Literal_Constant):
integer_type = ScalarType(ScalarType.Intrinsic.INTEGER,
get_literal_precision(node, parent))
return Literal(str(node.items[0]), integer_type, parent=parent)
if isinstance(node, Fortran2003.Real_Literal_Constant):
real_type = ScalarType(ScalarType.Intrinsic.REAL,
get_literal_precision(node, parent))
# Make sure any exponent is lower case
value = str(node.items[0]).lower()
# Make all exponents use the letter "e". (Fortran also
# allows "d").
value = value.replace("d", "e")
# If the value has a "." without a digit before it then
# add a "0" as the PSyIR does not allow this
# format. e.g. +.3 => +0.3
if value[0] == "." or value[0:1] in ["+.", "-."]:
value = value.replace(".", "0.")
return Literal(value, real_type, parent=parent)
# Unrecognised datatype - will result in a CodeBlock
raise NotImplementedError()
:param array: the reference that we are interested in.
:type array: :py:class:`psyir.nodes.Reference`
:param int index: the (array) reference index that we are \
interested in.
:returns: the loop bounds for this array index.
:rtype: (Literal, Literal, Literal) or \
(BinaryOperation, BinaryOperation, Literal)
:raises TransformationError: if the shape of the array's symbol is \
not supported.
'''
my_dim = array.symbol.shape[index]
if isinstance(my_dim, int):
lower_bound = Literal("1", INTEGER_TYPE)
upper_bound = Literal(str(my_dim), INTEGER_TYPE)
elif isinstance(my_dim, DataSymbol):
lower_bound = Literal("1", INTEGER_TYPE)
upper_bound = Reference(my_dim)
elif my_dim in [ArrayType.Extent.DEFERRED, ArrayType.Extent.ATTRIBUTE]:
lower_bound = BinaryOperation.create(
BinaryOperation.Operator.LBOUND, Reference(array.symbol),
Literal(str(index), INTEGER_TYPE))
upper_bound = BinaryOperation.create(
BinaryOperation.Operator.UBOUND, Reference(array.symbol),
Literal(str(index), INTEGER_TYPE))
else:
# Added import here to avoid circular dependencies.
from psyclone.psyir.transformations import TransformationError
raise TransformationError(
"Unsupported index type '{0}' found for dimension {1} of array "
# We look-up the upper bounds by enquiring about the SIZE of
# the array itself
stop = BinaryOperation(BinaryOperation.Operator.SIZE,
self)
# TODO 363 - needs to be updated once the PSyIR has support for
# Fortran derived types.
api_config = Config.get().api_conf("gocean1.0")
# Use the data property to access the member of the field that
# contains the actual grid points. The property value is a
# string with a placeholder ({0}) where the name of the field
# must go.
data = api_config.grid_properties["go_grid_data"].fortran \
.format(self.field_name)
stop.addchild(Literal(data, INTEGER_TYPE, parent=stop))
if self._loop_type == "inner":
stop.addchild(Literal("1", INTEGER_TYPE, parent=stop))
elif self._loop_type == "outer":
stop.addchild(Literal("2", INTEGER_TYPE, parent=stop))
return stop
# Loop bounds are pulled from the field object which
# is more straightforward for us but provides the
# Fortran compiler with less information.
if self._iteration_space.lower() == "go_internal_pts":
key = "internal"
elif self._iteration_space.lower() == "go_all_pts":
key = "whole"
else:
raise GenerationError("Unrecognised iteration space, '{0}'. "
"Cannot generate loop bounds.".
format(self._iteration_space))
children of the ExtractNode.
Nodes to extract can be individual constructs within an Invoke (e.g.
Loops containing a Kernel or BuiltIn call) or entire Invokes. This
functionality does not support distributed memory.
:param node_class: The Node class of which an instance will be inserted \
into the tree (defaults to ExtractNode), but can be any derived class.
:type node_class: :py:class:`psyclone.psyir.nodes.ExtractNode` or \
derived class
'''
from psyclone.psyir import nodes
from psyclone import psyGen
# The types of node that this transformation can enclose
valid_node_types = (nodes.Loop, psyGen.Kern, psyGen.BuiltIn,
psyGen.Directive, nodes.Literal, nodes.Reference)
def __init__(self, node_class=ExtractNode):
super(ExtractTrans, self).__init__(node_class=node_class)
def __str__(self):
return ("Create a sub-tree of the PSyIR that has ExtractNode "
"at its root.")
@property
def name(self):
''' Returns the name of this transformation as a string.'''
return "ExtractTrans"
def validate(self, node_list, options=None):
'''Performs validation checks specific to extract-based
transformations.
# Bounds are independent of the grid-offset convention in use
# We look-up the upper bounds by enquiring about the SIZE of
# the array itself
stop = BinaryOperation(BinaryOperation.Operator.SIZE,
self)
# TODO 363 - needs to be updated once the PSyIR has support for
# Fortran derived types.
api_config = Config.get().api_conf("gocean1.0")
# Use the data property to access the member of the field that
# contains the actual grid points. The property value is a
# string with a placeholder ({0}) where the name of the field
# must go.
data = api_config.grid_properties["go_grid_data"].fortran \
.format(self.field_name)
stop.addchild(Literal(data, INTEGER_TYPE, parent=stop))
if self._loop_type == "inner":
stop.addchild(Literal("1", INTEGER_TYPE, parent=stop))
elif self._loop_type == "outer":
stop.addchild(Literal("2", INTEGER_TYPE, parent=stop))
return stop
# Loop bounds are pulled from the field object which
# is more straightforward for us but provides the
# Fortran compiler with less information.
if self._iteration_space.lower() == "go_internal_pts":
key = "internal"
elif self._iteration_space.lower() == "go_all_pts":
key = "whole"
else:
raise GenerationError("Unrecognised iteration space, '{0}'. "