@Override public Value binary(Term.BinaryOperator operator, Term left, Term right) { Value leftValue = left.accept(this); Value rightValue = right.accept(this); double l = leftValue.accept(extractNumber); double r = rightValue.accept(extractNumber); switch (operator) { case add: return values.number(l + r); case sub: return values.number(l - r); case mult: return values.number(l * r); case div: return values.number(l / r); default: throw new RuntimeException("Unknown operator: " + operator); } }
@Override public Value match(final String typeName, final Map<String, Term.Case> cases, Term term) { Value value = term.accept(this); return value.accept( new Value.Visitor<Value>() { @Override public Value number(double value) { throw new RuntimeException("Expected sum type"); } @Override public Value record(String typeName, Map<String, Value> fields) { throw new RuntimeException("Expected sum type"); } @Override public Value constructor(String sumTypeName, String constructorName, Value value) { if (!sumTypeName.equals(typeName)) { throw new RuntimeException( "Wrong sum type constructor (found " + sumTypeName + " but expected " + typeName + ")"); } Term.Case target = cases.get(constructorName); if (target == null) { throw new RuntimeException("No such constructor: " + constructorName); } if (target.variableName != null) { Value oldValue = environment.get(target.variableName); Value result = target.body.accept(Evaluator.this); environment.put(target.variableName, oldValue); return result; } else { return target.body.accept(Evaluator.this); } } }); }