This file is indexed.

/usr/lib/python2.7/dist-packages/ufl/precedence.py is in python-ufl 1.6.0-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
"Precedence handling."

# Copyright (C) 2008-2014 Martin Sandve Alnes
#
# This file is part of UFL.
#
# UFL is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# UFL is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with UFL. If not, see <http://www.gnu.org/licenses/>.

from ufl.log import warning
from six import iteritems

# FIXME: This code is crap...

def parstr(child, parent, pre="(", post=")", format=str):
    # Execute when needed instead of on import,
    # which leads to all kinds of circular trouble.
    # Fixing this could be an optimization of str(expr) though.
    if not hasattr(parent, '_precedence'):
        assign_precedences(build_precedence_list())

    # We want child to be evaluated fully first,
    # and if the parent has higher precedence
    # we later wrap in ().
    s = format(child)

    # Operators where operands are always parenthesized because precedence is not defined below
    if parent._precedence == 0:
        return pre + s + post

    # If parent operator binds stronger than child, must parenthesize child
    # FIXME: Is this correct for all possible positions of () in a + b + c?
    # FIXME: Left-right rule
    if parent._precedence > child._precedence: # parent = indexed, child = terminal
        return pre + s + post

    # Nothing needed
    return s

def build_precedence_list():
    from ufl.classes import Operator, Terminal, Sum, IndexSum, Product, Division, Power, MathFunction, BesselFunction, Abs, Indexed

    # TODO: Fill in other types...
    #Power <= Transposed

    precedence_list = []
    # Default operator behaviour: should always add parentheses
    precedence_list.append((Operator,))

    precedence_list.append((Sum,))

    # sum_i a + b = (sum_i a) + b != sum_i (a + b), sum_i binds stronger than +, but weaker than product
    precedence_list.append((IndexSum,))

    precedence_list.append((Product, Division,))

    # NB! Depends on language!
    precedence_list.append((Power, MathFunction, BesselFunction, Abs))

    precedence_list.append((Indexed,))

    # Default terminal behaviour: should never add parentheses
    precedence_list.append((Terminal,))
    return precedence_list

def build_precedence_mapping(precedence_list):
    """Given a precedence list, build a dict with class->int mappings.
    Utility function used by some external code.
    """
    from ufl.classes import Expr, all_ufl_classes, abstract_classes
    pm = {}
    missing = set()
    # Assign integer values for each precedence level
    k = 0
    for p in precedence_list:
        for c in p:
            pm[c] = k
        k += 1
    # Check for missing classes, fill in subclasses
    for c in all_ufl_classes:
        if c not in abstract_classes and c not in pm:
            b = c.__bases__[0]
            while b is not Expr:
                if b in pm:
                    pm[c] = pm[b]
                    break
                b = b.__bases__[0]
            if c not in pm:
                missing.add(c)
    return pm, missing

def assign_precedences(precedence_list):
    "Given a precedence list, assign ints to class._precedence."
    pm, missing = build_precedence_mapping(precedence_list)
    for c, p in sorted(iteritems(pm), key=lambda x: x[0].__name__):
        c._precedence = p
    if missing:
        msg = "Missing precedence levels for classes:\n" +\
            "\n".join('  %s' % c for c in sorted(missing))
        warning(msg)


"""
# Code from uflacs:
import ufl

def build_precedence_list():
    "Builds a list of operator types by precedence order in the C language."
    # FIXME: Add all types we need here.
    pl = []
    pl.append((ufl.classes.Conditional,))
    pl.append((ufl.classes.OrCondition,))
    pl.append((ufl.classes.AndCondition,))
    pl.append((ufl.classes.EQ, ufl.classes.NE))
    pl.append((ufl.classes.Condition,))  # <,>,<=,>=
    pl.append((ufl.classes.NotCondition,))  # FIXME
    pl.append((ufl.classes.Sum,))
    pl.append((ufl.classes.Product, ufl.classes.Division,))
    # The highest precedence items will never need
    # parentheses around them or their operands
    pl.append((ufl.classes.Power, ufl.classes.MathFunction, ufl.classes.Abs, ufl.classes.BesselFunction,
               ufl.classes.Indexed, ufl.classes.Grad,
               ufl.classes.PositiveRestricted, ufl.classes.NegativeRestricted,
               ufl.classes.Terminal))
    # FIXME: Write a unit test that checks this list against all ufl classes
    return pl

def build_precedence_map():
    from ufl.precedence import build_precedence_mapping
    pm, missing = build_precedence_mapping(build_precedence_list())
    if 0 and missing:  # Enable to see which types we are missing
        print("Missing precedence levels for the types:")
        print("\n".join('  %s' % c for c in missing))
    return pm
"""