package de.gaalop.tba.cfgImport; import de.gaalop.cfg.AssignmentNode; import de.gaalop.cfg.EmptyControlFlowVisitor; import de.gaalop.dfg.BinaryOperation; import de.gaalop.dfg.Expression; import de.gaalop.dfg.ExpressionVisitor; import de.gaalop.dfg.MathFunctionCall; import de.gaalop.dfg.UnaryOperation; import de.gaalop.dfg.Variable; import de.gaalop.visitors.ExpressionTypeVisitor; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; /** * Extract MathFunctions so that the operand has an own temporary multivector. * The result is assigned to an own multivector. * * @author Christian Steinmetz */ public class MathFunctionSeparator extends EmptyControlFlowVisitor { private Expression resultValue = null; private int tempCounter = -1; private HashSet<String> variables; public MathFunctionSeparator(HashSet<String> variables) { this.variables = variables; } /** * Create a new temporary, recently unused variable name * @return The new name */ private Variable getNewTemporaryVariable() { tempCounter++; while (variables.contains("temp" + tempCounter)) { tempCounter++; } return new Variable("temp" + tempCounter); } private HashMap<Variable, Expression> toInsert = new HashMap<Variable, Expression>(); private LinkedList<Variable> toInsertVars = new LinkedList<Variable>(); private ExpressionVisitor expressionVisitor = new ExpressionTypeVisitor() { @Override protected void visitBinaryOperation(BinaryOperation node) { resultValue = null; node.getLeft().accept(this); if (resultValue != null) { node.setLeft(resultValue); resultValue = null; } node.getRight().accept(this); if (resultValue != null) { node.setRight(resultValue); resultValue = null; } } @Override protected void visitUnaryOperation(UnaryOperation node) { resultValue = null; node.getOperand().accept(this); if (resultValue != null) { node.setOperand(resultValue); resultValue = null; } } @Override protected void visitTerminal(Expression node) { } @Override public void visit(MathFunctionCall node) { resultValue = null; node.getOperand().accept(this); if (resultValue != null) { node.setOperand(resultValue); resultValue = null; } else { Variable var = getNewTemporaryVariable(); toInsert.put(var, node.getOperand()); toInsertVars.add(var); node.setOperand(var); } Variable var2 = getNewTemporaryVariable(); toInsert.put(var2, node); toInsertVars.add(var2); resultValue = var2; } }; @Override public void visit(AssignmentNode node) { node.getValue().accept(expressionVisitor); if (resultValue != null) { //Direct MathFunctionCalls won't need an extra temporary variable, //because they will be assigned to the AssignmentNode variable! //For this optimization the variable must be removed from the toInsertVars list toInsertVars.remove((Variable) resultValue); resultValue = null; } for (Variable var : toInsertVars) { AssignmentNode newNode = new AssignmentNode(node.getGraph(), var, toInsert.get(var)); node.insertBefore(newNode); } toInsertVars.clear(); toInsert.clear(); super.visit(node); } }