How to use the fparser.two.utils.walk_ast function in fparser

To help you get started, we’ve selected a few fparser examples, based on popular ways it is used in public projects.

Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.

github stfc / PSyclone / examples / nemo / scripts / kernels_trans.py View on Github external
def contains_unsupported_sum(fpnode):
    '''
    Examines the fparser2 parse tree represented by fpnode and returns True
    if it contains a use of the SUM intrinisc with a 'dim' argument. (If
    such a construct is included in a KERNELS region then the code produced
    by v. 18.10 of the PGI compiler seg. faults.)

    :returns: True if SUM(array(:,:), dim=blah) is found, False otherwise.
    :rtype: bool

    '''
    from fparser.two.utils import walk_ast
    from fparser.two import Fortran2003
    intrinsics = walk_ast([fpnode], [Fortran2003.Intrinsic_Function_Reference])
    for intrinsic in intrinsics:
        if str(intrinsic.items[0]).lower() == "sum":
            # If there's only one argument then we'll just have a Name
            # and not an Actual_Arg_Spec_List (in which case we don't need to
            # check for the 'dim' argument).
            if isinstance(intrinsic.items[1],
                          Fortran2003.Actual_Arg_Spec_List):
                # items[1] contains the Actual_Arg_Spec_List
                actual_args = walk_ast(intrinsic.items[1].items,
                                       [Fortran2003.Actual_Arg_Spec])
                for arg in actual_args:
                    if str(arg.items[0]).lower() == "dim":
                        return True
    return False
github stfc / PSyclone / src / psyclone / psyir / transformations / profile_trans.py View on Github external
except KeyError:
                # profile name is not supplied
                pass
        # pylint: enable=too-many-boolean-expressions

        # The checks below are only for the NEMO API and can be removed
        # once #435 is done.
        invoke = nodes[0].root.invoke
        if not isinstance(invoke, NemoInvoke):
            return
        # Get the parse tree of the routine containing this region
        # pylint: disable=protected-access
        ptree = invoke._ast
        # pylint: enable=protected-access
        # Search for the Specification_Part
        if not walk_ast([ptree], [Fortran2003.Specification_Part]):
            raise TransformationError(
                "For the NEMO API, profiling can only be added to routines "
                "which contain existing variable declarations (i.e. a "
                "Specification Part) but '{0}' does not have any.".format(
                    invoke.name))
github stfc / PSyclone / src / psyclone / parse_orig.py View on Github external
if not names:
                raise InternalError("Unsupported assignment statement: '{0}'".
                                    format(str(assign)))
            if str(names[0]) == name:
                # This is the variable declaration we're looking for
                if not isinstance(assign.items[2],
                                  Fortran2003.Array_Constructor):
                    from psyclone.parse import ParseError
                    raise ParseError(
                        "get_integer_array: RHS of assignment is not "
                        "an array constructor: '{0}'".format(str(assign)))
                # fparser2 AST for Array_Constructor is:
                # Array_Constructor('[', Ac_Value_List(',', (Name('w0'),
                #                                      Name('w1'))), ']')
                # Construct a list of the names in the array constructor
                names = walk_ast(assign.items[2].items, [Fortran2003.Name])
                if not names:
                    raise InternalError("Failed to parse array constructor: "
                                        "'{0}'".format(str(assign.items[2])))
                return [str(name) for name in names]
        return []
github stfc / PSyclone / examples / nemo / scripts / kernels_trans.py View on Github external
'''
    Checks the supplied fparser2 parse tree for calls to the RESHAPE intrinsic.
    The PGI compiler v.19.4 refuses to compile code that has such calls within
    a KERNELS region. We have to check the parse tree to allow for the use
    of RESHAPE within implicit loops which are not yet fully represented in
    the PSyIR.

    :param fpnode: fparser2 parse tree of code to check.
    :type fpnode: :py:class:`fparser.two.Fortran2003.xxx`

    :returns: True if the code fragment contains a RESHAPE call.
    :rtype: bool
    '''
    from fparser.two.utils import walk_ast
    from fparser.two import Fortran2003
    intrinsics = walk_ast([fpnode], [Fortran2003.Intrinsic_Function_Reference])
    for intrinsic in intrinsics:
        if str(intrinsic.items[0]).lower() == "reshape":
            return True
    return False
