diff --git a/AlgebraicDataflowArchitectureModel/models/TravelDistance.model b/AlgebraicDataflowArchitectureModel/models/TravelDistance.model new file mode 100644 index 0000000..a0c8fe2 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/models/TravelDistance.model @@ -0,0 +1,13 @@ +channel CX { + out pos_x(prev_x: Double, setX(cur_x: Double)) == cur_x +} + +channel CY { + out pos_y(prev_y: Double, setY(cur_y: Double)) == cur_y +} + +channel C { + in pos_x(prev_x, move(dx, dy)) == prev_x + dx + in pos_y(prev_y, move(dx, dy)) == prev_y + dy + out dist(prev_d, move(dx, dy)) == prev_d + sqrt(dx * dx + dy * dy) +} diff --git a/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java index 85973e0..87cd8a4 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java @@ -493,8 +493,8 @@ targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } - // for reference channel member - return new Parameter(targetRes.getResourceName(), + // use the cached value as the current state + return new Field(targetRes.getResourceName(), targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } diff --git a/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java b/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java index 0bd7352..ab7c0a9 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java @@ -684,8 +684,9 @@ } // Declare the field to cache the state of the source resource in the type of the destination resource. - if (resToCh.getDestination().getIndegree() > 1) { - // If incoming edges are multiple + if (resToCh.getDestination().getIndegree() > 1 + || (resToCh.getDestination().getIndegree() == 1 && ch.getInputChannelMembers().iterator().next().getStateTransition().isRightPartial())) { + // If incoming edges are multiple, or the current state of an input member is needed. if (langSpec.declareField()) { // Declare the cache field. FieldDeclaration cacheField = langSpec.newFieldDeclaration( @@ -702,7 +703,7 @@ // Update the cache field. String cashStatement = langSpec.getFieldAccessor(langSpec.toVariableName(srcResName)) + langSpec.getAssignment() + langSpec.toVariableName(srcResName) + langSpec.getStatementDelimiter(); if (update.getBody() == null || !update.getBody().getStatements().contains(cashStatement)) { - update.addFirstStatement(cashStatement); + update.addStatement(cashStatement); } } diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java index b383fb1..034f160 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java @@ -187,11 +187,13 @@ fieldInitializer += toVariableName(resName) + ","; f = true; } else { - if (re.getDestination().getIndegree() > 1) { - // Declare a field to cash the state of the source resource in the type of the destination resource. - ResourcePath cashRes = ((ResourceNode) re.getSource()).getOutSideResource(); + ChannelNode cn = (ChannelNode) re.getDestination(); + if (cn.getIndegree() > 1 + || (cn.getIndegree() == 1 && cn.getChannel().getInputChannelMembers().iterator().next().getStateTransition().isRightPartial())) { + // Declare a field to cache the state of the source resource in the type of the destination resource. + ResourcePath cacheRes = ((ResourceNode) re.getSource()).getOutSideResource(); component.addField(new FieldDeclaration( - cashRes.getResourceStateType(), ((ResourceNode) re.getSource()).getOutSideResource().getResourceName(), getInitializer(cashRes))); + cacheRes.getResourceStateType(), ((ResourceNode) re.getSource()).getOutSideResource().getResourceName(), getInitializer(cacheRes))); } } } @@ -1008,8 +1010,8 @@ targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } - // for reference channel member - return new Parameter(targetRes.getResourceName(), + // use the cached value as the current state + return new Field(targetRes.getResourceName(), targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java index b4fde5e..42788c6 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java @@ -127,11 +127,12 @@ update.addFirstStatement(updateStatement); } } - if (resToCh.getDestination().getIndegree() > 1) { - // update a cash of src side resource (when incoming edges are multiple) - String cashStatement = "this." + JavaCodeGenerator.toVariableName(srcResourceName) + " = " + JavaCodeGenerator.toVariableName(srcResourceName) + ";"; - if (update.getBody() == null || !update.getBody().getStatements().contains(cashStatement)) { - update.addFirstStatement(cashStatement); + if (resToCh.getDestination().getIndegree() > 1 + || (resToCh.getDestination().getIndegree() == 1 && ch.getInputChannelMembers().iterator().next().getStateTransition().isRightPartial())) { + // update a cache of src side resource (when incoming edges are multiple) + String cacheStatement = "this." + JavaCodeGenerator.toVariableName(srcResourceName) + " = " + JavaCodeGenerator.toVariableName(srcResourceName) + ";"; + if (update.getBody() == null || !update.getBody().getStatements().contains(cacheStatement)) { + update.addStatement(cacheStatement); } } if (((StoreAttribute) dst.getAttribute()).isStored()) { diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java index 89f87e9..c5eb874 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java @@ -270,12 +270,15 @@ } } } - if (re.getDestination().getIndegree() > 1) { - // For each source resource, a child resource is defined in the destination resource so that its state can be updated separately. - update.addAnnotation(new Annotation("Path", "\"/" + srcName + "\"")); - // Declare a field to cash the state of the source resource in the type of the destination resource. - ResourcePath cashRes = ((ResourceNode) re.getSource()).getOutSideResource(); - component.addField(new FieldDeclaration(cashRes.getResourceStateType(), srcName, getInitializer(cashRes))); + if (re.getDestination().getIndegree() > 1 + || (re.getDestination().getIndegree() == 1 && ch.getInputChannelMembers().iterator().next().getStateTransition().isRightPartial())) { + // Declare a field to cache the state of the source resource in the type of the destination resource. + ResourcePath cacheRes = ((ResourceNode) re.getSource()).getOutSideResource(); + component.addField(new FieldDeclaration(cacheRes.getResourceStateType(), srcName, getInitializer(cacheRes))); + if (re.getDestination().getIndegree() > 1) { + // For each source resource, a child resource is defined in the destination resource so that its state can be updated separately. + update.addAnnotation(new Annotation("Path", "\"/" + srcName + "\"")); + } } component.addMethod(update); } @@ -906,7 +909,10 @@ targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } - return null; + // use the cached value as the current state + return new Field(targetRes.getResourceName(), + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); } @Override @@ -937,6 +943,7 @@ return getDirectStateAccessorFor(targetRes, fromRes); } } + // for reference channel member return new Parameter(targetRes.getResourceName(), targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java index 35c57b8..60c64c3 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java @@ -148,11 +148,12 @@ update.addFirstStatement(updateStatement); } } - if (resToCh.getDestination().getIndegree() > 1) { - // update a cash of src side resource (when incoming edges are multiple) - String cashStatement = "this." + JerseyCodeGenerator.toVariableName(srcResourceName) + " = " + JerseyCodeGenerator.toVariableName(srcResourceName) + ";"; - if (update.getBody() == null || !update.getBody().getStatements().contains(cashStatement)) { - update.addFirstStatement(cashStatement); + if (resToCh.getDestination().getIndegree() > 1 + || (resToCh.getDestination().getIndegree() == 1 && ch.getInputChannelMembers().iterator().next().getStateTransition().isRightPartial())) { + // update a cache of src side resource (when incoming edges are multiple) + String cacheStatement = "this." + JerseyCodeGenerator.toVariableName(srcResourceName) + " = " + JerseyCodeGenerator.toVariableName(srcResourceName) + ";"; + if (update.getBody() == null || !update.getBody().getStatements().contains(cacheStatement)) { + update.addStatement(cacheStatement); } } // to convert a json param to a tuple, pair or map object. diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/StateTransition.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/StateTransition.java index 0186360..997d1f6 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/StateTransition.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/StateTransition.java @@ -44,11 +44,22 @@ } public boolean isRightUnary() { - for (Position pos : curStateExpression.getVariables().keySet()) { - if (nextStateExpression.contains(curStateExpression.getVariables().get(pos))) return false; + for (Variable var: curStateExpression.getVariables().values()) { + if (nextStateExpression.contains(var)) return false; } return true; } + + public boolean isRightPartial() { + for (Variable var: curStateExpression.getVariables().values()) { + if (messageExpression.contains(var)) return true; + } + if (isRightUnary()) return false; + for (Variable var: messageExpression.getVariables().values()) { + if (nextStateExpression.contains(var)) return true; + } + return false; + } public Expression deriveMessageConstraintFor(Expression curStateValue, Expression nextStateValue, Set substitutedPositions) throws InvalidMessage, ResolvingMultipleDefinitionIsFutureWork { HashMap> bindings = new HashMap<>();