package eu.wietsevenema.lang.oberon.ast.visitors.interpreter; import xtc.tree.Visitor; import eu.wietsevenema.lang.oberon.ast.declarations.RecordSelector; import eu.wietsevenema.lang.oberon.ast.expressions.AdditiveExpression; import eu.wietsevenema.lang.oberon.ast.expressions.ArraySelector; import eu.wietsevenema.lang.oberon.ast.expressions.BooleanConstant; import eu.wietsevenema.lang.oberon.ast.expressions.DivisiveExpression; import eu.wietsevenema.lang.oberon.ast.expressions.EqualityExpression; import eu.wietsevenema.lang.oberon.ast.expressions.Expression; import eu.wietsevenema.lang.oberon.ast.expressions.GreaterExpression; import eu.wietsevenema.lang.oberon.ast.expressions.GreaterOrEqualExpression; import eu.wietsevenema.lang.oberon.ast.expressions.Identifier; import eu.wietsevenema.lang.oberon.ast.expressions.IntegerConstant; import eu.wietsevenema.lang.oberon.ast.expressions.LessExpression; import eu.wietsevenema.lang.oberon.ast.expressions.LessOrEqualExpression; import eu.wietsevenema.lang.oberon.ast.expressions.LogicalConjunctiveExpression; import eu.wietsevenema.lang.oberon.ast.expressions.LogicalDisjunctiveExpression; import eu.wietsevenema.lang.oberon.ast.expressions.LogicalNegationExpression; import eu.wietsevenema.lang.oberon.ast.expressions.ModulusExpression; import eu.wietsevenema.lang.oberon.ast.expressions.MultiplicativeExpression; import eu.wietsevenema.lang.oberon.ast.expressions.NotExpression; import eu.wietsevenema.lang.oberon.ast.expressions.SubtractiveExpression; import eu.wietsevenema.lang.oberon.ast.expressions.UnaryMinExpression; import eu.wietsevenema.lang.oberon.exceptions.SymbolNotDeclaredException; import eu.wietsevenema.lang.oberon.exceptions.ValueUndefinedException; import eu.wietsevenema.lang.oberon.exceptions.VariableUndefinedException; import eu.wietsevenema.lang.oberon.interpreter.InterpreterScope; import eu.wietsevenema.lang.oberon.interpreter.ValueReference; import eu.wietsevenema.lang.oberon.interpreter.values.BooleanValue; import eu.wietsevenema.lang.oberon.interpreter.values.IntegerValue; import eu.wietsevenema.lang.oberon.interpreter.values.Value; public class ExpressionEvaluator extends Visitor { InterpreterScope scope; public ExpressionEvaluator(InterpreterScope scope) { this.scope = scope; } public IntegerValue visit(AdditiveExpression ae) throws ClassCastException, ValueUndefinedException { try { Integer left = ((IntegerValue) dispatch(ae.getLeft())).getValue(); Integer right = ((IntegerValue) dispatch(ae.getRight())).getValue(); return new IntegerValue(left + right); } catch (ValueUndefinedException e) { throw new ValueUndefinedException("Value undefined at " + ae.getLocation()); } } public IntegerValue visit(SubtractiveExpression se) throws ValueUndefinedException { Integer left = ((IntegerValue) dispatch(se.getLeft())).getValue(); Integer right = ((IntegerValue) dispatch(se.getRight())).getValue(); return new IntegerValue(left - right); } public BooleanValue visit(BooleanConstant bc) { return new BooleanValue(bc.getValue()); } public BooleanValue visit(GreaterOrEqualExpression ee) throws ValueUndefinedException { Integer left = ((IntegerValue) dispatch(ee.getLeft())).getValue(); Integer right = ((IntegerValue) dispatch(ee.getRight())).getValue(); return new BooleanValue(left >= right); } public BooleanValue visit(GreaterExpression ee) throws ValueUndefinedException { Integer left = ((IntegerValue) dispatch(ee.getLeft())).getValue(); Integer right = ((IntegerValue) dispatch(ee.getRight())).getValue(); return new BooleanValue(left > right); } public BooleanValue visit(LessOrEqualExpression ee) throws ValueUndefinedException { Integer left = ((IntegerValue) dispatch(ee.getLeft())).getValue(); Integer right = ((IntegerValue) dispatch(ee.getRight())).getValue(); return new BooleanValue(left <= right); } public BooleanValue visit(NotExpression ee) throws ValueUndefinedException { Integer left = ((IntegerValue) dispatch(ee.getLeft())).getValue(); Integer right = ((IntegerValue) dispatch(ee.getRight())).getValue(); return new BooleanValue(left != right); } public BooleanValue visit(LessExpression ee) throws ValueUndefinedException { Integer left = ((IntegerValue) dispatch(ee.getLeft())).getValue(); Integer right = ((IntegerValue) dispatch(ee.getRight())).getValue(); return new BooleanValue(left < right); } public BooleanValue visit(EqualityExpression ee) throws ValueUndefinedException { Integer left = ((IntegerValue) dispatch(ee.getLeft())).getValue(); Integer right = ((IntegerValue) dispatch(ee.getRight())).getValue(); return new BooleanValue(left == right); } public BooleanValue visit(LogicalConjunctiveExpression lce) throws ValueUndefinedException { return new BooleanValue(((BooleanValue) dispatch(lce.getLeft())).getValue() && ((BooleanValue) dispatch(lce.getRight())).getValue()); } public BooleanValue visit(LogicalDisjunctiveExpression lde) throws ValueUndefinedException { return new BooleanValue(((BooleanValue) dispatch(lde.getLeft())).getValue() || ((BooleanValue) dispatch(lde.getRight())).getValue()); } public BooleanValue visit(LogicalNegationExpression lne) throws ValueUndefinedException { Expression exp = lne.getChild(); Boolean value = ((BooleanValue) dispatch(exp)).getValue(); return new BooleanValue(!value); } public IntegerValue visit(MultiplicativeExpression me) throws ValueUndefinedException { Integer left = ((IntegerValue) dispatch(me.getLeft())).getValue(); Integer right = ((IntegerValue) dispatch(me.getRight())).getValue(); Integer result = left * right; return new IntegerValue(result); } public IntegerValue visit(DivisiveExpression de) throws ValueUndefinedException { Integer left = ((IntegerValue) dispatch(de.getLeft())).getValue(); Integer right = ((IntegerValue) dispatch(de.getRight())).getValue(); Integer result = (int) (left / right); return new IntegerValue(result); } public IntegerValue visit(ModulusExpression me) throws ValueUndefinedException { Integer left = ((IntegerValue) dispatch(me.getLeft())).getValue(); Integer right = ((IntegerValue) dispatch(me.getRight())).getValue(); Integer result = (int) (left % right); return new IntegerValue(result); } public Value visit(ArraySelector as) { ValueReferenceResolver resolver = new ValueReferenceResolver(scope); ValueReference result = (ValueReference) resolver.dispatch(as); return result.getValue(); } public Value visit(RecordSelector rs) { ValueReferenceResolver resolver = new ValueReferenceResolver(scope); ValueReference result = (ValueReference) resolver.dispatch(rs); return result.getValue(); } public IntegerValue visit(UnaryMinExpression um) { IntegerValue result = (IntegerValue) dispatch(um.getChild()); return result; } public IntegerValue visit(IntegerConstant ic) { return new IntegerValue(ic.getValue()); } public Value visit(Identifier id) throws VariableUndefinedException, SymbolNotDeclaredException { Value result = (Value) this.scope.lookupValue(id.getName()); if (result == null) { throw new VariableUndefinedException(id.getName() + "undefined."); } return result; } }