Example #1
0
def test_outer_index_idx():
    '''Check that when given an array reference the internal
    get_outer_index() function returns the outermost index of the
    array that is a range.

    '''
    _, invoke_info = get_invoke("implicit_do.f90", api=API, idx=0)
    schedule = invoke_info.schedule
    assignment = schedule[0]
    array_ref = assignment.lhs
    assert get_outer_index(array_ref) == 2
Example #2
0
def test_outer_index_error():
    '''Check that when given an array reference the internal
    get_outer_index() function returns an IndexError exception if
    there are no ranges in the array indices.

    '''
    _, invoke_info = get_invoke("explicit_do.f90", api=API, idx=0)
    schedule = invoke_info.schedule
    assignments = schedule.walk(Assignment)
    assert len(assignments) == 1
    assignment = assignments[0]
    array_ref = assignment.lhs
    with pytest.raises(IndexError):
        _ = get_outer_index(array_ref)
Example #3
0
    def validate(self, node, options=None):
        '''Perform various checks to ensure that it is valid to apply the
        NemoOuterArrayRange2LoopTrans transformation to the supplied
        PSyIR Node.

        :param node: the node that is being checked.
        :type node: :py:class:`psyclone.psyir.nodes.Assignment`
        :param options: a dictionary with options for \
            transformations. No options are used in this \
            transformation. This is an optional argument that defaults \
            to None.
        :type options: dict of string:values or None

        :raises TransformationError: if the supplied node is not an \
            Assignment node, if the Assignment node does not have an \
            Array-type Reference node on its left hand side or if the \
            Array-type node does not contain at least one Range \
            node.

        '''
        # Am I an assignment node?
        if not isinstance(node, Assignment):
            raise TransformationError(
                "Error in NemoOuterArrayRange2LoopTrans transformation. The "
                "supplied node argument should be a PSyIR Assignment, but "
                "found '{0}'.".format(type(node).__name__))

        # Is the LHS an array reference?
        if not isinstance(node.lhs,
                          (ArrayReference, ArrayOfStructuresReference)):
            raise TransformationError(
                "Error in NemoOuterArrayRange2LoopTrans transformation. The "
                "supplied assignment node should have either an ArrayReference"
                " or an ArrayOfStructuresReference node on its lhs but found "
                "'{0}'.".format(type(node.lhs).__name__))
        array_reference = node.lhs
        # Has the array reference got a range?
        try:
            _ = get_outer_index(array_reference)
        except IndexError as error:
            message = (
                "Error in NemoOuterArrayRange2LoopTrans transformation. The "
                "LHS of the supplied assignment node should be an "
                "ArrayReference/ArrayOfStructuresReference node containing at "
                "least one Range node but there are none.")
            six.raise_from(TransformationError(message), error)
Example #4
0
    def apply(self, node, options=None):
        '''Apply the NemoOuterArrayRange2Loop transformation to the specified
        node if the node is an Assignment and the left-hand-side of
        the assignment is an Array Reference containing at least one
        Range node specifying an access to an array index. If this is
        the case then the outermost Range nodes within array
        references within the assignment are replaced with references
        to a loop index. A NemoLoop loop (with the same loop index) is
        also placed around the modified assignment statement. If the
        array reference on the left-hand-side of the assignment only
        had one range node as an index (so now has none) then the
        assigment is also placed within a NemoKern.

        The name of the loop index is taken from the PSyclone
        configuration file if a name exists for the particular array
        index, otherwise a new name is generated. The bounds of the
        loop are taken from the Range node if they are provided. If
        not, the loop bounds are taken from the PSyclone configuration
        file if bounds values are supplied. If not, the LBOUND or
        UBOUND intrinsics are used as appropriate. The type of the
        NemoLoop is also taken from the configuration file if it is
        supplied for that index, otherwise it is specified as being
        "unknown".

        :param node: an Assignment node.
        :type node: :py:class:`psyclone.psyir.nodes.Assignment`
        :param options: a dictionary with options for \
            transformations. No options are used in this \
            transformation. This is an optional argument that defaults \
            to None.
        :type options: dict of string:values or None

        '''
        self.validate(node)

        # get lhs array
        lhs_array_ref = node.lhs
        index = get_outer_index(lhs_array_ref)
        nemo_arrayrange2loop = NemoArrayRange2LoopTrans()
        nemo_arrayrange2loop.apply(lhs_array_ref.children[index])