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..4386f2c 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> 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()); } @@ -415,20 +432,20 @@ List pairExps = new ArrayList<>(); pairExps.add(t); expToPair.put(System.identityHashCode(t), pairExps); - + if (t.getType() == DataConstraintModel.typePair) { for (Expression e : t.getChildren()) { pairExps.add(e); expToPair.put(System.identityHashCode(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,7 +456,7 @@ } } pair.put(System.identityHashCode(pairExps), t.getType()); - + } } else if (symbol.equals(DataConstraintModel.fst)) { // If the root symbol of the term is fst. @@ -593,6 +610,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); + expToMap.put(System.identityHashCode(arg1), mapExps); + Expression arg2 = t.getChildren().get(1); // key + mapExps.add(arg2); + expToMap.put(System.identityHashCode(arg2), mapExps); + mapExps.add(t); // value + expToMap.put(System.identityHashCode(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 + expToMap.put(System.identityHashCode(t), mapExps); + Expression arg1 = t.getChildren().get(1); // key + mapExps.add(arg1); + expToMap.put(System.identityHashCode(arg1), mapExps); + Expression arg2 = t.getChildren().get(2); // value + mapExps.add(arg2); + expToMap.put(System.identityHashCode(arg2), mapExps); + Expression arg0 = t.getChildren().get(0); // map + mapExps.add(arg0); + expToMap.put(System.identityHashCode(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 +837,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 +853,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 +869,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 +884,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 +900,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 +916,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,8 +932,24 @@ 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); + } } } } @@ -1002,36 +1124,6 @@ } } - private static Type createNewListType(Type compType, Type parentType) { - String compTypeName = getInterfaceTypeName(compType); - List childrenTypes = getChildrenTypesOfList(parentType); - Type newListType = new Type("List", "ArrayList<>", "List<" + compTypeName + ">", parentType); - listTypes.put(compType, newListType); - listComponentTypes.put(newListType, compType); - for (Type childType : childrenTypes) { - if (compareTypes(childType, newListType)) { - if (newListType.getParentTypes().contains(parentType)) { - newListType.replaceParentType(parentType, childType); - } else { - newListType.addParentType(childType); - } - } else if (compareTypes(newListType, childType)) { - childType.replaceParentType(parentType, newListType); - } - } - 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)); @@ -1140,6 +1232,113 @@ } } } + + private static void updateMapTypes(Expression exp, Map map, + Map> expToMap, Map> updateFromMap) { + List components = expToMap.get(System.identityHashCode(exp)); + if (components == null) + return; + int idx = components.indexOf(exp); + if (idx == 0 || idx == 3) { + Type mapType = map.get(System.identityHashCode(components)); + Type newMapType = getExpTypeIfUpdatable(mapType, exp); + if (newMapType != null) { + // Propagate an update of a map's type to its components' types. + map.put(System.identityHashCode(components), newMapType); + List componentTypes = mapComponentTypes.get(newMapType); + Map updateExps = getUpdateSet(updateFromMap, components); + for (int i = 1; i < components.size() && i < 3; 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); + } + } + } + // Propagate an update of a map's type to another map's type. + Expression compExp = null; + if (idx == 0 && components.size() == 4) { // for lookup + compExp = components.get(3); + } else if (idx == 3) { + compExp = components.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(components)); + 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, components); + Expression mapExp = components.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 (components.size() == 4) { // for lookup + mapExp = components.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(components), newMapType); + } + } + } + + private static Type createNewListType(Type compType, Type parentType) { + String compTypeName = getInterfaceTypeName(compType); + List childrenTypes = getChildrenTypes(parentType, listComponentTypes.keySet()); + Type newListType = new Type("List", "ArrayList<>", "List<" + compTypeName + ">", parentType); + listTypes.put(compType, newListType); + listComponentTypes.put(newListType, compType); + for (Type childType : childrenTypes) { + if (compareTypes(childType, newListType)) { + if (newListType.getParentTypes().contains(parentType)) { + newListType.replaceParentType(parentType, childType); + } else { + newListType.addParentType(childType); + } + } else if (compareTypes(newListType, childType)) { + childType.replaceParentType(parentType, newListType); + } + } + return newListType; + } private static Type createNewTupleType(List componentTypes, Type parentTupleType) { String implTypeName = "AbstractMap.SimpleEntry<>"; @@ -1158,7 +1357,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 +1375,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 +1414,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 +1423,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 +1467,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]; } });