View Javadoc
1   package visitor;
2   
3   import calculator.Expression;
4   import calculator.operations.Operation;
5   import calculator.atoms.*;
6   import calculator.atoms.visitor.AtomCaster;
7   import calculator.atoms.visitor.AtomComparator;
8   import calculator.functions.BinaryFunction;
9   import calculator.functions.UnaryFunction;
10  
11  import java.util.ArrayList;
12  
13  /**
14   * Evaluation is a concrete visitor that serves to
15   * compute and evaluate the results of arithmetic expressions.
16   */
17  public class Evaluator extends Visitor {
18  
19  	/**
20  	 * Default constructor of the class. Does not initialise anything.
21  	 */
22  	public Evaluator() {
23  	}
24  
25  	/** The result of the evaluation will be stored in this private variable */
26  	private Atom computedValue;
27  
28  	/**
29  	 * getter method to obtain the result of the evaluation
30  	 *
31  	 * @return an Integer object containing the result of the evaluation
32  	 */
33  	public Atom getResult() {
34  		return computedValue;
35  	}
36  
37  	/**
38  	 * Use the visitor design pattern to visit a Real.
39  	 *
40  	 * @param r The Real being visited
41  	 */
42  	public void visit(Real r) {
43  		computedValue = r;
44  	}
45  
46  	public void visit(IntegerAtom i) {
47  		computedValue = i;
48  	}
49  
50  	@Override
51  	public void visit(Complex c) {
52  		computedValue = c;
53  	}
54  
55  	@Override
56  	public void visit(Rationnal q) {
57  		computedValue = q;
58  	}
59  
60  	/**
61  	 * Use the visitor design pattern to visit an operation
62  	 * 
63  	 * @param o The operation being visited
64  	 */
65  	public void visit(Operation o) {
66  		ArrayList<Atom> evaluatedArgs = new ArrayList<>();
67  		// first loop to recursively evaluate each subexpression
68  		for (Expression a : o.args) {
69  			a.accept(this);
70  			evaluatedArgs.add(computedValue);
71  		}
72  		// second loop to accumulate all the evaluated subresults
73  		Atom result = evaluatedArgs.get(0);
74  		int max = evaluatedArgs.size();
75  
76  		for (int counter = 1; counter < max; counter++) {
77  			Atom other = evaluatedArgs.get(counter);
78  			// here compare the atoms to get the type to cast to
79  			AtomComparator atomComp = new AtomComparator();
80  			result.accept(atomComp);
81  			other.accept(atomComp);
82  
83  			// cast both the operand to the Atom Type to cast to
84  			AtomCaster atomCaster = new AtomCaster(atomComp.getResult());
85  			result.accept(atomCaster);
86  			result = atomCaster.getResult();
87  
88  			other.accept(atomCaster);
89  			other = atomCaster.getResult();
90  
91  			// apply the operation between the now casted Atoms
92  			result = result.apply(o, other);
93  		}
94  		// store the accumulated result
95  		computedValue = result;
96  	}
97  
98  	@Override
99  	public void visit(UnaryFunction o) {
100 		o.getArg().accept(this);
101 		computedValue = computedValue.apply(o);
102 	}
103 
104 	@Override
105 	public void visit(BinaryFunction f) {
106 		f.getFirstArg().accept(this);
107 		Atom firstValue = computedValue;
108 
109 		f.getSecondArg().accept(this);
110 		Atom secondValue = computedValue;
111 
112 		// Cast both operands to a compatible atom type before applying the function.
113 		AtomComparator atomComp = new AtomComparator();
114 		firstValue.accept(atomComp);
115 		secondValue.accept(atomComp);
116 
117 		AtomCaster atomCaster = new AtomCaster(atomComp.getResult());
118 		firstValue.accept(atomCaster);
119 		firstValue = atomCaster.getResult();
120 
121 		secondValue.accept(atomCaster);
122 		secondValue = atomCaster.getResult();
123 
124 		computedValue = firstValue.apply(f, secondValue);
125 	}
126 
127 }