smalller und neue testcases

This commit is contained in:
Florian Steurer 2016-03-28 01:01:46 +02:00
parent 257edfc0b3
commit 26cc9b85ef
6 changed files with 185 additions and 81 deletions

View File

@ -53,6 +53,6 @@ public interface IFiniteClosure {
public Set<Type> grArg(FunNType type); public Set<Type> grArg(FunNType type);
public Set<Type> smArg(FunNType type); public Set<Type> smArg(FunNType type);
public Optional<Type> getGenericType(String typeName); public Optional<Type> findGenericParent(String typeName);
public Set<Type> getAllTypesByName(String typeName); public Set<Type> getAllTypesByName(String typeName);
} }

View File

@ -18,15 +18,17 @@ public class FiniteClosure implements IFiniteClosure {
private HashMap<Type, Node<Type>> inheritanceGraph; private HashMap<Type, Node<Type>> inheritanceGraph;
private HashMap<String, HashSet<Node<Type>>> strInheritanceGraph; private HashMap<String, HashSet<Node<Type>>> strInheritanceGraph;
private Set<MPair> pairs;
private Set<Type> 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<MPair> pairs) { public FiniteClosure(Set<MPair> pairs) {
this.pairs = new HashSet<>(pairs);
inheritanceGraph = new HashMap<Type, Node<Type>>(); inheritanceGraph = new HashMap<Type, Node<Type>>();
// Build the transitive closure of the inheritance tree // Build the transitive closure of the inheritance tree
for(MPair pair : pairs) { for(MPair pair : pairs) {
if(!pair.getLhsType().getTypeParams().arePlaceholders())
throw new IllegalArgumentException("The finite closure only has pairs of the form D<a1, a2, ... , an> <= C<...>");
if(pair.getPairOp() != PairOperator.SMALLER) if(pair.getPairOp() != PairOperator.SMALLER)
continue; continue;
@ -64,51 +66,68 @@ public class FiniteClosure implements IFiniteClosure {
*/ */
@Override @Override
public Set<Type> smaller(Type type) { public Set<Type> smaller(Type type) {
if(inheritanceGraph.containsKey(type)) {
Set<Type> result = new HashSet<>(); Set<Type> result = new HashSet<>();
result.add(type); result.add(type);
result.addAll(inheritanceGraph.get(type).getContentOfDescendants());
// - if(T < T') then T <=* T' return result;
// 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)
IUnify unify = new MartelliMontanariUnify(); IUnify unify = new MartelliMontanariUnify();
HashSet<Type> candidates = new HashSet<>(); Set<Type> result1 = new HashSet<>();
if (strInheritanceGraph.containsKey(type.getName()))
strInheritanceGraph.get(type.getName()).forEach(x -> candidates.add(x.getContent()));
else
candidates.add(type);
for (Type theta2 : candidates) { // if T = T' then T <=* T'
Optional<Unifier> sigma2 = unify.unify(theta2, type); result1.add(type);
if (!sigma2.isPresent())
continue;
Set<Type> 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<Set<Type>> paramCandidates = new ArrayList<>(); {ArrayList<Set<Type>> paramCandidates = new ArrayList<>();
for (Type param : sigma1Theta1.getTypeParams()) for (Type param : type.getTypeParams())
paramCandidates.add(smArg(param)); paramCandidates.add(smArg(param));
Set<TypeParams> permResult = new HashSet<>(); Set<TypeParams> permResult = new HashSet<>();
permuteParams(paramCandidates, 0, permResult, new Type[paramCandidates.size()]); permuteParams(paramCandidates, 0, permResult, new Type[paramCandidates.size()]);
for (TypeParams newParams : permResult) for (TypeParams newParams : permResult)
result.add(sigma1Theta1.setTypeParams(newParams)); result1.add(type.setTypeParams(newParams));}
Set<Type> result2 = new HashSet<>();
if (strInheritanceGraph.containsKey(type.getName())) {
HashSet<Type> candidates = new HashSet<>();
strInheritanceGraph.get(type.getName()).forEach(x -> candidates.add(x.getContent()));
for(Type typePrime : result1) {
for (Type theta2 : candidates) {
Optional<Unifier> sigma2 = unify.unify(typePrime, theta2);
if (!sigma2.isPresent())
continue;
if(type.equals(theta2))
continue;
Set<Type> 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);
} }
} }
}
}
else
result2 = result1;
Set<Type> result3 = new HashSet<>();
for(Type t : result2) {
ArrayList<Set<Type>> paramCandidates = new ArrayList<>();
for (Type param : t.getTypeParams())
paramCandidates.add(smArg(param));
Set<TypeParams> permResult = new HashSet<>();
permuteParams(paramCandidates, 0, permResult, new Type[paramCandidates.size()]);
for (TypeParams newParams : permResult)
result3.add(t.setTypeParams(newParams));
}
return result; return result3;
} }
/** /**
@ -260,19 +279,37 @@ public class FiniteClosure implements IFiniteClosure {
return result; return result;
} }
@Override
public Optional<Type> getGenericType(String typeName) {
if(!strInheritanceGraph.containsKey(typeName))
return Optional.empty();
HashSet<Node<Type>> candidates = strInheritanceGraph.get(typeName); public boolean isGenericType(Type t) {
if(t.getTypeParams().size() == 0)
return true;
for(Node<Type> node : candidates) { if(!strInheritanceGraph.containsKey(t.getName()))
Type candidate = node.getContent(); return false;
if(candidate.getTypeParams().arePlaceholders())
return Optional.of(candidate); for(MPair pair : pairs)
if(pair.getLhsType().equals(t))
return true;
return false;
} }
@Override
public Optional<Type> 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(); return Optional.empty();
} }

View File

@ -101,8 +101,12 @@ public class MartelliMontanariUnify implements IUnify {
TypeParams rhsTypeParams = rhs.getTypeParams(); TypeParams rhsTypeParams = rhs.getTypeParams();
TypeParams lhsTypeParams = lhs.getTypeParams(); TypeParams lhsTypeParams = lhs.getTypeParams();
if(rhsTypeParams.size() != lhsTypeParams.size() || (!rhs.getName().equals(lhs.getName()) && rhsTypeParams.size() != 0)) if(!(rhs instanceof PlaceholderType) && !(lhs instanceof PlaceholderType)) {
if(!rhs.getName().equals(lhs.getName()))
return null; // conflict return null; // conflict
if(rhsTypeParams.size() != lhsTypeParams.size())
return null; // conflict;
}
if(rhsTypeParams.size() == 0 || lhsTypeParams.size() == 0) if(rhsTypeParams.size() == 0 || lhsTypeParams.size() == 0)
return Optional.empty(); return Optional.empty();

View File

@ -328,7 +328,7 @@ public class RuleSet implements IRuleSet{
if(typeD.getName().equals(typeDs.getName())) if(typeD.getName().equals(typeDs.getName()))
return Optional.empty(); return Optional.empty();
Optional<Type> opt = finiteClosure.getGenericType(typeD.getName()); Optional<Type> opt = finiteClosure.findGenericParent(typeD.getName());
if(!opt.isPresent()) if(!opt.isPresent())
return Optional.empty(); return Optional.empty();
@ -373,9 +373,9 @@ public class RuleSet implements IRuleSet{
Type typeDgen; Type typeDgen;
if(typeD instanceof SimpleType) if(typeD instanceof SimpleType)
typeDgen = finiteClosure.getGenericType(typeD.getName()).orElse(null); typeDgen = finiteClosure.findGenericParent(typeD.getName()).orElse(null);
else { else {
Optional<Type> opt = finiteClosure.getGenericType(((ExtendsType) typeD).getExtendedType().getName()); Optional<Type> opt = finiteClosure.findGenericParent(((ExtendsType) typeD).getExtendedType().getName());
typeDgen = opt.isPresent() ? new ExtendsType(opt.get()) : null; typeDgen = opt.isPresent() ? new ExtendsType(opt.get()) : null;
} }
@ -418,7 +418,7 @@ public class RuleSet implements IRuleSet{
return Optional.empty(); return Optional.empty();
Optional<Type> opt = finiteClosure.getGenericType(((SuperType) typeSupD).getSuperedType().getName()); Optional<Type> opt = finiteClosure.findGenericParent(((SuperType) typeSupD).getSuperedType().getName());
if(!opt.isPresent()) if(!opt.isPresent())
return Optional.empty(); return Optional.empty();
@ -462,13 +462,13 @@ public class RuleSet implements IRuleSet{
private int[] pi(Type C, Type D) { private int[] pi(Type C, Type D) {
Type cFromFc = null; Type cFromFc = null;
if(C instanceof SimpleType) if(C instanceof SimpleType)
cFromFc = finiteClosure.getGenericType(C.getName()).orElse(null); cFromFc = finiteClosure.findGenericParent(C.getName()).orElse(null);
else if(C instanceof ExtendsType) { else if(C instanceof ExtendsType) {
Optional<Type> opt = finiteClosure.getGenericType(((ExtendsType) C).getExtendedType().getName()); Optional<Type> opt = finiteClosure.findGenericParent(((ExtendsType) C).getExtendedType().getName());
if(opt.isPresent()) cFromFc = new ExtendsType(opt.get()); if(opt.isPresent()) cFromFc = new ExtendsType(opt.get());
} }
else if(C instanceof SuperType) { else if(C instanceof SuperType) {
Optional<Type> opt = finiteClosure.getGenericType(((SuperType) C).getSuperedType().getName()); Optional<Type> opt = finiteClosure.findGenericParent(((SuperType) C).getSuperedType().getName());
if(opt.isPresent()) cFromFc = new SuperType(opt.get()); if(opt.isPresent()) cFromFc = new SuperType(opt.get());
} }

View File

@ -33,7 +33,8 @@ public class FiniteClosureBuilder {
Type collection = tf.getSimpleType("Collection"); Type collection = tf.getSimpleType("Collection");
Type set = tf.getSimpleType("Set", "T"); 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 TreeSet = tf.getSimpleType("TreeSet", "T");
Type hashSet = tf.getSimpleType("HashSet", "T"); Type hashSet = tf.getSimpleType("HashSet", "T");
Type linkedHashSet = tf.getSimpleType("LinkedHashSet", "T"); Type linkedHashSet = tf.getSimpleType("LinkedHashSet", "T");
@ -46,8 +47,8 @@ public class FiniteClosureBuilder {
Type arrayList = tf.getSimpleType("ArrayList", "T"); Type arrayList = tf.getSimpleType("ArrayList", "T");
add(set, collection); add(set, collection);
add(sortedSet, set); //add(sortedSet, set);
add(TreeSet, sortedSet); add(TreeSet, set);
add(hashSet, set); add(hashSet, set);
add(linkedHashSet, set); add(linkedHashSet, set);
@ -67,7 +68,7 @@ public class FiniteClosureBuilder {
Type treeMap = tf.getSimpleType("TreeMap", "K", "V"); Type treeMap = tf.getSimpleType("TreeMap", "K", "V");
Type hashMap = tf.getSimpleType("HashMap", "K", "V"); Type hashMap = tf.getSimpleType("HashMap", "K", "V");
Type hashtable = tf.getSimpleType("Hashtable", "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(sortedMap, map);
add(hashMap, map); add(hashMap, map);

View File

@ -251,38 +251,92 @@ public class FiniteClosureTest {
/* /*
* Test Case 10: * Test Case 10:
* *
* smaller(HashMap<? extends Number, ? super Integer>) = * smaller(TreeMap<? extends Number, ? super Integer>) =
* { HashMap<? extends Number, ? super Integer>, HashMap<? extends Number, ? super Number>, HashMap<? extends Number, Integer>, HashMap<? extends Number, Number> * { TreeMap<? extends Number, ? super Integer>, TreeMap<? extends Number, ? super Number>, TreeMap<? extends Number, Integer>, TreeMap<? extends Number, Number>
* HashMap<Number, ? super Integer>, HashMap<Number, ? super Number>, HashMap<Number, Integer>, HashMap<Number, Number>, * TreeMap<Number, ? super Integer>, TreeMap<Number, ? super Number>, TreeMap<Number, Integer>, TreeMap<Number, Number>,
* HashMap<Integer, ? super Integer, HashMap<Integer, ? super Number>, HashMap<Integer, Integer>, HashMap<Integer, Number> * TreeMap<Integer, ? super Integer, TreeMap<Integer, ? super Number>, TreeMap<Integer, Integer>, TreeMap<Integer, Number>
* HashMap<? extends Integer, ? super Integer>, HashMap<? extends Integer, ? super Number>, HashMap<? extends Integer, Integer>, HashMap<? extends Integer, Number> } * TreeMap<? extends Integer, ? super Integer>, TreeMap<? extends Integer, ? super Number>, TreeMap<? extends Integer, Integer>, TreeMap<? extends Integer, Number> }
*/ */
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: * Test Case 11:
* *
* smaller(SortedMap<Number, T>) = { SortedMap<Number, T>, NavigableMap<Number, T>, TreeMap<Number, T> } * smaller(SortedMap<Number, T>) = { SortedMap<Number, T>, NavigableMap<Number, T>, TreeMap<Number, T> }
*/ */
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: * Test Case 12:
* *
* MyMap<K, List<K>> <* HashMap<K, V> * MyMap<K> <* TreeMap<K, List<K>>
* *
* smaller(HashMap<Number, List<Number>) = { HashMap<Number, List<Number>>, MyMap<Number, List<Number>> } * smaller(TreeMap<Number, List<Number>) = { TreeMap<Number, List<Number>>, MyMap<Number> }
*/ */
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: * Test Case 13:
* *
* MyMap<K, List<K>> <* HashMap<K, V> * MyMap<K> <* TreeMap<K, List<K>>
* *
* smaller(HashMap<? extends Number, List<Integer>) = * smaller(TreeMap<? extends Number, List<Integer>) =
* { HashMap<? extends Integer>, List<Integer>>, * { TreeMap<? extends Integer>, List<Integer>>,
* HashMap<? extends Number, List<Integer>>, * TreeMap<? extends Number, List<Integer>>,
* MyMap<Integer, List<Integer>> } * TreeMap<Number, List<Integer>>,
* TreeMap<Integer, List<Integer>>,
* MyMap<Integer> }
*/ */
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 * Test Case 14
* *
@ -292,7 +346,7 @@ public class FiniteClosureTest {
*/ */
/* /*
* Test Case 13: * Test Case 15:
* *
* MyMap<K, List<K>> <* HashMap<K, V> * MyMap<K, List<K>> <* HashMap<K, V>
// * TODO sinnvoll ausformulieren // * TODO sinnvoll ausformulieren
@ -350,4 +404,12 @@ public class FiniteClosureTest {
// TODO // TODO
} }
private void printDiff(Set<Type> expected, Set<Type> actual) {
System.out.println("Diff:");
System.out.println("In expected but not in actual:");
Set<Type> expected1 = new HashSet<>(expected);
expected1.removeAll(actual);
System.out.println(expected1);
}
} }