2.4 Finding the Answer
The final step in the evaluation process may be the most complicated. A
function called compile was used to parse through the expression and find the
final answer. There were a number of complexities involved with this. The
function had to check if the node it was given was a leaf, if it’s branches were
leafs, if it had two branches, and if it had only one branch, if that branch was a
leaf. All of these possibilities had to be handled differently, although the manner
in which they were handled was similar. Generally, the expression was evaluated
by calling the function gencode from left to right. This had the effect of storing
the left side of expressions in the primary variable in gencode, and then allowing
the right side to use that value to evaluate the middle (the expression). The first
exception to this method of evaluation is when there is a unary operator, such as
sin 5. In this case, the expression, along with the right side, was sent to the
gencode function, where it was evaluated. The other exception involves sub-trees
on the right branch of the tree. Sub-trees in this case required that temporary
registers be created to store the outcome of some evaluations. This is necessary
because compile does not evaluate the tree linearly, but recursively. If the
outcome of right side expressions were not stored in temporary registers, then
these values would be overwritten by left side expressions. Then, when the left
side and the right side were combined, the final answer would be wrong, because
the right side value would be incorrect. Hence, an array was used to store values
in a temporary register so that all of the proper values would be maintained. The
gencode function itself was fairly simple. It took an ID and a character and used
those two, plus either it’s primary variable or a temporary register to calculate the
new value. This was stored both in the primary variable for gencode and in the
variable final_answer, which is part of the class Calculation.