forked from JavaTX/JavaCompilerCore
smalller und neue testcases
This commit is contained in:
parent
257edfc0b3
commit
26cc9b85ef
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user