package de.gaalop.dot; import de.gaalop.dfg.*; import java.util.Map; import java.util.IdentityHashMap; /** * This class exports an expression and its children as a DOT graph. */ public class DfgVisitor implements ExpressionVisitor { private String idPrefix = "node"; private StringBuilder result = new StringBuilder(); private Map<Object, String> idMap = new IdentityHashMap<Object, String>(); private int highestId = 0; public String toString() { return result.toString(); } public void setIdPrefix(String idPrefix) { this.idPrefix = idPrefix; } private String getId(Object obj) { if (!idMap.containsKey(obj)) { highestId++; idMap.put(obj, idPrefix + highestId); } return idMap.get(obj); } private void addEdge(Object n1, Object n2) { result.append('\t'); result.append(getId(n1)); result.append(" -> "); result.append(getId(n2)); result.append(";\n"); } private void addNode(Object node, String label) { result.append("\t"); result.append(getId(node)); result.append(" [label=\""); result.append(label); result.append("\", shape=\"box\"];\n"); } private void addBinaryOp(BinaryOperation op, String label) { addNode(op, label); op.getLeft().accept(this); op.getRight().accept(this); addEdge(op.getLeft(), op); addEdge(op.getRight(), op); } @Override public void visit(Subtraction subtraction) { addBinaryOp(subtraction, "-"); } @Override public void visit(Addition addition) { addBinaryOp(addition, "+"); } @Override public void visit(Division division) { addBinaryOp(division, "/"); } @Override public void visit(InnerProduct innerProduct) { addBinaryOp(innerProduct, "."); } @Override public void visit(Multiplication multiplication) { addBinaryOp(multiplication, "*"); } @Override public void visit(MathFunctionCall mathFunctionCall) { addNode(mathFunctionCall, mathFunctionCall.getFunction().toString()); mathFunctionCall.getOperand().accept(this); addEdge(mathFunctionCall.getOperand(), mathFunctionCall); } @Override public void visit(BaseVector baseVector) { addNode(baseVector, baseVector.toString()); } @Override public void visit(Negation negation) { addUnaryOp(negation, "-"); } @Override public void visit(Reverse node) { addUnaryOp(node, "~"); } private void addUnaryOp(UnaryOperation node, String operator) { addNode(node, operator); node.getOperand().accept(this); addEdge(node.getOperand(), node); } @Override public void visit(Variable variable) { addNode(variable, variable.toString()); } @Override public void visit(MultivectorComponent component) { addNode(component, component.toString()); } @Override public void visit(Exponentiation exponentiation) { addBinaryOp(exponentiation, "^"); } @Override public void visit(FloatConstant floatConstant) { addNode(floatConstant, floatConstant.toString()); } @Override public void visit(OuterProduct outerProduct) { addBinaryOp(outerProduct, "^"); } @Override public void visit(LogicalOr node) { addBinaryOp(node, "||"); } @Override public void visit(LogicalAnd node) { addBinaryOp(node, "&&"); } @Override public void visit(LogicalNegation node) { addUnaryOp(node, "!"); } @Override public void visit(Equality node) { addBinaryOp(node, "=="); } @Override public void visit(Inequality node) { addBinaryOp(node, "!="); } @Override public void visit(Relation relation) { addBinaryOp(relation, relation.getTypeString()); } @Override public void visit(FunctionArgument node) { throw new IllegalArgumentException("Macros should have been inlined."); } @Override public void visit(MacroCall node) { throw new IllegalArgumentException("Macros should have been inlined."); } }