package de.gaalop.gapp.importing;
import de.gaalop.cfg.AssignmentNode;
import de.gaalop.cfg.EmptyControlFlowVisitor;
import de.gaalop.dfg.MultivectorComponent;
import de.gaalop.dfg.Variable;
import de.gaalop.gapp.GAPP;
import de.gaalop.gapp.importing.parallelObjects.DotProduct;
import de.gaalop.gapp.importing.parallelObjects.ExtCalculation;
import de.gaalop.gapp.importing.parallelObjects.ParVariable;
import de.gaalop.gapp.importing.parallelObjects.ParallelObject;
import de.gaalop.gapp.instructionSet.GAPPCalculateMv;
import de.gaalop.gapp.instructionSet.GAPPResetMv;
import de.gaalop.gapp.variables.GAPPMultivector;
import de.gaalop.gapp.variables.GAPPMultivectorComponent;
import de.gaalop.tba.Algebra;
import java.util.HashSet;
/**
* Decorates a Control Flow Graph with GAPP instructions
* @author Christian Steinmetz
*/
public class GAPPDecorator extends EmptyControlFlowVisitor {
private HashSet<String> createdGAPPVariables = new HashSet<String>();
private GAPPCreator gappCreator;
private GAPP gappStart;
private int bladeCount;
public GAPPDecorator(GAPP gappStart, HashSet<String> variables, int bladeCount, boolean scalarFunctions, Algebra algebra) {
this.gappStart = gappStart;
this.bladeCount = bladeCount;
gappCreator = new GAPPCreator(variables, bladeCount, algebra);
}
@Override
public void visit(AssignmentNode node) {
// create a new GAPP object and set it as member
GAPP gapp = new GAPP();
node.setGAPP(gapp);
gappCreator.setGapp(gapp);
if (gappStart != null) {
gapp.addGAPP(gappStart);
gappStart = null;
}
Variable variable = node.getVariable();
String name = variable.getName();
if (!createdGAPPVariables.contains(name)) {
// create a new GAPPMultivector for destination variable, if it does not exist
GAPPMultivector mv = new GAPPMultivector(name);
gapp.addInstruction(new GAPPResetMv(mv, bladeCount));
createdGAPPVariables.add(name);
}
// process expression
ExpressionCollector collector = new ExpressionCollector();
node.getValue().accept(collector);
ParallelObject parallelObject = collector.getResultValue();
DotProductsFinder finder = new DotProductsFinder();
DotProduct newDot = (DotProduct) parallelObject.accept(finder, null);
if (newDot != null) {
parallelObject = newDot;
}
if (variable instanceof MultivectorComponent) {
MultivectorComponent mvC = (MultivectorComponent) variable;
//process further: create GAPP from the ParallelObject data structure
GAPPMultivectorComponent gMvC = new GAPPMultivectorComponent(mvC.getName(), mvC.getBladeIndex());
parallelObject.accept(gappCreator, gMvC);
} else {
// only a MathFunctionCall is possible
//create gapp here
ExtCalculation extCalculation = (ExtCalculation) parallelObject;
gapp.addInstruction(new GAPPCalculateMv(extCalculation.getType(),
new GAPPMultivector(variable.getName()),
new GAPPMultivector(((ParVariable) extCalculation.getOperand1()).getName()),
(extCalculation.getOperand2() == null)
? null
: new GAPPMultivector(((ParVariable) extCalculation.getOperand2()).getName())));
}
// go further in graph
super.visit(node);
}
}