github stfc / PSyclone / src / psyclone / profiler.py View on Github external
for node in node_list[:]:
            if isinstance(node, Fortran2003.Use_Stmt) and \
               self.fortran_module == str(node.items[2]).lower():
                # Check that the use statement matches the one we would
                # insert (i.e. the code doesn't already contain a module
                # with the same name as that used by the profiling API)
                if str(node).lower() != self.use_stmt.lower():
                    raise NotImplementedError(
                        "Cannot add profiling to '{0}' because it already "
                        "'uses' a module named '{1}'".format(
                            routine_name, self.fortran_module))
                found = True
                # To make our check on name clashes below easier, remove
                # the Name nodes associated with this use from our
                # list of nodes.
                names = walk_ast([node], [Fortran2003.Name])
                for name in names:
                    node_list.remove(name)

        if not found:
            # We don't already have a use for the profiling module so
            # add one.
            reader = FortranStringReader(
                "use profile_mod, only: ProfileData, ProfileStart, ProfileEnd")
            # Tell the reader that the source is free format
            reader.set_format(FortranFormat(True, False))
            use = Fortran2003.Use_Stmt(reader)
            spec_part.content.insert(0, use)

        # Check that we won't have any name-clashes when we insert the
        # symbols required for profiling. This check uses the list of symbols
        # that we created before adding the `use profile_mod...` statement.
github stfc / PSyclone / examples / nemo / scripts / kernels_trans.py View on Github external
return False
            else:
                # Need to check for RESHAPE inside implicit loop
                if contains_reshape(enode.ast):
                    log_msg(routine_name,
                            "Implicit loop contains RESHAPE call", enode)
                    return False
            # Check for derived types. Should not have to do this as
            # derived-types should end up in CodeBlocks
            # but this does not happen for implicit loops.
            if walk_ast([node.ast], [Fortran2003.Data_Ref]):
                log_msg(routine_name, "Contains derived type", node)
                return False
            # Check for Function calls. Again, we should not have to do this
            # but currently Implicit Loops are leaves in the PSyIR.
            refs = walk_ast([node.ast], [Fortran2003.Part_Ref])
            for ref in refs:
                array_name = str(ref.items[0])
                if array_name in NEMO_FUNCTIONS:
                    log_msg(routine_name,
                            "Implicit loop contains call to function '{0}'".
                            format(array_name), node)
                    return False

        elif isinstance(enode, NemoLoop) and \
             not isinstance(enode, NemoImplicitLoop):
            # Heuristic:
            # We don't want to put loops around 3D loops into KERNELS regions
            # and nor do we want to put loops over levels into KERNELS regions
            # if they themselves contain several 2D loops.
            # In general, this heuristic will depend upon how many levels the
            # model configuration will contain.
github stfc / PSyclone / examples / nemo / eg3 / kernel_utils.py View on Github external
:rtype: bool

    '''
    from psyclone.psyGen import CodeBlock, IfBlock
    from fparser.two.utils import walk_ast
    from fparser.two import Fortran2003
    # PGI (18.10) often produces code that fails at run time if a Kernels
    # region includes If constructs.
    excluded_node_types = (CodeBlock, IfBlock)
    if node.walk(excluded_node_types):
        return False
    # Check that there are no derived-type references in the sub-tree (because
    # PGI deep-copy doesn't like them).
    # TODO #365 - this check should be part of our identification of valid
    # NEMO kernels.
    if walk_ast([node.ast], [Fortran2003.Data_Ref]):
        return False
    return True
github stfc / PSyclone / src / psyclone / alg_gen.py View on Github external
def gen(self):
        '''Return modified algorithm code.

        :returns: The modified algorithm specification as an fparser2 \
        parse tree.
        :rtype: :py:class:`fparser.two.utils.Base`

        '''

        from fparser.two.utils import walk_ast
        # pylint: disable=no-name-in-module
        from fparser.two.Fortran2003 import Call_Stmt, Section_Subscript_List

        idx = 0
        # Walk through all statements looking for procedure calls
        for statement in walk_ast(self._ast.content, [Call_Stmt]):
            # found a Fortran call statement
            call_name = str(statement.items[0])
            if call_name.lower() == self._invoke_name.lower():
                # The call statement is an invoke

                # Get the PSy callee name and argument list and
                # replace the existing algorithm invoke call with
                # these.
                psy_invoke_info = self._psy.invokes.invoke_list[idx]
                new_name = psy_invoke_info.name
                new_args = Section_Subscript_List(
                    ", ".join(psy_invoke_info.alg_unique_args))
                statement.items = (new_name, new_args)

                # The PSy-layer generates a subroutine within a module
                # so we need to add a 'use module_name, only :