diff --git a/AlgebraicDataflowArchitectureModel/src/algorithms/TypeInference.java b/AlgebraicDataflowArchitectureModel/src/algorithms/TypeInference.java index 4e190bf..fb48b10 100644 --- a/AlgebraicDataflowArchitectureModel/src/algorithms/TypeInference.java +++ b/AlgebraicDataflowArchitectureModel/src/algorithms/TypeInference.java @@ -1516,7 +1516,7 @@ } } - public static Type createNewListType(Type compType, Type parentType) { + private static Type createNewListType(Type compType, Type parentType) { String compTypeName = getInterfaceTypeName(compType); List childrenTypes = getChildrenTypes(parentType, listComponentTypes.keySet()); Type newListType = new Type("List", "ArrayList<>", "List<" + compTypeName + ">", parentType); @@ -1536,7 +1536,7 @@ return newListType; } - public static Type createNewTupleType(List componentTypes, Type parentTupleType) { + private static Type createNewTupleType(List componentTypes, Type parentTupleType) { String implTypeName = "AbstractMap.SimpleEntry<>"; String interfaceTypeName = "Map.Entry<$x>"; if (componentTypes.size() >= 2) { @@ -1571,7 +1571,7 @@ return newTupleType; } - public static Type createNewMapType(List componentTypes, Type parentMapType) { + private static Type createNewMapType(List componentTypes, Type parentMapType) { String implTypeName = "HashMap<>"; String interfaceTypeName = "Map<$x, $y>"; if (componentTypes.size() == 2) { diff --git a/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java index abb4dba..3a7ebcb 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java @@ -481,7 +481,7 @@ getterMethodName += langSpec.toComponentName(rn.getIdentifierTemplate().getResourceName()); } getterMethodName += "Values"; - Type returnType = createReturnType(resourcesToReturn); + Type returnType = createReturnType(resourcesToReturn, langSpec); MethodDeclaration mediateGetter = langSpec.newMethodDeclaration(getterMethodName, returnType); component.addMethod(mediateGetter); @@ -495,9 +495,16 @@ for (Edge outEdge: node.getOutEdges()) { ObjectNode dstNode = (ObjectNode) outEdge.getDestination(); List returnedResources = dataFlowInform.get(outEdge).get(PushPullValue.PULL); - if (returnedResources.contains(rn)) { // The case of returnedResoueces are multiple, ToDo. - MethodDeclaration nextGetter = declareAndFillGetterMethods(dstNode, outEdge, dataFlowInform, componentMap, langSpec); - params.add(langSpec.getMethodInvocation(dstNode.getName(), nextGetter.getName())); + if (returnedResources.contains(rn)) { + if (returnedResources.size() == 1) { + MethodDeclaration nextGetter = declareAndFillGetterMethods(dstNode, outEdge, dataFlowInform, componentMap, langSpec); + params.add(langSpec.getMethodInvocation(dstNode.getName(), nextGetter.getName())); + } else { + MethodDeclaration nextGetter = declareAndFillGetterMethods(dstNode, outEdge, dataFlowInform, componentMap, langSpec); + int idx = returnedResources.indexOf(rn); + int len = returnedResources.size(); + params.add(langSpec.getTupleGet(langSpec.getMethodInvocation(dstNode.getName(), nextGetter.getName()), idx, len)); + } break; } } @@ -537,18 +544,27 @@ } component.addMethod(updateOrInput); + Map resToVar = new HashMap<>(); + Map> varToRes = new HashMap<>(); for (Edge outEdge: node.getOutEdges()) { Node dstNode = outEdge.getDestination(); MethodDeclaration calleeMethod = declareAndFillUpdateAndInputMethods(dstNode, outEdge, node, dataFlowInform, componentMap, langSpec); // Add a statement to call the destination method. - addInvocationInResourceUpdate(node, updateOrInput, calleeMethod, ((ObjectNode) dstNode).getName(), dataFlowInform.get(outEdge).get(PushPullValue.PULL), langSpec); + List returnedResources = dataFlowInform.get(outEdge).get(PushPullValue.PULL); + String varName = addInvocationInResourceUpdate(node, updateOrInput, calleeMethod, ((ObjectNode) dstNode).getName(), returnedResources, langSpec); + if (varName != null && returnedResources != null) { + varToRes.put(varName, returnedResources); + for (ResourceNode rn: returnedResources) { + resToVar.put(rn, varName); + } + } } if (resourcesToReturn != null && resourcesToReturn.size() > 0) { // Set the return type and add a return statement. - Type returnType = createReturnType(resourcesToReturn); + Type returnType = createReturnType(resourcesToReturn, langSpec); updateOrInput.setReturnType(returnType); - String returnValue = createReturnValue(resourcesToReturn, node, returnType, langSpec); + String returnValue = createReturnValue(resourcesToReturn, node, returnType, resToVar, varToRes, langSpec); updateOrInput.addStatement(langSpec.getReturnStatement(returnValue) + langSpec.getStatementDelimiter()); } return updateOrInput; @@ -567,7 +583,7 @@ } } // Add a statement to call the destination method. - addInvocationInMediatorUpdate(input, calleeMethod, ((ObjectNode) dstNode).getName(), dataFlowInform.get(outEdge).get(PushPullValue.PULL), langSpec); + String varName = addInvocationInMediatorUpdate(input, calleeMethod, ((ObjectNode) dstNode).getName(), dataFlowInform.get(outEdge).get(PushPullValue.PULL), langSpec); } return input; } else { @@ -581,6 +597,8 @@ updateOrInput = declareUpdateMethod(node, inEdge, component, dataFlowInform, langSpec); component.addMethod(updateOrInput); } + Map resToVar = new HashMap<>(); + Map> varToRes = new HashMap<>(); for (Edge outEdge: node.getOutEdges()) { Node dstNode = outEdge.getDestination(); MethodDeclaration calleeMethod = declareAndFillUpdateAndInputMethods(dstNode, outEdge, prevResNode, dataFlowInform, componentMap, langSpec); @@ -594,27 +612,39 @@ component.addMethod(updateOrInput); } // Add a statement to call the destination method. - addInvocationInMediatorUpdate(updateOrInput, calleeMethod, ((ObjectNode) dstNode).getName(), dataFlowInform.get(outEdge).get(PushPullValue.PULL), langSpec); + List returnedResources = dataFlowInform.get(outEdge).get(PushPullValue.PULL); + String varName = addInvocationInMediatorUpdate(updateOrInput, calleeMethod, ((ObjectNode) dstNode).getName(), returnedResources, langSpec); + if (varName != null && returnedResources != null) { + varToRes.put(varName, returnedResources); + for (ResourceNode rn: returnedResources) { + resToVar.put(rn, varName); + } + } } if (resourcesToReturn != null && resourcesToReturn.size() > 0) { // Set the return type and add a return statement. - Type returnType = createReturnType(resourcesToReturn); + Type returnType = createReturnType(resourcesToReturn, langSpec); updateOrInput.setReturnType(returnType); - String returnValue = createReturnValue(resourcesToReturn, node, returnType, langSpec); + String returnValue = createReturnValue(resourcesToReturn, node, returnType, resToVar, varToRes, langSpec); updateOrInput.addStatement(langSpec.getReturnStatement(returnValue) + langSpec.getStatementDelimiter()); } return updateOrInput; } } - private static String createReturnValue(List resourcesToReturn, Node node, Type returnType, ILanguageSpecific langSpec) { + private static String createReturnValue(List resourcesToReturn, Node node, Type returnType, Map resToVar, Map> varToRes, ILanguageSpecific langSpec) { List params = new ArrayList<>(); for (ResourceNode rn: resourcesToReturn) { IdentifierTemplate rId = rn.getIdentifierTemplate(); if (rId.getResourceName().equals(((ObjectNode) node).getName())) { params.add(langSpec.getFieldAccessor(fieldOfResourceState)); } else { - params.add(rId.getResourceName()); + String varName = resToVar.get(rn); + if (varToRes.get(varName).size() == 1) { + params.add(varName); + } else { + params.add(langSpec.getTupleGet(varName, varToRes.get(varName).indexOf(rn), varToRes.get(varName).size())); + } } } if (params.size() == 1) { @@ -624,7 +654,7 @@ } } - private static Type createReturnType(List resourcesToReturn) { + private static Type createReturnType(List resourcesToReturn, ILanguageSpecific langSpec) { if (resourcesToReturn.size() == 1) { return resourcesToReturn.iterator().next().getIdentifierTemplate().getResourceStateType(); } @@ -633,7 +663,7 @@ IdentifierTemplate rId = rn.getIdentifierTemplate(); compTypes.add(rId.getResourceStateType()); } - Type returnType = TypeInference.createNewTupleType(compTypes, DataConstraintModel.typeTuple); + Type returnType = langSpec.newTupleType(compTypes); return returnType; } @@ -779,7 +809,7 @@ return input; } - private static void addInvocationInResourceUpdate(Node node, MethodDeclaration resourceUpdateMethod, MethodDeclaration calleeMethod, String dstNodeName, List returnedResources, ILanguageSpecific langSpec) { + private static String addInvocationInResourceUpdate(Node node, MethodDeclaration resourceUpdateMethod, MethodDeclaration calleeMethod, String dstNodeName, List returnResources, ILanguageSpecific langSpec) { List params = new ArrayList<>(); params.add(langSpec.getFieldAccessor(fieldOfResourceState)); if (calleeMethod.getParameters() != null) { @@ -809,52 +839,78 @@ // params.add(refVarName); // } // } - if (calleeMethod.getReturnType() == null || langSpec.isVoidType(calleeMethod.getReturnType())) { + if (calleeMethod.getReturnType() == null || langSpec.isVoidType(calleeMethod.getReturnType()) || returnResources == null) { resourceUpdateMethod.addStatement(langSpec.getMethodInvocation(langSpec.getFieldAccessor(dstNodeName), calleeMethod.getName(), params) + langSpec.getStatementDelimiter()); // this.dst.updateSrc(value, refParams); + return null; } else { String targetVarName = null; - if (returnedResources.size() == 1) { - ResourceNode targetNode = returnedResources.get(0); + if (returnResources.size() == 1) { + ResourceNode targetNode = returnResources.get(0); targetVarName = targetNode.getIdentifierTemplate().getResourceName(); + resourceUpdateMethod.addStatement( + langSpec.getVariableDeclaration(calleeMethod.getReturnType().getInterfaceTypeName(), targetVarName) + + langSpec.getAssignment() + + langSpec.getMethodInvocation(langSpec.getFieldAccessor(dstNodeName), + calleeMethod.getName(), + params) + langSpec.getStatementDelimiter()); // ResType res = this.dst.updateSrc(value, refParams); } else { - targetVarName = getMultipleResourcesVarName(returnedResources, langSpec); + targetVarName = getMultipleResourcesVarName(returnResources, langSpec); + VariableDeclaration targetVar = langSpec.newVariableDeclaration(calleeMethod.getReturnType(), targetVarName); + List vars = new ArrayList<>(); + for (ResourceNode rn: returnResources) { + IdentifierTemplate rId = rn.getIdentifierTemplate(); + vars.add(langSpec.newVariableDeclaration(rId.getResourceStateType(), rId.getResourceName())); + } + resourceUpdateMethod.addStatement( + langSpec.getDecomposedTuple( + langSpec.getMethodInvocation(langSpec.getFieldAccessor(dstNodeName), calleeMethod.getName(), params), + targetVar, + vars)); } - resourceUpdateMethod.addStatement( - langSpec.getVariableDeclaration(calleeMethod.getReturnType().getInterfaceTypeName(), targetVarName) - + langSpec.getAssignment() - + langSpec.getMethodInvocation(langSpec.getFieldAccessor(dstNodeName), - calleeMethod.getName(), - params) + langSpec.getStatementDelimiter()); // ResType res = this.dst.updateSrc(value, refParams); + return targetVarName; } } - private static void addInvocationInMediatorUpdate(MethodDeclaration resourceUpdateMethod, MethodDeclaration calleeMethod, String dstNodeName, List returnedResources, ILanguageSpecific langSpec) { + private static String addInvocationInMediatorUpdate(MethodDeclaration resourceUpdateMethod, MethodDeclaration calleeMethod, String dstNodeName, List returnResources, ILanguageSpecific langSpec) { List params = new ArrayList<>(); if (calleeMethod.getParameters() != null) { for (VariableDeclaration v: calleeMethod.getParameters()) { params.add(v.getName()); } } - if (calleeMethod.getReturnType() == null || langSpec.isVoidType(calleeMethod.getReturnType())) { + if (calleeMethod.getReturnType() == null || langSpec.isVoidType(calleeMethod.getReturnType()) || returnResources == null ) { resourceUpdateMethod.addStatement(langSpec.getMethodInvocation(langSpec.getFieldAccessor(dstNodeName), calleeMethod.getName(), params) + langSpec.getStatementDelimiter()); // this.dst.updateSrc(value, refParams); + return null; } else { String targetVarName = null; - if (returnedResources.size() == 1) { - ResourceNode targetNode = returnedResources.get(0); + if (returnResources.size() == 1) { + ResourceNode targetNode = returnResources.get(0); targetVarName = targetNode.getIdentifierTemplate().getResourceName(); + resourceUpdateMethod.addStatement( + langSpec.getVariableDeclaration(calleeMethod.getReturnType().getInterfaceTypeName(), targetVarName) + + langSpec.getAssignment() + + langSpec.getMethodInvocation(langSpec.getFieldAccessor(dstNodeName), + calleeMethod.getName(), + params) + langSpec.getStatementDelimiter()); // ResType res = this.dst.updateSrc(value, refParams); } else { - targetVarName = getMultipleResourcesVarName(returnedResources, langSpec); + targetVarName = getMultipleResourcesVarName(returnResources, langSpec); + VariableDeclaration targetVar = langSpec.newVariableDeclaration(calleeMethod.getReturnType(), targetVarName); + List vars = new ArrayList<>(); + for (ResourceNode rn: returnResources) { + IdentifierTemplate rId = rn.getIdentifierTemplate(); + vars.add(langSpec.newVariableDeclaration(rId.getResourceStateType(), rId.getResourceName())); + } + resourceUpdateMethod.addStatement( + langSpec.getDecomposedTuple( + langSpec.getMethodInvocation(langSpec.getFieldAccessor(dstNodeName), calleeMethod.getName(), params), + targetVar, + vars)); } - resourceUpdateMethod.addStatement( - langSpec.getVariableDeclaration(calleeMethod.getReturnType().getInterfaceTypeName(), targetVarName) - + langSpec.getAssignment() - + langSpec.getMethodInvocation(langSpec.getFieldAccessor(dstNodeName), - calleeMethod.getName(), - params) + langSpec.getStatementDelimiter()); // ResType res = this.dst.updateSrc(value, refParams); + return targetVarName; } } diff --git a/AlgebraicDataflowArchitectureModel/src/generators/ILanguageSpecific.java b/AlgebraicDataflowArchitectureModel/src/generators/ILanguageSpecific.java index bc677ff..40d2f25 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/ILanguageSpecific.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/ILanguageSpecific.java @@ -20,6 +20,7 @@ MethodDeclaration newMethodDeclaration(String methodName, boolean isConstructor, Type returnType, ArrayList parameters); FieldDeclaration newFieldDeclaration(Type fieldType, String fieldName); FieldDeclaration newFieldDeclaration(Type fieldType, String fieldName, String fieldInitializer); + Type newTupleType(List compTypes); String getVariableDeclaration(String typeName, String varName); String getFieldInitializer(Type type, Expression initialValue); boolean declareField(); @@ -31,6 +32,8 @@ String getReturnStatement(String returnValue); String toComponentName(String name); String getMainComponentName(); + String getTupleGet(String tupleExp, int idx, int length); + String getDecomposedTuple(String tupleExp, VariableDeclaration tupleVar, List vars); String getAssignment(); String getStatementDelimiter(); boolean isValueType(Type type); diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaSpecific.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaSpecific.java index 16a4588..0176b5e 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JavaSpecific.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JavaSpecific.java @@ -10,7 +10,10 @@ import code.ast.TypeDeclaration; import code.ast.VariableDeclaration; import models.algebra.Expression; +import models.algebra.Parameter; +import models.algebra.Term; import models.algebra.Type; +import models.algebra.Variable; import models.dataConstraintModel.DataConstraintModel; public class JavaSpecific implements ILanguageSpecific { @@ -60,6 +63,27 @@ return new FieldDeclaration(fieldType, fieldName, fieldInitializer); } + @Override + public Type newTupleType(List componentTypes) { + String implTypeName = "AbstractMap.SimpleEntry<>"; + String interfaceTypeName = "Map.Entry<$x>"; + if (componentTypes.size() >= 2) { + implTypeName = implTypeName.replace("$x", getImplementationTypeName(componentTypes.get(0)) + "$x"); + interfaceTypeName = interfaceTypeName.replace("$x", getInterfaceTypeName(componentTypes.get(0)) + "$x"); + for (Type argType : componentTypes.subList(1, componentTypes.size() - 1)) { + implTypeName = implTypeName.replace("$x", + ", AbstractMap.SimpleEntry<" + getImplementationTypeName(argType) + "$x>"); + interfaceTypeName = interfaceTypeName.replace("$x", + ", Map.Entry<" + getInterfaceTypeName(argType) + "$x>"); + } + implTypeName = implTypeName.replace("$x", + ", " + getImplementationTypeName(componentTypes.get(componentTypes.size() - 1))); + interfaceTypeName = interfaceTypeName.replace("$x", + ", " + getInterfaceTypeName(componentTypes.get(componentTypes.size() - 1))); + } + Type newTupleType = new Type("Tuple", implTypeName, interfaceTypeName, DataConstraintModel.typeTuple); + return newTupleType; + } @Override public String getVariableDeclaration(String typeName, String varName) { @@ -158,7 +182,38 @@ public String getStatementDelimiter() { return ";"; } - + + @Override + public String getTupleGet(String tupleExp, int idx, int length) { + Expression t = new Variable(tupleExp, DataConstraintModel.typeTuple); + for (int i = 0; i < idx; i++) { + Term next = new Term(DataConstraintModel.snd); + next.addChild(t); + t = next; + } + if (idx < length - 1) { + Term last = new Term(DataConstraintModel.fst); + last.addChild(t); + t = last; + } + return t.toImplementation(new String[]{}); + } + + @Override + public String getDecomposedTuple(String tupleExp, VariableDeclaration tupleVar, List vars) { + String statements = ""; + statements += getVariableDeclaration(tupleVar.getType().getInterfaceTypeName(), tupleVar.getName()) + + getAssignment() + tupleExp + getStatementDelimiter(); + for (int i = 0; i < vars.size(); i++) { + VariableDeclaration var = vars.get(i); + statements += "\n" + getVariableDeclaration(var.getType().getInterfaceTypeName(), var.getName()) + + getAssignment() + + getTupleGet(tupleVar.getName(), i, vars.size()) + + getStatementDelimiter(); + } + return statements; + } + @Override public boolean isValueType(Type type) { if (type == DataConstraintModel.typeInt @@ -179,4 +234,22 @@ } return false; } + + private String getImplementationTypeName(Type type) { + if (type == null) + return "Object"; + String wrapperType = DataConstraintModel.getWrapperType(type); + if (wrapperType != null) + return wrapperType; + return type.getImplementationTypeName(); + } + + private String getInterfaceTypeName(Type type) { + if (type == null) + return "Object"; + String wrapperType = DataConstraintModel.getWrapperType(type); + if (wrapperType != null) + return wrapperType; + return type.getInterfaceTypeName(); + } }