Spaces:
Sleeping
Sleeping
# 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 |