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> smArg(FunNType type);
public Optional<Type> getGenericType(String typeName);
public Optional<Type> findGenericParent(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<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) {
this.pairs = new HashSet<>(pairs);
inheritanceGraph = new HashMap<Type, Node<Type>>();
// 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<a1, a2, ... , an> <= C<...>");
if(pair.getPairOp() != PairOperator.SMALLER)
continue;
@ -64,51 +66,68 @@ public class FiniteClosure implements IFiniteClosure {
*/
@Override
public Set<Type> smaller(Type type) {
Set<Type> 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<Type> result = new HashSet<>();
result.add(type);
result.addAll(inheritanceGraph.get(type).getContentOfDescendants());
return result;
}
IUnify unify = new MartelliMontanariUnify();
HashSet<Type> candidates = new HashSet<>();
if (strInheritanceGraph.containsKey(type.getName()))
strInheritanceGraph.get(type.getName()).forEach(x -> candidates.add(x.getContent()));
else
candidates.add(type);
Set<Type> result1 = new HashSet<>();
for (Type theta2 : candidates) {
Optional<Unifier> sigma2 = unify.unify(theta2, 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<>();
for (Type param : sigma1Theta1.getTypeParams())
paramCandidates.add(smArg(param));
Set<TypeParams> 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<Set<Type>> paramCandidates = new ArrayList<>();
for (Type param : type.getTypeParams())
paramCandidates.add(smArg(param));
Set<TypeParams> permResult = new HashSet<>();
permuteParams(paramCandidates, 0, permResult, new Type[paramCandidates.size()]);
for (TypeParams newParams : permResult)
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);
}
}
}
}
return result;
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 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<Type> getGenericType(String typeName) {
if(!strInheritanceGraph.containsKey(typeName))
return Optional.empty();
HashSet<Node<Type>> candidates = strInheritanceGraph.get(typeName);
for(Node<Type> node : candidates) {
Type candidate = node.getContent();
if(candidate.getTypeParams().arePlaceholders())
return Optional.of(candidate);
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();
}

View File

@ -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();

View File

@ -328,7 +328,7 @@ public class RuleSet implements IRuleSet{
if(typeD.getName().equals(typeDs.getName()))
return Optional.empty();
Optional<Type> opt = finiteClosure.getGenericType(typeD.getName());
Optional<Type> 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<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;
}
@ -418,7 +418,7 @@ public class RuleSet implements IRuleSet{
return Optional.empty();
Optional<Type> opt = finiteClosure.getGenericType(((SuperType) typeSupD).getSuperedType().getName());
Optional<Type> 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<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());
}
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());
}

View File

@ -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);

View File

@ -251,37 +251,91 @@ public class FiniteClosureTest {
/*
* Test Case 10:
*
* smaller(HashMap<? extends Number, ? super Integer>) =
* { HashMap<? extends Number, ? super Integer>, HashMap<? extends Number, ? super Number>, HashMap<? extends Number, Integer>, HashMap<? extends Number, Number>
* HashMap<Number, ? super Integer>, HashMap<Number, ? super Number>, HashMap<Number, Integer>, HashMap<Number, Number>,
* HashMap<Integer, ? super Integer, HashMap<Integer, ? super Number>, HashMap<Integer, Integer>, HashMap<Integer, Number>
* HashMap<? extends Integer, ? super Integer>, HashMap<? extends Integer, ? super Number>, HashMap<? extends Integer, Integer>, HashMap<? extends Integer, Number> }
* smaller(TreeMap<? extends Number, ? super Integer>) =
* { TreeMap<? extends Number, ? super Integer>, TreeMap<? extends Number, ? super Number>, TreeMap<? extends Number, Integer>, TreeMap<? extends Number, Number>
* TreeMap<Number, ? super Integer>, TreeMap<Number, ? super Number>, TreeMap<Number, Integer>, TreeMap<Number, Number>,
* TreeMap<Integer, ? super Integer, TreeMap<Integer, ? super Number>, TreeMap<Integer, Integer>, TreeMap<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:
*
* 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:
*
* 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:
*
* MyMap<K, List<K>> <* HashMap<K, V>
* MyMap<K> <* TreeMap<K, List<K>>
*
* smaller(HashMap<? extends Number, List<Integer>) =
* { HashMap<? extends Integer>, List<Integer>>,
* HashMap<? extends Number, List<Integer>>,
* MyMap<Integer, List<Integer>> }
* smaller(TreeMap<? extends Number, List<Integer>) =
* { TreeMap<? extends Integer>, List<Integer>>,
* TreeMap<? extends Number, 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
@ -292,7 +346,7 @@ public class FiniteClosureTest {
*/
/*
* Test Case 13:
* Test Case 15:
*
* MyMap<K, List<K>> <* HashMap<K, V>
// * TODO sinnvoll ausformulieren
@ -350,4 +404,12 @@ public class FiniteClosureTest {
// 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);
}
}