diff --git a/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java b/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java index 3f8105c..495452c 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java @@ -750,35 +750,53 @@ for (Edge resToCh: chToRes.getSource().getInEdges()) { DataTransferChannel ch = ((ChannelNode) resToCh.getDestination()).getChannel(); DataFlowEdge re = (DataFlowEdge) resToCh; - ResourcePath srcRes = ((ResourceNode) re.getSource()).getOutSideResource(); - String srcResComponentName = getComponentName(srcRes.getResourceHierarchy(), langSpec); + ResourcePath srcResPath = ((ResourceNode) re.getSource()).getOutSideResource(); + String srcResComponentName = getComponentName(srcResPath.getResourceHierarchy(), langSpec); String srcResName = langSpec.toVariableName(srcResComponentName); // Check if the input resource is outside of the channel scope. boolean outsideInputResource = false; for (ChannelMember cm: ch.getInputChannelMembers()) { - if (cm.getResource().equals(srcRes) && cm.isOutside()) { + if (cm.getResource().equals(srcResPath) && cm.isOutside()) { outsideInputResource = true; // Regarded as pull transfer. break; } } // Check if the output resource is outside of the channel scope. boolean outsideOutputResource = false; + ResourcePath dstResPath = null; for (ChannelMember cm: ch.getOutputChannelMembers()) { - if (resourceNode.getInSideResources().contains(cm.getResource()) && cm.isOutside()) { - outsideOutputResource = true; // Regarded as push transfer. - break; + if (resourceNode.getInSideResources().contains(cm.getResource())) { + dstResPath = cm.getResource(); + if (cm.isOutside()) { + outsideOutputResource = true; // Regarded as push transfer. + break; + } } } if ((((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH && !outsideInputResource) || outsideOutputResource) { // for push data transfer // Declare an update method in the type of the destination resource. - ArrayList vars = new ArrayList<>(); - vars.add(langSpec.newVariableDeclaration(srcRes.getResourceStateType(), srcRes.getResourceName())); + ArrayList parameters = new ArrayList<>(); + for (Expression exp: dstResPath.getPathParams()) { + if (exp instanceof Variable) { + Variable pathVar = (Variable) exp; + VariableDeclaration pathParam = langSpec.newVariableDeclaration(pathVar.getType(), pathVar.getName()); + parameters.add(pathParam); // A path parameter to identify the self resource. + } + } + for (Selector selector: ch.getAllSelectors()) { + if (selector.getExpression() instanceof Variable) { + Variable selVar = (Variable) selector.getExpression(); + VariableDeclaration chParam = langSpec.newVariableDeclaration(selVar.getType(), selVar.getName()); + parameters.add(chParam); // A channel parameter to specify the context of the collaboration. + } + } + parameters.add(langSpec.newVariableDeclaration(srcResPath.getResourceStateType(), srcResPath.getResourceName())); // The state of the source resource to carry the data-flow. // For the refs. for (ResourcePath ref: ch.getReferenceResources()) { if (!resourceNode.getInSideResources().contains(ref)) { - vars.add(langSpec.newVariableDeclaration(ref.getResourceStateType(), ref.getResourceName())); + parameters.add(langSpec.newVariableDeclaration(ref.getResourceStateType(), ref.getResourceName())); } } MethodDeclaration update = null; @@ -790,7 +808,7 @@ } } if (update == null) { - update = langSpec.newMethodDeclaration(updateMethodPrefix + from + srcResComponentName, false, null, vars); + update = langSpec.newMethodDeclaration(updateMethodPrefix + from + srcResComponentName, false, null, parameters); component.addMethod(update); } } else if (parentComponent != null) { @@ -801,7 +819,7 @@ } } if (update == null) { - update = langSpec.newMethodDeclaration(updateMethodPrefix + resComponentName + from + srcResComponentName, false, null, vars); + update = langSpec.newMethodDeclaration(updateMethodPrefix + resComponentName + from + srcResComponentName, false, null, parameters); parentComponent.addMethod(update); } } @@ -895,9 +913,9 @@ if (langSpec.declareField()) { // Declare the cache field. FieldDeclaration cacheField = langSpec.newFieldDeclaration( - srcRes.getResourceStateType(), - srcRes.getResourceName(), - langSpec.getFieldInitializer(srcRes.getResourceStateType(), srcRes.getResourceHierarchy().getInitialValue())); + srcResPath.getResourceStateType(), + srcResPath.getResourceName(), + langSpec.getFieldInitializer(srcResPath.getResourceStateType(), srcResPath.getResourceHierarchy().getInitialValue())); if (component != null) { component.addField(cacheField); } else if (parentComponent != null){ @@ -934,7 +952,7 @@ if (resourcePaths != null && resourcePaths.size() > 0) { for (ChannelMember outsideMember: outsideInputMembers) { for (ChannelMember dependingMember: resourcePaths.get(outsideMember).getValue()) { - if (dependingMember.getResource().equals(srcRes)) { + if (dependingMember.getResource().equals(srcResPath)) { // An outside input resource path depends on srcRes. ResourcePath outsidePath = resourcePaths.get(outsideMember).getKey(); String outsideResName = langSpec.toVariableName(getComponentName(outsidePath.getResourceHierarchy(), langSpec)); @@ -990,15 +1008,34 @@ ResourceNode dstNode = ((ResourceNode) chToRes2.getDestination()); // Check if the output resource is outside of the channel scope. boolean outsideOutputResource2 = false; + ChannelMember out = null; for (ChannelMember cm: ch2.getOutputChannelMembers()) { - if (dstNode.getInSideResources().contains(cm.getResource()) && cm.isOutside()) { - outsideOutputResource2 = true; + if (dstNode.getInSideResources().contains(cm.getResource())) { + out = cm; + if (cm.isOutside()) { + outsideOutputResource2 = true; + break; + } } } if ((((PushPullAttribute) dOut.getAttribute()).getOptions().get(0) == PushPullValue.PUSH && !outsideInputResource2) || outsideOutputResource2) { // PUSH transfer - Map> referredResources = new HashMap<>(); - List params = new ArrayList<>(); + List params = new ArrayList<>(); + // Values of path parameters. + for (Expression pathParam: out.getResource().getPathParams()) { + if (pathParam instanceof Variable) { + Variable pathVar = (Variable) pathParam; + params.add(pathVar.getName()); + } + } + // Values of channel parameters. + for (Selector selector: ch.getAllSelectors()) { + if (selector.getExpression() instanceof Variable) { + Variable selVar = (Variable) selector.getExpression(); + params.add(selVar.getName()); + } + } + // Value of the source side (input side) resource. ResourceHierarchy srcRes2 = resourceNode.getResourceHierarchy(); if (generatesComponent(srcRes2)) { params.add(langSpec.getFieldAccessor(fieldOfResourceState)); @@ -1006,6 +1043,7 @@ params.add(langSpec.getFieldAccessor(langSpec.toVariableName(srcRes2.getResourceName()))); srcRes2 = srcRes2.getParent(); } + Map> referredResources = new HashMap<>(); Set referredSet = referredResources.get(update); for (ChannelMember rc: ch2.getReferenceChannelMembers()) { // to get the value of reference member. @@ -1134,32 +1172,36 @@ // Declare an input method in this component. ArrayList resInputParams = new ArrayList<>(); ArrayList mainInputParams = new ArrayList<>(); + // The path parameters are not to be passed to the input method of each resource (resInputParams) + // because they are always equal to either channel selectors or message parameters. + + // Channel parameters to specify the context of the collaboration. int v = 1; - if (out.getResource().getLastParam() != null) { - Expression param = out.getResource().getLastParam(); - if (param instanceof Variable) { - Variable var = (Variable) param; - resInputParams.add(langSpec.newVariableDeclaration(var.getType(), var.getName())); - mainInputParams.add(langSpec.newVariableDeclaration(var.getType(), var.getName())); - } else if (param instanceof Term) { - Term var = (Term) param; + for (Selector selector: ch.getSelectors()) { + if (selector.getExpression() instanceof Variable) { + Variable selVar = (Variable) selector.getExpression(); + resInputParams.add(langSpec.newVariableDeclaration(selVar.getType(), selVar.getName())); + mainInputParams.add(langSpec.newVariableDeclaration(selVar.getType(), selVar.getName())); + } else if (selector.getExpression() instanceof Term) { + Term var = (Term) selector.getExpression(); resInputParams.add(langSpec.newVariableDeclaration(var.getType(), "v" + v)); - mainInputParams.add(langSpec.newVariableDeclaration(var.getType(), "v" + v)); + mainInputParams.add(langSpec.newVariableDeclaration(var.getType(), "v" + v)); } v++; } - if (out.getResource().getParent() != null) { - for (Expression param: out.getResource().getParent().getPathParams()) { - if (param instanceof Variable) { - Variable var = (Variable) param; - mainInputParams.add(langSpec.newVariableDeclaration(var.getType(), var.getName())); - } else if (param instanceof Term) { - Term var = (Term) param; - mainInputParams.add(langSpec.newVariableDeclaration(var.getType(), "v" + v)); + if (ch.getParent() != null) { + for (Selector selector: ch.getParent().getAllSelectors()) { + if (selector.getExpression() instanceof Variable) { + Variable selVar = (Variable) selector.getExpression(); + mainInputParams.add(langSpec.newVariableDeclaration(selVar.getType(), selVar.getName())); + } else if (selector.getExpression() instanceof Term) { + Term var = (Term) selector.getExpression(); + mainInputParams.add(langSpec.newVariableDeclaration(var.getType(), "v" + v)); } v++; } } + // Message parameters to carry the data-flows. for (Map.Entry varEnt: message.getVariables().entrySet()) { Variable var = varEnt.getValue(); String refVarName = null; @@ -1345,6 +1387,14 @@ resExp = ((Term) resExp).getChild(0); } String resourceAccess = resExp.toImplementation(new String[] {null}); + // Values of channel parameters. + for (Selector selector: ch.getAllSelectors()) { + if (selector.getExpression() instanceof Variable) { + Variable selVar = (Variable) selector.getExpression(); + args.add(selVar.getName()); + } + } + // Values of message parameters. if (message instanceof Term) { for (Map.Entry varEnt: message.getVariables().entrySet()) { String refVarName = null; @@ -1452,15 +1502,35 @@ ResourceNode dstNode = ((ResourceNode) chToRes.getDestination()); // Check if the output resource is outside of the channel scope. boolean outsideOutputResource2 = false; + ChannelMember out2 = null; for (ChannelMember cm: ch2.getOutputChannelMembers()) { - if (dstNode.getInSideResources().contains(cm.getResource()) && cm.isOutside()) { - outsideOutputResource2 = true; + if (dstNode.getInSideResources().contains(cm.getResource())) { + out2 = cm; + if (cm.isOutside()) { + outsideOutputResource2 = true; + break; + } } } if ((((PushPullAttribute) dOut.getAttribute()).getOptions().get(0) == PushPullValue.PUSH && !outsideInputResource2) || outsideOutputResource2) { // PUSH transfer Map> referredResources = new HashMap<>(); List params = new ArrayList<>(); + // Values of path parameters. + for (Expression pathParam: out2.getResource().getPathParams()) { + if (pathParam instanceof Variable) { + Variable pathVar = (Variable) pathParam; + params.add(pathVar.getName()); + } + } + // Values of channel parameters. + for (Selector selector: ch2.getAllSelectors()) { + if (selector.getExpression() instanceof Variable) { + Variable selVar = (Variable) selector.getExpression(); + params.add(selVar.getName()); + } + } + // Value of the source side (input side) resource. ResourceHierarchy srcRes = resourceNode.getResourceHierarchy(); if (generatesComponent(srcRes)) { params.add(langSpec.getFieldAccessor(fieldOfResourceState));