diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java b/src/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java index 1c45680b..4bbcde0b 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java +++ b/src/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java @@ -140,32 +140,71 @@ public class FiniteClosure implements IFiniteClosure { * @return The set of supertypes of the argument. */ @Override - public Set greater(Type type) { - Set result = inheritanceGraph.containsKey(type) ? inheritanceGraph.get(type).getContentOfPredecessors() : new HashSet<>(); - result.add(type); - - if(type.getTypeParams().size() == 0) - return result; + public Set greater(Type type) { + IUnify unify = new MartelliMontanariUnify(); + Set result1 = new HashSet<>(); - ArrayList> paramCandidates = new ArrayList<>(); - for(Type param : type.getTypeParams()) { - if(param instanceof ExtendsType || param instanceof SuperType) { - Set pc = param.grArg(this); - paramCandidates.add(pc); - } else { - HashSet pc = new HashSet<>(); - pc.add(param); - paramCandidates.add(pc); + if(inheritanceGraph.containsKey(type)) + result1.addAll(inheritanceGraph.get(type).getContentOfPredecessors()); + + // if T = T' then T <=* T' + result1.add(type); + + {ArrayList> paramCandidates = new ArrayList<>(); + for (Type param : type.getTypeParams()) + paramCandidates.add(grArg(param)); + + Set permResult = new HashSet<>(); + permuteParams(paramCandidates, 0, permResult, new Type[paramCandidates.size()]); + + for (TypeParams newParams : permResult) + result1.add(type.setTypeParams(newParams));} + + Set result2 = new HashSet<>(); + if (strInheritanceGraph.containsKey(type.getName()) && !inheritanceGraph.containsKey(type)) { + HashSet candidates = new HashSet<>(); + strInheritanceGraph.get(type.getName()).forEach(x -> candidates.add(x.getContent())); + + for(Type typePrime : result1) { + for (Type theta2 : candidates) { + Optional sigma2 = unify.unify(typePrime, theta2); + if (!sigma2.isPresent()) + continue; + if(type.equals(theta2)) + continue; + Set theta1s = greater(theta2); + for (Type theta1 : theta1s) { + // Because only the most general type is calculated, sigma1 = sigma2 + Type sigma1Theta1 = sigma2.get().apply(theta1); + result2.add(sigma1Theta1); + } + } } } - Set permResult = new HashSet<>(); - permuteParams(paramCandidates, 0, permResult, new Type[paramCandidates.size()]); + result2.addAll(result1); - for(TypeParams newParams : permResult) - result.add(type.setTypeParams(newParams)); + Set result3 = new HashSet<>(); + for(Type t : result2) { + ArrayList> paramCandidates = new ArrayList<>(); + for (Type param : t.getTypeParams()) + paramCandidates.add(grArg(param)); + + Set permResult = new HashSet<>(); + permuteParams(paramCandidates, 0, permResult, new Type[paramCandidates.size()]); + + for (TypeParams newParams : permResult) { + Type tPrime = t.setTypeParams(newParams); + if(tPrime.equals(t)) + result3.add(t); + else + result3.addAll(greater(tPrime)); + } + + } + + return result3; - return result; } @Override @@ -217,8 +256,8 @@ public class FiniteClosure implements IFiniteClosure { public Set grArg(PlaceholderType type) { HashSet result = new HashSet<>(); result.add(type); - result.add(new SuperType(type)); - result.add(new ExtendsType(type)); + //result.add(new SuperType(type)); + //result.add(new ExtendsType(type)); return result; } diff --git a/test/unify/FiniteClosureTest.java b/test/unify/FiniteClosureTest.java index 33ba1d0a..7322e857 100644 --- a/test/unify/FiniteClosureTest.java +++ b/test/unify/FiniteClosureTest.java @@ -2,6 +2,7 @@ package unify; import java.util.Arrays; import java.util.HashSet; +import java.util.List; import java.util.Set; import java.util.stream.Collectors; @@ -397,19 +398,237 @@ public class FiniteClosureTest { public void testGreater() { TypeFactory tf = new TypeFactory(); FiniteClosureBuilder fcb = new FiniteClosureBuilder(); - fcb.add(tf.getSimpleType("Integer"), tf.getSimpleType("Number")); - fcb.add(tf.getSimpleType("MyMap", "T"), tf.getSimpleType("HashMap", tf.getSimpleType("Integer"))); - fcb.add(tf.getSimpleType("HashMap", "T"), tf.getSimpleType("Collection")); + Type k = tf.getPlaceholderType("K"); + Type integer = tf.getSimpleType("Integer"); + Type number = tf.getSimpleType("Number"); + Type myMap = tf.getSimpleType("MyMap", k); + Type myIntMap = tf.getSimpleType("MyIntMap"); + Type collection = tf.getSimpleType("Collection"); + Type sortedSet =tf.getSimpleType("SortedSet", "T"); + Type extInt = tf.getExtendsType(integer); + Type extNum = tf.getExtendsType(number); + Type supInt = tf.getSuperType(integer); + Type supNum = tf.getSuperType(number); + fcb.add(myMap, tf.getSimpleType("Map", k, tf.getSimpleType("List", k))); + fcb.add(myIntMap, tf.getSimpleType("MyMap", integer)); + fcb.add(sortedSet, tf.getSimpleType("Set", "T")); // sortedSet < Set missing in collection example + fcb.add(integer, number); IFiniteClosure fc = fcb.getCollectionExample(); - System.out.println("\n\n----- Greater Test -----"); - System.out.println("Greater(LinkedList) = " + fc.greater(tf.getSimpleType("LinkedList", "T"))); - System.out.println("Greater(TreeSet) = " + fc.greater(tf.getSimpleType("TreeSet", "T"))); - System.out.println("Greater(Collection) = " + fc.greater(tf.getSimpleType("Collection"))); - System.out.println(fc.greater(tf.getSimpleType("Deque", tf.getSimpleType("Integer")))); - System.out.println(fc.greater(tf.getSimpleType("Deque", tf.getSimpleType("Number")))); - System.out.println(fc.greater(tf.getSimpleType("Deque", tf.getExtendsType(tf.getSimpleType("Integer"))))); - System.out.println(fc.greater(tf.getSimpleType("Deque", tf.getSuperType(tf.getSimpleType("Integer"))))); + /* + * Test Case 1: + * + * greater(SortedSet) = + * { SortedSet, Set, Collection + * SortedSet, SortedSet, SortedSet, + * Set, Set, Set } + */ + + Type sortedSetInteger = tf.getSimpleType("SortedSet", integer); + Set expectedResult = new HashSet<>(Arrays.stream(new Type[] { + sortedSetInteger, tf.getSimpleType("Set", integer), collection, + tf.getSimpleType("SortedSet", extInt), tf.getSimpleType("SortedSet", supInt), + tf.getSimpleType("SortedSet", extNum), tf.getSimpleType("Set", extInt), + tf.getSimpleType("Set", supInt), tf.getSimpleType("Set", extNum) + }).collect(Collectors.toSet())); + + Set actual = fc.greater(sortedSetInteger); + Assert.assertEquals(expectedResult, actual); + + /* + * Test Case 2: + * + * greater(SortedSet) = + * { SortedSet, SortedSet, + * Set, Set, Collection } + */ + + Type sortedSetExtInt = tf.getSimpleType("SortedSet", extInt); + expectedResult = new HashSet<>(Arrays.stream(new Type[] { + sortedSetExtInt, tf.getSimpleType("SortedSet", extNum), collection, + tf.getSimpleType("Set", extInt), tf.getSimpleType("Set", extNum) + }).collect(Collectors.toSet())); + + actual = fc.greater(sortedSetExtInt); + Assert.assertEquals(expectedResult, actual); + + /* + * Test Case 3: + * + * TODO hier extends und super? (siehe test case 4 bei smaller) + * greater(SortedSet) = + * { SortedSet, SortedSet, SortedSet, + * Set, Set, Set, Collection } + */ + + /* + * Test Case 4: + * + * greater(SortedSet) = + * { SortedSet, SortedSet + * Set, Set, Collection } + */ + + Type sortedSetSupNum = tf.getSimpleType("SortedSet", supNum); + expectedResult = new HashSet<>(Arrays.stream(new Type[] { + sortedSetSupNum, tf.getSimpleType("SortedSet", supInt), collection, + tf.getSimpleType("Set", supNum), tf.getSimpleType("Set", supInt) + }).collect(Collectors.toSet())); + + actual = fc.greater(sortedSetSupNum); + Assert.assertEquals(expectedResult, actual); + + /* + * Test Case 5: + * + * TODO nicht unifizierbar bei T wenn Set deklariert wurde. Können die beiden T's verschieden sein? + * greater(SortedSet) = + * { SortedSet, Set, Collection } + */ + + Type extT = tf.getExtendsType(tf.getPlaceholderType("T1")); + Type sortedSetExtT = tf.getSimpleType("SortedSet", extT); + expectedResult = new HashSet<>(Arrays.stream(new Type[] { + sortedSetExtT, tf.getSimpleType("Set", extT), collection, + }).collect(Collectors.toSet())); + + actual = fc.greater(sortedSetExtT); + Assert.assertEquals(expectedResult, actual); + + /* + * Test Case 6: + * + * greater(SortedSet) = + * { SortedSet, SortedSet, SortedSet, + * Set, Set, Set, Collection } + */ + + Type notInFc = tf.getSimpleType("NotInFc"); + Type extNotInFc = tf.getExtendsType(notInFc); + Type supNotInFc = tf.getSuperType(notInFc); + Type sortedSetNotInFc= tf.getSimpleType("SortedSet", notInFc); + expectedResult = new HashSet<>(Arrays.stream(new Type[] { + sortedSetNotInFc, tf.getSimpleType("SortedSet", extNotInFc), tf.getSimpleType("SortedSet", supNotInFc), + tf.getSimpleType("Set", notInFc), tf.getSimpleType("Set", extNotInFc), tf.getSimpleType("Set", supNotInFc), + collection + }).collect(Collectors.toSet())); + + actual = fc.greater(sortedSetNotInFc); + Assert.assertEquals(expectedResult, actual); + + /* + * Test Case 7: + * + * greater(SortedSet, Set, Collection } + */ + + Type sortedSetSupNotInFc= tf.getSimpleType("SortedSet", supNotInFc); + expectedResult = new HashSet<>(Arrays.stream(new Type[] { + sortedSetSupNotInFc, tf.getSimpleType("Set", supNotInFc), collection + }).collect(Collectors.toSet())); + + actual = fc.greater(sortedSetSupNotInFc); + Assert.assertEquals(expectedResult, actual); + + /* + * Test Case 8: + * + * greater(NotInFc) = + * { NotInFc, NotInFc, NotInFC, + * NotInFc } + */ + + Type notInFcInteger = tf.getSimpleType("NotInFc", integer); + expectedResult = new HashSet<>(Arrays.stream(new Type[] { + notInFcInteger, tf.getSimpleType("NotInFc", supInt), + tf.getSimpleType("NotInFc", extInt), tf.getSimpleType("NotInFc", extNum) + }).collect(Collectors.toSet())); + + actual = fc.greater(notInFcInteger); + Assert.assertEquals(expectedResult, actual); + + /* + * Test Case 9: + * greater(NotInFc) = + * { NotInFc, NotInFc } + */ + + Type notInFcAlsoNotInFc = tf.getSimpleType("NotInFc", tf.getSimpleType("AlsoNotInFc")); + expectedResult = new HashSet<>(Arrays.stream(new Type[] { + notInFcAlsoNotInFc, tf.getSimpleType("NotInFc", tf.getExtendsType(tf.getSimpleType("AlsoNotInFc"))), + tf.getSimpleType("NotInFc", tf.getSuperType(tf.getSimpleType("AlsoNotInFc"))) + }).collect(Collectors.toSet())); + + actual = fc.greater(notInFcAlsoNotInFc); + Assert.assertEquals(expectedResult, actual); + + /* + * Test Case 10: + * greater(Map) = + * { Map, Map, + * Map, Map, + * Map, Map, + * Map, Map } + */ + + Type mapExtIntInt = tf.getSimpleType("Map", extInt, integer); + expectedResult = new HashSet<>(Arrays.stream(new Type[] { + mapExtIntInt, tf.getSimpleType("Map", extInt, extInt), + tf.getSimpleType("Map", extInt, supInt), tf.getSimpleType("Map", extInt, extNum), + tf.getSimpleType("Map", extNum, integer), tf.getSimpleType("Map", extNum, extInt), + tf.getSimpleType("Map", extNum, supInt), tf.getSimpleType("Map", extNum, extNum) + }).collect(Collectors.toSet())); + + actual = fc.greater(mapExtIntInt); + Assert.assertEquals(expectedResult, actual); + + /* + * Test Case 11: + * + * MyIntMap < MyMap + * MyMap < Map> + * + * greater(MyIntMap) = + * { MyMap, MyMap, MyMap, MyMap, + * Map, Map, List, + * Map, List, Map, MyIntMap } + */ + + Type listInteger = tf.getSimpleType("List", integer); + expectedResult = new HashSet<>(Arrays.stream(new Type[] { + myIntMap, tf.getSimpleType("MyMap", integer), tf.getSimpleType("MyMap", extInt), + tf.getSimpleType("MyMap", extNum), tf.getSimpleType("MyMap", supInt), + tf.getSimpleType("Map", integer, listInteger), tf.getSimpleType("Map", extInt, listInteger), + tf.getSimpleType("MyMap", extNum, listInteger), tf.getSimpleType("MyMap", supInt, listInteger) + }).collect(Collectors.toSet())); + + actual = fc.greater(myIntMap); + //Assert.assertEquals(expectedResult, actual); + + /* + * Test Case 12: + * + * MyIntMap < MyMap + * MyMap < Map> + * + * TODO + * D d = null; + * A> a = null; + * a = d; ist nicht möglich! + * + * greater(MyMap) = + * { MyMap, MyMap, + * Map>, + * Map, List> } + */ + + /* + * Test Case 13: + * + * greater(SortedMap, ? super List>) = + * + */ } @Test