How to use the fparser.two.utils.walk 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 / src / psyclone / psyir / frontend / fparser2.py View on Github external
# sanity check the readers and writers we identify.
        all_array_refs = {}

        # Loop over a flat list of all the nodes in the supplied region
        for node in walk(nodes):

            if isinstance(node, Assignment_Stmt):
                # Found lhs = rhs
                structure_name_str = None

                lhs = node.items[0]
                rhs = node.items[2]
                # Do RHS first as we cull readers after writers but want to
                # keep a = a + ... as the RHS is computed before assigning
                # to the LHS
                for node2 in walk(rhs):
                    if isinstance(node2, Part_Ref):
                        name = node2.items[0].string
                        if name.upper() not in FORTRAN_INTRINSICS:
                            if name not in writers:
                                readers.add(name)
                    if isinstance(node2, Data_Ref):
                        # TODO we need a robust implementation - issue #309.
                        raise NotImplementedError(
                            "get_inputs_outputs: derived-type references on "
                            "the RHS of assignments are not yet supported.")
                # Now do LHS
                if isinstance(lhs, Data_Ref):
                    # This is a structure which contains an array access.
                    structure_name_str = lhs.items[0].string
                    writers.add(structure_name_str)
                    lhs = lhs.items[1]
github stfc / PSyclone / src / psyclone / parse / algorithm.py View on Github external
lhs = create_var_name(lhs)
            rhs = str(designator.items[2])
            var_name = "{0}_{1}".format(lhs, rhs)
            var_name = var_name.lower()
            arguments.append(Arg('indexed_variable', full_text, var_name))
        elif isinstance(argument, Data_Ref):
            # A structure dereference e.g. base%arg, base%arg(n)
            full_text = argument.tostr().lower()
            var_name = create_var_name(argument).lower()
            arguments.append(Arg('variable', full_text, var_name))
        elif isinstance(argument, (Level_2_Unary_Expr, Add_Operand,
                                   Parenthesis)):
            # An expression e.g. -1, 1*n, ((1*n)/m). Note, for some
            # reason Add_Operation represents binary expressions in
            # fparser2.  Walk the tree to look for an argument.
            if not walk(argument, Name):
                # This is a literal so store the full expression as a
                # string
                arguments.append(Arg('literal', argument.tostr().lower()))
            else:
                raise NotImplementedError(
                    "algorithm.py:get_kernel: Expressions containing "
                    "variables are not yet supported '{0}', value '{1}', "
                    "kernel '{2}' in file '{3}'.".format(
                        type(argument), str(argument), parse_tree,
                        alg_filename))
        else:
            raise InternalError(
                "algorithm.py:get_kernel: Unsupported argument structure "
                "'{0}', value '{1}', kernel '{2}' in file '{3}'.".format(
                    type(argument), str(argument), parse_tree, alg_filename))
github stfc / PSyclone / src / psyclone / nemo.py View on Github external
self.invoke_map = {}
        self.invoke_list = []
        # Keep a pointer to the whole fparser2 AST
        self._ast = ast

        # TODO #737 - this routine should really process generic PSyIR to
        # create domain-specific PSyIR (D-PSyIR) for the NEMO domain.
        # Use the fparser2 frontend to construct the PSyIR from the parse tree
        processor = NemoFparser2Reader()
        # First create a Container representing any Fortran module
        # contained in the parse tree.
        self._container = processor.generate_container(ast)

        # Find all the subroutines contained in the file
        routines = walk(ast.content, (Subroutine_Subprogram,
                                      Function_Subprogram))
        # Add the main program as a routine to analyse - take care
        # here as the Fortran source file might not contain a
        # main program (might just be a subroutine in a module)
        main_prog = get_child(ast, Main_Program)
        if main_prog:
            routines.append(main_prog)

        # Analyse each routine we've found
        for subroutine in routines:
            # Get the name of this subroutine, program or function
            substmt = subroutine.content[0]
            if isinstance(substmt, Function_Stmt):
                for item in substmt.items:
                    if isinstance(item, Name):
                        sub_name = str(item)
github stfc / PSyclone / src / psyclone / psyir / frontend / fparser2.py View on Github external
ArgumentInterface.Access.READWRITE)
                arg_symbols.append(symbol)
            # Now that we've updated the Symbols themselves, set the
            # argument list
            parent.symbol_table.specify_argument_list(arg_symbols)
        except KeyError:
            raise InternalError("The kernel argument "
                                "list '{0}' does not match the variable "
                                "declarations for fparser nodes {1}."
                                "".format(str(arg_list), nodes))

        # fparser2 does not always handle Statement Functions correctly, this
        # loop checks for Stmt_Functions that should be an array statement
        # and recovers them, otherwise it raises an error as currently
        # Statement Functions are not supported in PSyIR.
        for stmtfn in walk(nodes, Fortran2003.Stmt_Function_Stmt):
            (fn_name, arg_list, scalar_expr) = stmtfn.items
            try:
                symbol = parent.symbol_table.lookup(fn_name.string.lower())
                if symbol.is_array:
                    # This is an array assignment wrongly categorized as a
                    # statement_function by fparser2.
                    array_name = fn_name
                    array_subscript = arg_list.items

                    assignment_rhs = scalar_expr

                    # Create assingment node
                    assignment = Assignment(parent=parent)
                    parent.addchild(assignment)

                    # Build lhs
