diff --git a/AlgebraicDataflowArchitectureModel/models/JumpGame.model b/AlgebraicDataflowArchitectureModel/models/JumpGame.model new file mode 100644 index 0000000..c4b525d --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/models/JumpGame.model @@ -0,0 +1,61 @@ +channel CIO { + out force(f:Tuple, gravity(y:Double)) == tuple(0.0, y) + out time(t:Double, gravity(y)) == t + 0.01 + out force(f, e) == f2 + out time(t, e) == t +} + +channel CIO2 { + out move(v:Tuple, moveX(x:Double)) == tuple(x, snd(v)) + out move(v, moveY(y:Double)) == tuple(fst(v), y) + out move(v, e) == v2 +} + +channel CIO3 { + out mass(m:Double, setMass(x:Double)) == x + out mass(m, e) == m +} + +channel CIO4 { + out ground(g:Bool, openHole) == false + out ground(g, closeHole) == true + out ground(g, e) == g +} + +channel C1 { + in force(f, update1(f2, m2)) == f2 + in mass(m, update1(f2, m2)) == m2 + out acceleration(a:Tuple, update1(f2, m2)) == tuple(fst(f2) / m2, snd(f2) / m2) +} + +channel C2 { + ref position(p, update2(p, g2)) + in ground(g, update2(p, g2)) == g2 + out onground(o:Bool, update2(p, g2)) == and(eq(g2, true), le(snd(p), 0.0)) +} + +channel C3 { + in acceleration(a, update3(a2, o2)) == a2 + in onground(o, update3(a2, o2)) == o2 + out velocity(v:Tuple, update3(a2, o2)) == if(and(o2, lt(snd(v), 0.0)), tuple(fst(v) + 0.01 * fst(a2), 0.0), + tuple(fst(v) + 0.01 * fst(a2), snd(v) + 0.01 * snd(a2))) +} + +channel C4 { + in move(m, update4(m2, o2)) == m2 + in onground(o, update4(m2, o2)) == o2 + out velocity(v:Tuple, update4(m2, o2)) == if(o2, m2, v) +} + +channel C5 { + in velocity(v, update5(v2, o2)) == v2 + in onground(o, update5(v2, o2)) == o2 + out position(p:Tuple, update5(v2, o2)) == if(and(o2, lt(snd(p), 0.0)), tuple(fst(p) + 0.01 * fst(v2), 0.0), + tuple(fst(p) + 0.01 * fst(v2), snd(p) + 0.01 * snd(v2))) +} + +channel C6 { + in position(p, update6(p2)) == p2 + out clear(c:Bool, update6(p2)) == if(gt(fst(p2), 100.0), true, false) + out gameover(g:Bool, update6(p2)) == if(lt(snd(p2), -1.0), true, false) +} diff --git a/AlgebraicDataflowArchitectureModel/src/algorithms/JavaCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/algorithms/JavaCodeGenerator.java index 623cf06..dd7b919 100644 --- a/AlgebraicDataflowArchitectureModel/src/algorithms/JavaCodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/algorithms/JavaCodeGenerator.java @@ -395,7 +395,11 @@ target.getResourceStateType() != null ? target.getResourceStateType() : DataConstraintModel.typeInt); } - return null; + // for reference channel member + Term getter = new Term(new Symbol("get" + target.getResourceName().substring(0, 1).toUpperCase() + + target.getResourceName().substring(1), 1, Symbol.Type.METHOD)); + getter.addChild(new Field(target.getResourceName(), target.getResourceStateType())); + return getter; } @Override diff --git a/AlgebraicDataflowArchitectureModel/src/algorithms/JavaMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/algorithms/JavaMethodBodyGenerator.java index d8a8d9c..4278567 100644 --- a/AlgebraicDataflowArchitectureModel/src/algorithms/JavaMethodBodyGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/algorithms/JavaMethodBodyGenerator.java @@ -59,8 +59,22 @@ // for push data transfer MethodDeclaration update = getUpdateMethod(dstType, srcType); if (((StoreAttribute) dst.getAttribute()).isStored()) { - // update stored state of dst resource (when every incoming edge is in push style) - Expression updateExp = d.getChannelGenerator().deriveUpdateExpressionOf(out, JavaCodeGenerator.pushAccessor); + // update stored state of dst side resource (when every incoming edge is in push style) + Expression updateExp = null; + if (d.getChannelGenerator().getReferenceChannelMembers().size() == 0) { + updateExp = d.getChannelGenerator().deriveUpdateExpressionOf(out, JavaCodeGenerator.pushAccessor); + } else { + // if there exists one or more reference channel member. + HashMap inputIdentifierToStateAccessor = new HashMap<>(); + for (Edge eIn: dst.getInEdges()) { + ResourceDependency dIn = (ResourceDependency) eIn; + inputIdentifierToStateAccessor.put(((ResourceNode) dIn.getSource()).getIdentifierTemplate(), JavaCodeGenerator.pushAccessor); + } + for (ChannelMember c: d.getChannelGenerator().getReferenceChannelMembers()) { + inputIdentifierToStateAccessor.put(c.getIdentifierTemplate(), JavaCodeGenerator.pullAccessor); // by pull transfer + } + updateExp = d.getChannelGenerator().deriveUpdateExpressionOf(out, JavaCodeGenerator.pushAccessor, inputIdentifierToStateAccessor); + } String[] sideEffects = new String[] {""}; String curState = updateExp.toImplementation(sideEffects); String updateStatement; @@ -74,7 +88,7 @@ } } if (dst.getIndegree() > 1) { - // update a cash of src resource (when incoming edges are multiple) + // update a cash of src side resource (when incoming edges are multiple) String cashStatement = "this." + srcResourceName + " = " + srcResourceName + ";"; if (update.getBody() == null || !update.getBody().getStatements().contains(cashStatement)) { update.addFirstStatement(cashStatement); @@ -108,7 +122,12 @@ inputIdentifierToStateAccessor.put(((ResourceNode) dIn.getSource()).getIdentifierTemplate(), JavaCodeGenerator.pullAccessor); } } + // for reference channel members + for (ChannelMember c: d.getChannelGenerator().getReferenceChannelMembers()) { + inputIdentifierToStateAccessor.put(c.getIdentifierTemplate(), JavaCodeGenerator.pullAccessor); // by pull data transfer + } String[] sideEffects = new String[] {""}; + // generate a return statement. if (!isContainedPush) { // All incoming edges are in PULL style. String curState = d.getChannelGenerator().deriveUpdateExpressionOf(out, JavaCodeGenerator.pullAccessor).toImplementation(sideEffects); diff --git a/AlgebraicDataflowArchitectureModel/src/algorithms/JerseyCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/algorithms/JerseyCodeGenerator.java index dfd8574..65ae736 100644 --- a/AlgebraicDataflowArchitectureModel/src/algorithms/JerseyCodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/algorithms/JerseyCodeGenerator.java @@ -286,7 +286,10 @@ target.getResourceStateType() != null ? target.getResourceStateType() : DataConstraintModel.typeInt); } - return null; + // for reference channel member + return new Parameter(target.getResourceName(), + target.getResourceStateType() != null ? target.getResourceStateType() + : DataConstraintModel.typeInt); } @Override diff --git a/AlgebraicDataflowArchitectureModel/src/algorithms/JerseyMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/algorithms/JerseyMethodBodyGenerator.java index edc2624..c7e5ae5 100644 --- a/AlgebraicDataflowArchitectureModel/src/algorithms/JerseyMethodBodyGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/algorithms/JerseyMethodBodyGenerator.java @@ -25,6 +25,7 @@ import models.dataConstraintModel.ChannelGenerator; import models.dataConstraintModel.ChannelMember; import models.dataConstraintModel.DataConstraintModel; +import models.dataConstraintModel.IdentifierTemplate; import models.dataFlowModel.DataFlowModel; import models.dataFlowModel.DataflowChannelGenerator; import models.dataFlowModel.PushPullAttribute; @@ -34,6 +35,7 @@ import models.dataFlowModel.ResourceDependencyGraph; import models.dataFlowModel.ResourceNode; import models.dataFlowModel.StoreAttribute; +import models.dataFlowModel.DataflowChannelGenerator.IResourceStateAccessor; public class JerseyMethodBodyGenerator { private static String baseURL = "http://localhost:8080"; @@ -65,8 +67,22 @@ // for push data transfer MethodDeclaration update = getUpdateMethod(dstType, srcType); if (((StoreAttribute) dst.getAttribute()).isStored()) { - // update stored state of dst resource (when every incoming edge is in push style) - Expression updateExp = d.getChannelGenerator().deriveUpdateExpressionOf(out, JerseyCodeGenerator.pushAccessor); + // update stored state of dst side resource (when every incoming edge is in push style) + Expression updateExp = null; + if (d.getChannelGenerator().getReferenceChannelMembers().size() == 0) { + updateExp = d.getChannelGenerator().deriveUpdateExpressionOf(out, JerseyCodeGenerator.pushAccessor); + } else { + // if there exists one or more reference channel member. + HashMap inputIdentifierToStateAccessor = new HashMap<>(); + for (Edge eIn: dst.getInEdges()) { + ResourceDependency dIn = (ResourceDependency) eIn; + inputIdentifierToStateAccessor.put(((ResourceNode) dIn.getSource()).getIdentifierTemplate(), JerseyCodeGenerator.pushAccessor); + } + for (ChannelMember c: d.getChannelGenerator().getReferenceChannelMembers()) { + inputIdentifierToStateAccessor.put(c.getIdentifierTemplate(), JerseyCodeGenerator.pullAccessor); + } + updateExp = d.getChannelGenerator().deriveUpdateExpressionOf(out, JerseyCodeGenerator.pushAccessor, inputIdentifierToStateAccessor); + } String[] sideEffects = new String[] {""}; String curState = updateExp.toImplementation(sideEffects); String updateStatement; @@ -76,11 +92,20 @@ updateStatement = sideEffects[0] + dstResourceName + " = " + curState + ";"; } if (update.getBody() == null || !update.getBody().getStatements().contains(updateStatement)) { + // add an update statement of the statement of dst side resource. update.addFirstStatement(updateStatement); + if (d.getChannelGenerator().getReferenceChannelMembers().size() > 0) { + // For each reference channel member, get the current state of the reference side resource by pull data transfer. + for (ChannelMember c: d.getChannelGenerator().getReferenceChannelMembers()) { + String refResourceName = c.getIdentifierTemplate().getResourceName(); + Type refResourceType = c.getIdentifierTemplate().getResourceStateType(); + generatePullDataTransfer(update, refResourceName, refResourceType); + } + } } } if (dst.getIndegree() > 1) { - // update a cash of src resource (when incoming edges are multiple) + // update a cash of src side resource (when incoming edges are multiple) String cashStatement = "this." + srcResourceName + " = " + srcResourceName + ";"; if (update.getBody() == null || !update.getBody().getStatements().contains(cashStatement)) { update.addFirstStatement(cashStatement); @@ -165,37 +190,20 @@ // for pull (or push/pull) data transfer MethodDeclaration getter = getGetterMethod(dstType); if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { + // generate a return statement. String[] sideEffects = new String[] {""}; - String curState = d.getChannelGenerator().deriveUpdateExpressionOf(out, JerseyCodeGenerator.pullAccessor).toImplementation(sideEffects); + String curState = d.getChannelGenerator().deriveUpdateExpressionOf(out, JerseyCodeGenerator.pullAccessor).toImplementation(sideEffects); // no pull data transfer is included. getter.addStatement(sideEffects[0] + "return " + curState + ";"); + // For each reference channel member, get the current state of the reference side resource by pull data transfer. + for (ChannelMember c: d.getChannelGenerator().getReferenceChannelMembers()) { + String refResourceName = c.getIdentifierTemplate().getResourceName(); + Type refResourceType = c.getIdentifierTemplate().getResourceStateType(); + generatePullDataTransfer(getter, refResourceName, refResourceType); + } } // get src side resource state by pull data transfer. - String varName = new String(srcResourceName); Type srcResourceType = src.getIdentifierTemplate().getResourceStateType(); - String respTypeName = srcResourceType.getInterfaceTypeName(); - String respConverter = ""; - if (DataConstraintModel.typeList.isAncestorOf(srcResourceType) && srcResourceType != DataConstraintModel.typeList) { - Type compType = TypeInference.getListComponentType(srcResourceType); - if (DataConstraintModel.typeTuple.isAncestorOf(compType)) { - varName += "_json"; - String mapTypeName = convertFromEntryToMapType(compType); - respTypeName = "List<" + mapTypeName + ">"; - respConverter += srcResourceType.getInterfaceTypeName() + " " + srcResourceName + " = new " + srcResourceType.getImplementationTypeName() + "();\n"; - respConverter += "for (" + mapTypeName + " i: " + varName + ") {\n"; - respConverter += "\t" + srcResourceName + ".add(" + getCodeForConversionFromMapToTuple(compType, "i") + ");\n"; - respConverter += "}"; - getter.addThrow("JsonProcessingException"); - } - } else if (DataConstraintModel.typeTuple.isAncestorOf(srcResourceType)) { - varName += "_json"; - respTypeName = convertFromEntryToMapType(srcResourceType); - respConverter += srcResourceName + " = " + getCodeForConversionFromMapToTuple(srcResourceType, varName) + ";"; - getter.addThrow("JsonProcessingException"); - } - if (respConverter.length() > 0) { - getter.addFirstStatement(respConverter); - } - getter.addFirstStatement(respTypeName + " " + varName + " = " + getHttpMethodCallStatementWithResponse(baseURL, srcResourceName, "get", srcResourceType.getImplementationTypeName())); + generatePullDataTransfer(getter, srcResourceName, srcResourceType); } } } @@ -241,6 +249,34 @@ return codes; } + private static void generatePullDataTransfer(MethodDeclaration methodBody, String fromResourceName, Type fromResourceType) { + String varName = new String(fromResourceName); + String respTypeName = fromResourceType.getInterfaceTypeName(); + String respConverter = ""; + if (DataConstraintModel.typeList.isAncestorOf(fromResourceType) && fromResourceType != DataConstraintModel.typeList) { + Type compType = TypeInference.getListComponentType(fromResourceType); + if (DataConstraintModel.typeTuple.isAncestorOf(compType)) { + varName += "_json"; + String mapTypeName = convertFromEntryToMapType(compType); + respTypeName = "List<" + mapTypeName + ">"; + respConverter += fromResourceType.getInterfaceTypeName() + " " + fromResourceName + " = new " + fromResourceType.getImplementationTypeName() + "();\n"; + respConverter += "for (" + mapTypeName + " i: " + varName + ") {\n"; + respConverter += "\t" + fromResourceName + ".add(" + getCodeForConversionFromMapToTuple(compType, "i") + ");\n"; + respConverter += "}"; + methodBody.addThrow("JsonProcessingException"); + } + } else if (DataConstraintModel.typeTuple.isAncestorOf(fromResourceType)) { +// varName += "_json"; + respTypeName = fromResourceType.getInterfaceTypeName(); +// respConverter += fromResourceName + " = " + getCodeForConversionFromMapToTuple(fromResourceType, varName) + ";"; +// methodBody.addThrow("JsonProcessingException"); + } + if (respConverter.length() > 0) { + methodBody.addFirstStatement(respConverter); + } + methodBody.addFirstStatement(respTypeName + " " + varName + " = " + getHttpMethodCallStatementWithResponse(baseURL, fromResourceName, "get", fromResourceType.getImplementationTypeName())); + } + private static String convertFromEntryToMapType(Type type) { String mapTypeName = type.getInterfaceTypeName(); mapTypeName = mapTypeName.replace("Map.Entry", "Map"); diff --git a/AlgebraicDataflowArchitectureModel/src/algorithms/TypeInference.java b/AlgebraicDataflowArchitectureModel/src/algorithms/TypeInference.java index 8bf79c6..3eaffde 100644 --- a/AlgebraicDataflowArchitectureModel/src/algorithms/TypeInference.java +++ b/AlgebraicDataflowArchitectureModel/src/algorithms/TypeInference.java @@ -165,7 +165,7 @@ List allVariables = new ArrayList<>(); allVariables.addAll(st.getCurStateExpression().getVariables().values()); allVariables.addAll(st.getMessageExpression().getVariables().values()); - allVariables.addAll(st.getNextStateExpression().getVariables().values()); + if (st.getNextStateExpression() != null) allVariables.addAll(st.getNextStateExpression().getVariables().values()); for (Variable var: allVariables) { List sameVariable = locals.get(var.getName()); if (sameVariable == null) { diff --git a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/editor/Editor.java b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/editor/Editor.java index 16a15a6..367ae7c 100644 --- a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/editor/Editor.java +++ b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/editor/Editor.java @@ -29,7 +29,7 @@ import parser.ExpectedChannel; import parser.ExpectedChannelName; import parser.ExpectedEquals; -import parser.ExpectedInOrOutKeyword; +import parser.ExpectedInOrOutOrRefKeyword; import parser.ExpectedLeftCurlyBracket; import parser.ExpectedRHSExpression; import parser.ExpectedRightBracket; @@ -99,7 +99,7 @@ resourceDependencyGraph = SelectableDataTransfers.init(resourceGraph); graph = constructGraph(model, resourceDependencyGraph); return model; - } catch (ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket | ExpectedInOrOutKeyword + } catch (ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket | ExpectedInOrOutOrRefKeyword | ExpectedStateTransition | ExpectedEquals | ExpectedRHSExpression | WrongLHSExpression | WrongRHSExpression | ExpectedRightBracket e) { e.printStackTrace(); diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java index f063173..2061f71 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java @@ -54,6 +54,8 @@ public static final Symbol neq = new Symbol("neq", 2, Symbol.Type.PREFIX, "!=", Symbol.Type.INFIX); public static final Symbol gt = new Symbol("gt", 2, Symbol.Type.PREFIX, ">", Symbol.Type.INFIX); public static final Symbol lt = new Symbol("lt", 2, Symbol.Type.PREFIX, "<", Symbol.Type.INFIX); + public static final Symbol ge = new Symbol("ge", 2, Symbol.Type.PREFIX, ">=", Symbol.Type.INFIX); + public static final Symbol le = new Symbol("le", 2, Symbol.Type.PREFIX, "<=", Symbol.Type.INFIX); public static final Symbol and = new Symbol("and", 2, Symbol.Type.PREFIX, "&&", Symbol.Type.INFIX); public static final Symbol or = new Symbol("or", 2, Symbol.Type.PREFIX, "||", Symbol.Type.INFIX); public static final Symbol neg = new Symbol("neg", 1, Symbol.Type.PREFIX, "!", Symbol.Type.PREFIX); @@ -84,6 +86,12 @@ contains.setSignature(new Type[] {typeBoolean, typeList, null}); get.setSignature(new Type[] {null, typeList, typeInt}); set.setSignature(new Type[] {typeList, typeList, typeInt, null}); + eq.setSignature(new Type[] {null, null, typeBoolean}); + neq.setSignature(new Type[] {null, null, typeBoolean}); + gt.setSignature(new Type[] {null, null, typeBoolean}); + lt.setSignature(new Type[] {null, null, typeBoolean}); + ge.setSignature(new Type[] {null, null, typeBoolean}); + le.setSignature(new Type[] {null, null, typeBoolean}); and.setSignature(new Type[] {typeBoolean, typeBoolean, typeBoolean}); or.setSignature(new Type[] {typeBoolean, typeBoolean, typeBoolean}); neg.setSignature(new Type[] {typeBoolean, typeBoolean}); @@ -126,6 +134,8 @@ addSymbol(neq); addSymbol(gt); addSymbol(lt); + addSymbol(ge); + addSymbol(le); addSymbol(and); addSymbol(or); addSymbol(neg); diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/StateTransition.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/StateTransition.java index cf41733..e3493b5 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/StateTransition.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/StateTransition.java @@ -108,6 +108,37 @@ return messageTerm; } + public Expression deriveMessageConstraintFor(Expression curStateValue) throws InvalidMessage, ResolvingMultipleDefinitionIsFutureWork { + HashMap> bindings = new HashMap<>(); + + Expression curStateTerm = getCurStateExpression(); + HashMap curStateVars = curStateTerm.getVariables(); + for (Entry curStateVarEnt: curStateVars.entrySet()) { + Variable var = curStateVarEnt.getValue(); + Position varPos = curStateVarEnt.getKey(); + Expression valueCalc = curStateTerm.getInverseMap(curStateValue, varPos); + if (valueCalc != null) { + ArrayList values = bindings.get(var); + if (values == null) { + values = new ArrayList(); + bindings.put(var, values); + } + values.add(valueCalc); + } + } + + Expression messageTerm = getMessageExpression(); + if (!(messageTerm instanceof Term)) throw new InvalidMessage(); + HashMap messageVars = messageTerm.getVariables(); + for (Variable var: messageVars.values()) { + if (bindings.get(var) != null) { + if (bindings.get(var).size() > 1) throw new ResolvingMultipleDefinitionIsFutureWork(); + messageTerm = ((Term) messageTerm).substitute(var, bindings.get(var).iterator().next()); + } + } + return messageTerm; + } + public Expression deriveNextStateExpressionFor(Expression curStateValue, Term concreteMessage) throws ResolvingMultipleDefinitionIsFutureWork, ValueUndefined { HashMap bindings = new HashMap<>(); diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataflowChannelGenerator.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataflowChannelGenerator.java index 8ebc0a6..2839622 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataflowChannelGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataflowChannelGenerator.java @@ -18,11 +18,13 @@ public class DataflowChannelGenerator extends ChannelGenerator { protected Set inputChannelMembers = null; protected Set outputChannelMembers = null; + protected Set referenceChannelMembers = null; public DataflowChannelGenerator(String channelName) { super(channelName); inputChannelMembers = new HashSet<>(); outputChannelMembers = new HashSet<>(); + referenceChannelMembers = new HashSet<>(); } public Set getInputChannelMembers() { @@ -48,6 +50,18 @@ public void addOutputChannelMember(ChannelMember outputChannelMember) { outputChannelMembers.add(outputChannelMember); } + + public Set getReferenceChannelMembers() { + return referenceChannelMembers; + } + + public void setReferenceChannelMembers(Set referenceChannelMembers) { + this.referenceChannelMembers = referenceChannelMembers; + } + + public void addReferenceChannelMember(ChannelMember referenceChannelMember) { + referenceChannelMembers.add(referenceChannelMember); + } public void addChannelMemberAsInput(ChannelMember groupDependentResource) { addChannelMember(groupDependentResource); @@ -59,6 +73,11 @@ addOutputChannelMember(groupDependentResource); } + public void addChannelMemberAsReference(ChannelMember groupDependentResource) { + addChannelMember(groupDependentResource); + addReferenceChannelMember(groupDependentResource); + } + public Set getInputIdentifierTemplates() { Set inputIdentifierTemplates = new HashSet<>(); for (ChannelMember member: inputChannelMembers) { @@ -75,6 +94,24 @@ return outputIdentifierTemplates; } + public Set getReferenceIdentifierTemplates() { + Set referenceIdentifierTemplates = new HashSet<>(); + for (ChannelMember member: referenceChannelMembers) { + referenceIdentifierTemplates.add(member.getIdentifierTemplate()); + } + return referenceIdentifierTemplates; + } + + /** + * Derive the update expression of the state of the target channel member. + * @param targetMember a channel member whose state is to be updated + * @return the derived update expression + * @throws ParameterizedIdentifierIsFutureWork + * @throws ResolvingMultipleDefinitionIsFutureWork + * @throws InvalidMessage + * @throws UnificationFailed + * @throws ValueUndefined + */ public Expression deriveUpdateExpressionOf(ChannelMember targetMember) throws ParameterizedIdentifierIsFutureWork, ResolvingMultipleDefinitionIsFutureWork, InvalidMessage, UnificationFailed, ValueUndefined { IResourceStateAccessor defaultStateAccessor = new IResourceStateAccessor() { HashMap curStateParams = new HashMap<>(); @@ -105,6 +142,17 @@ return deriveUpdateExpressionOf(targetMember, defaultStateAccessor); } + /** + * Derive the update expression of the state of the target channel member with a given resource state accessor. + * @param targetMember a channel member whose state is to be updated + * @param stateAccessor a resource state accessor + * @return the derived update expression + * @throws ParameterizedIdentifierIsFutureWork + * @throws ResolvingMultipleDefinitionIsFutureWork + * @throws InvalidMessage + * @throws UnificationFailed + * @throws ValueUndefined + */ public Expression deriveUpdateExpressionOf(ChannelMember targetMember, IResourceStateAccessor stateAccessor) throws ParameterizedIdentifierIsFutureWork, ResolvingMultipleDefinitionIsFutureWork, InvalidMessage, UnificationFailed, ValueUndefined { return deriveUpdateExpressionOf(targetMember, stateAccessor, null); @@ -133,8 +181,24 @@ Expression messageConstraintByInput = inputMember.getStateTransition().deriveMessageConstraintFor(curInputStateAccessor, nextInputStateAccessor); messageConstraints.add((Term) messageConstraintByInput); } - - // Unify message constaints + + // Calculate message constraints from reference state transitions + for (ChannelMember referenceMember: getReferenceChannelMembers()) { + IdentifierTemplate referenceIdentifier = referenceMember.getIdentifierTemplate(); + if (referenceIdentifier.getNumberOfParameters() > 0) { + throw new ParameterizedIdentifierIsFutureWork(); + } + Expression curInputStateAccessor = null; + if (inputIdentifierToStateAccessor == null) { + curInputStateAccessor = stateAccessor.getCurrentStateAccessorFor(referenceIdentifier, targetMember.getIdentifierTemplate()); + } else { + curInputStateAccessor = inputIdentifierToStateAccessor.get(referenceIdentifier).getCurrentStateAccessorFor(referenceIdentifier, targetMember.getIdentifierTemplate()); + } + Expression messageConstraintByReference = referenceMember.getStateTransition().deriveMessageConstraintFor(curInputStateAccessor); + messageConstraints.add((Term) messageConstraintByReference); + } + + // Unify message constraints Term unifiedMessage = null; for (Term messageContraint: messageConstraints) { if (unifiedMessage == null) { diff --git a/AlgebraicDataflowArchitectureModel/src/parser/ExpectedInOrOutKeyword.java b/AlgebraicDataflowArchitectureModel/src/parser/ExpectedInOrOutKeyword.java deleted file mode 100644 index 7bd81de..0000000 --- a/AlgebraicDataflowArchitectureModel/src/parser/ExpectedInOrOutKeyword.java +++ /dev/null @@ -1,9 +0,0 @@ -package parser; - -public class ExpectedInOrOutKeyword extends ParseException { - - public ExpectedInOrOutKeyword(int line) { - super(line); - } - -} diff --git a/AlgebraicDataflowArchitectureModel/src/parser/ExpectedInOrOutOrRefKeyword.java b/AlgebraicDataflowArchitectureModel/src/parser/ExpectedInOrOutOrRefKeyword.java new file mode 100644 index 0000000..bb10522 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/parser/ExpectedInOrOutOrRefKeyword.java @@ -0,0 +1,9 @@ +package parser; + +public class ExpectedInOrOutOrRefKeyword extends ParseException { + + public ExpectedInOrOutOrRefKeyword(int line) { + super(line); + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/parser/Parser.java b/AlgebraicDataflowArchitectureModel/src/parser/Parser.java index 500d428..1cd023e 100644 --- a/AlgebraicDataflowArchitectureModel/src/parser/Parser.java +++ b/AlgebraicDataflowArchitectureModel/src/parser/Parser.java @@ -40,6 +40,7 @@ public static final String DIV_REGX = "/"; public static final String IN = "in"; public static final String OUT = "out"; + public static final String REF = "ref"; public static final String EQUALS = "=="; public static final String COMMA = ","; public static final String COLON = ":"; @@ -49,7 +50,7 @@ } public DataFlowModel doParse() - throws ExpectedRightBracket, ExpectedChannel, ExpectedChannelName, ExpectedLeftCurlyBracket, ExpectedInOrOutKeyword, ExpectedStateTransition, ExpectedEquals, ExpectedRHSExpression, WrongLHSExpression, WrongRHSExpression { + throws ExpectedRightBracket, ExpectedChannel, ExpectedChannelName, ExpectedLeftCurlyBracket, ExpectedInOrOutOrRefKeyword, ExpectedStateTransition, ExpectedEquals, ExpectedRHSExpression, WrongLHSExpression, WrongRHSExpression { TokenStream stream = new TokenStream(); try { String line; @@ -66,7 +67,7 @@ } public static DataFlowModel parseDataFlowModel(TokenStream stream) - throws ExpectedRightBracket, ExpectedChannel, ExpectedChannelName, ExpectedLeftCurlyBracket, ExpectedInOrOutKeyword, ExpectedStateTransition, ExpectedEquals, ExpectedRHSExpression, WrongLHSExpression, WrongRHSExpression { + throws ExpectedRightBracket, ExpectedChannel, ExpectedChannelName, ExpectedLeftCurlyBracket, ExpectedInOrOutOrRefKeyword, ExpectedStateTransition, ExpectedEquals, ExpectedRHSExpression, WrongLHSExpression, WrongRHSExpression { DataFlowModel model = new DataFlowModel(); DataflowChannelGenerator channel; while ((channel = parseChannel(stream, model)) != null) { @@ -80,7 +81,7 @@ } public static DataflowChannelGenerator parseChannel(TokenStream stream, DataFlowModel model) - throws ExpectedRightBracket, ExpectedChannel, ExpectedChannelName, ExpectedLeftCurlyBracket, ExpectedInOrOutKeyword, ExpectedStateTransition, ExpectedEquals, ExpectedRHSExpression, WrongLHSExpression, WrongRHSExpression { + throws ExpectedRightBracket, ExpectedChannel, ExpectedChannelName, ExpectedLeftCurlyBracket, ExpectedInOrOutOrRefKeyword, ExpectedStateTransition, ExpectedEquals, ExpectedRHSExpression, WrongLHSExpression, WrongRHSExpression { if (!stream.hasNext()) return null; String channelKeyword = stream.next(); if (!channelKeyword.equals(CHANNEL)) throw new ExpectedChannel(stream.getLine()); @@ -91,39 +92,47 @@ DataflowChannelGenerator channel = new DataflowChannelGenerator(channelName); String leftBracket = stream.next(); if (!leftBracket.equals(LEFT_CURLY_BRACKET)) throw new ExpectedLeftCurlyBracket(stream.getLine()); - String inOrOut = null; - while (stream.hasNext() && !(inOrOut = stream.next()).equals(RIGHT_CURLY_BRACKET)) { + String inOrOutOrRef = null; + while (stream.hasNext() && !(inOrOutOrRef = stream.next()).equals(RIGHT_CURLY_BRACKET)) { ChannelMember channelMember = null; - if (inOrOut.equals(IN)) { - channelMember = parseChannelMember(stream, model); + if (inOrOutOrRef.equals(IN)) { + channelMember = parseChannelMember(stream, model, inOrOutOrRef); if (channelMember != null) { channel.addChannelMemberAsInput(channelMember); } - } else if (inOrOut.equals(OUT)) { - channelMember = parseChannelMember(stream, model); + } else if (inOrOutOrRef.equals(OUT)) { + channelMember = parseChannelMember(stream, model, inOrOutOrRef); if (channelMember != null) { channel.addChannelMemberAsOutput(channelMember); } + } else if (inOrOutOrRef.equals(REF)) { + channelMember = parseChannelMember(stream, model, inOrOutOrRef); + if (channelMember != null) { + channel.addChannelMemberAsReference(channelMember); + } } else { - throw new ExpectedInOrOutKeyword(stream.getLine()); + throw new ExpectedInOrOutOrRefKeyword(stream.getLine()); } } return channel; } - public static ChannelMember parseChannelMember(TokenStream stream, DataFlowModel model) + public static ChannelMember parseChannelMember(TokenStream stream, DataFlowModel model, String inOrOutOrRef) throws ExpectedRightBracket, ExpectedStateTransition, ExpectedEquals, ExpectedRHSExpression, WrongLHSExpression, WrongRHSExpression { if (!stream.hasNext()) throw new ExpectedStateTransition(stream.getLine()); Expression leftTerm = parseTerm(stream, model); if (leftTerm == null || !(leftTerm instanceof Term)) throw new WrongLHSExpression(stream.getLine()); + Expression rightTerm = null; - if (!stream.hasNext()) throw new ExpectedEquals(stream.getLine()); - String equals = stream.next(); - if (!equals.equals(EQUALS)) throw new ExpectedEquals(stream.getLine()); - - if (!stream.hasNext()) throw new ExpectedRHSExpression(stream.getLine()); - Expression rightTerm = parseTerm(stream, model); - if (rightTerm == null) throw new WrongRHSExpression(stream.getLine()); + if (!inOrOutOrRef.equals(REF)) { + if (!stream.hasNext()) throw new ExpectedEquals(stream.getLine()); + String equals = stream.next(); + if (!equals.equals(EQUALS)) throw new ExpectedEquals(stream.getLine()); + + if (!stream.hasNext()) throw new ExpectedRHSExpression(stream.getLine()); + rightTerm = parseTerm(stream, model); + if (rightTerm == null) throw new WrongRHSExpression(stream.getLine()); + } String resourceName = ((Term) leftTerm).getSymbol().getName(); IdentifierTemplate identifier = model.getIdentifierTemplate(resourceName); @@ -135,7 +144,7 @@ StateTransition stateTransition = new StateTransition(); stateTransition.setCurStateExpression(((Term) leftTerm).getChild(0)); stateTransition.setMessageExpression(((Term) leftTerm).getChild(1)); - stateTransition.setNextStateExpression(rightTerm); + if (!inOrOutOrRef.equals(REF)) stateTransition.setNextStateExpression(rightTerm); channelMember.setStateTransition(stateTransition); // for type definition if (identifier.getResourceStateType() == null && ((Term) leftTerm).getChild(0) instanceof Variable) { diff --git a/AlgebraicDataflowArchitectureModel/src/tests/CodeGeneratorTest.java b/AlgebraicDataflowArchitectureModel/src/tests/CodeGeneratorTest.java index ffba2e3..4186c68 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/CodeGeneratorTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/CodeGeneratorTest.java @@ -25,7 +25,7 @@ FinalDecisionOfStoringResourceStates.doDecide(graph); ArrayList codetree = JavaMethodBodyGenerator.doGenerate(graph, model, JavaCodeGenerator.doGenerate(graph, model)); System.out.println(codetree); - } catch (ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket | ExpectedInOrOutKeyword + } catch (ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket | ExpectedInOrOutOrRefKeyword | ExpectedStateTransition | ExpectedEquals | ExpectedRHSExpression | WrongLHSExpression | WrongRHSExpression | ExpectedRightBracket e) { e.printStackTrace(); diff --git a/AlgebraicDataflowArchitectureModel/src/tests/DataStorageDecisionTest.java b/AlgebraicDataflowArchitectureModel/src/tests/DataStorageDecisionTest.java index e67f25c..fe2d5be 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/DataStorageDecisionTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/DataStorageDecisionTest.java @@ -25,7 +25,7 @@ for(Node n:graph.getNodes()) { System.out.println(((ResourceNode) n).getIdentifierTemplate().getResourceName() + ":" + ((StoreAttribute) ((ResourceNode) n).getAttribute()).isStored()); } - } catch (ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket | ExpectedInOrOutKeyword + } catch (ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket | ExpectedInOrOutOrRefKeyword | ExpectedStateTransition | ExpectedEquals | ExpectedRHSExpression | WrongLHSExpression | WrongRHSExpression | ExpectedRightBracket e) { e.printStackTrace(); diff --git a/AlgebraicDataflowArchitectureModel/src/tests/DataStorageNecessityTest.java b/AlgebraicDataflowArchitectureModel/src/tests/DataStorageNecessityTest.java index a4e58d6..d82ab9d 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/DataStorageNecessityTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/DataStorageNecessityTest.java @@ -11,7 +11,7 @@ import parser.ExpectedChannel; import parser.ExpectedChannelName; import parser.ExpectedEquals; -import parser.ExpectedInOrOutKeyword; +import parser.ExpectedInOrOutOrRefKeyword; import parser.ExpectedLeftCurlyBracket; import parser.ExpectedRHSExpression; import parser.ExpectedRightBracket; @@ -36,7 +36,7 @@ System.out.println(resource.toString() + ":" + ((StoreAttribute)resource.getAttribute()).isNeeded()); } } - } catch (ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket | ExpectedInOrOutKeyword + } catch (ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket | ExpectedInOrOutOrRefKeyword | ExpectedStateTransition | ExpectedEquals | ExpectedRHSExpression | WrongLHSExpression | WrongRHSExpression | ExpectedRightBracket e) { e.printStackTrace(); diff --git a/AlgebraicDataflowArchitectureModel/src/tests/EdgeTransitionSelectableTest.java b/AlgebraicDataflowArchitectureModel/src/tests/EdgeTransitionSelectableTest.java index 0d165ec..b90f5c3 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/EdgeTransitionSelectableTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/EdgeTransitionSelectableTest.java @@ -25,7 +25,7 @@ ResourceDependency re = (ResourceDependency) e; System.out.println(re.getSource() + "-" + re.getDestination() + ":" + ((PushPullAttribute)(re.getAttribute())).getOptions()); } - } catch (ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket | ExpectedInOrOutKeyword + } catch (ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket | ExpectedInOrOutOrRefKeyword | ExpectedStateTransition | ExpectedEquals | ExpectedRHSExpression | WrongLHSExpression | WrongRHSExpression | ExpectedRightBracket e) { e.printStackTrace(); diff --git a/AlgebraicDataflowArchitectureModel/src/tests/ParseTest.java b/AlgebraicDataflowArchitectureModel/src/tests/ParseTest.java index 56d3740..1a2e487 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/ParseTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/ParseTest.java @@ -16,7 +16,7 @@ import parser.ExpectedChannel; import parser.ExpectedChannelName; import parser.ExpectedEquals; -import parser.ExpectedInOrOutKeyword; +import parser.ExpectedInOrOutOrRefKeyword; import parser.ExpectedLeftCurlyBracket; import parser.ExpectedRHSExpression; import parser.ExpectedRightBracket; @@ -49,7 +49,7 @@ for (Edge e: resourceDependencyGraph.getEdges()) { System.out.println(e.getSource() + "-(" + e + ")->" + e.getDestination()); } - } catch (ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket | ExpectedInOrOutKeyword + } catch (ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket | ExpectedInOrOutOrRefKeyword | ExpectedStateTransition | ExpectedEquals | ExpectedRHSExpression | WrongLHSExpression | WrongRHSExpression | ExpectedRightBracket | ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork | InvalidMessage diff --git a/AlgebraicDataflowArchitectureModel/src/tests/UpdateConflictCheckTest.java b/AlgebraicDataflowArchitectureModel/src/tests/UpdateConflictCheckTest.java index 2816aba..5ad03af 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/UpdateConflictCheckTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/UpdateConflictCheckTest.java @@ -10,7 +10,7 @@ import parser.ExpectedChannel; import parser.ExpectedChannelName; import parser.ExpectedEquals; -import parser.ExpectedInOrOutKeyword; +import parser.ExpectedInOrOutOrRefKeyword; import parser.ExpectedLeftCurlyBracket; import parser.ExpectedRHSExpression; import parser.ExpectedRightBracket; @@ -39,7 +39,7 @@ } catch (ExpectedLeftCurlyBracket e) { // TODO Auto-generated catch block e.printStackTrace(); - } catch (ExpectedInOrOutKeyword e) { + } catch (ExpectedInOrOutOrRefKeyword e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ExpectedStateTransition e) {