blob: b92565d4e156aa2d6ffb3967ce2365b151e99855 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 itemis AG (http://www.itemis.eu) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.eclipse.xtext.example.arithmetics.interpreter;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Map;
import org.eclipse.xtext.example.arithmetics.arithmetics.ArithmeticsPackage;
import org.eclipse.xtext.example.arithmetics.arithmetics.DeclaredParameter;
import org.eclipse.xtext.example.arithmetics.arithmetics.Definition;
import org.eclipse.xtext.example.arithmetics.arithmetics.Div;
import org.eclipse.xtext.example.arithmetics.arithmetics.Expression;
import org.eclipse.xtext.example.arithmetics.arithmetics.FunctionCall;
import org.eclipse.xtext.example.arithmetics.arithmetics.Minus;
import org.eclipse.xtext.example.arithmetics.arithmetics.Multi;
import org.eclipse.xtext.example.arithmetics.arithmetics.NumberLiteral;
import org.eclipse.xtext.example.arithmetics.arithmetics.Plus;
import org.eclipse.xtext.util.PolymorphicDispatcher;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
/**
* an interpreter for instances of EClasses of the {@link ArithmeticsPackage}.
*
* It internally uses a polymorphic dispatcher to dispatch between the implementations for the different EClasses.
*
* @author Sven Efftinge - initial contribution and API
*/
public class Calculator {
private PolymorphicDispatcher<BigDecimal> dispatcher = PolymorphicDispatcher.createForSingleTarget("internalEvaluate", 2, 2, this);
public BigDecimal evaluate(Expression obj) {
return evaluate(obj, ImmutableMap.<String,BigDecimal>of());
}
public BigDecimal evaluate(Expression obj, ImmutableMap<String,BigDecimal> values) {
BigDecimal invoke = dispatcher.invoke(obj, values);
return invoke;
}
protected BigDecimal internalEvaluate(Expression e, ImmutableMap<String,BigDecimal> values) {
throw new UnsupportedOperationException(e.toString());
}
protected BigDecimal internalEvaluate(NumberLiteral e, ImmutableMap<String,BigDecimal> values) {
return e.getValue();
}
protected BigDecimal internalEvaluate(FunctionCall e, ImmutableMap<String,BigDecimal> values) {
if (e.getFunc() instanceof DeclaredParameter) {
return values.get(e.getFunc().getName());
}
Definition d = (Definition) e.getFunc();
Map<String,BigDecimal> params = Maps.newHashMap();
for (int i=0; i<e.getArgs().size();i++) {
DeclaredParameter declaredParameter = d.getArgs().get(i);
BigDecimal evaluate = evaluate(e.getArgs().get(i), values);
params.put(declaredParameter.getName(), evaluate);
}
return evaluate(d.getExpr(),ImmutableMap.copyOf(params));
}
protected BigDecimal internalEvaluate(Plus plus, ImmutableMap<String,BigDecimal> values) {
return evaluate(plus.getLeft(),values).add(evaluate(plus.getRight(),values));
}
protected BigDecimal internalEvaluate(Minus minus, ImmutableMap<String,BigDecimal> values) {
return evaluate(minus.getLeft(),values).subtract(evaluate(minus.getRight(),values));
}
protected BigDecimal internalEvaluate(Div div, ImmutableMap<String,BigDecimal> values) {
BigDecimal left = evaluate(div.getLeft(),values);
BigDecimal right = evaluate(div.getRight(),values);
return left.divide(right,20,RoundingMode.HALF_UP);
}
protected BigDecimal internalEvaluate(Multi multi, ImmutableMap<String,BigDecimal> values) {
return evaluate(multi.getLeft(),values).multiply(evaluate(multi.getRight(),values));
}
}