github stfc / PSyclone / src / psyclone / nemo.py View on Github external
#   array(1,:,:) = a_func(array2(:,:,:), mask(:,:))
        # where a_func is an array-valued function and `array2(:,:,:)`
        # could just be `array2`.
        # We check the left-hand side...
        lhs = node.items[0]
        if not isinstance(lhs, Fortran2003.Part_Ref):
            # LHS is not an array reference
            return False
        colons = walk(lhs.items, Fortran2003.Subscript_Triplet)
        if not colons:
            # LHS does not use array syntax
            return False
        # Now check the right-hand side...
        rhs = node.items[2]
        try:
            if not walk(rhs.items, Fortran2003.Subscript_Triplet):
                # We don't have any array syntax on the RHS
                return True
        except AttributeError:
            # The RHS doesn't have the `items` attribute (it may be just
            # a Name for instance).
            return True
        # Check that we haven't got array syntax used within the index
        # expression to another array. Array references are represented by
        # Part_Ref nodes in the fparser2 AST.
        # Find all array references
        array_refs = walk(rhs, Fortran2003.Part_Ref)
        for ref in array_refs:
            nested_refs = walk(ref.items, Fortran2003.Part_Ref)
            # Do any of these nested array references use array syntax?
            for nested_ref in nested_refs:
                colons = walk(nested_ref.items, Fortran2003.Subscript_Triplet)
github stfc / PSyclone / src / psyclone / nemo.py View on Github external
# We don't have any array syntax on the RHS
                return True
        except AttributeError:
            # The RHS doesn't have the `items` attribute (it may be just
            # a Name for instance).
            return True
        # Check that we haven't got array syntax used within the index
        # expression to another array. Array references are represented by
        # Part_Ref nodes in the fparser2 AST.
        # Find all array references
        array_refs = walk(rhs, Fortran2003.Part_Ref)
        for ref in array_refs:
            nested_refs = walk(ref.items, Fortran2003.Part_Ref)
            # Do any of these nested array references use array syntax?
            for nested_ref in nested_refs:
                colons = walk(nested_ref.items, Fortran2003.Subscript_Triplet)
                if colons:
                    return False
        return True
github stfc / PSyclone / src / psyclone / psyir / nodes / psy_data_node.py View on Github external
for node in node_list[:]:
            if isinstance(node, Fortran2003.Use_Stmt) and \
               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 PSyData API)
                if str(node).lower() != self.use_stmt.lower():
                    raise NotImplementedError(
                        "Cannot add PSyData calls to '{0}' because it "
                        "already 'uses' a module named '{1}'".format(
                            routine_name, 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([node], Fortran2003.Name)
                for name in names:
                    node_list.remove(name)

        if not found:
            # We don't already have a use for the PSyData module so
            # add one.
            reader = FortranStringReader(
                "use {0}, only: {1}"
                .format(self.add_psydata_class_prefix("psy_data_mod"),
                        self.add_psydata_class_prefix("PSyDataType")))
            # 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
github stfc / PSyclone / src / psyclone / nemo.py View on Github external
def __init__(self, ast):
        # pylint: disable=super-init-not-called
        names = walk(ast.content, Fortran2003.Name)
        # The name of the program unit will be the first in the list
        if not names:
            raise InternalError("Found no names in supplied Fortran - should "
                                "be impossible!")
        self._name = str(names[0]) + "_psy"
        self._invokes = NemoInvokes(ast)
        self._ast = ast
github stfc / PSyclone / src / psyclone / psyir / frontend / fparser2.py View on Github external
symbol_table = _get_symbol_table(psyir_parent)

        if not isinstance(type_spec.items[1], Fortran2003.Kind_Selector):
            # No precision is specified
            return None

        kind_selector = type_spec.items[1]

        if (isinstance(kind_selector.children[0], str) and
                kind_selector.children[0] == "*"):
            # Precision is provided in the form *N
            precision = int(str(kind_selector.children[1]))
            return precision

        # Precision is supplied in the form "kind=..."
        intrinsics = walk(kind_selector.items,
                          Fortran2003.Intrinsic_Function_Reference)
        if intrinsics and isinstance(intrinsics[0].items[0],
                                     Fortran2003.Intrinsic_Name) and \
           str(intrinsics[0].items[0]).lower() == "kind":
            # We have kind=KIND(X) where X may be of any intrinsic type. It
            # may be a scalar or an array. items[1] is an
            # Actual_Arg_Spec_List with the first entry being the argument.
            kind_arg = intrinsics[0].items[1].items[0]

            # We currently only support integer and real literals as
            # arguments to KIND
            if isinstance(kind_arg, (Fortran2003.Int_Literal_Constant,
                                     Fortran2003.Real_Literal_Constant)):
                return get_literal_precision(kind_arg, psyir_parent)

            raise NotImplementedError(