package models.dataFlowModel;
import models.algebra.Symbol;
import models.algebra.Type;
import models.dataConstraintModel.DataConstraintModel;
public class ModelExtension {
private static Symbol.Memento floorMem;
private static Symbol.Memento sumMem;
private static Symbol.Memento mergeMem;
public static void extendModel(DataFlowModel model) {
Symbol floor = model.getSymbol("floor");
floorMem = null;
if (floor != null) {
floorMem = floor.createMemento();
floor.setImplName("(int)Math.floor");
floor.setImplOperatorType(Symbol.Type.PREFIX);
}
Symbol sum = model.getSymbol("sum");
sumMem = null;
if (sum != null) {
sumMem = sum.createMemento();
final int[] count = new int[] {0};
sum.setGenerator(new Symbol.IImplGenerator() {
@Override
public String generate(Type type, String[] children, String[] sideEffects) {
String compType = "Integer";
if (type != null) {
String interfaceType = type.getInterfaceTypeName();
if (interfaceType.contains("<")) {
compType = interfaceType.substring(interfaceType.indexOf("<") + 1, interfaceType.lastIndexOf(">"));
}
}
count[0]++;
String impl = compType + " " + "temp_sum" + count[0] + " = 0;\n";
impl += "for (" + compType + " x: " + children[0] + ") {\n";
impl += "\t" + "temp_sum" + count[0] + " += x;\n";
impl += "}\n";
sideEffects[0] = sideEffects[0] + impl;
return "temp_sum" + count[0];
}
});
sum.setImplOperatorType(Symbol.Type.GENERATIVE);
sum.setSignature(new Type[] {DataConstraintModel.typeInt, DataConstraintModel.typeList});
// sum.setImplName("stream().mapToInt(x->x).sum");
// sum.setImplOperatorType(Symbol.Type.METHOD);
}
Symbol merge = model.getSymbol("merge");
mergeMem = null;
if (merge != null) {
mergeMem = merge.createMemento();
merge.setArity(2);
final int[] count = new int[] {0};
merge.setGenerator(new Symbol.IImplGenerator() {
@Override
public String generate(Type type, String[] childrenImpl, String[] sideEffects) {
String implType = "Arrayist<>";
String interfaceType = "List<Integer>";
String compType = "Integer";
if (type != null) {
implType = type.getImplementationTypeName();
interfaceType = type.getInterfaceTypeName();
if (interfaceType.contains("<")) {
compType = interfaceType.substring(interfaceType.indexOf("<") + 1, interfaceType.lastIndexOf(">"));
}
}
String idxGetter = "";
if (compType.startsWith("Map.Entry")) {
idxGetter = ".getKey()";
}
count[0]++;
String impl = "";
impl += "" + interfaceType + " temp_l" + count[0] + " = new " + implType + "();\n";
impl += "{\n";
impl += "\tIterator<" + compType + "> i1 = " + childrenImpl[0] + ".iterator();\n";
impl += "\tIterator<" + compType + "> i2 = " + childrenImpl[1] + ".iterator();\n";
impl += "\t" + compType + " t1 = null;\n";
impl += "\t" + compType + " t2 = null;\n";
impl += "\twhile (i1.hasNext() || i2.hasNext() || t1 != null || t2 != null) {\n";
impl += "\t\tif (t1 == null && i1.hasNext()) {\n";
impl += "\t\t\tt1 = i1.next();\n";
impl += "\t\t}\n";
impl += "\t\tif (t2 == null && i2.hasNext()) {\n";
impl += "\t\t\tt2 = i2.next();\n";
impl += "\t\t}\n";
impl += "\t\tif (t1 == null || (t2 != null && t1" + idxGetter + " < t2" + idxGetter + ")) {\n";
impl += "\t\t\ttemp_l" + count[0] +".add(t2);\n";
impl += "\t\t\tt2 = null;\n";
impl += "\t\t} else {\n";
impl += "\t\t\ttemp_l" + count[0] + ".add(t1);\n";
impl += "\t\t\tt1 = null;\n";
impl += "\t\t}\n";
impl += "\t}\n";
impl += "}\n";
sideEffects[0] = sideEffects[0] + impl;
return "temp_l" + count[0];
}
});
merge.setImplOperatorType(Symbol.Type.GENERATIVE);
merge.setSignature(new Type[] {DataConstraintModel.typeList, DataConstraintModel.typeList, DataConstraintModel.typeList});
}
}
public static void recoverModel(DataFlowModel model) {
Symbol floor = model.getSymbol("floor");
if (floor != null) floor.setMemento(floorMem);
Symbol sum = model.getSymbol("sum");
if (sum != null) sum.setMemento(sumMem);
Symbol merge = model.getSymbol("merge");
if (merge != null) merge.setMemento(mergeMem);
}
}