diff --git a/AlgebraicDataflowArchitectureModel/src/algorithms/TypeInference.java b/AlgebraicDataflowArchitectureModel/src/algorithms/TypeInference.java index d2c98ef..7b6de77 100644 --- a/AlgebraicDataflowArchitectureModel/src/algorithms/TypeInference.java +++ b/AlgebraicDataflowArchitectureModel/src/algorithms/TypeInference.java @@ -833,11 +833,33 @@ 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)); @@ -847,6 +869,7 @@ 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); @@ -871,6 +894,7 @@ 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); @@ -905,12 +929,34 @@ implTypeName = implTypeName.replace("$x", ", " + getImplementationTypeName(componentTypes.get(componentTypes.size() - 1))); interfaceTypeName = interfaceTypeName.replace("$x", ", " + getInterfaceTypeName(componentTypes.get(componentTypes.size() - 1))); } + List childrenTypes = getChildrenTypesOfTuple(parentTupleType); Type newTupleType = new Type("Tuple", implTypeName, interfaceTypeName, parentTupleType); tupleTypes.put(componentTypes, newTupleType); tupleComponentTypes.put(newTupleType, componentTypes); + for (Type childType: childrenTypes) { + if (compareTypes(childType, newTupleType)) { + if (newTupleType.getParentTypes().contains(parentTupleType)) { + newTupleType.replaceParentType(parentTupleType, childType); + } else { + newTupleType.addParentType(childType); + } + } else if (compareTypes(newTupleType, childType)) { + childType.replaceParentType(parentTupleType, newTupleType); + } + } return newTupleType; } + private static List getChildrenTypesOfTuple(Type parentTupleType) { + List childrenTypes = new ArrayList<>(); + for (Type tupleType: tupleComponentTypes.keySet()) { + if (tupleType.getParentTypes().contains(parentTupleType)) { + childrenTypes.add(tupleType); + } + } + return childrenTypes; + } + private static String getImplementationTypeName(Type type) { if (type == null) return "Integer"; String wrapperType = DataConstraintModel.getWrapperType(type); @@ -947,6 +993,12 @@ return null; } + /** + * Is an given original type an ancestor of a given new type? + * @param originalType original type + * @param newType new type (may not have been registered) + * @return true: if the original type equals to the new type or is an ancestor of the new type, false: otherwise + */ private static boolean compareTypes(Type originalType, Type newType) { if (originalType == null) return true; if (originalType != newType && newType != null) { diff --git a/AlgebraicDataflowArchitectureModel/src/models/algebra/Type.java b/AlgebraicDataflowArchitectureModel/src/models/algebra/Type.java index f61e4d9..50b0285 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/algebra/Type.java +++ b/AlgebraicDataflowArchitectureModel/src/models/algebra/Type.java @@ -1,10 +1,13 @@ package models.algebra; +import java.util.ArrayList; +import java.util.List; + public class Type { private String typeName; private String implementationTypeName; private String interfaceTypeName; - private Type parentType = null; + private List parentTypes = new ArrayList<>(); public Type(String typeName, String implementastionTypeName) { this.typeName = typeName; @@ -22,14 +25,14 @@ this.typeName = typeName; this.implementationTypeName = implementastionTypeName; this.interfaceTypeName = implementastionTypeName; - this.parentType = parentType; + this.parentTypes.add(parentType); } public Type(String typeName, String implementastionTypeName, String interfaceTypeName, Type parentType) { this.typeName = typeName; this.implementationTypeName = implementastionTypeName; this.interfaceTypeName = interfaceTypeName; - this.parentType = parentType; + this.parentTypes.add(parentType); } public String getTypeName() { @@ -56,39 +59,46 @@ this.interfaceTypeName = interfaceTypeName; } - public Type getParentType() { - return parentType; + public List getParentTypes() { + return parentTypes; } - public void setParentType(Type parentType) { - this.parentType = parentType; + public void addParentType(Type parentType) { + parentTypes.add(parentType); + } + + public void replaceParentType(Type oldParentType, Type newParentType) { + parentTypes.set(parentTypes.indexOf(oldParentType), newParentType); } public boolean isAncestorOf(Type another) { if (this.equals(another)) return true; - if (another.getParentType() == null) return false; - return isAncestorOf(another.getParentType()); + if (another.getParentTypes() == null) return false; + for (Type anothersParentType: another.getParentTypes()) { + if (isAncestorOf(anothersParentType)) return true; + } + return false; } public Memento createMemento() { - return new Memento(implementationTypeName, interfaceTypeName, parentType); + return new Memento(implementationTypeName, interfaceTypeName, parentTypes); } public void setMemento(Memento memento) { this.implementationTypeName = memento.implementationTypeName; this.interfaceTypeName = memento.interfaceTypeName; - this.parentType = memento.parentType; + this.parentTypes = memento.parentTypes; } public static class Memento { private String implementationTypeName; private String interfaceTypeName; - private Type parentType; + private List parentTypes; - public Memento(String implementationTypeName, String interfaceTypeName, Type parentType) { + public Memento(String implementationTypeName, String interfaceTypeName, List parentTypes) { this.implementationTypeName = implementationTypeName; this.interfaceTypeName = interfaceTypeName; - this.parentType = parentType; + this.parentTypes = parentTypes; } } }