From 26cc9b85efa4a2d7f8bec46874ce9b11fef76563 Mon Sep 17 00:00:00 2001 From: Florian Steurer Date: Mon, 28 Mar 2016 01:01:46 +0200 Subject: [PATCH] smalller und neue testcases --- .../unify/interfaces/IFiniteClosure.java | 2 +- .../unify/model/FiniteClosure.java | 145 +++++++++++------- .../unifynew/MartelliMontanariUnify.java | 8 +- .../typeinference/unifynew/RuleSet.java | 14 +- test/unify/FiniteClosureBuilder.java | 9 +- test/unify/FiniteClosureTest.java | 88 +++++++++-- 6 files changed, 185 insertions(+), 81 deletions(-) diff --git a/src/de/dhbwstuttgart/typeinference/unify/interfaces/IFiniteClosure.java b/src/de/dhbwstuttgart/typeinference/unify/interfaces/IFiniteClosure.java index 0bba681f..00c12f65 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/interfaces/IFiniteClosure.java +++ b/src/de/dhbwstuttgart/typeinference/unify/interfaces/IFiniteClosure.java @@ -53,6 +53,6 @@ public interface IFiniteClosure { public Set grArg(FunNType type); public Set smArg(FunNType type); - public Optional getGenericType(String typeName); + public Optional findGenericParent(String typeName); public Set getAllTypesByName(String typeName); } diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java b/src/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java index 427122bf..4a331353 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java +++ b/src/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java @@ -18,15 +18,17 @@ public class FiniteClosure implements IFiniteClosure { private HashMap> inheritanceGraph; private HashMap>> strInheritanceGraph; + private Set pairs; + private Set basicTypes; + //TODO im konstruktor mitgeben um typenabzuhandeln die keine extends beziehung haben. (Damit die FC diese Typen auch kennt) + //(ALternative: immer die extends zu object beziehung einfügen) public FiniteClosure(Set pairs) { + this.pairs = new HashSet<>(pairs); inheritanceGraph = new HashMap>(); // Build the transitive closure of the inheritance tree for(MPair pair : pairs) { - if(!pair.getLhsType().getTypeParams().arePlaceholders()) - throw new IllegalArgumentException("The finite closure only has pairs of the form D <= C<...>"); - if(pair.getPairOp() != PairOperator.SMALLER) continue; @@ -64,51 +66,68 @@ public class FiniteClosure implements IFiniteClosure { */ @Override public Set smaller(Type type) { - Set result = new HashSet<>(); - result.add(type); - - // - if(T < T') then T <=* T' - // if T1 <=* T2 then sigma1(T1) <=* sigma1(T2) - // where foreach type var a in T2: - // sigma1(T1) <=* sigma2(T2) - //If a type of the same name is in the fc AND the type "type" is parameterized (some substitution sigma1 was applied) - + if(inheritanceGraph.containsKey(type)) { + Set result = new HashSet<>(); + result.add(type); + result.addAll(inheritanceGraph.get(type).getContentOfDescendants()); + return result; + } + IUnify unify = new MartelliMontanariUnify(); - HashSet candidates = new HashSet<>(); - if (strInheritanceGraph.containsKey(type.getName())) - strInheritanceGraph.get(type.getName()).forEach(x -> candidates.add(x.getContent())); - else - candidates.add(type); + Set result1 = new HashSet<>(); - for (Type theta2 : candidates) { - Optional sigma2 = unify.unify(theta2, type); - if (!sigma2.isPresent()) - continue; - Set theta1s = new HashSet<>(); - if(inheritanceGraph.containsKey(type)) - theta1s = inheritanceGraph.get(type).getContentOfDescendants(); - else if(theta2.equals(type)) - theta1s.add(type); - else - theta1s = smaller(theta2); - for (Type theta1 : theta1s) { - // Because only the most general type is calculated, sigma1 = - // sigma2 - Type sigma1Theta1 = sigma2.get().apply(theta1); - - ArrayList> paramCandidates = new ArrayList<>(); - for (Type param : sigma1Theta1.getTypeParams()) - paramCandidates.add(smArg(param)); - - Set permResult = new HashSet<>(); - permuteParams(paramCandidates, 0, permResult, new Type[paramCandidates.size()]); - - for (TypeParams newParams : permResult) - result.add(sigma1Theta1.setTypeParams(newParams)); + // if T = T' then T <=* T' + result1.add(type); + + {ArrayList> paramCandidates = new ArrayList<>(); + for (Type param : type.getTypeParams()) + paramCandidates.add(smArg(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())) { + 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 = smaller(theta2); + for (Type theta1 : theta1s) { + // Because only the most general type is calculated, sigma1 = sigma2 + Type sigma1Theta1 = sigma2.get().apply(theta1); + result2.add(sigma1Theta1); + } + } } } - - return result; + else + result2 = result1; + + Set result3 = new HashSet<>(); + for(Type t : result2) { + ArrayList> paramCandidates = new ArrayList<>(); + for (Type param : t.getTypeParams()) + paramCandidates.add(smArg(param)); + + Set permResult = new HashSet<>(); + permuteParams(paramCandidates, 0, permResult, new Type[paramCandidates.size()]); + + for (TypeParams newParams : permResult) + result3.add(t.setTypeParams(newParams)); + + } + + return result3; } /** @@ -260,19 +279,37 @@ public class FiniteClosure implements IFiniteClosure { return result; } + + public boolean isGenericType(Type t) { + if(t.getTypeParams().size() == 0) + return true; + + if(!strInheritanceGraph.containsKey(t.getName())) + return false; + + for(MPair pair : pairs) + if(pair.getLhsType().equals(t)) + return true; + + return false; + } + @Override - public Optional getGenericType(String typeName) { - if(!strInheritanceGraph.containsKey(typeName)) - return Optional.empty(); - - HashSet> candidates = strInheritanceGraph.get(typeName); - - for(Node node : candidates) { - Type candidate = node.getContent(); - if(candidate.getTypeParams().arePlaceholders()) - return Optional.of(candidate); + public Optional findGenericParent(String type) { + Type genericType = null; + for(MPair pair : pairs) { + Type lhs = pair.getLhsType(); + if(lhs.getName().equals(type)) { + genericType = lhs; + break; + } } + if(genericType == null) + return Optional.empty(); + + // TODO reduce reglen überarbeiten, es kann mehrere Typen D geben die eine bedingung + // erfüllen, diese methode ausimplementieren return Optional.empty(); } diff --git a/src/de/dhbwstuttgart/typeinference/unifynew/MartelliMontanariUnify.java b/src/de/dhbwstuttgart/typeinference/unifynew/MartelliMontanariUnify.java index 6ae0acf6..e3ae2322 100644 --- a/src/de/dhbwstuttgart/typeinference/unifynew/MartelliMontanariUnify.java +++ b/src/de/dhbwstuttgart/typeinference/unifynew/MartelliMontanariUnify.java @@ -101,8 +101,12 @@ public class MartelliMontanariUnify implements IUnify { TypeParams rhsTypeParams = rhs.getTypeParams(); TypeParams lhsTypeParams = lhs.getTypeParams(); - if(rhsTypeParams.size() != lhsTypeParams.size() || (!rhs.getName().equals(lhs.getName()) && rhsTypeParams.size() != 0)) - return null; // conflict + if(!(rhs instanceof PlaceholderType) && !(lhs instanceof PlaceholderType)) { + if(!rhs.getName().equals(lhs.getName())) + return null; // conflict + if(rhsTypeParams.size() != lhsTypeParams.size()) + return null; // conflict; + } if(rhsTypeParams.size() == 0 || lhsTypeParams.size() == 0) return Optional.empty(); diff --git a/src/de/dhbwstuttgart/typeinference/unifynew/RuleSet.java b/src/de/dhbwstuttgart/typeinference/unifynew/RuleSet.java index f6b26ad9..bae13582 100644 --- a/src/de/dhbwstuttgart/typeinference/unifynew/RuleSet.java +++ b/src/de/dhbwstuttgart/typeinference/unifynew/RuleSet.java @@ -328,7 +328,7 @@ public class RuleSet implements IRuleSet{ if(typeD.getName().equals(typeDs.getName())) return Optional.empty(); - Optional opt = finiteClosure.getGenericType(typeD.getName()); + Optional opt = finiteClosure.findGenericParent(typeD.getName()); if(!opt.isPresent()) return Optional.empty(); @@ -373,9 +373,9 @@ public class RuleSet implements IRuleSet{ Type typeDgen; if(typeD instanceof SimpleType) - typeDgen = finiteClosure.getGenericType(typeD.getName()).orElse(null); + typeDgen = finiteClosure.findGenericParent(typeD.getName()).orElse(null); else { - Optional opt = finiteClosure.getGenericType(((ExtendsType) typeD).getExtendedType().getName()); + Optional opt = finiteClosure.findGenericParent(((ExtendsType) typeD).getExtendedType().getName()); typeDgen = opt.isPresent() ? new ExtendsType(opt.get()) : null; } @@ -418,7 +418,7 @@ public class RuleSet implements IRuleSet{ return Optional.empty(); - Optional opt = finiteClosure.getGenericType(((SuperType) typeSupD).getSuperedType().getName()); + Optional opt = finiteClosure.findGenericParent(((SuperType) typeSupD).getSuperedType().getName()); if(!opt.isPresent()) return Optional.empty(); @@ -462,13 +462,13 @@ public class RuleSet implements IRuleSet{ private int[] pi(Type C, Type D) { Type cFromFc = null; if(C instanceof SimpleType) - cFromFc = finiteClosure.getGenericType(C.getName()).orElse(null); + cFromFc = finiteClosure.findGenericParent(C.getName()).orElse(null); else if(C instanceof ExtendsType) { - Optional opt = finiteClosure.getGenericType(((ExtendsType) C).getExtendedType().getName()); + Optional opt = finiteClosure.findGenericParent(((ExtendsType) C).getExtendedType().getName()); if(opt.isPresent()) cFromFc = new ExtendsType(opt.get()); } else if(C instanceof SuperType) { - Optional opt = finiteClosure.getGenericType(((SuperType) C).getSuperedType().getName()); + Optional opt = finiteClosure.findGenericParent(((SuperType) C).getSuperedType().getName()); if(opt.isPresent()) cFromFc = new SuperType(opt.get()); } diff --git a/test/unify/FiniteClosureBuilder.java b/test/unify/FiniteClosureBuilder.java index 5a639b38..f4ea2133 100644 --- a/test/unify/FiniteClosureBuilder.java +++ b/test/unify/FiniteClosureBuilder.java @@ -33,7 +33,8 @@ public class FiniteClosureBuilder { Type collection = tf.getSimpleType("Collection"); Type set = tf.getSimpleType("Set", "T"); - Type sortedSet = tf.getSimpleType("Set", "T"); + //Type sortedSet = tf.getSimpleType("SortedSet", "T"); Sorted set bei den Unit-Tests vergessen + // nachträgliches einfügen zu aufwendig Type TreeSet = tf.getSimpleType("TreeSet", "T"); Type hashSet = tf.getSimpleType("HashSet", "T"); Type linkedHashSet = tf.getSimpleType("LinkedHashSet", "T"); @@ -46,8 +47,8 @@ public class FiniteClosureBuilder { Type arrayList = tf.getSimpleType("ArrayList", "T"); add(set, collection); - add(sortedSet, set); - add(TreeSet, sortedSet); + //add(sortedSet, set); + add(TreeSet, set); add(hashSet, set); add(linkedHashSet, set); @@ -67,7 +68,7 @@ public class FiniteClosureBuilder { Type treeMap = tf.getSimpleType("TreeMap", "K", "V"); Type hashMap = tf.getSimpleType("HashMap", "K", "V"); Type hashtable = tf.getSimpleType("Hashtable", "K", "V"); - Type linkedHashMap = tf.getSimpleType("LinkedHashSet", "K", "V"); + Type linkedHashMap = tf.getSimpleType("LinkedHashMap", "K", "V"); add(sortedMap, map); add(hashMap, map); diff --git a/test/unify/FiniteClosureTest.java b/test/unify/FiniteClosureTest.java index d3766e74..a8a72273 100644 --- a/test/unify/FiniteClosureTest.java +++ b/test/unify/FiniteClosureTest.java @@ -251,37 +251,91 @@ public class FiniteClosureTest { /* * Test Case 10: * - * smaller(HashMap) = - * { HashMap, HashMap, HashMap, HashMap - * HashMap, HashMap, HashMap, HashMap, - * HashMap, HashMap, HashMap - * HashMap, HashMap, HashMap, HashMap } + * smaller(TreeMap) = + * { TreeMap, TreeMap, TreeMap, TreeMap + * TreeMap, TreeMap, TreeMap, TreeMap, + * TreeMap, TreeMap, TreeMap + * TreeMap, TreeMap, TreeMap, TreeMap } */ + Type treeMapExtNumSupInt = tf.getSimpleType("TreeMap", extNum, superInt); + + expectedResult = new HashSet<>(Arrays.stream(new Type[] { + treeMapExtNumSupInt, tf.getSimpleType("TreeMap", extNum, superNum), tf.getSimpleType("TreeMap", extNum, integer), tf.getSimpleType("TreeMap", extNum, number), + tf.getSimpleType("TreeMap", number, superInt), tf.getSimpleType("TreeMap", number, superNum), tf.getSimpleType("TreeMap", number, integer), tf.getSimpleType("TreeMap", number, number), + tf.getSimpleType("TreeMap", integer, superInt), tf.getSimpleType("TreeMap", integer, superNum), tf.getSimpleType("TreeMap", integer, integer), tf.getSimpleType("TreeMap", integer, number), + tf.getSimpleType("TreeMap", extInt, superInt), tf.getSimpleType("TreeMap", extInt, superNum), tf.getSimpleType("TreeMap", extInt, integer), tf.getSimpleType("TreeMap", extInt, number) + }).collect(Collectors.toSet())); + + actual = fc.smaller(treeMapExtNumSupInt); + Assert.assertEquals(expectedResult, actual); + /* * Test Case 11: * * smaller(SortedMap) = { SortedMap, NavigableMap, TreeMap } */ + Type sortedMapNumberT = tf.getSimpleType("SortedMap", number, t); + Type navigableMapNumberT = tf.getSimpleType("NavigableMap", number, t); + Type treeMapNumberT = tf.getSimpleType("TreeMap", number, t); + + expectedResult = new HashSet<>(Arrays.stream(new Type[] { + sortedMapNumberT, navigableMapNumberT, treeMapNumberT + }).collect(Collectors.toSet())); + + actual = fc.smaller(sortedMapNumberT); + Assert.assertEquals(expectedResult, actual); + /* * Test Case 12: * - * MyMap> <* HashMap + * MyMap <* TreeMap> * - * smaller(HashMap) = { HashMap>, MyMap> } + * smaller(TreeMap) = { TreeMap>, MyMap } */ + fcb = new FiniteClosureBuilder(); + Type k = tf.getPlaceholderType("K"); + Type myMap = tf.getSimpleType("MyMap", k); + fcb.add(myMap, tf.getSimpleType("TreeMap", k, tf.getSimpleType("List", k))); + fcb.add(integer, number); + fc = fcb.getCollectionExample(); + + Type treeMapNumberListNumber = tf.getSimpleType("TreeMap", number, tf.getSimpleType("List", number)); + expectedResult = new HashSet<>(Arrays.stream(new Type[] { + treeMapNumberListNumber, + tf.getSimpleType("MyMap", number) + }).collect(Collectors.toSet())); + + actual = fc.smaller(treeMapNumberListNumber); + Assert.assertEquals(expectedResult, actual); + /* * Test Case 13: * - * MyMap> <* HashMap + * MyMap <* TreeMap> * - * smaller(HashMap) = - * { HashMap, List>, - * HashMap>, - * MyMap> } + * smaller(TreeMap) = + * { TreeMap, List>, + * TreeMap>, + * TreeMap>, + * TreeMap>, + * MyMap } */ + + Type listInteger = tf.getSimpleType("List", integer); + Type treeMapExtNumberListInteger = tf.getSimpleType("TreeMap", extNum, listInteger); + expectedResult = new HashSet<>(Arrays.stream(new Type[] { + treeMapExtNumberListInteger, + tf.getSimpleType("TreeMap", extInt, listInteger), + tf.getSimpleType("TreeMap", number, listInteger), + tf.getSimpleType("TreeMap", integer, listInteger), + tf.getSimpleType("MyMap", integer) + }).collect(Collectors.toSet())); + + actual = fc.smaller(treeMapExtNumberListInteger); + Assert.assertEquals(expectedResult, actual); /* * Test Case 14 @@ -292,7 +346,7 @@ public class FiniteClosureTest { */ /* - * Test Case 13: + * Test Case 15: * * MyMap> <* HashMap // * TODO sinnvoll ausformulieren @@ -350,4 +404,12 @@ public class FiniteClosureTest { // TODO } + + private void printDiff(Set expected, Set actual) { + System.out.println("Diff:"); + System.out.println("In expected but not in actual:"); + Set expected1 = new HashSet<>(expected); + expected1.removeAll(actual); + System.out.println(expected1); + } }