package rapanui.dsl;

import java.util.Map;

import org.eclipse.emf.ecore.util.EcoreUtil;

public class Translator {
	private final Map<String, Term> dictionary;

	public Translator(Map<String, Term> dictionary) {
		this.dictionary = dictionary;
	}

	public Term translate(Term input) {
		if (input instanceof BinaryOperation)
			return translate((BinaryOperation)input);
		else if (input instanceof UnaryOperation)
			return translate((UnaryOperation)input);
		else if (input instanceof VariableReference)
			return translate((VariableReference)input);
		else if (input instanceof ConstantReference)
			return input;
		throw new IllegalStateException("Unknown term type: " + input.getClass());
	}

	public BinaryOperation translate(BinaryOperation input) {
		return Builder.createBinaryOperation(
			translate(input.getLeft()),
			input.getOperator(),
			translate(input.getRight())
		);
	}

	public UnaryOperation translate(UnaryOperation input) {
		return Builder.createUnaryOperation(translate(input.getOperand()), input.getOperator());
	}

	public Term translate(VariableReference input) {
		return EcoreUtil.copy(dictionary.get(input.getVariable()));
	}

	public Formula translate(Formula input) {
		if (input instanceof Equation)
			return translate((Equation)input);
		else if (input instanceof Inclusion)
			return translate((Inclusion)input);
		else if (input instanceof DefinitionReference)
			return translate((DefinitionReference)input);
		throw new IllegalStateException("Unknown formula type: " + input.getClass());
	}

	public Equation translate(Equation input){
		return Builder.createEquation(translate(input.getLeft()), translate(input.getRight()));
	}

	public Inclusion translate(Inclusion input) {
		return Builder.createInclusion(translate(input.getLeft()), translate(input.getRight()));
	}

	public DefinitionReference translate(DefinitionReference input) {
		return Builder.createDefinitionReference(translate(input.getTarget()), input.getDefinition());
	}
}

@@ -36,16 +36,40 @@
 til.Map;
+%0Aimport java.util.Stack;
 %0A%0Aimport
@@ -132,16 +132,35 @@
 nslator 
+implements Visitor 
 %7B%0A%09priva
@@ -197,16 +197,75 @@
 tionary;
+%0A%09private final Stack%3CTerm%3E termResult = new Stack%3CTerm%3E();
 %0A%0A%09publi
@@ -388,644 +388,343 @@
 %7B%0A%09%09
-if (input instanceof BinaryOperation)%0A%09%09%09return translate((BinaryOperation)input);%0A%09%09else if (input instanceof UnaryOperation)%0A%09%09%09return translate((UnaryOperation)input
+termResult.clear();%0A%09%09input.accept(this
 );%0A
+%0A
 %09%09
-else if (input instanceof VariableReference)%0A%09%09%09return translate((VariableReference)input);%0A%09%09else if (input instanceof ConstantReference)%0A%09%09%09return input;%0A%09%09throw new IllegalStateException(%22Unknown term type: %22 + input.getClass());%0A%09%7D%0A%0A%09public BinaryOperation translate(BinaryOperation input) %7B%0A%09%09return Builder.createBinaryOperation(%0A%09%09%09translate(input.getLeft()),%0A%09%09%09input.getOperator(),%0A%09%09%09translate(input.getR
+assert termResult.size() == 1;%0A%09%09return termResult.pop();%0A%09%7D%0A%0A%09@Override public void visit(BinaryOperation input) %7B%0A%09%09Term right = termResult.pop(), left = termResult.pop();%0A%09%09termResult.push(Builder.createBinaryOperation(left, input.getOperator(), r
 ight
-(
 ))
-%0A%09%09)
 ;%0A%09%7D%0A%0A%09
-public UnaryOperation translate
+@Override public void visit
 (Una
@@ -738,39 +738,48 @@
 tion input) %7B%0A%09%09
-return 
+termResult.push(
 Builder.createUn
@@ -796,35 +796,22 @@
 on(t
-ranslate(input.getOperand()
+ermResult.pop(
 ), i
@@ -833,36 +833,43 @@
 r())
+)
 ;%0A%09%7D%0A%0A%09
-public Term translate
+@Override public void visit
 (Var
@@ -894,23 +894,32 @@
 ut) %7B%0A%09%09
-return 
+termResult.push(
 EcoreUti
@@ -957,24 +957,127 @@
 Variable()))
+);%0A%09%7D%0A%0A%09@Override public void visit(ConstantReference input) %7B%0A%09%09termResult.push(EcoreUtil.copy(input))
 ;%0A%09%7D%0A%0A%09publi

migrate translation (of terms) to Visitor pattern