package de.gaalop.algebra;
import de.gaalop.AlgebraStrategy;
import de.gaalop.CodeParserException;
import de.gaalop.CompilationException;
import de.gaalop.InputFile;
import de.gaalop.OptimizationException;
import de.gaalop.cfg.AlgebraDefinitionFile;
import de.gaalop.cfg.ControlFlowGraph;
import de.gaalop.cfg.FindStoreOutputNodes;
import de.gaalop.cfg.Macro;
import de.gaalop.dfg.Expression;
import de.gaalop.dfg.OuterProduct;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Sets the algebra on a Control Flow Graph
* @author Christian Steinmetz
*/
public class AlStrategy implements AlgebraStrategy {
private Plugin plugin;
public AlStrategy(Plugin plugin) {
this.plugin = plugin;
}
@Override
public void transform(ControlFlowGraph graph) throws OptimizationException {
//Check if graph contains at least one StoreResultNode
FindStoreOutputNodes outputNodes = new FindStoreOutputNodes();
graph.accept(outputNodes);
if (outputNodes.getNodes().isEmpty()) {
throw new OptimizationException("There are no lines marked for optimization ('?')", graph);
}
InputStream inputStream = null;
try {
//load algebra
AlgebraDefinitionFile alFile = graph.getAlgebraDefinitionFile();
alFile.setUsePrecalculatedTable(plugin.usePrecalulatedTables);
alFile.setUseAsRessource(graph.asRessource);
String baseDir = (graph.asRessource) ? "algebra" : graph.algebraBaseDirectory;
if (!baseDir.endsWith("/")) baseDir += "/";
baseDir += graph.algebraName+"/";
alFile.setProductsFilePath(baseDir+"products.csv");
inputStream = (graph.asRessource)
? getClass().getResourceAsStream(baseDir+"definition.csv")
: new FileInputStream(new File(baseDir+"definition.csv"));
alFile.loadFromFile(inputStream);
createBlades(alFile);
//replace all functions / macros
inputStream = (graph.asRessource)
? getClass().getResourceAsStream(baseDir+"macros.clu")
: new FileInputStream(new File(baseDir+"macros.clu"));
ControlFlowGraph macrosGraph = new de.gaalop.clucalc.input.Plugin().createCodeParser().parseFile(inputStreamToInputFile(inputStream, "macros", null));
inputStream.close();
HashMap<StringIntContainer, Macro> macros = MacrosVisitor.getAllMacros(macrosGraph);
MacrosVisitor.getAllMacros(graph, macros);
StringIntContainer dual = new StringIntContainer("Dual",1);
if (macros.containsKey(dual)) {
macros.put(new StringIntContainer("*",1), macros.get(dual));
macros.remove(dual);
}
//load user macros
if (!plugin.getUserMacroFilePath().trim().equals("")) {
File f = new File(plugin.userMacroFilePath);
if (f.exists()) {
inputStream = new FileInputStream(f);
ControlFlowGraph userMacrosGraph = new de.gaalop.clucalc.input.Plugin().createCodeParser().parseFile(inputStreamToInputFile(inputStream, "userMacros", f.getParentFile()));
inputStream.close();
MacrosVisitor.getAllMacros(userMacrosGraph, macros);
} else
System.err.println("Algebra Plugin: User Macro File Path does not exist!");
}
//inline all macros
Inliner.inline(graph, macros);
//Remove Macro definitions from graph
for (Macro macro: macros.values())
graph.removeNode(macro);
//replace Variables which are basevectors
BaseVectorDefiner definer = new BaseVectorDefiner();
definer.createFromAlBase(alFile.base);
BaseVectorReplaceVisitor replacerB = new BaseVectorReplaceVisitor(definer);
graph.accept(replacerB);
//Update variable set
UpdateLocalVariableSet.updateVariableSets(graph);
//RemoveDefVars.removeDefVars(graph);
//update output blades
HashMap<String, Integer> mapIndices = new HashMap<String, Integer>();
for (int index = 0;index<alFile.blades.length;index++)
mapIndices.put(bladeToString(alFile.blades[index]), new Integer(index));
Set<String> set = graph.getPragmaOutputVariables();
HashSet<String> copySet = new HashSet<String>(set);
set.clear();
for (String str: copySet) {
if (str.contains(" ")) {
String[] parts = str.split(" ");
if (parts[1].equals("1")) parts[1] = "1.0";
if (!mapIndices.containsKey(parts[1]))
throw new OptimizationException("The bladename "+parts[1]+" is not found in the default blade list.", graph);
set.add(parts[0]+"$"+mapIndices.get(parts[1]));
} else
set.add(str);
}
} catch (CodeParserException ex) {
Logger.getLogger(AlStrategy.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(AlStrategy.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
inputStream.close();
} catch (IOException ex) {
Logger.getLogger(AlStrategy.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
private String bladeToString(Expression blade) {
if (!blade.isComposite()) return blade.toString();
OuterProduct outerProduct = (OuterProduct) blade;
return bladeToString(outerProduct.getLeft())+"^"+bladeToString(outerProduct.getRight());
}
/**
* Create blades in a AlgebraDefinitionFile
* @param alFile The AlgebraDefinitionFile
*/
public static void createBlades(AlgebraDefinitionFile alFile) {
TCBlade[] blades = BladeArrayRoutines.createBlades(Arrays.copyOfRange(alFile.base,1,alFile.base.length));
alFile.blades = new Expression[blades.length];
for (int i = 0; i < blades.length; i++)
alFile.blades[i] = blades[i].toExpression();
}
/**
* Puts an inputStream into an InputFile
* @param inputStream The inputStream
* @param cluName The cluName to use
* @param parent The parent file object
* @return The InputFile
*/
private InputFile inputStreamToInputFile(InputStream inputStream, String cluName, File parent) {
StringBuilder sb = new StringBuilder();
readIn(inputStream, sb, parent);
sb.append("\n");
return new InputFile(cluName, sb.toString());
}
/**
* Reads an inputStream in a stringbuilder object
* @param inputStream The inputStream
* @param sb The stringbuilder object to use
* @param parent The parent file object
*/
private void readIn(InputStream inputStream, StringBuilder sb, File parent) {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
if (line.trim().startsWith("#include")) {
line = line.trim();
String filename = line.substring(line.indexOf(" ")+1).trim();
File newParent = new File(parent, filename);
FileInputStream inp = new FileInputStream(newParent);
readIn(inp, sb, newParent);
inp.close();
} else
sb.append(line);
sb.append("\n");
}
reader.close();
} catch (IOException ex) {
Logger.getLogger(AlStrategy.class.getName()).log(Level.SEVERE, null, ex);
}
}
}