diff --git a/AlgebraicDataflowArchitectureModel/models/CustomerOffice.model b/AlgebraicDataflowArchitectureModel/models/CustomerOffice.model index 4f94bd2..f140bff 100644 --- a/AlgebraicDataflowArchitectureModel/models/CustomerOffice.model +++ b/AlgebraicDataflowArchitectureModel/models/CustomerOffice.model @@ -22,12 +22,12 @@ in customerA_off(c, sync(z, u, v)) == z in companyC1_add(a1, sync(z, u, v)) == u in companyC2_add(a2, sync(z, u, v)) == v - out customerA_add(a3:String, sync(z, u, v)) == if(eq(z, C1), u, if(eq(z, C2), v, nil)) + out customerA_add(a3:String, sync(z, u, v)) == if(eq(z, C1), u, if(eq(z, C2), v, null)) } channel CB { in customerB_off(c, sync(z, u, v)) == z in companyC1_add(a1, sync(z, u, v)) == u in companyC2_add(a2, sync(z, u, v)) == v - out customerB_add(a3:String, sync(z, u, v)) == if(eq(z, C1), u, if(eq(z, C2), v, nil)) + out customerB_add(a3:String, sync(z, u, v)) == if(eq(z, C1), u, if(eq(z, C2), v, null)) } diff --git a/AlgebraicDataflowArchitectureModel/models/StockManagement.model b/AlgebraicDataflowArchitectureModel/models/StockManagement.model new file mode 100644 index 0000000..d3ed3f2 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/models/StockManagement.model @@ -0,0 +1,47 @@ +init { + stock := nil + shortage := nil +} +channel CIO_req { + out request(r:Tuple, req(item:Str, num:Int)) == tuple(item, num) +} + +channel CIO_enter { + out entering(e:Tuple, enter(item:Str, num:Int)) == tuple(item, num) +} + +channel C1 { + in request(r, update1(r2)) == r2 + out stock(st:Map, update1(r2)) == if(le(snd(r2), lookup(st, fst(r2))), + insert(st, fst(r2), lookup(st, fst(r2)) - snd(r2)), + st) + out shortage(sh:Map, update1(r2)) == if(le(snd(r2), lookup(sh, fst(r2))), + sh, + insert(sh, fst(r2), lookup(sh, fst(r2)) + snd(r2))) +} + +channel C2 { + in entering(e, update2(e2, st)) == e2 + ref stock(st, update2(e2, st)) + out shortage(sh, update2(e2, st)) == if(ge(snd(e2) + lookup(st, fst(e2)), lookup(sh, fst(e2))), + insert(sh, fst(e2), 0), + sh) +} + +channel C3 { + in entering(e, update3(e2, sh)) == e2 + ref shortage(sh, update3(e2, sh)) + out stock(st, update3(e2, sh)) == if(ge(snd(e2) + lookup(st, fst(e2)), lookup(sh, fst(e2))), + insert(st, fst(e2), snd(e2) + lookup(st, fst(e2)) - lookup(sh, fst(e2))), + insert(st, fst(e2), snd(e2) + lookup(st, fst(e2)))) +} + +channel C4 { + in entering(e, update4(e2, sh, st)) == e2 + ref shortage(sh, update4(e2, sh, st)) + ref stock(st, update4(e2, sh, st)) + out dispatching(d:Tuple, update4(e2, sh, st)) == if(and(gt(lookup(sh, fst(e2)), 0), ge(snd(e2) + lookup(st, fst(e2)), lookup(sh, fst(e2)))), + tuple(fst(e2), lookup(sh, fst(e2))), + null) +} + diff --git a/AlgebraicDataflowArchitectureModel/src/algorithms/JavaCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/algorithms/JavaCodeGenerator.java index d6bea99..6f0b0f5 100644 --- a/AlgebraicDataflowArchitectureModel/src/algorithms/JavaCodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/algorithms/JavaCodeGenerator.java @@ -332,6 +332,8 @@ } else { if (DataConstraintModel.typeList.isAncestorOf(stateType)) { initializer = "new " + resId.getResourceStateType().getImplementationTypeName() + "()"; + } else if (DataConstraintModel.typeMap.isAncestorOf(stateType)) { + initializer = "new " + resId.getResourceStateType().getImplementationTypeName() + "()"; } } return initializer; diff --git a/AlgebraicDataflowArchitectureModel/src/algorithms/JerseyCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/algorithms/JerseyCodeGenerator.java index c6ba347..7c66b96 100644 --- a/AlgebraicDataflowArchitectureModel/src/algorithms/JerseyCodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/algorithms/JerseyCodeGenerator.java @@ -256,6 +256,8 @@ } else { if (DataConstraintModel.typeList.isAncestorOf(stateType)) { initializer = "new " + resId.getResourceStateType().getImplementationTypeName() + "()"; + } else if (DataConstraintModel.typeMap.isAncestorOf(stateType)) { + initializer = "new " + resId.getResourceStateType().getImplementationTypeName() + "()"; } } return initializer; diff --git a/AlgebraicDataflowArchitectureModel/src/algorithms/TypeInference.java b/AlgebraicDataflowArchitectureModel/src/algorithms/TypeInference.java index 5c1ebbf..df93e13 100644 --- a/AlgebraicDataflowArchitectureModel/src/algorithms/TypeInference.java +++ b/AlgebraicDataflowArchitectureModel/src/algorithms/TypeInference.java @@ -35,6 +35,8 @@ static private Map> tupleComponentTypes = new HashMap<>(); static private Map pairTypes = new HashMap<>(); static private Map pairComponentTypes = new HashMap<>(); + static private Map, Type> mapTypes = new HashMap<>(); + static private Map> mapComponentTypes = new HashMap<>(); public static Type getListType(Type compType) { return listTypes.get(compType); @@ -68,6 +70,14 @@ return pairComponentTypes.get(pairType); } + public static Type getMapType(List compTypes) { + return mapTypes.get(compTypes); + } + + public static List getMapComponentTypes(Type mapType) { + return mapComponentTypes.get(mapType); + } + static public void infer(ResourceDependencyGraph graph, DataFlowModel model) { Map> resources = new HashMap<>(); Map variables = new HashMap<>(); @@ -75,12 +85,14 @@ Map cons = new HashMap<>(); Map tuple = new HashMap<>(); Map pair = new HashMap<>(); + Map map = new HashMap<>(); Map> expToResource = new HashMap<>(); Map> expToVariable = new HashMap<>(); Map> expToMessage = new HashMap<>(); - Map> expToCons = new HashMap<>(); - Map> expToTuple = new HashMap<>(); - Map> expToPair = new HashMap<>(); + Map>> expToCons = new HashMap<>(); + Map>> expToTuple = new HashMap<>(); + Map>> expToPair = new HashMap<>(); + Map>> expToMap = new HashMap<>(); Map idToRes = new HashMap<>(); Map> updateFromResource = new HashMap<>(); @@ -89,6 +101,7 @@ Map> updateFromCons = new HashMap<>(); Map> updateFromTuple = new HashMap<>(); Map> updateFromPair = new HashMap<>(); + Map> updateFromMap = new HashMap<>(); listComponentTypes.put(DataConstraintModel.typeList, null); listComponentTypes.put(DataConstraintModel.typeListInt, DataConstraintModel.typeInt); @@ -103,29 +116,30 @@ pairTypes.put(DataConstraintModel.typeString, DataConstraintModel.typePairStr); pairTypes.put(DataConstraintModel.typeDouble, DataConstraintModel.typePairDouble); tupleComponentTypes.put(DataConstraintModel.typeTuple, Arrays.asList(new Type[] { null, null })); + mapComponentTypes.put(DataConstraintModel.typeMap, Arrays.asList(new Type[] { null, null })); for (Node n : graph.getNodes()) { ResourceNode resource = (ResourceNode) n; idToRes.put(resource.getIdentifierTemplate(), resource); } - // Collect type information from the architecture model. + // 1. Collect type information from the architecture model. Collection channels = new HashSet<>(model.getIOChannelGenerators()); channels.addAll(model.getChannelGenerators()); for (ChannelGenerator c : channels) { for (ChannelMember cm : c.getChannelMembers()) { StateTransition st = cm.getStateTransition(); IdentifierTemplate id = cm.getIdentifierTemplate(); - - // Group expressions by resources. + + // 1.1 Group expressions by resources. List sameResource = resources.get(id); if (sameResource == null) { sameResource = new ArrayList<>(); resources.put(id, sameResource); } sameResource.add(st.getCurStateExpression()); - sameResource.add(st.getNextStateExpression()); + if (st.getNextStateExpression() != null) sameResource.add(st.getNextStateExpression()); expToResource.put(System.identityHashCode(st.getCurStateExpression()), sameResource); - expToResource.put(System.identityHashCode(st.getNextStateExpression()), sameResource); + if (st.getNextStateExpression() != null) expToResource.put(System.identityHashCode(st.getNextStateExpression()), sameResource); Map updatedExps = getUpdateSet(updateFromResource, sameResource); Type resType = id.getResourceStateType(); Expression exp = st.getCurStateExpression(); @@ -156,33 +170,35 @@ } resType = id.getResourceStateType(); exp = st.getNextStateExpression(); - expType = getExpTypeIfUpdatable(resType, exp); - if (expType != null) { - id.setResourceStateType(expType); - for (Expression resExp : sameResource) { - if (resExp != exp) { - if (resExp instanceof Variable && compareTypes(((Variable) resExp).getType(), expType)) { - ((Variable) resExp).setType(expType); - updatedExps.put(System.identityHashCode(resExp), resExp); - } else if (resExp instanceof Term && compareTypes(((Term) resExp).getType(), expType)) { - ((Term) resExp).setType(expType); - updatedExps.put(System.identityHashCode(resExp), resExp); + if (exp != null) { + expType = getExpTypeIfUpdatable(resType, exp); + if (expType != null) { + id.setResourceStateType(expType); + for (Expression resExp : sameResource) { + if (resExp != exp) { + if (resExp instanceof Variable && compareTypes(((Variable) resExp).getType(), expType)) { + ((Variable) resExp).setType(expType); + updatedExps.put(System.identityHashCode(resExp), resExp); + } else if (resExp instanceof Term && compareTypes(((Term) resExp).getType(), expType)) { + ((Term) resExp).setType(expType); + updatedExps.put(System.identityHashCode(resExp), resExp); + } } } - } - } else if (exp instanceof Variable) { - if (compareTypes(((Variable) exp).getType(), resType)) { - ((Variable) exp).setType(resType); - updatedExps.put(System.identityHashCode(exp), exp); - } - } else if (exp instanceof Term) { - if (compareTypes(((Term) exp).getType(), resType)) { - ((Term) exp).setType(resType); - updatedExps.put(System.identityHashCode(exp), exp); + } else if (exp instanceof Variable) { + if (compareTypes(((Variable) exp).getType(), resType)) { + ((Variable) exp).setType(resType); + updatedExps.put(System.identityHashCode(exp), exp); + } + } else if (exp instanceof Term) { + if (compareTypes(((Term) exp).getType(), resType)) { + ((Term) exp).setType(resType); + updatedExps.put(System.identityHashCode(exp), exp); + } } } - - // Group expressions by variable. + + // 1.2 Group expressions by variable. Map> locals = new HashMap<>(); Map localTypes = new HashMap<>(); List allVariables = new ArrayList<>(); @@ -222,8 +238,8 @@ for (String varName : locals.keySet()) { variables.put(System.identityHashCode(locals.get(varName)), localTypes.get(varName)); } - - // Group expressions by message. + + // 1.3 Group expressions by message. Expression message = st.getMessageExpression(); if (message instanceof Variable) { Type msgType = ((Variable) message).getType(); @@ -307,7 +323,8 @@ } } } - + + // 1.4 Extract constraints on expressions in each term. List terms = new ArrayList<>(); if (st.getCurStateExpression() instanceof Term) { Map subTerms = ((Term) st.getCurStateExpression()).getSubTerms(Term.class); @@ -317,7 +334,7 @@ Map subTerms = ((Term) st.getMessageExpression()).getSubTerms(Term.class); terms.addAll(subTerms.values()); } - if (st.getNextStateExpression() instanceof Term) { + if (st.getNextStateExpression() != null && st.getNextStateExpression() instanceof Term) { Map subTerms = ((Term) st.getNextStateExpression()).getSubTerms(Term.class); terms.addAll(subTerms.values()); } @@ -327,10 +344,10 @@ // If the root symbol of the term is cons. List consExps = new ArrayList<>(); consExps.add(t); - expToCons.put(System.identityHashCode(t), consExps); + updateExpressionBelonging(expToCons, t, consExps); for (Expression e : t.getChildren()) { consExps.add(e); - expToCons.put(System.identityHashCode(e), consExps); + updateExpressionBelonging(expToCons, e, consExps); } Type newType = getExpTypeIfUpdatable(t.getType(), consExps.get(2)); if (newType != null) { @@ -387,10 +404,10 @@ List tupleExps = new ArrayList<>(); List argsTypeList = new ArrayList<>(); tupleExps.add(t); - expToTuple.put(System.identityHashCode(t), tupleExps); + updateExpressionBelonging(expToTuple, t, tupleExps); for (Expression e : t.getChildren()) { tupleExps.add(e); - expToTuple.put(System.identityHashCode(e), tupleExps); + updateExpressionBelonging(expToTuple, e, tupleExps); if (e instanceof Variable) { argsTypeList.add(((Variable) e).getType()); } else if (e instanceof Term) { @@ -414,21 +431,19 @@ // If the root symbol of the term is pair. List pairExps = new ArrayList<>(); pairExps.add(t); - expToPair.put(System.identityHashCode(t), pairExps); - + updateExpressionBelonging(expToPair, t, pairExps); if (t.getType() == DataConstraintModel.typePair) { for (Expression e : t.getChildren()) { pairExps.add(e); - expToPair.put(System.identityHashCode(e), pairExps); - + updateExpressionBelonging(expToPair, e, pairExps); Type argType = null; if (e instanceof Variable) { argType = (((Variable) e).getType()); - + } else if (e instanceof Term) { argType = (((Term) e).getType()); } - + if (argType != null) { Type newPairType = pairTypes.get(argType); if (newPairType != null) { @@ -439,16 +454,16 @@ } } pair.put(System.identityHashCode(pairExps), t.getType()); - + } } else if (symbol.equals(DataConstraintModel.fst)) { // If the root symbol of the term is fst. List tupleExps = new ArrayList<>(); Expression arg = t.getChildren().get(0); tupleExps.add(arg); - expToTuple.put(System.identityHashCode(arg), tupleExps); + updateExpressionBelonging(expToTuple, arg, tupleExps); tupleExps.add(t); - expToTuple.put(System.identityHashCode(t), tupleExps); + updateExpressionBelonging(expToTuple, t, tupleExps); tupleExps.add(null); Type argType = null; if (arg instanceof Variable) { @@ -484,10 +499,10 @@ List tupleExps = new ArrayList<>(); Expression arg = t.getChildren().get(0); tupleExps.add(arg); - expToTuple.put(System.identityHashCode(arg), tupleExps); + updateExpressionBelonging(expToTuple, arg, tupleExps); tupleExps.add(null); tupleExps.add(t); - expToTuple.put(System.identityHashCode(t), tupleExps); + updateExpressionBelonging(expToTuple, t, tupleExps); Type argType = null; if (arg instanceof Variable) { argType = ((Variable) arg).getType(); @@ -522,9 +537,9 @@ List pairExps = new ArrayList<>(); Expression arg = t.getChildren().get(0); pairExps.add(arg); - expToPair.put(System.identityHashCode(arg), pairExps); + updateExpressionBelonging(expToPair, arg, pairExps); pairExps.add(t); - expToPair.put(System.identityHashCode(t), pairExps); + updateExpressionBelonging(expToPair, t, pairExps); pairExps.add(null); Type argType = null; if (arg instanceof Variable) { @@ -560,10 +575,10 @@ List pairExps = new ArrayList<>(); Expression arg = t.getChildren().get(0); pairExps.add(arg); - expToPair.put(System.identityHashCode(arg), pairExps); + updateExpressionBelonging(expToPair, arg, pairExps); pairExps.add(null); pairExps.add(t); - expToPair.put(System.identityHashCode(t), pairExps); + updateExpressionBelonging(expToPair, t, pairExps); Type argType = null; if (arg instanceof Variable) { argType = ((Variable) arg).getType(); @@ -593,6 +608,91 @@ updateExps.put(System.identityHashCode(arg), arg); } pair.put(System.identityHashCode(pairExps), argType); + } else if (symbol.equals(DataConstraintModel.lookup)) { + // If the root symbol of the term is lookup. + List mapExps = new ArrayList<>(); + Expression arg1 = t.getChildren().get(0); // map + mapExps.add(arg1); + updateExpressionBelonging(expToMap, arg1, mapExps); + Expression arg2 = t.getChildren().get(1); // key + mapExps.add(arg2); + updateExpressionBelonging(expToMap, arg2, mapExps); + mapExps.add(t); // value + updateExpressionBelonging(expToMap, t, mapExps); + Type arg1Type = null; + if (arg1 instanceof Variable) { + arg1Type = ((Variable) arg1).getType(); + } else if (arg1 instanceof Term) { + arg1Type = ((Term) arg1).getType(); + } + List compTypeList = new ArrayList<>(); + if (arg2 instanceof Variable) { + compTypeList.add(((Variable) arg2).getType()); + } else if (arg2 instanceof Term) { + compTypeList.add(((Term) arg2).getType()); + } else { + compTypeList.add(null); + } + compTypeList.add(t.getType()); + if (arg1Type == DataConstraintModel.typeMap || arg1Type == null) { + Type newMapType = mapTypes.get(compTypeList); + if (newMapType == null) { + // Create new tuple type; + newMapType = createNewMapType(compTypeList, DataConstraintModel.typeMap); + } + if (arg1 instanceof Variable) { + ((Variable) arg1).setType(newMapType); + arg1Type = newMapType; + } else if (arg1 instanceof Term) { + ((Term) arg1).setType(newMapType); + arg1Type = newMapType; + } + Map updateExps = getUpdateSet(updateFromMap, mapExps); + updateExps.put(System.identityHashCode(arg1), arg1); + } + map.put(System.identityHashCode(mapExps), arg1Type); + } else if (symbol.equals(DataConstraintModel.insert)) { + // If the root symbol of the term is insert. + List mapExps = new ArrayList<>(); + mapExps.add(t); // map + updateExpressionBelonging(expToMap, t, mapExps); + Expression arg1 = t.getChildren().get(1); // key + mapExps.add(arg1); + updateExpressionBelonging(expToMap, arg1, mapExps); + Expression arg2 = t.getChildren().get(2); // value + mapExps.add(arg2); + updateExpressionBelonging(expToMap, arg2, mapExps); + Expression arg0 = t.getChildren().get(0); // map + mapExps.add(arg0); + updateExpressionBelonging(expToMap, arg0, mapExps); + Type termType = t.getType(); + List compTypeList = new ArrayList<>(); + if (arg1 instanceof Variable) { + compTypeList.add(((Variable) arg1).getType()); + } else if (arg1 instanceof Term) { + compTypeList.add(((Term) arg1).getType()); + } else { + compTypeList.add(null); + } + if (arg2 instanceof Variable) { + compTypeList.add(((Variable) arg2).getType()); + } else if (arg2 instanceof Term) { + compTypeList.add(((Term) arg2).getType()); + } else { + compTypeList.add(null); + } + if (termType == DataConstraintModel.typeMap || termType == null) { + Type newMapType = mapTypes.get(compTypeList); + if (newMapType == null) { + // Create new tuple type; + newMapType = createNewMapType(compTypeList, DataConstraintModel.typeMap); + } + t.setType(newMapType); + termType = newMapType; + Map updateExps = getUpdateSet(updateFromMap, mapExps); + updateExps.put(System.identityHashCode(t), t); + } + map.put(System.identityHashCode(mapExps), termType); } else if (symbol.equals(DataConstraintModel.cond)) { // If the root symbol of the term is if function. Expression c1 = t.getChild(1); @@ -735,10 +835,10 @@ } } } - - // Propagate type information. + + // 2. Propagate type information. while (updateFromResource.size() > 0 || updateFromVariable.size() > 0 || updateFromMessage.size() > 0 - || updateFromCons.size() > 0 || updateFromTuple.size() > 0 || updateFromPair.size() > 0) { + || updateFromCons.size() > 0 || updateFromTuple.size() > 0 || updateFromPair.size() > 0 || updateFromMap.size() > 0) { if (updateFromResource.size() > 0) { Set resourceKeys = updateFromResource.keySet(); Integer resourceKey = resourceKeys.iterator().next(); @@ -751,6 +851,7 @@ updateConsTypes(resExp, cons, expToCons, updateFromCons); updateTupleTypes(resExp, tuple, expToTuple, updateFromTuple); updatePairTypes(resExp, pair, expToPair, updateFromPair); + updateMapTypes(resExp, map, expToMap, updateFromMap); } } if (updateFromVariable.size() > 0) { @@ -766,6 +867,7 @@ updateConsTypes(var, cons, expToCons, updateFromCons); updateTupleTypes(var, tuple, expToTuple, updateFromTuple); updatePairTypes(var, pair, expToPair, updateFromPair); + updateMapTypes(var, map, expToMap, updateFromMap); } } if (updateFromMessage.size() > 0) { @@ -780,6 +882,7 @@ updateConsTypes(mesExp, cons, expToCons, updateFromCons); updateTupleTypes(mesExp, tuple, expToTuple, updateFromTuple); updatePairTypes(mesExp, pair, expToPair, updateFromPair); + updateMapTypes(mesExp, map, expToMap, updateFromMap); } } if (updateFromCons.size() > 0) { @@ -795,6 +898,7 @@ updateConsTypes(consExp, cons, expToCons, updateFromCons); updateTupleTypes(consExp, tuple, expToTuple, updateFromTuple); updatePairTypes(consExp, pair, expToPair, updateFromPair); + updateMapTypes(consExp, map, expToMap, updateFromMap); } } if (updateFromTuple.size() > 0) { @@ -810,9 +914,9 @@ updateConsTypes(tupleExp, cons, expToCons, updateFromCons); updateTupleTypes(tupleExp, tuple, expToTuple, updateFromTuple); updatePairTypes(tupleExp, pair, expToPair, updateFromPair); + updateMapTypes(tupleExp, map, expToMap, updateFromMap); } } - if (updateFromPair.size() > 0) { Set pairKeys = updateFromPair.keySet(); Integer pairKey = pairKeys.iterator().next(); @@ -826,17 +930,45 @@ updateConsTypes(pairExp, cons, expToCons, updateFromCons); updateTupleTypes(pairExp, tuple, expToTuple, updateFromTuple); updatePairTypes(pairExp, pair, expToPair, updateFromPair); + updateMapTypes(pairExp, map, expToMap, updateFromMap); } - } + if (updateFromMap.size() > 0) { + Set mapKeys = updateFromMap.keySet(); + Integer mapKey = mapKeys.iterator().next(); + Map mapValue = updateFromMap.get(mapKey); + updateFromMap.remove(mapKey); + for (int i : mapValue.keySet()) { + Expression mapExp = mapValue.get(i); + updateResourceTypes(mapExp, resources, expToResource, updateFromResource); + updateVaribleTypes(mapExp, variables, expToVariable, updateFromVariable); + updateMessageTypes(mapExp, messages, expToMessage, updateFromMessage); + updateConsTypes(mapExp, cons, expToCons, updateFromCons); + updateTupleTypes(mapExp, tuple, expToTuple, updateFromTuple); + updatePairTypes(mapExp, pair, expToPair, updateFromPair); + updateMapTypes(mapExp, map, expToMap, updateFromMap); + } + } + } + } + + private static void updateExpressionBelonging(Map>> belonging, Expression exp, List group) { + Set> groups = belonging.get(System.identityHashCode(exp)); + if (groups == null) { + groups = new HashSet<>(); + belonging.put(System.identityHashCode(exp), groups); + groups.add(group); + return; + } + if (!groups.contains(group)) { + groups.add(group); } } private static void updateResourceTypes(Expression exp, Map> resources, Map> expToResource, Map> updateFromResource) { List sameResource = expToResource.get(System.identityHashCode(exp)); - if (sameResource == null) - return; + if (sameResource == null) return; for (IdentifierTemplate id : resources.keySet()) { if (resources.get(id) == sameResource) { Type resType = id.getResourceStateType(); @@ -863,8 +995,7 @@ private static void updateVaribleTypes(Expression exp, Map variables, Map> expToVariable, Map> updateFromVariable) { List sameVariable = expToVariable.get(System.identityHashCode(exp)); - if (sameVariable == null) - return; + if (sameVariable == null) return; Type varType = variables.get(System.identityHashCode(sameVariable)); Type newVarType = getExpTypeIfUpdatable(varType, exp); if (newVarType != null) { @@ -888,8 +1019,7 @@ Map, Type>>> messages, Map> expToMessage, Map> updateFromMessage) { List messageExps = expToMessage.get(System.identityHashCode(exp)); - if (messageExps == null) - return; + if (messageExps == null) return; Type msgType = null; Map.Entry, Type> expsAndType = null; for (ChannelGenerator c : messages.keySet()) { @@ -900,11 +1030,9 @@ break; } } - if (msgType != null) - break; + if (msgType != null) break; } - if (msgType == null) - return; + if (msgType == null) return; Type newMsgType = getExpTypeIfUpdatable(msgType, exp); if (newMsgType != null) { expsAndType.setValue(newMsgType); @@ -924,87 +1052,286 @@ } private static void updateConsTypes(Expression exp, Map cons, - Map> expToCons, Map> updateFromCons) { - List consComponents = expToCons.get(System.identityHashCode(exp)); - if (consComponents == null) - return; - int idx = consComponents.indexOf(exp); - switch (idx) { - case 0: - if (!(exp instanceof Term)) - return; - Type listType = cons.get(System.identityHashCode(consComponents)); - Type expType = getExpTypeIfUpdatable(listType, exp); - if (expType != null) { - cons.put(System.identityHashCode(consComponents), expType); - Map updateExps = getUpdateSet(updateFromCons, consComponents); - if (consComponents.get(2) instanceof Variable) { - ((Variable) consComponents.get(2)).setType(expType); - updateExps.put(System.identityHashCode(consComponents.get(2)), consComponents.get(2)); - } else if (consComponents.get(2) instanceof Term) { - ((Term) consComponents.get(2)).setType(expType); - updateExps.put(System.identityHashCode(consComponents.get(2)), consComponents.get(2)); + Map>> expToCons, Map> updateFromCons) { + Set> consComponentGroups = expToCons.get(System.identityHashCode(exp)); + if (consComponentGroups == null) return; + for (List consComponentGroup: consComponentGroups) { + int idx = consComponentGroup.indexOf(exp); + switch (idx) { + case 0: + if (!(exp instanceof Term)) break; + Type listType = cons.get(System.identityHashCode(consComponentGroup)); + Type expType = getExpTypeIfUpdatable(listType, exp); + if (expType != null) { + cons.put(System.identityHashCode(consComponentGroup), expType); + Map updateExps = getUpdateSet(updateFromCons, consComponentGroup); + if (consComponentGroup.get(2) instanceof Variable) { + ((Variable) consComponentGroup.get(2)).setType(expType); + updateExps.put(System.identityHashCode(consComponentGroup.get(2)), consComponentGroup.get(2)); + } else if (consComponentGroup.get(2) instanceof Term) { + ((Term) consComponentGroup.get(2)).setType(expType); + updateExps.put(System.identityHashCode(consComponentGroup.get(2)), consComponentGroup.get(2)); + } + Type compType = listComponentTypes.get(expType); + if (consComponentGroup.get(1) != null && consComponentGroup.get(1) instanceof Variable) { + ((Variable) consComponentGroup.get(1)).setType(compType); + updateExps.put(System.identityHashCode(consComponentGroup.get(1)), consComponentGroup.get(1)); + } else if (consComponentGroup.get(1) != null && consComponentGroup.get(1) instanceof Term) { + ((Term) consComponentGroup.get(1)).setType(compType); + updateExps.put(System.identityHashCode(consComponentGroup.get(1)), consComponentGroup.get(1)); + } } - Type compType = listComponentTypes.get(expType); - if (consComponents.get(1) != null && consComponents.get(1) instanceof Variable) { - ((Variable) consComponents.get(1)).setType(compType); - updateExps.put(System.identityHashCode(consComponents.get(1)), consComponents.get(1)); - } else if (consComponents.get(1) != null && consComponents.get(1) instanceof Term) { - ((Term) consComponents.get(1)).setType(compType); - updateExps.put(System.identityHashCode(consComponents.get(1)), consComponents.get(1)); + break; + case 1: + listType = cons.get(System.identityHashCode(consComponentGroup)); + Type compType = listComponentTypes.get(listType); + Type newCompType = getExpTypeIfUpdatable(compType, exp); + if (newCompType != null) { + Type newListType = listTypes.get(newCompType); + if (newListType == null) { + // Create new list type. + newListType = createNewListType(newCompType, listType); + } + cons.put(System.identityHashCode(consComponentGroup), newListType); + Map updateExps = getUpdateSet(updateFromCons, consComponentGroup); + if (consComponentGroup.get(0) instanceof Term) { + ((Term) consComponentGroup.get(0)).setType(newListType); + updateExps.put(System.identityHashCode(consComponentGroup.get(0)), consComponentGroup.get(0)); + } + if (consComponentGroup.get(2) instanceof Variable) { + ((Variable) consComponentGroup.get(2)).setType(newListType); + updateExps.put(System.identityHashCode(consComponentGroup.get(2)), consComponentGroup.get(2)); + } else if (consComponentGroup.get(2) instanceof Term) { + ((Term) consComponentGroup.get(2)).setType(newListType); + updateExps.put(System.identityHashCode(consComponentGroup.get(2)), consComponentGroup.get(2)); + } } - } - break; - case 1: - listType = cons.get(System.identityHashCode(consComponents)); - Type compType = listComponentTypes.get(listType); - Type newCompType = getExpTypeIfUpdatable(compType, exp); - if (newCompType != null) { - Type newListType = listTypes.get(newCompType); - if (newListType == null) { - // Create new list type. - newListType = createNewListType(newCompType, listType); - } - cons.put(System.identityHashCode(consComponents), newListType); - Map updateExps = getUpdateSet(updateFromCons, consComponents); - if (consComponents.get(0) instanceof Term) { - ((Term) consComponents.get(0)).setType(newListType); - updateExps.put(System.identityHashCode(consComponents.get(0)), consComponents.get(0)); - } - if (consComponents.get(2) instanceof Variable) { - ((Variable) consComponents.get(2)).setType(newListType); - updateExps.put(System.identityHashCode(consComponents.get(2)), consComponents.get(2)); - } else if (consComponents.get(2) instanceof Term) { - ((Term) consComponents.get(2)).setType(newListType); - updateExps.put(System.identityHashCode(consComponents.get(2)), consComponents.get(2)); - } - } - break; - case 2: - listType = cons.get(System.identityHashCode(consComponents)); - expType = getExpTypeIfUpdatable(listType, exp); - if (expType != null) { - cons.put(System.identityHashCode(consComponents), expType); - Map updateExps = getUpdateSet(updateFromCons, consComponents); - if (consComponents.get(0) instanceof Term) { - ((Term) consComponents.get(0)).setType(expType); - updateExps.put(System.identityHashCode(consComponents.get(0)), consComponents.get(0)); - } - compType = listComponentTypes.get(expType); - if (consComponents.get(1) != null && consComponents.get(1) instanceof Variable) { - ((Variable) consComponents.get(1)).setType(compType); - updateExps.put(System.identityHashCode(consComponents.get(1)), consComponents.get(1)); - } else if (consComponents.get(1) != null && consComponents.get(1) instanceof Term) { - ((Term) consComponents.get(1)).setType(compType); - updateExps.put(System.identityHashCode(consComponents.get(1)), consComponents.get(1)); + break; + case 2: + listType = cons.get(System.identityHashCode(consComponentGroup)); + expType = getExpTypeIfUpdatable(listType, exp); + if (expType != null) { + cons.put(System.identityHashCode(consComponentGroup), expType); + Map updateExps = getUpdateSet(updateFromCons, consComponentGroup); + if (consComponentGroup.get(0) instanceof Term) { + ((Term) consComponentGroup.get(0)).setType(expType); + updateExps.put(System.identityHashCode(consComponentGroup.get(0)), consComponentGroup.get(0)); + } + compType = listComponentTypes.get(expType); + if (consComponentGroup.get(1) != null && consComponentGroup.get(1) instanceof Variable) { + ((Variable) consComponentGroup.get(1)).setType(compType); + updateExps.put(System.identityHashCode(consComponentGroup.get(1)), consComponentGroup.get(1)); + } else if (consComponentGroup.get(1) != null && consComponentGroup.get(1) instanceof Term) { + ((Term) consComponentGroup.get(1)).setType(compType); + updateExps.put(System.identityHashCode(consComponentGroup.get(1)), consComponentGroup.get(1)); + } } } } } + private static void updateTupleTypes(Expression exp, Map tuple, + Map>> expToTuple, Map> updateFromTuple) { + Set> tupleComponentGroups = expToTuple.get(System.identityHashCode(exp)); + if (tupleComponentGroups == null) return; + for (List tupleComponentGroup: tupleComponentGroups) { + int idx = tupleComponentGroup.indexOf(exp); + if (idx == 0) { + Type tupleType = tuple.get(System.identityHashCode(tupleComponentGroup)); + Type newTupleType = getExpTypeIfUpdatable(tupleType, exp); + if (newTupleType != null) { + // Propagate an update of a tuple's type to its components' types. + tuple.put(System.identityHashCode(tupleComponentGroup), newTupleType); + List componentTypes = tupleComponentTypes.get(newTupleType); + Map updateExps = getUpdateSet(updateFromTuple, tupleComponentGroup); + for (int i = 1; i < tupleComponentGroup.size(); i++) { + Expression compExp = tupleComponentGroup.get(i); + if (compExp instanceof Variable) { + if (compareTypes(((Variable) compExp).getType(), componentTypes.get(i - 1))) { + ((Variable) compExp).setType(componentTypes.get(i - 1)); + updateExps.put(System.identityHashCode(compExp), compExp); + } + } else if (compExp instanceof Term) { + if (compareTypes(((Term) compExp).getType(), componentTypes.get(i - 1))) { + ((Term) compExp).setType(componentTypes.get(i - 1)); + updateExps.put(System.identityHashCode(compExp), compExp); + } + } + } + } + } else { + Type tupleType = tuple.get(System.identityHashCode(tupleComponentGroup)); + List componentTypes = tupleComponentTypes.get(tupleType); + Type compType = componentTypes.get(idx - 1); + Type newCompType = getExpTypeIfUpdatable(compType, exp); + if (newCompType != null) { + // Propagate an update of a component's type to its container's (tuple's) type. + componentTypes = new ArrayList<>(componentTypes); + componentTypes.set(idx - 1, newCompType); + Type newTupleType = tupleTypes.get(componentTypes); + if (newTupleType == null) { + // Create new tuple type; + newTupleType = createNewTupleType(componentTypes, tupleType); + } + Map updateExps = getUpdateSet(updateFromTuple, tupleComponentGroup); + Expression tupleExp = tupleComponentGroup.get(0); + if (tupleExp instanceof Variable) { + ((Variable) tupleExp).setType(newTupleType); + updateExps.put(System.identityHashCode(tupleExp), tupleExp); + } else if (tupleExp instanceof Term) { + ((Term) tupleExp).setType(newTupleType); + updateExps.put(System.identityHashCode(tupleExp), tupleExp); + } + tuple.put(System.identityHashCode(tupleComponentGroup), newTupleType); + } + } + } + } + + private static void updatePairTypes(Expression exp, Map pair, + Map>> expToPair, Map> updateFromPair) { + Set> pairComponentGroups = expToPair.get(System.identityHashCode(exp)); + if (pairComponentGroups == null) return; + for (List pairComponentGroup: pairComponentGroups) { + int idx = pairComponentGroup.indexOf(exp); + if (idx == 0) { + Type pairType = pair.get(System.identityHashCode(pairComponentGroup)); + Type newPairType = getExpTypeIfUpdatable(pairType, exp); + if (newPairType != null) { + // Propagate an update of a pair's type to its components' types. + pair.put(System.identityHashCode(pairComponentGroup), newPairType); + Type componentType = pairComponentTypes.get(newPairType); + Map updateExps = getUpdateSet(updateFromPair, pairComponentGroup); + for (int i = 1; i < pairComponentGroup.size(); i++) { + Expression compExp = pairComponentGroup.get(i); + if (compExp instanceof Variable) { + if (compareTypes(((Variable) compExp).getType(), componentType)) { + ((Variable) compExp).setType(componentType); + updateExps.put(System.identityHashCode(compExp), compExp); + } + } else if (compExp instanceof Term) { + if (compareTypes(((Term) compExp).getType(), componentType)) { + ((Term) compExp).setType(componentType); + updateExps.put(System.identityHashCode(compExp), compExp); + } + } + } + } + } else { + Type pairType = pair.get(System.identityHashCode(pairComponentGroup)); + Type compType = pairComponentTypes.get(pairType); + Type newCompType = getExpTypeIfUpdatable(compType, exp); + if (newCompType != null) { + // Propagate an update of a component's type to its container's (pair's) type. + Type newPairType = pairTypes.get(compType); + if (newPairType != null) { + Map updateExps = getUpdateSet(updateFromPair, pairComponentGroup); + Expression pairExp = pairComponentGroup.get(0); + if (pairExp instanceof Variable) { + ((Variable) pairExp).setType(newPairType); + updateExps.put(System.identityHashCode(pairExp), pairExp); + } else if (pairExp instanceof Term) { + ((Term) pairExp).setType(newPairType); + updateExps.put(System.identityHashCode(pairExp), pairExp); + } + pair.put(System.identityHashCode(pairComponentGroup), newPairType); + } + } + } + } + } + + private static void updateMapTypes(Expression exp, Map map, + Map>> expToMap, Map> updateFromMap) { + Set> mapComponentGroups = expToMap.get(System.identityHashCode(exp)); + if (mapComponentGroups == null) return; + for (List mapComponentGroup: mapComponentGroups) { + int idx = mapComponentGroup.indexOf(exp); + if (idx == 0 || idx == 3) { + Type mapType = map.get(System.identityHashCode(mapComponentGroup)); + Type newMapType = getExpTypeIfUpdatable(mapType, exp); + if (newMapType != null) { + // Propagate an update of a map's type to its components' types. + map.put(System.identityHashCode(mapComponentGroup), newMapType); + List componentTypes = mapComponentTypes.get(newMapType); + Map updateExps = getUpdateSet(updateFromMap, mapComponentGroup); + for (int i = 1; i < mapComponentGroup.size() && i < 3; i++) { + Expression compExp = mapComponentGroup.get(i); + if (compExp instanceof Variable) { + if (compareTypes(((Variable) compExp).getType(), componentTypes.get(i - 1))) { + ((Variable) compExp).setType(componentTypes.get(i - 1)); + updateExps.put(System.identityHashCode(compExp), compExp); + } + } else if (compExp instanceof Term) { + if (compareTypes(((Term) compExp).getType(), componentTypes.get(i - 1))) { + ((Term) compExp).setType(componentTypes.get(i - 1)); + updateExps.put(System.identityHashCode(compExp), compExp); + } + } + } + // Propagate an update of a map's type to another map's type. + Expression compExp = null; + if (idx == 0 && mapComponentGroup.size() == 4) { // for lookup + compExp = mapComponentGroup.get(3); + } else if (idx == 3) { + compExp = mapComponentGroup.get(0); + } + if (compExp != null) { + if (compExp instanceof Variable) { + if (compareTypes(((Variable) compExp).getType(), newMapType)) { + ((Variable) compExp).setType(newMapType); + updateExps.put(System.identityHashCode(compExp), compExp); + } + } else if (compExp instanceof Term) { + if (compareTypes(((Term) compExp).getType(), newMapType)) { + ((Term) compExp).setType(newMapType); + updateExps.put(System.identityHashCode(compExp), compExp); + } + } + } + } + } else { + Type mapType = map.get(System.identityHashCode(mapComponentGroup)); + List componentTypes = mapComponentTypes.get(mapType); + Type compType = componentTypes.get(idx - 1); + Type newCompType = getExpTypeIfUpdatable(compType, exp); + if (newCompType != null) { + // Propagate an update of a component's type to its container's (map's) type. + componentTypes = new ArrayList<>(componentTypes); + componentTypes.set(idx - 1, newCompType); + Type newMapType = mapTypes.get(componentTypes); + if (newMapType == null) { + // Create new map type; + newMapType = createNewMapType(componentTypes, mapType); + } + Map updateExps = getUpdateSet(updateFromMap, mapComponentGroup); + Expression mapExp = mapComponentGroup.get(0); + if (mapExp instanceof Variable) { + ((Variable) mapExp).setType(newMapType); + updateExps.put(System.identityHashCode(mapExp), mapExp); + } else if (mapExp instanceof Term) { + ((Term) mapExp).setType(newMapType); + updateExps.put(System.identityHashCode(mapExp), mapExp); + } + if (mapComponentGroup.size() == 4) { // for lookup + mapExp = mapComponentGroup.get(3); + if (mapExp instanceof Variable) { + ((Variable) mapExp).setType(newMapType); + updateExps.put(System.identityHashCode(mapExp), mapExp); + } else if (mapExp instanceof Term) { + ((Term) mapExp).setType(newMapType); + updateExps.put(System.identityHashCode(mapExp), mapExp); + } + } + map.put(System.identityHashCode(mapComponentGroup), newMapType); + } + } + } + } + private static Type createNewListType(Type compType, Type parentType) { String compTypeName = getInterfaceTypeName(compType); - List childrenTypes = getChildrenTypesOfList(parentType); + List childrenTypes = getChildrenTypes(parentType, listComponentTypes.keySet()); Type newListType = new Type("List", "ArrayList<>", "List<" + compTypeName + ">", parentType); listTypes.put(compType, newListType); listComponentTypes.put(newListType, compType); @@ -1022,125 +1349,6 @@ return newListType; } - private static List getChildrenTypesOfList(Type parentListType) { - List childrenTypes = new ArrayList<>(); - for (Type listType : listComponentTypes.keySet()) { - if (listType.getParentTypes().contains(parentListType)) { - childrenTypes.add(listType); - } - } - return childrenTypes; - } - - private static void updateTupleTypes(Expression exp, Map tuple, - Map> expToTuple, Map> updateFromTuple) { - List components = expToTuple.get(System.identityHashCode(exp)); - if (components == null) - return; - int idx = components.indexOf(exp); - if (idx == 0) { - Type tupleType = tuple.get(System.identityHashCode(components)); - Type newTupleType = getExpTypeIfUpdatable(tupleType, exp); - if (newTupleType != null) { - // Propagate an update of a tuple's type to its components' types. - tuple.put(System.identityHashCode(components), newTupleType); - List componentTypes = tupleComponentTypes.get(newTupleType); - Map updateExps = getUpdateSet(updateFromTuple, components); - for (int i = 1; i < components.size(); i++) { - Expression compExp = components.get(i); - if (compExp instanceof Variable) { - if (compareTypes(((Variable) compExp).getType(), componentTypes.get(i - 1))) { - ((Variable) compExp).setType(componentTypes.get(i - 1)); - updateExps.put(System.identityHashCode(compExp), compExp); - } - } else if (compExp instanceof Term) { - if (compareTypes(((Term) compExp).getType(), componentTypes.get(i - 1))) { - ((Term) compExp).setType(componentTypes.get(i - 1)); - updateExps.put(System.identityHashCode(compExp), compExp); - } - } - } - } - } else { - Type tupleType = tuple.get(System.identityHashCode(components)); - List componentTypes = tupleComponentTypes.get(tupleType); - Type compType = componentTypes.get(idx - 1); - Type newCompType = getExpTypeIfUpdatable(compType, exp); - if (newCompType != null) { - // Propagate an update of a component's type to its container's (tuple's) type. - componentTypes = new ArrayList<>(componentTypes); - componentTypes.set(idx - 1, newCompType); - Type newTupleType = tupleTypes.get(componentTypes); - if (newTupleType == null) { - // Create new tuple type; - newTupleType = createNewTupleType(componentTypes, tupleType); - } - Map updateExps = getUpdateSet(updateFromTuple, components); - Expression tupleExp = components.get(0); - if (tupleExp instanceof Variable) { - ((Variable) tupleExp).setType(newTupleType); - updateExps.put(System.identityHashCode(tupleExp), tupleExp); - } else if (tupleExp instanceof Term) { - ((Term) tupleExp).setType(newTupleType); - updateExps.put(System.identityHashCode(tupleExp), tupleExp); - } - tuple.put(System.identityHashCode(components), newTupleType); - } - } - } - - private static void updatePairTypes(Expression exp, Map pair, - Map> expToPair, Map> updateFromPair) { - List components = expToPair.get(System.identityHashCode(exp)); - if (components == null) - return; - int idx = components.indexOf(exp); - if (idx == 0) { - Type pairType = pair.get(System.identityHashCode(components)); - Type newPairType = getExpTypeIfUpdatable(pairType, exp); - if (newPairType != null) { - // Propagate an update of a pair's type to its components' types. - pair.put(System.identityHashCode(components), newPairType); - Type componentType = pairComponentTypes.get(newPairType); - Map updateExps = getUpdateSet(updateFromPair, components); - for (int i = 1; i < components.size(); i++) { - Expression compExp = components.get(i); - if (compExp instanceof Variable) { - if (compareTypes(((Variable) compExp).getType(), componentType)) { - ((Variable) compExp).setType(componentType); - updateExps.put(System.identityHashCode(compExp), compExp); - } - } else if (compExp instanceof Term) { - if (compareTypes(((Term) compExp).getType(), componentType)) { - ((Term) compExp).setType(componentType); - updateExps.put(System.identityHashCode(compExp), compExp); - } - } - } - } - } else { - Type pairType = pair.get(System.identityHashCode(components)); - Type compType = pairComponentTypes.get(pairType); - Type newCompType = getExpTypeIfUpdatable(compType, exp); - if (newCompType != null) { - // Propagate an update of a component's type to its container's (pair's) type. - Type newPairType = pairTypes.get(compType); - if (newPairType != null) { - Map updateExps = getUpdateSet(updateFromPair, components); - Expression pairExp = components.get(0); - if (pairExp instanceof Variable) { - ((Variable) pairExp).setType(newPairType); - updateExps.put(System.identityHashCode(pairExp), pairExp); - } else if (pairExp instanceof Term) { - ((Term) pairExp).setType(newPairType); - updateExps.put(System.identityHashCode(pairExp), pairExp); - } - pair.put(System.identityHashCode(components), newPairType); - } - } - } - } - private static Type createNewTupleType(List componentTypes, Type parentTupleType) { String implTypeName = "AbstractMap.SimpleEntry<>"; String interfaceTypeName = "Map.Entry<$x>"; @@ -1158,7 +1366,7 @@ interfaceTypeName = interfaceTypeName.replace("$x", ", " + getInterfaceTypeName(componentTypes.get(componentTypes.size() - 1))); } - List childrenTypes = getChildrenTypesOfTuple(parentTupleType); + List childrenTypes = getChildrenTypes(parentTupleType, tupleComponentTypes.keySet()); Type newTupleType = new Type("Tuple", implTypeName, interfaceTypeName, parentTupleType); tupleTypes.put(componentTypes, newTupleType); tupleComponentTypes.put(newTupleType, componentTypes); @@ -1176,11 +1384,38 @@ return newTupleType; } - private static List getChildrenTypesOfTuple(Type parentTupleType) { + private static Type createNewMapType(List componentTypes, Type parentMapType) { + String implTypeName = "HashMap<>"; + String interfaceTypeName = "Map<$x, $y>"; + if (componentTypes.size() == 2) { + implTypeName = implTypeName.replace("$x", getImplementationTypeName(componentTypes.get(0))); + interfaceTypeName = interfaceTypeName.replace("$x", getInterfaceTypeName(componentTypes.get(0))); + implTypeName = implTypeName.replace("$y", getImplementationTypeName(componentTypes.get(1))); + interfaceTypeName = interfaceTypeName.replace("$y", getInterfaceTypeName(componentTypes.get(1))); + } + List childrenTypes = getChildrenTypes(parentMapType, mapComponentTypes.keySet()); + Type newMapType = new Type("Map", implTypeName, interfaceTypeName, parentMapType); + mapTypes.put(componentTypes, newMapType); + mapComponentTypes.put(newMapType, componentTypes); + for (Type childType : childrenTypes) { + if (compareTypes(childType, newMapType)) { + if (newMapType.getParentTypes().contains(parentMapType)) { + newMapType.replaceParentType(parentMapType, childType); + } else { + newMapType.addParentType(childType); + } + } else if (compareTypes(newMapType, childType)) { + childType.replaceParentType(parentMapType, newMapType); + } + } + return newMapType; + } + + private static List getChildrenTypes(Type parentType, Set componentTypes) { List childrenTypes = new ArrayList<>(); - for (Type tupleType : tupleComponentTypes.keySet()) { - if (tupleType.getParentTypes().contains(parentTupleType)) { - childrenTypes.add(tupleType); + for (Type childType : componentTypes) { + if (childType.getParentTypes().contains(parentType)) { + childrenTypes.add(childType); } } return childrenTypes; @@ -1188,7 +1423,7 @@ private static String getImplementationTypeName(Type type) { if (type == null) - return "Integer"; + return "Object"; String wrapperType = DataConstraintModel.getWrapperType(type); if (wrapperType != null) return wrapperType; @@ -1197,7 +1432,7 @@ private static String getInterfaceTypeName(Type type) { if (type == null) - return "Integer"; + return "Object"; String wrapperType = DataConstraintModel.getWrapperType(type); if (wrapperType != null) return wrapperType; @@ -1241,6 +1476,19 @@ if (originalType != newType && newType != null) { if (originalType.isAncestorOf(newType)) return true; + if (DataConstraintModel.typeMap.isAncestorOf(originalType) + && DataConstraintModel.typeMap.isAncestorOf(newType)) { + List originalCompTypes = mapComponentTypes.get(originalType); + List newCompTypes = mapComponentTypes.get(newType); + if (originalCompTypes == null) + return true; + for (int i = 0; i < originalCompTypes.size(); i++) { + if (originalCompTypes.get(i) != null && (newCompTypes.get(i) == null + || !originalCompTypes.get(i).isAncestorOf(newCompTypes.get(i)))) + return false; + } + return true; + } if (DataConstraintModel.typeTuple.isAncestorOf(originalType) && DataConstraintModel.typeTuple.isAncestorOf(newType)) { List originalCompTypes = tupleComponentTypes.get(originalType); diff --git a/AlgebraicDataflowArchitectureModel/src/models/algebra/Constant.java b/AlgebraicDataflowArchitectureModel/src/models/algebra/Constant.java index d368dc8..440145e 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/algebra/Constant.java +++ b/AlgebraicDataflowArchitectureModel/src/models/algebra/Constant.java @@ -36,7 +36,7 @@ public String toImplementation(String[] sideEffects) { if (symbol.isImplGenerative()) { - String exp = symbol.generate(getType(), new String[] {}, sideEffects); + String exp = symbol.generate(getType(), new String[] {}, new String[] {}, sideEffects); return exp; } return symbol.getImplName(); diff --git a/AlgebraicDataflowArchitectureModel/src/models/algebra/Expression.java b/AlgebraicDataflowArchitectureModel/src/models/algebra/Expression.java index 872f54a..f0aeadb 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/algebra/Expression.java +++ b/AlgebraicDataflowArchitectureModel/src/models/algebra/Expression.java @@ -14,6 +14,11 @@ return getSubTerms(Variable.class); } + /** + * Get the implementation of this expression. + * @param sideEffects an array with an optional implementation that should be written before the evaluation of this expression + * @return the implementation to represent the value of this expression + */ public String toImplementation(String[] sideEffects) { return toString(); } diff --git a/AlgebraicDataflowArchitectureModel/src/models/algebra/Symbol.java b/AlgebraicDataflowArchitectureModel/src/models/algebra/Symbol.java index 9d7cc57..5a06873 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/algebra/Symbol.java +++ b/AlgebraicDataflowArchitectureModel/src/models/algebra/Symbol.java @@ -152,9 +152,17 @@ this.generator = generator; } - public String generate(models.algebra.Type type, String[] childrenImpl, String[] sideEffects) { + /** + * Generate the implementation of this symbol + * @param type the type of this symbol + * @param childrenImpl the implementations of the children + * @param childrenSideEffects (input) an array of the side effects of the children + * @param sideEffect (output) an array of the side effect of this symbol + * @return the implementation + */ + public String generate(models.algebra.Type type, String[] childrenImpl, String[] childrenSideEffects, String[] sideEffect) { if (generator != null) { - return generator.generate(type, childrenImpl, sideEffects); + return generator.generate(type, childrenImpl, childrenSideEffects, sideEffect); } return null; } @@ -208,6 +216,14 @@ } public interface IImplGenerator { - public String generate(models.algebra.Type type, String children[], String[] sideEffects); + /** + * Generate the implementation + * @param type the type of this expression + * @param children the implementations of the children + * @param childrenSideEffects (input) an array of the side effects of the children + * @param sideEffect (output) an array of the side effect of this generator + * @return the generated implementation + */ + public String generate(models.algebra.Type type, String children[], String[] childrenSideEffects, String[] sideEffect); } } diff --git a/AlgebraicDataflowArchitectureModel/src/models/algebra/Term.java b/AlgebraicDataflowArchitectureModel/src/models/algebra/Term.java index 74bf544..b7cad09 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/algebra/Term.java +++ b/AlgebraicDataflowArchitectureModel/src/models/algebra/Term.java @@ -223,7 +223,7 @@ } } if (symbol.isImplWithSideEffect()) { - sideEffects[0] = sideEffects[0] + exp + ";"; + sideEffects[0] = sideEffects[0] + exp + ";\n"; if (implParamOrder == null) { exp = children.get(0).toImplementation(new String[] {""}); } else { @@ -234,24 +234,29 @@ } if (symbol.isImplGenerative()) { String childrenImpl[] = new String[children.size()]; + String childrenSideEffects[] = new String[children.size()]; if (implParamOrder == null) { for (int i = 0; i < children.size(); i++) { - childrenImpl[i] = children.get(i).toImplementation(sideEffects); + String childSideEffect[] = new String[] {""}; + childrenImpl[i] = children.get(i).toImplementation(childSideEffect); + childrenSideEffects[i] = childSideEffect[0]; } - String exp = symbol.generate(getType(), childrenImpl, sideEffects); + String exp = symbol.generate(getType(), childrenImpl, childrenSideEffects, sideEffects); if (symbol.isImplWithSideEffect()) { sideEffects[0] = sideEffects[0] + exp; - exp = children.get(0).toImplementation(new String[] {""}); + exp = children.get(0).toImplementation(new String[] {""}); // the value of this term } return exp; } else { for (int i = 0; i < children.size(); i++) { - childrenImpl[i] = children.get(implParamOrder[i]).toImplementation(sideEffects); + String childSideEffect[] = new String[] {""}; + childrenImpl[i] = children.get(implParamOrder[i]).toImplementation(childSideEffect); + childrenSideEffects[i] = childSideEffect[0]; } - String exp = symbol.generate(getType(), childrenImpl, sideEffects); + String exp = symbol.generate(getType(), childrenImpl, childrenSideEffects, sideEffects); if (symbol.isImplWithSideEffect()) { sideEffects[0] = sideEffects[0] + exp; - exp = children.get(implParamOrder[0]).toImplementation(new String[] {""}); + exp = children.get(implParamOrder[0]).toImplementation(new String[] {""}); // the value of this term } return exp; } @@ -274,7 +279,7 @@ } exp += ")"; if (symbol.isImplWithSideEffect()) { - sideEffects[0] = sideEffects[0] + exp + ";"; + sideEffects[0] = sideEffects[0] + exp + ";\n"; exp = children.get(0).toImplementation(new String[] {""}); } return exp; @@ -288,7 +293,7 @@ } exp += ")"; if (symbol.isImplWithSideEffect()) { - sideEffects[0] = sideEffects[0] + exp + ";"; + sideEffects[0] = sideEffects[0] + exp + ";\n"; exp = children.get(implParamOrder[0]).toImplementation(new String[] {""}); } return exp; diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ChannelMember.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ChannelMember.java index d862851..8c2f210 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ChannelMember.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ChannelMember.java @@ -45,6 +45,11 @@ @Override public String toString() { + if (stateTransition.getNextStateExpression() == null) { + return identifierTemplate.getResourceName() + "(" + + stateTransition.getCurStateExpression() + "," + + stateTransition.getMessageExpression() + ")"; + } return identifierTemplate.getResourceName() + "(" + stateTransition.getCurStateExpression() + "," + stateTransition.getMessageExpression() + ")" diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java index e5b70de..79f8fe0 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java @@ -2,8 +2,6 @@ import java.util.Collection; import java.util.HashMap; -import java.util.HashSet; -import java.util.Set; import models.algebra.Symbol; import models.algebra.Type; @@ -26,9 +24,10 @@ public static final Type typeListStr = new Type("List", "ArrayList<>", "List", typeList); public static final Type typeTuple = new Type("Tuple", "AbstractMap.SimpleEntry", "Map.Entry"); public static final Type typePair = new Type("Pair", "Pair", "Pair"); - public static final Type typePairInt = new Type("Pair", "Pair", "Pair",typePair); - public static final Type typePairStr = new Type("Pair", "Pair", "Pair",typePair); - public static final Type typePairDouble = new Type("Pair", "Pair", "Pair",typePair); + public static final Type typePairInt = new Type("Pair", "Pair", "Pair", typePair); + public static final Type typePairStr = new Type("Pair", "Pair", "Pair", typePair); + public static final Type typePairDouble = new Type("Pair", "Pair", "Pair", typePair); + public static final Type typeMap = new Type("Map", "HashMap", "Map"); public static final Symbol add = new Symbol(Parser.ADD, 2, Symbol.Type.INFIX); public static final Symbol mul = new Symbol(Parser.MUL, 2, Symbol.Type.INFIX);; public static final Symbol sub = new Symbol(Parser.SUB, 2, Symbol.Type.INFIX); @@ -42,33 +41,41 @@ public static final Symbol contains = new Symbol("contains", 2, Symbol.Type.PREFIX, "contains", Symbol.Type.METHOD); public static final Symbol nil = new Symbol("nil", 0, Symbol.Type.PREFIX, new Symbol.IImplGenerator() { @Override - public String generate(Type type, String[] children, String[] sideEffects) { + public String generate(Type type, String[] children, String[] childrenSideEffects, String[] sideEffect) { String compType = ""; if (type != null) { String interfaceType = type.getInterfaceTypeName(); if (interfaceType.contains("<")) { compType = interfaceType.substring(interfaceType.indexOf("<") + 1, interfaceType.lastIndexOf(">")); } + String implType = type.getImplementationTypeName(); + if (implType.indexOf('<') >= 0) { + implType = implType.substring(0, implType.indexOf('<')); + } + return "new " + implType + "<" + compType + ">()"; } return "new ArrayList<" + compType + ">()"; } }); + public static final Symbol null_ = new Symbol("null", 0, Symbol.Type.PREFIX, "null", Symbol.Type.PREFIX); public static final Symbol cond = new Symbol("if", 3, Symbol.Type.PREFIX, new Symbol.IImplGenerator() { final int count[] = {0}; @Override - public String generate(Type type, String[] children, String[] sideEffects) { - // TODO Auto-generated method stub + public String generate(Type type, String[] children, String[] childrenSideEffects, String[] sideEffect) { String temp = "temp_if" + count[0]; String impl = ""; impl += type.getInterfaceTypeName() + " " + temp + ";\n"; - impl += "if (" + children[0] + ") {\n"; - impl +="\t" + temp + " = " + children[1] + ";\n"; + if (childrenSideEffects[0] != null && childrenSideEffects[0].length() > 0) impl += childrenSideEffects[0]; + impl += "if (" + children[0] + ") {\n"; + if (childrenSideEffects[1] != null && childrenSideEffects[1].length() > 0) impl += "\t" + childrenSideEffects[1]; + impl += "\t" + temp + " = " + children[1] + ";\n"; impl += "} else {\n"; + if (childrenSideEffects[2] != null && childrenSideEffects[2].length() > 0) impl += "\t" + childrenSideEffects[2]; impl += "\t" + temp + " = " + children[2] + ";\n"; impl += "}\n"; - sideEffects[0] += impl; + sideEffect[0] += impl; count[0]++; return temp; @@ -88,14 +95,20 @@ public static final Symbol false_ = new Symbol("false", 0, Symbol.Type.PREFIX, "false", Symbol.Type.PREFIX); public static final Symbol pair = new Symbol("pair", -1, Symbol.Type.PREFIX, new Symbol.IImplGenerator() { @Override - public String generate(Type type, String[] childrenImpl, String[] sideEffects) { + public String generate(Type type, String[] childrenImpl, String[] childrenSideEffects, String[] sideEffect) { + for (String s: childrenSideEffects) { + sideEffect[0] += s; + } String impl = "new Pair<>(" + childrenImpl[0] + "," + childrenImpl[1] + ")"; return impl; } }); public static final Symbol tuple = new Symbol("tuple", -1, Symbol.Type.PREFIX, new Symbol.IImplGenerator() { @Override - public String generate(Type type, String[] childrenImpl, String[] sideEffects) { + public String generate(Type type, String[] childrenImpl, String[] childrenSideEffects, String[] sideEffect) { + for (String s: childrenSideEffects) { + sideEffect[0] += s; + } String impl = "new AbstractMap.SimpleEntry<>(" + childrenImpl[0] + "$x)"; for (int i = 1; i < childrenImpl.length - 1; i++) { impl = impl.replace("$x", ", new AbstractMap.SimpleEntry<>(" + childrenImpl[i] + "$x)"); @@ -108,6 +121,8 @@ public static final Symbol snd = new Symbol("snd", 1, Symbol.Type.PREFIX, "getValue", Symbol.Type.METHOD); public static final Symbol left = new Symbol("left", 1, Symbol.Type.PREFIX, "getLeft", Symbol.Type.METHOD); public static final Symbol right = new Symbol("right", 1, Symbol.Type.PREFIX, "getRight", Symbol.Type.METHOD); + public static final Symbol insert = new Symbol("insert", 3, Symbol.Type.PREFIX, "put", Symbol.Type.METHOD_WITH_SIDE_EFFECT); + public static final Symbol lookup = new Symbol("lookup", 2, Symbol.Type.PREFIX, "get", Symbol.Type.METHOD); static { add.setInverses(new Symbol[] {sub, sub}); @@ -115,23 +130,24 @@ sub.setInverses(new Symbol[] {add}); div.setInverses(new Symbol[] {mul}); minus.setInverses(new Symbol[] {minus}); + mod.setSignature(new Type[] {typeInt, null, null}); cons.setInverses(new Symbol[] {head, tail}); cons.setSignature(new Type[] {typeList, null, typeList}); contains.setSignature(new Type[] {typeBoolean, typeList, null}); get.setSignature(new Type[] {null, typeList, typeInt}); set.setSignature(new Type[] {typeList, typeList, typeInt, null}); - mod.setSignature(new Type[] {null, null, typeInt}); - 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}); + eq.setSignature(new Type[] {typeBoolean, null, null}); + neq.setSignature(new Type[] {typeBoolean, null, null}); + gt.setSignature(new Type[] {typeBoolean, null, null}); + lt.setSignature(new Type[] {typeBoolean, null, null}); + ge.setSignature(new Type[] {typeBoolean, null, null}); + le.setSignature(new Type[] {typeBoolean, null, null}); and.setSignature(new Type[] {typeBoolean, typeBoolean, typeBoolean}); or.setSignature(new Type[] {typeBoolean, typeBoolean, typeBoolean}); neg.setSignature(new Type[] {typeBoolean, typeBoolean}); true_.setSignature(new Type[] {typeBoolean}); false_.setSignature(new Type[] {typeBoolean}); + null_.setSignature(new Type[] {null}); pair.setSignature(new Type[] {typePair,null,null}); pair.setInverses(new Symbol[] {left, right}); left.setSignature(new Type[] {null, typePair}); @@ -140,6 +156,8 @@ tuple.setInverses(new Symbol[] {fst, snd}); fst.setSignature(new Type[] {null, typeTuple}); snd.setSignature(new Type[] {null, typeTuple}); + insert.setSignature(new Type[] {typeMap, typeMap, null, null}); + lookup.setSignature(new Type[] {null, typeMap, null}); } public DataConstraintModel() { @@ -156,12 +174,14 @@ addType(typeList); addType(typePair); addType(typeTuple); + addType(typeMap); symbols = new HashMap<>(); addSymbol(add); addSymbol(mul); addSymbol(sub); addSymbol(div); addSymbol(minus); + addSymbol(mod); addSymbol(cons); addSymbol(head); addSymbol(tail); @@ -170,7 +190,6 @@ addSymbol(set); addSymbol(nil); addSymbol(cond); - addSymbol(mod); addSymbol(eq); addSymbol(neq); addSymbol(gt); @@ -182,12 +201,15 @@ addSymbol(neg); addSymbol(true_); addSymbol(false_); + addSymbol(null_); addSymbol(pair); addSymbol(left); addSymbol(right); addSymbol(tuple); addSymbol(fst); addSymbol(snd); + addSymbol(insert); + addSymbol(lookup); } public Collection getIdentifierTemplates() { diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/IdentifierTemplate.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/IdentifierTemplate.java index 22f5c48..d0e62ff 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/IdentifierTemplate.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/IdentifierTemplate.java @@ -1,6 +1,7 @@ package models.dataConstraintModel; import models.algebra.Expression; +import models.algebra.Term; import models.algebra.Type; public class IdentifierTemplate { @@ -34,6 +35,11 @@ public void setResourceStateType(Type resourceStateType) { this.resourceStateType = resourceStateType; + if (initialValue != null) { + if (initialValue instanceof Term) { + ((Term) initialValue).setType(resourceStateType); + } + } } public Expression getInitialValue() { diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataflowChannelGenerator.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataflowChannelGenerator.java index 40dd36d..b4bdb35 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataflowChannelGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataflowChannelGenerator.java @@ -232,6 +232,9 @@ for (ChannelMember inputMember: inputChannelMembers) { channelSource += "\t in " + inputMember + "\n"; } + for (ChannelMember refMember: referenceChannelMembers) { + channelSource += "\t ref " + refMember + "\n"; + } for (ChannelMember outputMember: outputChannelMembers) { channelSource += "\t out " + outputMember + "\n"; } diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ModelExtension.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ModelExtension.java index b4b812f..0666fa2 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ModelExtension.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ModelExtension.java @@ -24,7 +24,7 @@ final int[] count = new int[] {0}; sum.setGenerator(new Symbol.IImplGenerator() { @Override - public String generate(Type type, String[] children, String[] sideEffects) { + public String generate(Type type, String[] children, String[] childrenSideEffects, String[] sideEffect) { String compType = "Integer"; if (type != null) { String interfaceType = type.getInterfaceTypeName(); @@ -37,7 +37,7 @@ impl += "for (" + compType + " x: " + children[0] + ") {\n"; impl += "\t" + "temp_sum" + count[0] + " += x;\n"; impl += "}\n"; - sideEffects[0] = sideEffects[0] + impl; + sideEffect[0] = sideEffect[0] + impl; return "temp_sum" + count[0]; } }); @@ -54,7 +54,7 @@ final int[] count = new int[] {0}; merge.setGenerator(new Symbol.IImplGenerator() { @Override - public String generate(Type type, String[] childrenImpl, String[] sideEffects) { + public String generate(Type type, String[] childrenImpl, String[] childrenSideEffects, String[] sideEffect) { String implType = "Arrayist<>"; String interfaceType = "List"; String compType = "Integer"; @@ -93,7 +93,7 @@ impl += "\t\t}\n"; impl += "\t}\n"; impl += "}\n"; - sideEffects[0] = sideEffects[0] + impl; + sideEffect[0] = sideEffect[0] + impl; return "temp_l" + count[0]; } });