package de.gaalop.gaalet.output; import de.gaalop.cfg.*; import de.gaalop.dfg.*; import de.gaalop.NameTable; import de.gaalop.gaalet.GaaletMultiVector; import java.util.*; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * This visitor traverses the control and data flow graphs and generates C/C++ code. */ public class CppVisitor extends de.gaalop.cpp.CppVisitor { private boolean ifPossible = true; // dont know if we can misuse gealgs mv as arrays. // Maps the nodes that output variables to their result parameter names protected Map<StoreResultNode, String> outputNamesMap = new HashMap<StoreResultNode, String>(); protected Set<GaaletMultiVector> vectorSet = new HashSet<GaaletMultiVector>(); public CppVisitor(boolean standalone) { super(standalone); } public CppVisitor(String variableType) { super(false); this.variableType = variableType; } protected void printVarName(String key) { code.append(NameTable.getInstance().get(key)); } @Override public void visit(StartNode node) { graph = node.getGraph(); FindStoreOutputNodes findOutput = new FindStoreOutputNodes(); graph.accept(findOutput); for (StoreResultNode var : findOutput.getNodes()) { String outputName = var.getValue().getName() + suffix; outputNamesMap.put(var, outputName); } if (standalone) { code.append("void calculate("); // Input Parameters List<Variable> inputParameters = sortVariables(graph.getInputVariables()); for (Variable var : inputParameters) { code.append(variableType).append(" "); // The assumption here is that they all are normal scalars printVarName(var.getName()); code.append(", "); } for (StoreResultNode var : findOutput.getNodes()) { code.append(variableType).append(" **"); printVarName(outputNamesMap.get(var)); code.append(", "); } if (!graph.getInputVariables().isEmpty() || !findOutput.getNodes().isEmpty()) { code.setLength(code.length() - 2); } code.append(") {\n"); indentation++; } if (ifPossible && !standalone) { List<Variable> inputParameters = sortVariables(graph.getInputVariables()); for (Variable var : inputParameters) { FieldsUsedVisitor fieldVisitor = new FieldsUsedVisitor(var.getName()); graph.accept(fieldVisitor); code.append("// This is input: "); code.append(fieldVisitor.giveDefinition(variableType)); code.append("\n"); } code.append("\n"); for (StoreResultNode var : findOutput.getNodes()) { FieldsUsedVisitor fieldVisitor = new FieldsUsedVisitor(var.getValue().getName()); graph.accept(fieldVisitor); code.append("// This is output: "); code.append(fieldVisitor.giveDefinition()); code.append("\n"); } } handleLocalVariables(); createVectorSet(findOutput); node.getSuccessor().accept(this); } protected void createVectorSet (FindStoreOutputNodes findOutput) { for (Variable var : graph.getInputVariables()) { FieldsUsedVisitor fieldVisitor = new FieldsUsedVisitor(var.getName()); graph.accept(fieldVisitor); vectorSet.add(fieldVisitor.getMultiVector()); } for (Variable var : graph.getLocalVariables()) { FieldsUsedVisitor fieldVisitor = new FieldsUsedVisitor(var.getName()); graph.accept(fieldVisitor); vectorSet.add(fieldVisitor.getMultiVector()); } for (StoreResultNode var : findOutput.getNodes()) { FieldsUsedVisitor fieldVisitor = new FieldsUsedVisitor(var.getValue().getName()); graph.accept(fieldVisitor); vectorSet.add(fieldVisitor.getMultiVector()); } } /** * Declare local variables * but first local variables in a set, so we reduce redundancy */ protected void handleLocalVariables() { Set <String> varNames = new HashSet<String> (); for (Variable var : graph.getLocalVariables()) { varNames.add(var.getName()); } for (String var : varNames) { appendIndentation(); FieldsUsedVisitor fieldVisitor = new FieldsUsedVisitor(var); graph.accept(fieldVisitor); code.append(fieldVisitor.giveDefinition(variableType)); code.append("\n"); } if (!graph.getLocalVariables().isEmpty()) { code.append("\n"); } } @Override public void visit(AssignmentNode node) { if (assigned.contains(node.getVariable().getName())) { log.warn("Reuse of variable " + node.getVariable().getName() + ". Make sure to reset this variable or use another name."); code.append("\n"); appendIndentation(); code.append("// Warning: reuse of variable "); code.append(node.getVariable().getName()); code.append(".\n"); appendIndentation(); code.append("// Make sure to reset this variable or use another name.\n"); assigned.remove(node.getVariable().getName()); } appendIndentation(); node.getVariable().accept(this); code.append(" = "); node.getValue().accept(this); code.append(";\n"); node.getSuccessor().accept(this); } }