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