package algorithms; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import code.ast.MethodDeclaration; import code.ast.TypeDeclaration; import models.Edge; import models.Node; import models.algebra.Expression; import models.algebra.InvalidMessage; import models.algebra.ParameterizedIdentifierIsFutureWork; import models.algebra.Symbol; import models.algebra.Term; import models.algebra.UnificationFailed; import models.algebra.ValueUndefined; import models.dataConstraintModel.ChannelMember; import models.dataFlowModel.DataFlowModel; import models.dataFlowModel.PushPullAttribute; import models.dataFlowModel.PushPullValue; import models.dataFlowModel.ResolvingMultipleDefinitionIsFutureWork; import models.dataFlowModel.ResourceDependency; import models.dataFlowModel.ResourceDependencyGraph; import models.dataFlowModel.ResourceNode; public class MethodBodyGenerator { public static ArrayList<TypeDeclaration> doGenerate(ResourceDependencyGraph graph, DataFlowModel model, ArrayList<TypeDeclaration> types) { Symbol floor = model.getSymbol("floor"); Symbol.Memento floorMem = null; if (floor != null) { floorMem = floor.createMemento(); floor.setImplName("(int)Math.floor"); floor.setImplOperatorType(Symbol.Type.PREFIX); } Symbol sum = model.getSymbol("sum"); Symbol.Memento sumMem = null; if (sum != null) { sumMem = sum.createMemento(); sum.setImplName("stream().mapToInt(x->x).sum"); sum.setImplOperatorType(Symbol.Type.METHOD); } // Create a map from type names (lower case) to their types. Map<String, TypeDeclaration> typeMap = new HashMap<>(); for (TypeDeclaration type: types) { typeMap.put(type.getTypeName().substring(0,1).toLowerCase() + type.getTypeName().substring(1), type); } // Generate the body of each update or getter method. try { for (Edge e: graph.getEdges()) { ResourceDependency d = (ResourceDependency) e; PushPullAttribute pushPull = (PushPullAttribute) d.getAttribute(); ResourceNode src = (ResourceNode) d.getSource(); ResourceNode dst = (ResourceNode) d.getDestination(); String srcResourceName = src.getIdentifierTemplate().getResourceName(); String dstResourceName = dst.getIdentifierTemplate().getResourceName(); TypeDeclaration srcType = typeMap.get(srcResourceName); TypeDeclaration dstType = typeMap.get(dstResourceName); for (ChannelMember out: d.getChannelGenerator().getOutputChannelMembers()) { if (out.getIdentifierTemplate() == dst.getIdentifierTemplate()) { if (pushPull.getOptions().get(0) == PushPullValue.PUSH) { // push MethodDeclaration update = getUpdateMethod(dstType); Expression updateExp = d.getChannelGenerator().deriveUpdateExpressionOf(out, CodeGenerator.pushAccessor); String curState = updateExp.toImplementation(); String updateStatement; if (updateExp instanceof Term && ((Term) updateExp).getSymbol().getImplOperatorType() == Symbol.Type.METHOD_WITH_SIDE_EFFECT) { updateStatement = curState + ";"; } else { updateStatement = dstResourceName + " = " + curState + ";"; } if (update.getBody() == null || !update.getBody().getStatements().contains(updateStatement)) { update.addFirstStatement(updateStatement); } MethodDeclaration getter = getGetterMethod(dstType); if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { getter.addStatement("return " + dstResourceName + ";"); } // src side MethodDeclaration srcUpdate = getUpdateMethod(srcType); if (srcUpdate != null) srcUpdate.addStatement(dstResourceName + ".update(" + srcResourceName + ");"); } else { // pull or push/pull MethodDeclaration getter = getGetterMethod(dstType); if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { String curState = d.getChannelGenerator().deriveUpdateExpressionOf(out, CodeGenerator.pullAccessor).toImplementation(); getter.addStatement("return " + curState + ";"); } } } } } for (Node n: graph.getNodes()) { ResourceNode resource = (ResourceNode) n; TypeDeclaration type = typeMap.get(resource.getIdentifierTemplate().getResourceName()); MethodDeclaration getter = getGetterMethod(type); if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { getter.addStatement("return " + resource.getIdentifierTemplate().getResourceName() + ";"); } } } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork | InvalidMessage | UnificationFailed | ValueUndefined e1) { e1.printStackTrace(); } if (floor != null) floor.setMemento(floorMem); if (sum != null) sum.setMemento(sumMem); return types; } private static MethodDeclaration getUpdateMethod(TypeDeclaration dstType) { for (MethodDeclaration m: dstType.getMethods()) { if (m.getName().startsWith("update")) return m; if (m.getName().startsWith("set")) return m; } return null; } private static MethodDeclaration getGetterMethod(TypeDeclaration dstType) { for (MethodDeclaration m: dstType.getMethods()) { if (m.getName().startsWith("get")) return m; } return null; } }