package rapanui.dsl;

import java.util.Stack;

public class Serializer implements Visitor {
	private static final Serializer instance = new Serializer();

	private final Stack<String> result = new Stack<String>();

	private Serializer() {}

	public static Serializer getInstance() {
		return instance;
	}

	public String serialize(Predicate predicate) {
		result.clear();
		predicate.accept(this);

		assert result.size() == 1;
		return result.pop();
	}

	public String serialize(Term term) {
		result.clear();
		term.accept(this);

		assert result.size() == 1;
		return result.pop();
	}

	@Override public void visit(Formula formula) {
		String right = result.pop(), left = result.pop();
		result.push(left + " " + formula.getFormulaType().getLiteral() + " " + right);
	}

	@Override public void visit(DefinitionReference reference) {
		result.push(result.pop() + " is \"" + reference.getDefinition().getName() + "\"");
	}

	@Override public void visit(BinaryOperation operation) {
		String right = result.pop(), left = result.pop();

		if (operation.getLeft() instanceof BinaryOperation || operation.getLeft() instanceof UnaryOperation)
			left = "(" + left + ")";
		if (operation.getRight() instanceof BinaryOperation || operation.getRight() instanceof UnaryOperation)
			right = "(" + right + ")";

		result.push(left + " " + operation.getOperator().getLiteral() + " " + right);
	}

	@Override public void visit(UnaryOperation operation) {
		String operand = result.pop();

		if (operation.getOperand() instanceof BinaryOperation || operation.getOperand() instanceof UnaryOperation)
			operand = "(" + operand + ")";

		result.push(operand + operation.getOperator().getLiteral());	}

	@Override public void visit(VariableReference variable) {
		result.push(variable.getVariable());
	}

	@Override public void visit(ConstantReference constant) {
		result.push(constant.getConstant());
	}
}

@@ -107,16 +107,28 @@
 c final 
+ThreadLocal%3C
 Serializ
@@ -129,16 +129,17 @@
 rializer
+%3E
  instanc
@@ -139,23 +139,36 @@
 instance
+s
  = new 
+ThreadLocal%3C
 Serializ
@@ -169,18 +169,106 @@
 rializer
+%3E
 ()
+ %7B%0A%09%09@Override protected Serializer initialValue() %7B%0A%09%09%09return new Serializer();%0A%09%09%7D%0A%09%7D
 ;%0A%0A%09priv
@@ -386,24 +386,24 @@
 nstance() %7B%0A
-
 %09%09return ins
@@ -407,16 +407,23 @@
 instance
+s.get()
 ;%0A%09%7D%0A%0A%09p

make singleton thread-local