diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java b/src/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java index 6fff42cc..2ac30e19 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java +++ b/src/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java @@ -65,6 +65,13 @@ public class FiniteClosure implements IFiniteClosure { */ @Override public Set smaller(UnifyType type) { + if(type instanceof FunNType) + return computeSmallerFunN((FunNType) type); + + return computeSmaller(type); + } + + private Set computeSmaller(UnifyType type) { if(inheritanceGraph.containsKey(type)) { Set result = new HashSet<>(); result.add(type); @@ -82,8 +89,7 @@ public class FiniteClosure implements IFiniteClosure { for (UnifyType param : type.getTypeParams()) paramCandidates.add(smArg(param)); - Set permResult = new HashSet<>(); - permuteParams(paramCandidates, 0, permResult, new UnifyType[paramCandidates.size()]); + Set permResult = permuteParams(paramCandidates); for (TypeParams newParams : permResult) result1.add(type.setTypeParams(newParams));} @@ -94,16 +100,18 @@ public class FiniteClosure implements IFiniteClosure { strInheritanceGraph.get(type.getName()).forEach(x -> candidates.add(x.getContent())); for(UnifyType typePrime : result1) { - for (UnifyType theta2 : candidates) { - Optional sigma2 = unify.unify(typePrime, theta2); - if (!sigma2.isPresent()) + for (UnifyType theta2 : candidates) { + Optional sigma2Opt = unify.unify(typePrime, theta2); + if (!sigma2Opt.isPresent()) continue; + Unifier sigma2 = sigma2Opt.get(); + sigma2.swapPlaceholderSubstitutions(typePrime.getTypeParams().toArray()); if(type.equals(theta2)) continue; Set theta1s = smaller(theta2); for (UnifyType theta1 : theta1s) { // Because only the most general type is calculated, sigma1 = sigma2 - UnifyType sigma1Theta1 = sigma2.get().apply(theta1); + UnifyType sigma1Theta1 = sigma2.apply(theta1); result2.add(sigma1Theta1); } } @@ -118,8 +126,7 @@ public class FiniteClosure implements IFiniteClosure { for (UnifyType param : t.getTypeParams()) paramCandidates.add(smArg(param)); - Set permResult = new HashSet<>(); - permuteParams(paramCandidates, 0, permResult, new UnifyType[paramCandidates.size()]); + Set permResult = permuteParams(paramCandidates); for (TypeParams newParams : permResult) { UnifyType tPrime = t.setTypeParams(newParams); @@ -127,19 +134,44 @@ public class FiniteClosure implements IFiniteClosure { result3.add(t); else result3.addAll(smaller(tPrime)); - } + } } return result3; } + + private Set computeSmallerFunN(FunNType type) { + Set result = new HashSet<>(); + + // if T = T' then T <=* T' + result.add(type); + + ArrayList> paramCandidates = new ArrayList<>(); + paramCandidates.add(smaller(type.getTypeParams().get(0))); + for (int i = 1; i < type.getTypeParams().size(); i++) + paramCandidates.add(greater(type.getTypeParams().get(i))); + + Set permResult = permuteParams(paramCandidates); + + for (TypeParams newParams : permResult) + result.add(type.setTypeParams(newParams)); + + return result; + } /** * Returns all types of the finite closure that are supertypes of the argument. * @return The set of supertypes of the argument. */ @Override - public Set greater(UnifyType type) { + public Set greater(UnifyType type) { + if(type instanceof FunNType) + return computeGreaterFunN((FunNType) type); + return computeGreater(type); + } + + protected Set computeGreater(UnifyType type) { IUnify unify = new MartelliMontanariUnify(); Set result1 = new HashSet<>(); @@ -166,22 +198,25 @@ public class FiniteClosure implements IFiniteClosure { for(UnifyType typePrime : result1) { for (UnifyType theta2 : candidates) { - Optional sigma2 = unify.unify(typePrime, theta2); - if (!sigma2.isPresent()) + Optional sigma2Opt = unify.unify(typePrime, theta2); + if (!sigma2Opt.isPresent()) continue; if(type.equals(theta2)) continue; + + Unifier sigma2 = sigma2Opt.get(); + sigma2.swapPlaceholderSubstitutions(typePrime.getTypeParams().toArray()); Set theta1s = greater(theta2); for (UnifyType theta1 : theta1s) { // Because only the most general type is calculated, sigma1 = sigma2 - UnifyType sigma1Theta1 = sigma2.get().apply(theta1); + UnifyType sigma1Theta1 = sigma2.apply(theta1); result2.add(sigma1Theta1); } } } } - result2.addAll(result1); + result2.addAll(result1); Set result3 = new HashSet<>(); for(UnifyType t : result2) { @@ -203,8 +238,13 @@ public class FiniteClosure implements IFiniteClosure { } return result3; - } + + protected Set computeGreaterFunN(FunNType type) { + // TODO Auto-generated method stub + return null; + } + @Override public Set grArg(UnifyType type) { @@ -370,6 +410,12 @@ public class FiniteClosure implements IFiniteClosure { return result; } + protected Set permuteParams(ArrayList> candidates) { + Set result = new HashSet<>(); + permuteParams(candidates, 0, result, new UnifyType[candidates.size()]); + return result; + } + protected void permuteParams(ArrayList> candidates, int idx, Set result, UnifyType[] current) { if(candidates.size() == idx) { result.add(new TypeParams(Arrays.copyOf(current, current.length))); diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/FunNType.java b/src/de/dhbwstuttgart/typeinference/unify/model/FunNType.java index cb431cf9..3363be75 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/model/FunNType.java +++ b/src/de/dhbwstuttgart/typeinference/unify/model/FunNType.java @@ -43,13 +43,26 @@ public class FunNType extends UnifyType { Set grArg(IFiniteClosure fc) { return fc.grArg(this); } - + @Override UnifyType apply(Unifier unif) { // TODO Auto-generated method stub return null; } - // TODO equals und hashcode + @Override + public int hashCode() { + return 31 + typeParams.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof FunNType)) + return false; + + FunNType other = (FunNType) obj; + + return other.getTypeParams().equals(typeParams); + } } diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/ReferenceType.java b/src/de/dhbwstuttgart/typeinference/unify/model/ReferenceType.java index fd5a0ec1..4f557b53 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/model/ReferenceType.java +++ b/src/de/dhbwstuttgart/typeinference/unify/model/ReferenceType.java @@ -22,7 +22,7 @@ public final class ReferenceType extends UnifyType { Set grArg(IFiniteClosure fc) { return fc.grArg(this); } - + @Override UnifyType apply(Unifier unif) { return new ReferenceType(typeName, typeParams.apply(unif)); @@ -35,7 +35,7 @@ public final class ReferenceType extends UnifyType { @Override public int hashCode() { - return typeName.hashCode(); + return 31 + 17 * typeName.hashCode() + 17 * typeParams.hashCode(); } @Override diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/SuperType.java b/src/de/dhbwstuttgart/typeinference/unify/model/SuperType.java index 51f640c9..363dbbf6 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/model/SuperType.java +++ b/src/de/dhbwstuttgart/typeinference/unify/model/SuperType.java @@ -5,8 +5,6 @@ import java.util.Set; import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; public final class SuperType extends WildcardType { - - public SuperType(UnifyType superedType) { super("? super " + superedType.getName(), superedType, superedType.getTypeParams()); } diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/TypeParams.java b/src/de/dhbwstuttgart/typeinference/unify/model/TypeParams.java index 0f39a621..f5b7686b 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/model/TypeParams.java +++ b/src/de/dhbwstuttgart/typeinference/unify/model/TypeParams.java @@ -77,6 +77,9 @@ public final class TypeParams implements Iterable{ return new TypeParams(newparams); } + public UnifyType[] toArray() { + return Arrays.copyOf(typeParams, typeParams.length); + } @Override public Iterator iterator() { diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/Unifier.java b/src/de/dhbwstuttgart/typeinference/unify/model/Unifier.java index 33f9daec..cccaf591 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/model/Unifier.java +++ b/src/de/dhbwstuttgart/typeinference/unify/model/Unifier.java @@ -52,6 +52,18 @@ public class Unifier implements Function /*, Set*/ public Set> getSubstitutions() { return substitutions.entrySet(); } + + public void swapPlaceholderSubstitutions(UnifyType... targetParams) { + for(UnifyType tph : targetParams) { + if(!(tph instanceof PlaceholderType)) + continue; + if(substitutions.containsKey(tph) && substitutions.get(tph) instanceof PlaceholderType) { + PlaceholderType newLhs = (PlaceholderType) substitutions.get(tph); + substitutions.remove(tph); + substitutions.put(newLhs, tph); + } + } + } @Override public String toString() { diff --git a/test/unify/FiniteClosureTest.java b/test/unify/FiniteClosureTest.java index 519cf509..25cd417e 100644 --- a/test/unify/FiniteClosureTest.java +++ b/test/unify/FiniteClosureTest.java @@ -169,6 +169,7 @@ public class FiniteClosureTest { setExtT1, hashSetExtT1, treeSetExtT1, linkedHashSetExtT1 }).collect(Collectors.toSet())); + System.out.println(fc.smaller(setExtT1)); Assert.assertEquals(expectedResult, fc.smaller(setExtT1)); /* @@ -395,7 +396,37 @@ public class FiniteClosureTest { Assert.assertEquals(82, actual.size()); Assert.assertTrue(actual.contains(myMapExtInt)); - Assert.assertTrue(actual.contains(myMapInt)); + Assert.assertTrue(actual.contains(myMapInt)); + + /* + * Test Case 16: + * + * smaller(FunN) = + * { FunN, FunN, + * FunN, FunN, + * FunN, FunN, + * FunN, FunN } + */ + + UnifyType object = tf.getSimpleType("Object"); + + fcb = new FiniteClosureBuilder(); + fcb.add(integer, number); + fcb.add(number, object); + fc = fcb.getCollectionExample(); + + UnifyType funNNumber = tf.getFunNType(number, number, number); + expectedResult = new HashSet<>(Arrays.stream(new UnifyType[] { + tf.getFunNType(number, number, number), tf.getFunNType(number, object, number), + tf.getFunNType(number, number, object), tf.getFunNType(number, object, object), + tf.getFunNType(integer, number, number), tf.getFunNType(integer, object, number), + tf.getFunNType(integer, number, object), tf.getFunNType(integer, object, object), + }).collect(Collectors.toSet())); + + actual = fc.smaller(funNNumber); + System.out.println(actual); + Assert.assertEquals(expectedResult, actual); + } @Test diff --git a/test/unify/TypeFactory.java b/test/unify/TypeFactory.java index 099638e7..881222c8 100644 --- a/test/unify/TypeFactory.java +++ b/test/unify/TypeFactory.java @@ -4,9 +4,11 @@ import java.util.Arrays; import java.util.stream.Collectors; import de.dhbwstuttgart.typeinference.unify.model.ExtendsType; +import de.dhbwstuttgart.typeinference.unify.model.FunNType; import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType; import de.dhbwstuttgart.typeinference.unify.model.ReferenceType; import de.dhbwstuttgart.typeinference.unify.model.SuperType; +import de.dhbwstuttgart.typeinference.unify.model.TypeParams; import de.dhbwstuttgart.typeinference.unify.model.UnifyType; public class TypeFactory { @@ -34,4 +36,9 @@ public class TypeFactory { public PlaceholderType getPlaceholderType(String name) { return new PlaceholderType(name); } + + public FunNType getFunNType(UnifyType... typeParams) { + return FunNType.getFunNType(new TypeParams(typeParams)); + } + }