# Source code for ufl_legacy.formatting.printing

    # -*- coding: utf-8 -*-
    """A collection of utility algorithms for printing
    of UFL objects, mostly intended for debugging purposes."""

    # Copyright (C) 2008-2016 Martin Sandve Alnæs
    #
    # This file is part of UFL (https://www.fenicsproject.org)
    #
    # SPDX-License-Identifier:    LGPL-3.0-or-later
    #
    # Modified by Anders Logg 2009, 2014

    from ufl_legacy.log import error
    from ufl_legacy.core.expr import Expr
    from ufl_legacy.form import Form
    from ufl_legacy.integral import Integral

    # --- Utilities for constructing informative strings from UFL objects

    def integral_info(integral):
        if not isinstance(integral, Integral):
            error("Expecting an Integral.")
        s = "  Integral:\n"
        s += "    Type:\n"
        s += "      %s\n" % integral.integral_type()
        s += "    Domain:\n"
        s += "      %s\n" % integral.ufl_domain()
        s += "    Domain id:\n"
        s += "      %s\n" % integral.subdomain_id()
        s += "    Domain data:\n"
        s += "      %s\n" % integral.subdomain_data()
        s += "    Compiler metadata:\n"
        s += "      %s\n" % integral.metadata()
        return s

    def form_info(form):
        if not isinstance(form, Form):
            error("Expecting a Form.")

        bf = form.arguments()
        cf = form.coefficients()

        s = "Form info:\n"
        s += "  rank:                          %d\n" % len(bf)
        s += "  num_coefficients:              %d\n" % len(cf)
        s += "\n"

        for f in cf:
            if f._name:
                s += "\n"
                s += "  Coefficient %d is named '%s'" % (f._count, f._name)
        s += "\n"

        integrals = form.integrals()
        integral_types = sorted(set(itg.integral_type() for itg in integrals))
        for integral_type in integral_types:
            itgs = form.integrals_by_type(integral_type)
            s += "  num_{0}_integrals:  {1}\n".format(integral_type, len(itgs))
        s += "\n"

        for integral_type in integral_types:
            itgs = form.integrals_by_type(integral_type)
            for itg in itgs:
                s += integral_info(itg)
                s += "\n"

        return s

    def _indent_string(n):
        return "    " * n

    def _tree_format_expression(expression, indentation, parentheses):
        ind = _indent_string(indentation)
        if expression._ufl_is_terminal_:
            s = "%s%s" % (ind, repr(expression))
        else:
            sops = [_tree_format_expression(o, indentation + 1, parentheses) for o in expression.ufl_operands]
            s = "%s%s\n" % (ind, expression._ufl_class_.__name__)
            if parentheses and len(sops) > 1:
                s += "%s(\n" % (ind,)
            s += "\n".join(sops)
            if parentheses and len(sops) > 1:
                s += "\n%s)" % (ind,)
        return s

    def tree_format(expression, indentation=0, parentheses=True):
        s = ""

        if isinstance(expression, Form):
            form = expression
            integrals = form.integrals()
            integral_types = sorted(set(itg.integral_type() for itg in integrals))
            itgs = []
            for integral_type in integral_types:
                itgs += list(form.integrals_by_type(integral_type))

            ind = _indent_string(indentation)
            s += ind + "Form:\n"
            s += "\n".join(tree_format(itg, indentation + 1, parentheses) for itg in itgs)

        elif isinstance(expression, Integral):
            ind = _indent_string(indentation)
            s += ind + "Integral:\n"
            ind = _indent_string(indentation + 1)
            s += ind + "integral type: %s\n" % expression.integral_type()
            s += ind + "subdomain id: %s\n" % expression.subdomain_id()
            s += ind + "integrand:\n"
            s += tree_format(expression._integrand, indentation + 2, parentheses)

        elif isinstance(expression, Expr):
            s += _tree_format_expression(expression, indentation, parentheses)

        else:
            error("Invalid object type %s" % type(expression))

        return s