/usr/lib/python3/dist-packages/ufl/precedence.py is in python3-ufl 2016.2.0-2.
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 146 147 148 149 150 151 152 | # -*- coding: utf-8 -*-
"Precedence handling."
# Copyright (C) 2008-2016 Martin Sandve Alnæs
#
# 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
"""
|