Spaces:
Running
Running
File size: 3,970 Bytes
f50d9d6 |
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 |
# Simplify tree
function combineOperators(tree::Node)::Node
# NOTE: (const (+*-) const) already accounted for. Call simplifyTree before.
# ((const + var) + const) => (const + var)
# ((const * var) * const) => (const * var)
# ((const - var) - const) => (const - var)
# (want to add anything commutative!)
# TODO - need to combine plus/sub if they are both there.
if tree.degree == 0
return tree
elseif tree.degree == 1
tree.l = combineOperators(tree.l)
elseif tree.degree == 2
tree.l = combineOperators(tree.l)
tree.r = combineOperators(tree.r)
end
top_level_constant = tree.degree == 2 && (tree.l.constant || tree.r.constant)
if tree.degree == 2 && (binops[tree.op] === mult || binops[tree.op] === plus) && top_level_constant
op = tree.op
# Put the constant in r. Need to assume var in left for simplification assumption.
if tree.l.constant
tmp = tree.r
tree.r = tree.l
tree.l = tmp
end
topconstant = tree.r.val
# Simplify down first
below = tree.l
if below.degree == 2 && below.op == op
if below.l.constant
tree = below
tree.l.val = binops[op](tree.l.val, topconstant)
elseif below.r.constant
tree = below
tree.r.val = binops[op](tree.r.val, topconstant)
end
end
end
if tree.degree == 2 && binops[tree.op] === sub && top_level_constant
# Currently just simplifies subtraction. (can't assume both plus and sub are operators)
# Not commutative, so use different op.
if tree.l.constant
if tree.r.degree == 2 && binops[tree.r.op] === sub
if tree.r.l.constant
#(const - (const - var)) => (var - const)
l = tree.l
r = tree.r
simplified_const = -(l.val - r.l.val) #neg(sub(l.val, r.l.val))
tree.l = tree.r.r
tree.r = l
tree.r.val = simplified_const
elseif tree.r.r.constant
#(const - (var - const)) => (const - var)
l = tree.l
r = tree.r
simplified_const = l.val + r.r.val #plus(l.val, r.r.val)
tree.r = tree.r.l
tree.l.val = simplified_const
end
end
else #tree.r.constant is true
if tree.l.degree == 2 && binops[tree.l.op] === sub
if tree.l.l.constant
#((const - var) - const) => (const - var)
l = tree.l
r = tree.r
simplified_const = l.l.val - r.val#sub(l.l.val, r.val)
tree.r = tree.l.r
tree.l = r
tree.l.val = simplified_const
elseif tree.l.r.constant
#((var - const) - const) => (var - const)
l = tree.l
r = tree.r
simplified_const = r.val + l.r.val #plus(r.val, l.r.val)
tree.l = tree.l.l
tree.r.val = simplified_const
end
end
end
end
return tree
end
# Simplify tree
function simplifyTree(tree::Node)::Node
if tree.degree == 1
tree.l = simplifyTree(tree.l)
if tree.l.degree == 0 && tree.l.constant
return Node(unaops[tree.op](tree.l.val))
end
elseif tree.degree == 2
tree.l = simplifyTree(tree.l)
tree.r = simplifyTree(tree.r)
constantsBelow = (
tree.l.degree == 0 && tree.l.constant &&
tree.r.degree == 0 && tree.r.constant
)
if constantsBelow
return Node(binops[tree.op](tree.l.val, tree.r.val))
end
end
return tree
end |