Merge mit Unify und Bytecode

This commit is contained in:
JanUlrich 2015-12-11 15:44:44 +01:00
commit ac42bdf0a2
27 changed files with 2981 additions and 299 deletions

View File

@ -13,4 +13,38 @@
- Wie kommen die Mengen des Unify-Algorithmus zustande? Siehe test:
/*
* Test b <. a, a <. b
*/
*/
-
- Transitiven Abschluss von FC bilden um schneller Subtypen bestimmen zu können
- Problem: 2 FCs für Pairs und MPairs durch das Mapping
- Equals der Typen schreiben um instanceof Prüfungen zu vermeiden
- Refactoring der Klassen Menge und Pair erlaubt?
++++++++++++++++++++++++++++++++++++++++++++++
Instanceof wird verwendet da:
-> Entscheidung für diese Lösung, da 2-Fach-Visitor oder DoubleDispatch Pattern
enorm viele überladene Methoden zur folge hätten, nicht intuitiv wären und die rules in die Typen verschoben hätten.
Gilt reduce für alle Typen oder nur für simple und tphs? (Vermutlich nur s und tph sonst bräuchte man keine upLow regel)
+++++++++++++++++++++++++++++++++++++++++++++++
HashCode implementierungen testen (type paramerte mit einbeziehen, hashcodes cachen -> da immutable)
+++++++++++++++++++++++++++++++++++++++++++++++
- Typen sind anhand ihres identifiers durchgängig identifizierbar
- ReduceEq nur auf SimpleTypes oder auf alles anwenden? (Momentan alles)
- ReduceEq Permutation?
EED UP
- Anwendungsreihenfolge der Regeln (wahrscheinlichste zuerst, evtl ist nach regel 1 regel 2 nie möglich etc...)
- Erase vor Reduce
- Rechenarm vor rechenintensiv

View File

@ -1,15 +1,13 @@
package de.dhbwstuttgart.syntaxtree.factory;
import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.syntaxtree.type.WildcardType;
import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType;
import de.dhbwstuttgart.syntaxtree.type.ObjectType;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType;
import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.syntaxtree.type.WildcardType;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.typeinference.Pair;
import de.dhbwstuttgart.typeinference.Pair.PairOperator;
public class UnifyTypeFactory {

View File

@ -2582,6 +2582,8 @@ tempKlasse.get_Superclass_Name() ); System.out.println( "P. S.:
*/
// ino.end
/* Alte pi-Methode:
<<<<<<< HEAD
// ino.method.pi.28118.definition
public static int pi( int n, String C, String D, Menge tto )
throws SCException
@ -2681,6 +2683,59 @@ tempKlasse.get_Superclass_Name() ); System.out.println( "P. S.:
return nPos;
}
}
=======
*/
// ino.method.pi.28118.definition
public static int pi(int n, String C, String D, Menge tto)
throws SCException {
if (C.equals(D))
return n; // Reduktion mit gleichen Typkonstruktoren
RefType KlasseC = null;
RefType KlasseD = null;
for (int i = 0; i < tto.size(); i++) {
KlasseC = (RefType) ((Pair) tto.elementAt(i)).TA1;
KlasseD = (RefType) ((Pair) tto.elementAt(i)).TA2;
if (KlasseC.getTypeName().equals(C)
&& KlasseD.getTypeName().equals(D))
break;
else {
KlasseC = null;
KlasseD = null;
}
}
SCException F = new SCException();
if (KlasseC == null && KlasseD == null)
throw F; // Fehler
// Vektorlisten extrahieren
Menge vC = KlasseC.get_ParaList();
Menge vD = KlasseD.get_ParaList();
if (vC == null || vD == null)
throw F;
if (n >= vD.size())
throw F;
// Permuationswert ¯Â¿Â½r 'n' berechnen
Type TV = (Type) vD.elementAt(n);
int nPos = -1;
for (int i = 0; i < vC.size(); i++)
if (((Type) vC.elementAt(i)).getName().equals(TV.getName())) {
nPos = i;
break;
}
return nPos;
}
// ino.end
// ino.method.printMengeUnifier.28121.definition
public static void printMengeUnifier(String strMenge, Menge<Menge<Pair>> Uni, int nDebug )

View File

@ -0,0 +1,53 @@
package de.dhbwstuttgart.typeinference.unify.interfaces;
import java.util.Optional;
import java.util.Set;
import de.dhbwstuttgart.typinference.unify.model.ExtendsType;
import de.dhbwstuttgart.typinference.unify.model.PlaceholderType;
import de.dhbwstuttgart.typinference.unify.model.SimpleType;
import de.dhbwstuttgart.typinference.unify.model.SuperType;
import de.dhbwstuttgart.typinference.unify.model.Type;
public interface IFiniteClosure {
/**
* Returns all types of the finite closure that are subtypes of the argument.
* @return The set of subtypes of the argument.
*/
public Set<Type> smaller(Type type);
/**
* Returns all types of the finite closure that are supertypes of the argument.
* @return The set of supertypes of the argument.
*/
public Set<Type> greater(Type type);
/**
* Wo passt Type rein?
* @param type
* @return
*/
public Set<Type> grArg(Type type);
/**
* Was passt in Type rein?
* @param type
* @return
*/
public Set<Type> smArg(Type type);
public Set<Type> grArg(SimpleType type);
public Set<Type> smArg(SimpleType type);
public Set<Type> grArg(ExtendsType type);
public Set<Type> smArg(ExtendsType type);
public Set<Type> grArg(SuperType type);
public Set<Type> smArg(SuperType type);
public Set<Type> grArg(PlaceholderType type);
public Set<Type> smArg(PlaceholderType type);
public Optional<Type> getGenericType(String typeName);
}

View File

@ -0,0 +1,31 @@
package de.dhbwstuttgart.typeinference.unify.interfaces;
import java.util.Optional;
import java.util.Set;
import de.dhbwstuttgart.typeinference.unifynew.Unifier;
import de.dhbwstuttgart.typinference.unify.model.MPair;
public interface IRuleSet {
public Optional<MPair> reduceUp(MPair pair);
public Optional<MPair> reduceLow(MPair pair);
public Optional<MPair> reduceUpLow(MPair pair);
public Optional<Set<MPair>> reduceExt(MPair pair);
public Optional<Set<MPair>> reduceSup(MPair pair);
public Optional<Set<MPair>> reduceEq(MPair pair);
public Optional<Set<MPair>> reduce1(MPair pair);
public Optional<Set<MPair>> reduce2(MPair pair);
public boolean erase1(MPair pair);
public boolean erase2(MPair pair);
public boolean erase3(MPair pair);
public Optional<MPair> swap(MPair pair);
public Optional<MPair> adapt(MPair pair);
public Optional<MPair> adaptExt(MPair pair);
public Optional<MPair> adaptSup(MPair pair);
public Set<MPair> subst(Set<MPair> pair);
}

View File

@ -0,0 +1,8 @@
package de.dhbwstuttgart.typeinference.unify.interfaces;
import java.util.List;
import java.util.Set;
public interface ISetOperations {
<B> Set<List<B>> cartesianProduct(List<? extends Set<? extends B>> sets);
}

View File

@ -0,0 +1,7 @@
package de.dhbwstuttgart.typeinference.unify.interfaces;
import de.dhbwstuttgart.typeinference.Menge;
public interface ITypeMapper<T> {
}

View File

@ -0,0 +1,17 @@
package de.dhbwstuttgart.typeinference.unifynew;
import java.util.List;
import java.util.Set;
import com.google.common.collect.Sets;
import de.dhbwstuttgart.typeinference.unify.interfaces.ISetOperations;
public class GuavaSetOperations implements ISetOperations {
@Override
public <B> Set<List<B>> cartesianProduct(List<? extends Set<? extends B>> sets) {
return Sets.cartesianProduct(sets);
}
}

View File

@ -0,0 +1,69 @@
package de.dhbwstuttgart.typeinference.unifynew;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType;
import de.dhbwstuttgart.syntaxtree.type.FunN;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType;
import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.exceptions.NotImplementedException;
/**
* First three bits indicate the meta type:
* 000b = 0 = Simpletype
* 001b = 1 = Extends
* 010b = 2 = Super
* 011b = 3 = Type Placeholder
* 100b = 4 = Function
*
* @author DH10STF
*
*/
public class Mapping {
private static final int ST_MASK = 0;
private static final int EXTENDS_MASK = 536870912;
private static final int SUPER_MASK = 1073741824;
private static final int TPH_MASK = 1610612736;
private static final int FUN_MASK = -2147483648;
private static HashMap<Type, Type> mapping;
public Set<Type> createMapping(Iterable<Type> types) {
mapping = new HashMap<>();
Iterator<Type> iterator = types.iterator();
while(iterator.hasNext() && mapping.size() <= 536870911)
createMapping(iterator.next());
return mapping.keySet();
}
private void createMapping(Type type) {
/*if(type instanceof RefType) {
Set<Type> params = ((RefType) type).get_ParaList();
params.stream().forEach(x -> createMapping(x));
}
*/
int typeId = mapping.size();
if(type instanceof RefType)
typeId |= ST_MASK;
else if(type instanceof SuperWildcardType)
typeId |= SUPER_MASK;
else if(type instanceof ExtendsWildcardType)
typeId |= EXTENDS_MASK;
else if(type instanceof TypePlaceholder)
typeId |= TPH_MASK;
else if(type instanceof FunN)
typeId |= FUN_MASK;
//mapping.put(new MType())
}
}

View File

@ -0,0 +1,524 @@
package de.dhbwstuttgart.typeinference.unifynew;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import junit.framework.Assert;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unify.interfaces.IRuleSet;
import de.dhbwstuttgart.typinference.unify.model.ExtendsType;
import de.dhbwstuttgart.typinference.unify.model.MPair;
import de.dhbwstuttgart.typinference.unify.model.MPair.PairOperator;
import de.dhbwstuttgart.typinference.unify.model.PlaceholderType;
import de.dhbwstuttgart.typinference.unify.model.SimpleType;
import de.dhbwstuttgart.typinference.unify.model.SuperType;
import de.dhbwstuttgart.typinference.unify.model.Type;
import de.dhbwstuttgart.typinference.unify.model.TypeParams;
public class RuleSet implements IRuleSet{
protected IFiniteClosure finiteClosure;
public RuleSet(IFiniteClosure fc) {
finiteClosure = fc;
}
@Override
public Optional<MPair> reduceUp(MPair pair) {
if(pair.getPairOp() != PairOperator.SMALLERDOT)
return Optional.empty();
Type rhsType = pair.getRhsType();
if(!(rhsType instanceof SuperType))
return Optional.empty();
Type lhsType = pair.getLhsType();
if(!(lhsType instanceof SimpleType) && !(lhsType instanceof PlaceholderType))
return Optional.empty();
return Optional.of(new MPair(lhsType, ((SuperType) rhsType).getSuperedType(), PairOperator.SMALLERDOT));
}
@Override
public Optional<MPair> reduceLow(MPair pair) {
if(pair.getPairOp() != PairOperator.SMALLERDOT)
return Optional.empty();
Type lhsType = pair.getLhsType();
if(!(lhsType instanceof ExtendsType))
return Optional.empty();
Type rhsType = pair.getRhsType();
if(!(rhsType instanceof SimpleType) && !(rhsType instanceof PlaceholderType))
return Optional.empty();
return Optional.of(new MPair(((ExtendsType) lhsType).getExtendedType(), rhsType, PairOperator.SMALLERDOT));
}
@Override
public Optional<MPair> reduceUpLow(MPair pair) {
if(pair.getPairOp() != PairOperator.SMALLERDOT)
return Optional.empty();
Type lhsType = pair.getLhsType();
if(!(lhsType instanceof ExtendsType))
return Optional.empty();
Type rhsType = pair.getRhsType();
if(!(rhsType instanceof SuperType))
return Optional.empty();
return Optional.of(new MPair(((ExtendsType) lhsType).getExtendedType(),((SuperType) rhsType).getSuperedType(), PairOperator.SMALLERDOT));
}
@Override
public Optional<Set<MPair>> reduceExt(MPair pair) {
if(pair.getPairOp() != PairOperator.SMALLERDOTWC)
return Optional.empty();
Type lhsType = pair.getLhsType();
if(!(lhsType instanceof SimpleType) && !(lhsType instanceof ExtendsType))
return Optional.empty();
Type rhsType = pair.getRhsType();
if(!(rhsType instanceof ExtendsType))
return Optional.empty();
if(lhsType.getTypeParams().empty() || rhsType.getTypeParams().size() != lhsType.getTypeParams().size())
return Optional.empty();
int[] pi = pi(lhsType, rhsType);
if(pi.length == 0)
return Optional.empty();
TypeParams rhsTypeParams = rhsType.getTypeParams();
TypeParams lhsTypeParams = lhsType.getTypeParams();
Set<MPair> result = new HashSet<>();
for(int rhsIdx = 0; rhsIdx < rhsTypeParams.size(); rhsIdx++)
result.add(new MPair(lhsTypeParams.get(pi[rhsIdx]), rhsTypeParams.get(rhsIdx), PairOperator.SMALLERDOTWC));
return Optional.of(result);
}
@Override
public Optional<Set<MPair>> reduceSup(MPair pair) {
if(pair.getPairOp() != PairOperator.SMALLERDOTWC)
return Optional.empty();
Type lhsType = pair.getLhsType();
if(!(lhsType instanceof SimpleType) && !(lhsType instanceof SuperType))
return Optional.empty();
Type rhsType = pair.getRhsType();
if(!(rhsType instanceof SuperType))
return Optional.empty();
if(lhsType.getTypeParams().empty() || rhsType.getTypeParams().size() != lhsType.getTypeParams().size())
return Optional.empty();
int[] pi = pi(lhsType, rhsType);
if(pi.length == 0)
return Optional.empty();
TypeParams rhsTypeParams = rhsType.getTypeParams();
TypeParams lhsTypeParams = lhsType.getTypeParams();
Set<MPair> result = new HashSet<>();
for(int rhsIdx = 0; rhsIdx < rhsTypeParams.size(); rhsIdx++)
result.add(new MPair(lhsTypeParams.get(pi[rhsIdx]), rhsTypeParams.get(rhsIdx), PairOperator.SMALLERDOTWC));
return Optional.of(result);
}
@Override
public Optional<Set<MPair>> reduceEq(MPair pair) {
if(pair.getPairOp() != PairOperator.SMALLERDOTWC)
return Optional.empty();
Type lhsType = pair.getLhsType();
if(lhsType instanceof PlaceholderType || lhsType.getTypeParams().empty())
return Optional.empty();
Type rhsType = pair.getRhsType();
if(!rhsType.getName().equals(lhsType.getName()))
return Optional.empty();
if(rhsType instanceof PlaceholderType || rhsType.getTypeParams().empty())
return Optional.empty();
if(rhsType.getTypeParams().size() != lhsType.getTypeParams().size())
return Optional.empty();
// TODO Permutation?
Set<MPair> result = new HashSet<>();
TypeParams lhsTypeParams = lhsType.getTypeParams();
TypeParams rhsTypeParams = rhsType.getTypeParams();
for(int i = 0; i < lhsTypeParams.size(); i++)
result.add(new MPair(lhsTypeParams.get(i), rhsTypeParams.get(i), PairOperator.EQUALSDOT));
return Optional.of(result);
}
@Override
public Optional<Set<MPair>> reduce1(MPair pair) {
if(pair.getPairOp() != PairOperator.SMALLERDOT)
return Optional.empty();
Type lhsType = pair.getLhsType();
if(!(lhsType instanceof SimpleType))
return Optional.empty();
Type rhsType = pair.getRhsType();
if(!(rhsType instanceof SimpleType))
return Optional.empty();
SimpleType lhsSType = (SimpleType) lhsType;
SimpleType rhsSType = (SimpleType) rhsType;
if(lhsSType.getTypeParams().empty() || lhsSType.getTypeParams().size() != rhsSType.getTypeParams().size())
return Optional.empty();
int[] pi = pi(lhsSType, rhsSType);
if(pi.length == 0)
return Optional.empty();
TypeParams rhsTypeParams = rhsType.getTypeParams();
TypeParams lhsTypeParams = lhsType.getTypeParams();
Set<MPair> result = new HashSet<>();
for(int rhsIdx = 0; rhsIdx < rhsTypeParams.size(); rhsIdx++)
result.add(new MPair(lhsTypeParams.get(pi[rhsIdx]), rhsTypeParams.get(rhsIdx), PairOperator.SMALLERDOTWC));
return Optional.of(result);
}
@Override
public Optional<Set<MPair>> reduce2(MPair pair) {
if(pair.getPairOp() != PairOperator.EQUALSDOT)
return Optional.empty();
Type lhsType = pair.getLhsType();
SimpleType lhsSType;
if(lhsType instanceof SimpleType)
lhsSType = (SimpleType) lhsType;
else if(lhsType instanceof ExtendsType)
lhsSType = (SimpleType) ((ExtendsType) lhsType).getExtendedType();
else if(lhsType instanceof SuperType)
lhsSType = (SimpleType) ((SuperType) lhsType).getSuperedType();
else
return Optional.empty();
if(lhsSType.getTypeParams().empty())
return Optional.empty();
Type rhsType = pair.getLhsType();
SimpleType rhsSType;
if(rhsType instanceof SimpleType)
rhsSType = (SimpleType) rhsType;
else if(rhsType instanceof ExtendsType)
rhsSType = (SimpleType) ((ExtendsType) rhsType).getExtendedType();
else if(rhsType instanceof SuperType)
rhsSType = (SimpleType) ((SuperType) rhsType).getSuperedType();
else
return Optional.empty();
if(!rhsSType.getName().equals(lhsSType.getName()))
return Optional.empty();
Assert.assertEquals(lhsSType.getTypeParams().size(), rhsSType.getTypeParams().size());
//if(rhsSType.getTypeParams().size() != lhsSType.getTypeParams().size())
// return Optional.empty();
Set<MPair> result = new HashSet<>();
TypeParams rhsTypeParams = rhsSType.getTypeParams();
TypeParams lhsTypeParams = lhsSType.getTypeParams();
for(int i = 0; i < rhsTypeParams.size(); i++)
result.add(new MPair(lhsTypeParams.get(i), rhsTypeParams.get(i), PairOperator.EQUALSDOT));
return Optional.of(result);
}
@Override
public boolean erase1(MPair pair) {
if(pair.getPairOp() != PairOperator.SMALLERDOT)
return false;
Type lhsType = pair.getLhsType();
if(!(lhsType instanceof SimpleType) && !(lhsType instanceof PlaceholderType))
return false;
Type rhsType = pair.getRhsType();
if(!(rhsType instanceof SimpleType) && !(rhsType instanceof PlaceholderType))
return false;
return finiteClosure.greater(lhsType).contains(rhsType);
}
@Override
public boolean erase2(MPair pair) {
if(pair.getPairOp() != PairOperator.SMALLERDOTWC)
return false;
Type lhsType = pair.getLhsType();
Type rhsType = pair.getRhsType();
return finiteClosure.grArg(lhsType).contains(rhsType);
}
@Override
public boolean erase3(MPair pair) {
if(pair.getPairOp() != PairOperator.EQUALSDOT)
return false;
return pair.getLhsType().equals(pair.getRhsType());
}
@Override
public Optional<MPair> swap(MPair pair) {
if(pair.getPairOp() != PairOperator.EQUALSDOT)
return Optional.empty();
if(pair.getLhsType() instanceof PlaceholderType)
return Optional.empty();
if(!(pair.getRhsType() instanceof PlaceholderType))
return Optional.empty();
return Optional.of(new MPair(pair.getRhsType(), pair.getLhsType(), PairOperator.EQUALSDOT));
}
@Override
public Optional<MPair> adapt(MPair pair) {
if(pair.getPairOp() != PairOperator.SMALLERDOT)
return Optional.empty();
Type typeD = pair.getLhsType();
if(!(typeD instanceof SimpleType))
return Optional.empty();
Type typeDs = pair.getRhsType();
if(!(typeDs instanceof SimpleType))
return Optional.empty();
if(typeD.getTypeParams().size() == 0 || typeDs.getTypeParams().size() == 0)
return Optional.empty();
if(typeD.getName().equals(typeDs.getName()))
return Optional.empty();
Optional<Type> opt = finiteClosure.getGenericType(typeD.getName());
if(!opt.isPresent())
return Optional.empty();
// The generic Version of Type D (D<a1, a2, a3, ... >)
Type typeDgen = opt.get();
// Actually greater+ because the types are ensured to have different names
Set<Type> greater = finiteClosure.greater(typeDgen);
opt = greater.stream().filter(x -> x.getName().equals(typeDs.getName())).findAny();
if(!opt.isPresent())
return Optional.empty();
Type newLhs = opt.get();
TypeParams typeDParams = typeD.getTypeParams();
TypeParams typeDgenParams = typeDgen.getTypeParams();
Unifier unif = new Unifier(typeDgenParams.get(0), typeDParams.get(0));
for(int i = 1; i < typeDParams.size(); i++)
unif.andThen(new Unifier(typeDgenParams.get(i), typeDParams.get(i)));
return Optional.of(new MPair(newLhs.apply(unif), typeDs, PairOperator.SMALLERDOT));
}
@Override
public Optional<MPair> adaptExt(MPair pair) {
if(pair.getPairOp() != PairOperator.SMALLERDOTWC)
return Optional.empty();
Type typeD = pair.getLhsType();
if(!(typeD instanceof SimpleType) && !(typeD instanceof ExtendsType))
return Optional.empty();
Type typeExtDs = pair.getRhsType();
if(!(typeExtDs instanceof ExtendsType))
return Optional.empty();
if(typeD.getTypeParams().size() == 0 || typeExtDs.getTypeParams().size() == 0)
return Optional.empty();
Type typeDgen;
if(typeD instanceof SimpleType)
typeDgen = finiteClosure.getGenericType(typeD.getName()).orElse(null);
else {
Optional<Type> opt = finiteClosure.getGenericType(((ExtendsType) typeD).getExtendedType().getName());
typeDgen = opt.isPresent() ? new ExtendsType(opt.get()) : null;
}
if(typeDgen == null)
return Optional.empty();
Set<Type> grArg = finiteClosure.grArg(typeDgen);
Optional<Type> opt = grArg.stream().filter(x -> x.getName().equals(typeExtDs.getName())).findAny();
if(!opt.isPresent())
return Optional.empty();
Type newLhs = ((ExtendsType) opt.get()).getExtendedType();
TypeParams typeDParams = typeD.getTypeParams();
TypeParams typeDgenParams = typeDgen.getTypeParams();
Unifier unif = new Unifier(typeDgenParams.get(0), typeDParams.get(0));
for(int i = 1; i < typeDParams.size(); i++)
unif.andThen(new Unifier(typeDgenParams.get(i), typeDParams.get(i)));
return Optional.of(new MPair(newLhs.apply(unif), typeExtDs, PairOperator.SMALLERDOTWC));
}
@Override
public Optional<MPair> adaptSup(MPair pair) {
if(pair.getPairOp() != PairOperator.SMALLERDOTWC)
return Optional.empty();
Type typeDs = pair.getLhsType();
if(!(typeDs instanceof SimpleType) && !(typeDs instanceof SuperType))
return Optional.empty();
Type typeSupD = pair.getRhsType();
if(!(typeSupD instanceof SuperType))
return Optional.empty();
if(typeDs.getTypeParams().size() == 0 || typeSupD.getTypeParams().size() == 0)
return Optional.empty();
Optional<Type> opt = finiteClosure.getGenericType(((SuperType) typeSupD).getSuperedType().getName());
if(!opt.isPresent())
return Optional.empty();
Type typeDgen = opt.get();
Type typeSupDgen = new SuperType(typeDgen);
// Use of smArg instead of grArg because
// a in grArg(b) => b in smArg(a)
Set<Type> smArg = finiteClosure.smArg(typeSupDgen);
opt = smArg.stream().filter(x -> x.getName().equals(typeDs.getName())).findAny();
if(!opt.isPresent())
return Optional.empty();
// New RHS
Type newRhs = null;
if(typeDs instanceof SimpleType)
newRhs = new ExtendsType(typeDs);
else
newRhs = new ExtendsType(((SuperType) typeDs).getSuperedType());
// New LHS
Type newLhs = opt.get();
TypeParams typeDParams = typeSupD.getTypeParams();
TypeParams typeSupDsgenParams = typeSupDgen.getTypeParams();
Unifier unif = new Unifier(typeSupDsgenParams.get(0), typeDParams.get(0));
for(int i = 1; i < typeDParams.size(); i++)
unif.andThen(new Unifier(typeSupDsgenParams.get(i), typeDParams.get(i)));
return Optional.of(new MPair(newLhs.apply(unif), newRhs, PairOperator.SMALLERDOTWC));
}
/**
* Finds the permutation pi of the type arguments of two types based on the finite closure
* @param C The type which arguments are permuted
* @param D The other type
* @return An array containing the values of pi for every type argument of C or an empty array if the search failed.
*/
private int[] pi(Type C, Type D) {
Type cFromFc = null;
if(C instanceof SimpleType)
cFromFc = finiteClosure.getGenericType(C.getName()).orElse(null);
else if(C instanceof ExtendsType) {
Optional<Type> opt = finiteClosure.getGenericType(((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());
if(opt.isPresent()) cFromFc = new SuperType(opt.get());
}
if(cFromFc == null)
return new int[0];
Optional<Type> opt = Optional.empty();
if(D instanceof ExtendsType) {
SimpleType dSType = (SimpleType) ((ExtendsType) D).getExtendedType();
opt = finiteClosure.grArg(cFromFc).stream()
.filter(x -> x instanceof ExtendsType)
.filter(x -> ((ExtendsType) x).getExtendedType().getName().equals(dSType.getName())).findAny();
}
else if(D instanceof SuperType) {
SimpleType dSType = (SimpleType) ((SuperType) D).getSuperedType();
opt = finiteClosure.grArg(cFromFc).stream()
.filter(x -> x instanceof SuperType)
.filter(x -> ((SuperType) x).getSuperedType().getName().equals(dSType.getName())).findAny();
}
else if (D instanceof SimpleType)
opt = finiteClosure.greater(cFromFc).stream()
.filter(x -> x.getName().equals(D.getName())).findAny();
if(!opt.isPresent())
return new int[0];
Type dFromFc = opt.get();
Assert.assertEquals(cFromFc.getTypeParams().size(), dFromFc.getTypeParams().size());
Assert.assertTrue(dFromFc.getTypeParams().size() > 0);
TypeParams cArgs = cFromFc.getTypeParams();
TypeParams dArgs = dFromFc.getTypeParams();
int[] permutation = new int[dArgs.size()];
boolean succ = true;
for (int dArgIdx = 0; dArgIdx < dArgs.size() && succ; dArgIdx++) {
Type dArg = dArgs.get(dArgIdx);
succ = false;
for (int pi = 0; pi < cArgs.size(); pi++)
if (cArgs.get(pi).getName().equals(dArg.getName())) {
permutation[dArgIdx] = pi;
succ = true;
break;
}
}
if(succ) return permutation;
return new int[0];
}
@Override
public Set<MPair> subst(Set<MPair> pair) {
// TODO Auto-generated method stub
return null;
}
}

View File

@ -0,0 +1,29 @@
package de.dhbwstuttgart.typeinference.unifynew;
import java.util.function.Function;
import de.dhbwstuttgart.typinference.unify.model.Type;
import de.dhbwstuttgart.typinference.unify.model.TypeParams;
public class Unifier implements Function<Type, Type> {
private Type source;
private Type target;
public Unifier(Type source, Type target) {
this.source = source;
this.target = target;
}
@Override
public Type apply(Type t) {
return t.apply(this);
}
public Type getSource() {
return source;
}
public Type getTarget() {
return target;
}
}

View File

@ -0,0 +1,257 @@
package de.dhbwstuttgart.typeinference.unifynew;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.typeinference.Pair;
import de.dhbwstuttgart.typeinference.exceptions.NotImplementedException;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unify.interfaces.IRuleSet;
import de.dhbwstuttgart.typeinference.unify.interfaces.ISetOperations;
import de.dhbwstuttgart.typinference.unify.model.ExtendsType;
import de.dhbwstuttgart.typinference.unify.model.MPair;
import de.dhbwstuttgart.typinference.unify.model.MPair.PairOperator;
import de.dhbwstuttgart.typinference.unify.model.PlaceholderType;
import de.dhbwstuttgart.typinference.unify.model.SuperType;
import de.dhbwstuttgart.typinference.unify.model.Type;
/**
* Implementation of the type unification algorithm
* @author Florian Steurer
*/
public class Unify {
public Menge<Menge<Pair>> unify(Set<MPair> eq, IFiniteClosure fc) {
/*
* Step 1: Repeated application of reduce, adapt, erase, swap
*/
Set<MPair> eq0 = applyTypeUnificationRules(eq, fc);
/*
* Step 2 and 3: Create a subset eq1s of pairs where both sides are TPH and eq2s of the other pairs
*/
Set<MPair> eq1s = new HashSet<>();
Set<MPair> eq2s = new HashSet<>();
splitEq(eq0, eq1s, eq2s);
/*
* Step 4: Create possible typings
*/
// Sets that originate from pair pattern matching
// Sets of the "second level"
List<List<Set<MPair>>> pairSetsSet = calculatePairSets(eq2s, fc);
// The sets of the "first level"
Set<Set<MPair>> sets = new HashSet<Set<MPair>>();
sets.add(eq1s); // Add Eq1'
// Add the set of [a =. Theta | (a=. Theta) in Eq2']
sets.add(eq2s.stream()
.filter(x -> x.getPairOp() == PairOperator.EQUALSDOT && x.getLhsType() instanceof PlaceholderType)
.collect(Collectors.toSet()));
/* Up to here, no cartesian products are calculated.
* Around here, filters for pairs and sets can be applied */
ISetOperations setOps = new GuavaSetOperations();
// Calculate the inner cartesian products
// Cartesian products of the second level
for(List<Set<MPair>> pairSets : pairSetsSet) // Prüfen ob addAll stimmt oder ob hier eigentlich nur 1 set sein sollte
setOps.cartesianProduct(pairSets).forEach(x -> sets.add(new HashSet<MPair>(x)));
// Calculate the outer cartesian products
// Cartesian products of the first level
Set<List<MPair>> eqsSet = setOps.cartesianProduct(new ArrayList<>(sets));
/*
* Step 5: Substitution
*/
/*
* Step 6: a) Restart for pairs where subst was applied
* b) Union over everything
*/
/*
* Step 7: Filter result for solved pairs
*/
throw new NotImplementedException();
}
protected Set<MPair> applyTypeUnificationRules(Set<MPair> eq, IFiniteClosure fc) {
/*
* Rule Application Strategy:
*
* 1. Swap all pairs and erase all erasable pairs
* 2. Apply all possible rules to a single pair, then move it to the result set.
* Iterating over pairs first, then iterating over rules prevents the application
* of rules to a "finished" pair over and over.
* 2.1 Apply all rules repeatedly except for erase rules. If
* the application of a rule creates new pairs, check immediately
* against the erase rules.
*/
LinkedHashSet<MPair> targetSet = new LinkedHashSet<MPair>();
LinkedList<MPair> eqQueue = new LinkedList<>();
IRuleSet rules = new RuleSet(fc);
/*
* Swap all pairs and erase all erasable pairs
*/
eq.forEach(x -> swapAddOrErase(x, rules, eqQueue));
/*
* Apply rules until the queue is empty
*/
while(!eqQueue.isEmpty()) {
MPair pair = eqQueue.pollFirst();
// ReduceUp, ReduceLow, ReduceUpLow
Optional<MPair> opt = rules.reduceUpLow(pair);
opt = opt.isPresent() ? opt : rules.reduceLow(pair);
opt = opt.isPresent() ? opt : rules.reduceUp(pair);
// One of the rules has been applied
if(opt.isPresent()) {
swapAddOrErase(opt.get(), rules, eqQueue);
continue;
}
// Reduce1, Reduce2, ReduceExt, ReduceSup, ReduceEq
Optional<Set<MPair>> optSet = rules.reduce1(pair);
optSet = optSet.isPresent() ? optSet : rules.reduce2(pair);
optSet = optSet.isPresent() ? optSet : rules.reduceExt(pair);
optSet = optSet.isPresent() ? optSet : rules.reduceSup(pair);
optSet = optSet.isPresent() ? optSet : rules.reduceEq(pair);
// One of the rules has been applied
if(optSet.isPresent()) {
optSet.get().forEach(x -> swapAddOrErase(x, rules, eqQueue));
continue;
}
// Adapt, AdaptExt, AdaptSup
opt = rules.adapt(pair);
opt = opt.isPresent() ? opt : rules.adaptExt(pair);
opt = opt.isPresent() ? opt : rules.adaptSup(pair);
// One of the rules has been applied
if(opt.isPresent()) {
swapAddOrErase(opt.get(), rules, eqQueue);
continue;
}
// None of the rules has been applied
targetSet.add(pair);
}
return targetSet;
}
protected void swapAddOrErase(MPair pair, IRuleSet rules, Collection<MPair> collection) {
Optional<MPair> opt = rules.swap(pair);
MPair pair2 = opt.isPresent() ? opt.get() : pair;
if(rules.erase1(pair2) || rules.erase3(pair2) || rules.erase2(pair2))
return;
collection.add(pair2);
}
protected void splitEq(Set<MPair> eq, Set<MPair> eq1s, Set<MPair> eq2s) {
for(MPair pair : eq)
if(pair.getLhsType() instanceof PlaceholderType && pair.getRhsType() instanceof PlaceholderType)
eq1s.add(pair);
else
eq2s.add(pair);
}
protected List<List<Set<MPair>>> calculatePairSets(Set<MPair> eq2s, IFiniteClosure fc) {
List<List<Set<MPair>>> result = new ArrayList<List<Set<MPair>>>();
for(int i = 0; i < 8; i++)
result.add(new ArrayList<Set<MPair>>());
for(MPair pair : eq2s) {
PairOperator pairOp = pair.getPairOp();
Type lhsType = pair.getLhsType();
Type rhsType = pair.getRhsType();
// Case 1: (a <. Theta')
if(pairOp == PairOperator.SMALLERDOT && lhsType instanceof PlaceholderType) {
// TODO
}
// Case 2: (a <.? ? ext Theta')
else if(pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof PlaceholderType && rhsType instanceof ExtendsType){
// TODO
}
// Case 3: (a <.? ? sup Theta')
else if(pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof PlaceholderType && rhsType instanceof SuperType) {
Set<MPair> set = new HashSet<>();
for(Type theta : fc.smArg(rhsType))
set.add(new MPair(lhsType, theta, PairOperator.EQUALSDOT));
result.get(2).add(set);
}
// Case 4: (a <.? Theta')
else if(pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof PlaceholderType) {
Set<MPair> set = new HashSet<>();
set.add(new MPair(lhsType, ((ExtendsType) rhsType).getExtendedType(), PairOperator.EQUALSDOT));
result.get(3).add(set);
}
// Case 5: (Theta <. a)
else if(pairOp == PairOperator.SMALLERDOT && rhsType instanceof PlaceholderType) {
Set<MPair> set = new HashSet<>();
for(Type thetaS : fc.greater(lhsType))
set.add(new MPair(rhsType, thetaS, PairOperator.EQUALSDOT));
result.get(4).add(set);
}
// Case 6: (? ext Theta <.? a)
else if(pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof ExtendsType && rhsType instanceof PlaceholderType) {
Set<MPair> set = new HashSet<>();
for(Type thetaS : fc.grArg(lhsType))
set.add(new MPair(rhsType, thetaS, PairOperator.EQUALSDOT));
result.get(5).add(set);
}
// Case 7: (? sup Theta <.? a)
else if(pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof SuperType && rhsType instanceof PlaceholderType) {
// TODO
}
// Case 8: (Theta <.? a)
else if(pairOp == PairOperator.SMALLERDOTWC && rhsType instanceof PlaceholderType) {
Set<MPair> set = new HashSet<>();
for(Type thetaS : fc.grArg(lhsType))
set.add(new MPair(rhsType, thetaS, PairOperator.EQUALSDOT));
result.get(7).add(set);
}
}
return result.stream().filter(x -> !x.isEmpty()).collect(Collectors.toList());
}
}

View File

@ -0,0 +1,58 @@
package de.dhbwstuttgart.typinference.unify.model;
import java.util.Set;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unifynew.Unifier;
public final class ExtendsType extends Type {
private Type extendedType;
public ExtendsType(Type extendedType) {
super("? extends " + extendedType.getName(), extendedType.getTypeParams());
this.extendedType = extendedType;
}
public Type getExtendedType() {
return extendedType;
}
@Override
public TypeParams getTypeParams() {
return extendedType.getTypeParams();
}
@Override
public String toString() {
return "? extends " + extendedType;
}
@Override
public Set<Type> smArg(IFiniteClosure fc) {
return fc.smArg(this);
}
@Override
public Set<Type> grArg(IFiniteClosure fc) {
return fc.grArg(this);
}
@Override
public int hashCode() {
return extendedType.hashCode() + 17;
}
@Override
public boolean equals(Object obj) {
if(!(obj instanceof ExtendsType))
return false;
ExtendsType other = (ExtendsType) obj;
return other.getExtendedType().equals(extendedType);
}
@Override
public Type apply(Unifier unif) {
return new ExtendsType(extendedType.apply(unif));
}
}

View File

@ -0,0 +1,208 @@
package de.dhbwstuttgart.typinference.unify.model;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typinference.unify.model.MPair.PairOperator;
public class FiniteClosure implements IFiniteClosure {
private HashMap<Type, Node<Type>> inheritanceGraph;
private HashMap<String, HashSet<Node<Type>>> strInheritanceGraph;
public FiniteClosure(Set<MPair> pairs) {
inheritanceGraph = new HashMap<Type, Node<Type>>();
// Build the transitive closure of the inheritance tree
for(MPair pair : pairs) {
if(pair.getPairOp() != PairOperator.SMALLER)
continue;
// Add nodes if not already in the graph
if(!inheritanceGraph.containsKey(pair.getLhsType()))
inheritanceGraph.put(pair.getLhsType(), new Node<Type>(pair.getLhsType()));
if(!inheritanceGraph.containsKey(pair.getRhsType()))
inheritanceGraph.put(pair.getRhsType(), new Node<Type>(pair.getRhsType()));
Node<Type> childNode = inheritanceGraph.get(pair.getLhsType());
Node<Type> parentNode = inheritanceGraph.get(pair.getRhsType());
// Add edge
parentNode.AddDescendant(childNode);
// Add edges to build the transitive closure
parentNode.getPredecessors().stream().forEach(x -> x.AddDescendant(childNode));
childNode.getDescendants().stream().forEach(x -> x.AddPredecessor(parentNode));
}
// Build the alternative representation with strings as keys
strInheritanceGraph = new HashMap<>();
for(Type key : inheritanceGraph.keySet()) {
if(!strInheritanceGraph.containsKey(key.getName()))
strInheritanceGraph.put(key.getName(), new HashSet<>());
strInheritanceGraph.get(key.getName()).add(inheritanceGraph.get(key));
}
}
/**
* Returns all types of the finite closure that are subtypes of the argument.
* @return The set of subtypes of the argument.
*/
@Override
public Set<Type> smaller(Type type) {
if(!inheritanceGraph.containsKey(type))
return new HashSet<>();
Set<Type> result = inheritanceGraph.get(type).getContentOfDescendants();
result.add(type);
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<Type> greater(Type type) {
if(!inheritanceGraph.containsKey(type))
return new HashSet<>();
Set<Type> result = inheritanceGraph.get(type).getContentOfPredecessors();
result.add(type);
return result;
}
@Override
public Set<Type> grArg(Type type) {
return type.grArg(this);
}
@Override
public Set<Type> grArg(SimpleType type) {
if(!inheritanceGraph.containsKey(type))
return new HashSet<Type>();
Set<Type> result = new HashSet<Type>();
result.add(type);
smaller(type).forEach(x -> result.add(new SuperType(x)));
greater(type).forEach(x -> result.add(new ExtendsType(x)));
return result;
}
@Override
public Set<Type> grArg(ExtendsType type) {
if(!inheritanceGraph.containsKey(type.getExtendedType()))
return new HashSet<Type>();
Set<Type> result = new HashSet<Type>();
Type t = type.getExtendedType();
greater(t).forEach(x -> result.add(new ExtendsType(x)));
return result;
}
@Override
public Set<Type> grArg(SuperType type) {
if(!inheritanceGraph.containsKey(type.getSuperedType()))
return new HashSet<Type>();
Set<Type> result = new HashSet<Type>();
Type t = type.getSuperedType();
smaller(t).forEach(x -> result.add(new SuperType(x)));
return result;
}
@Override
public Set<Type> grArg(PlaceholderType type) {
return new HashSet<>();
}
@Override
public Set<Type> smArg(Type type) {
return type.smArg(this);
}
@Override
public Set<Type> smArg(SimpleType type) {
if(!inheritanceGraph.containsKey(type))
return new HashSet<Type>();
Set<Type> result = new HashSet<Type>();
result.add(type);
smaller(type).forEach(x -> result.add(new ExtendsType(x)));
return result;
}
public Set<Type> smArg(ExtendsType type) {
if(!inheritanceGraph.containsKey(type.getExtendedType()))
return new HashSet<Type>();
Set<Type> result = new HashSet<Type>();
Type t = type.getExtendedType();
result.add(t);
smaller(t).forEach(x -> {
result.add(new ExtendsType(x));
result.add(x);
});
return result;
}
@Override
public Set<Type> smArg(SuperType type) {
if(!inheritanceGraph.containsKey(type.getSuperedType()))
return new HashSet<Type>();
Set<Type> result = new HashSet<Type>();
Type t = type.getSuperedType();
result.add(t);
greater(t).forEach(x -> {
result.add(new SuperType(x));
result.add(x);
});
return result;
}
@Override
public Set<Type> smArg(PlaceholderType type) {
return new HashSet<>();
}
@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);
}
return Optional.empty();
}
}

View File

@ -0,0 +1,97 @@
package de.dhbwstuttgart.typinference.unify.model;
public class MPair {
public enum PairOperator {
SMALLER,
SMALLERDOT,
SMALLERDOTWC,
EQUALS,
EQUALSDOT;
@Override
public String toString() {
switch (this) {
case SMALLER:
return "<";
case SMALLERDOT:
return "<.";
case SMALLERDOTWC:
return "<.?";
case EQUALS:
return "=";
default:
return "=.";
}
};
}
private Type lhs;
private Type rhs;
private PairOperator pairOp;
/*public MPair(Type t1, Type t2) {
lhs = t1;
rhs = t2;
pairOp = PairOperator.SMALLER;
}*/
public MPair(Type t1, Type t2, PairOperator op) {
lhs = t1;
rhs = t2;
pairOp = op;
}
public Type getLhsType() {
return lhs;
}
public Type getRhsType() {
return rhs;
}
public PairOperator getPairOp() {
return pairOp;
}
@Override
public boolean equals(Object obj) {
if(!(obj instanceof MPair))
return false;
MPair other = (MPair) obj;
return other.getPairOp() == pairOp
&& other.getLhsType().equals(lhs)
&& other.getRhsType().equals(rhs);
}
/**
* Substitutes the occurrences of Type t on the left or right side of the pair with the Type subst.
* @param t Type to be replaced.
* @param subst The type replacing t.
* @return A pair where occurrences of t are replaced by subst.
*/
public MPair substitute(Type t, Type subst) {
Type newlhs = lhs;
if(lhs.equals(t)) newlhs = subst;
Type newrhs = rhs;
if(rhs.equals(t)) newrhs = subst;
if(newlhs == lhs && newrhs == rhs) return this;
return new MPair(newlhs, newrhs, pairOp);
}
@Override
public int hashCode() {
return 17 + 31 * lhs.hashCode() + 31 * rhs.hashCode() + 31 * pairOp.hashCode();
}
@Override
public String toString() {
return "(" + lhs + " " + pairOp + " " + rhs + ")";
}
}

View File

@ -0,0 +1,57 @@
package de.dhbwstuttgart.typinference.unify.model;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;
public class Node<T> {
private T content;
private HashSet<Node<T>> predecessors = new HashSet<>();
private HashSet<Node<T>> descendants = new HashSet<>();
public Node(T content) {
this.content = content;
}
public void AddDescendant(Node<T> descendant) {
if(descendants.contains(descendant))
return;
descendants.add(descendant);
descendant.AddPredecessor(this);
}
public void AddPredecessor(Node<T> predecessor) {
if(predecessors.contains(predecessor))
return;
predecessors.add(predecessor);
predecessor.AddDescendant(this);
}
public T getContent() {
return content;
}
public Set<Node<T>> getPredecessors() {
return predecessors;
}
public Set<Node<T>> getDescendants() {
return descendants;
}
public Set<T> getContentOfDescendants() {
return descendants.stream().map(x -> x.getContent()).collect(Collectors.toSet());
}
public Set<T> getContentOfPredecessors() {
return predecessors.stream().map(x -> x.getContent()).collect(Collectors.toSet());
}
@Override
public String toString() {
return "Node(" + content.toString() + ")";
}
}

View File

@ -0,0 +1,44 @@
package de.dhbwstuttgart.typinference.unify.model;
import java.util.Set;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unifynew.Unifier;
public final class PlaceholderType extends Type{
public PlaceholderType(String name) {
super(name);
}
@Override
public Set<Type> smArg(IFiniteClosure fc) {
return fc.smArg(this);
}
@Override
public Set<Type> grArg(IFiniteClosure fc) {
return fc.grArg(this);
}
@Override
public int hashCode() {
return typeName.hashCode();
}
@Override
public boolean equals(Object obj) {
if(!(obj instanceof PlaceholderType))
return false;
return ((PlaceholderType) obj).getName().equals(typeName);
}
@Override
public Type apply(Unifier unif) {
if(this.equals(unif.getSource()))
return unif.getTarget();
return this;
}
}

View File

@ -0,0 +1,52 @@
package de.dhbwstuttgart.typinference.unify.model;
import java.util.Set;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unifynew.Unifier;
public final class SimpleType extends Type {
public SimpleType(String name, Type... typeParams) {
super(name, new TypeParams(typeParams));
}
private SimpleType(String name, TypeParams params) {
super(name, params);
}
@Override
public Set<Type> smArg(IFiniteClosure fc) {
return fc.smArg(this);
}
@Override
public Set<Type> grArg(IFiniteClosure fc) {
return fc.grArg(this);
}
@Override
public int hashCode() {
return typeName.hashCode();
}
@Override
public boolean equals(Object obj) {
if(!(obj instanceof SimpleType))
return false;
SimpleType other = (SimpleType) obj;
if(!other.getName().equals(typeName))
return false;
return other.getTypeParams().equals(typeParams);
}
@Override
public Type apply(Unifier unif) {
if(this.equals(unif.getSource()))
return unif.getTarget();
return new SimpleType(typeName, typeParams.apply(unif));
}
}

View File

@ -0,0 +1,59 @@
package de.dhbwstuttgart.typinference.unify.model;
import java.util.Set;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unifynew.Unifier;
public final class SuperType extends Type {
private Type superedType;
public SuperType(Type superedType) {
super("? super " + superedType.getName(), superedType.getTypeParams());
this.superedType = superedType;
}
public Type getSuperedType() {
return superedType;
}
@Override
public String toString() {
return "? super " + superedType;
}
@Override
public TypeParams getTypeParams() {
return superedType.getTypeParams();
}
@Override
public Set<Type> smArg(IFiniteClosure fc) {
return fc.smArg(this);
}
@Override
public Set<Type> grArg(IFiniteClosure fc) {
return fc.grArg(this);
}
@Override
public int hashCode() {
return superedType.hashCode() + 17;
}
@Override
public boolean equals(Object obj) {
if(!(obj instanceof SuperType))
return false;
SuperType other = (SuperType) obj;
return other.getSuperedType().equals(superedType);
}
@Override
public Type apply(Unifier unif) {
return new SuperType(superedType.apply(unif));
}
}

View File

@ -0,0 +1,48 @@
package de.dhbwstuttgart.typinference.unify.model;
import java.util.Set;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unifynew.Unifier;
public abstract class Type {
protected final String typeName;
protected final TypeParams typeParams;
protected Type(String name, Type... typeParams) {
typeName = name;
this.typeParams = new TypeParams(typeParams);
}
protected Type(String name, TypeParams p) {
typeName = name;
typeParams = p;
}
public String getName() {
return typeName;
}
public TypeParams getTypeParams() {
return typeParams;
}
public abstract Set<Type> smArg(IFiniteClosure fc);
public abstract Set<Type> grArg(IFiniteClosure fc);
public abstract Type apply(Unifier unif);
@Override
public String toString() {
String params = "";
if(typeParams.size() != 0) {
for(Type param : typeParams)
params += param.toString() + ",";
params = "<" + params.substring(0, params.length()-1) + ">";
}
return typeName + params;
}
}

View File

@ -0,0 +1,83 @@
package de.dhbwstuttgart.typinference.unify.model;
import java.util.Arrays;
import java.util.Iterator;
import de.dhbwstuttgart.typeinference.unifynew.Unifier;
public final class TypeParams implements Iterable<Type>{
private final Type[] typeParams;
public TypeParams(Type... types) {
typeParams = types;
}
public boolean arePlaceholders() {
for(Type t : typeParams)
if(!(t instanceof PlaceholderType))
return false;
return true;
}
@Override
public String toString() {
String res = "";
for(Type t : typeParams)
res += t + ",";
return "<" + res.substring(0, res.length()-1) + ">";
}
public int size() {
return typeParams.length;
}
public boolean empty() {
return typeParams.length == 0;
}
public TypeParams apply(Unifier unif) {
Type[] newParams = new Type[typeParams.length];
for(int i = 0; i < typeParams.length; i++)
newParams[i] = typeParams[i].apply(unif);
return new TypeParams(newParams);
}
public boolean contains(Type t) {
for(Type t1 : typeParams)
if(t1.equals(t1))
return true;
return false;
}
public Type get(int i) {
return typeParams[i];
}
@Override
public Iterator<Type> iterator() {
return Arrays.stream(typeParams).iterator();
}
@Override
public int hashCode() {
return Arrays.hashCode(typeParams);
}
@Override
public boolean equals(Object obj) {
if(!(obj instanceof TypeParams))
return false;
TypeParams other = (TypeParams) obj;
if(other.size() != this.size())
return false;
for(int i = 0; i < this.size(); i++)
if(!(this.get(i).equals(other.get(i))))
return false;
return true;
}
}

View File

@ -0,0 +1,64 @@
package unify;
import java.util.HashSet;
import java.util.Set;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typinference.unify.model.FiniteClosure;
import de.dhbwstuttgart.typinference.unify.model.MPair;
import de.dhbwstuttgart.typinference.unify.model.MPair.PairOperator;
import de.dhbwstuttgart.typinference.unify.model.Type;
public class FiniteClosureBuilder {
private Set<MPair> pairs = new HashSet<>();
public void add(Type sub, Type sup) {
pairs.add(new MPair(sub, sup, PairOperator.SMALLER));
}
public IFiniteClosure getFiniteClosure() {
return new FiniteClosure(pairs);
}
public void clear() {
pairs = new HashSet<>();
}
public IFiniteClosure getCollectionExample() {
TypeFactory tf = new TypeFactory();
Type collection = tf.getSimpleType("Collection");
Type set = tf.getSimpleType("Set", "T");
Type sortedSet = tf.getSimpleType("Set", "T");
Type TreeSet = tf.getSimpleType("TreeSet", "T");
Type hashSet = tf.getSimpleType("HashSet", "T");
Type linkedHashSet = tf.getSimpleType("LinkedHashSet", "T");
Type queue = tf.getSimpleType("Queue", "T");
Type deque = tf.getSimpleType("Deque", "T");
Type linkedList = tf.getSimpleType("LinkedList", "T");
Type list = tf.getSimpleType("List", "T");
Type vector = tf.getSimpleType("Vector", "T");
Type stack = tf.getSimpleType("Stack", "T");
Type arrayList = tf.getSimpleType("ArrayList", "T");
add(set, collection);
add(sortedSet, set);
add(TreeSet, sortedSet);
add(hashSet, set);
add(linkedHashSet, set);
add(queue, collection);
add(deque, queue);
add(linkedList, deque);
add(list, collection);
add(linkedList, list);
add(vector, list);
add(arrayList, list);
add(stack, vector);
IFiniteClosure fc = getFiniteClosure();
clear();
return fc;
}
}

View File

@ -0,0 +1,57 @@
package unify;
import java.util.HashSet;
import java.util.Set;
import org.junit.Test;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typinference.unify.model.MPair;
import de.dhbwstuttgart.typinference.unify.model.Type;
public class FiniteClosureTest {
@Test
public void testGreater() {
IFiniteClosure fc = new FiniteClosureBuilder().getCollectionExample();
TypeFactory tf = new TypeFactory();
System.out.println("\n\n----- Greater Test -----");
System.out.println("Greater(LinkedList<T>) = " + fc.greater(tf.getSimpleType("LinkedList", "T")));
System.out.println("Greater(TreeSet<T>) = " + fc.greater(tf.getSimpleType("TreeSet", "T")));
System.out.println("Greater(Collection) = " + fc.greater(tf.getSimpleType("Collection")));
}
@Test
public void testGrArg() {
IFiniteClosure fc = new FiniteClosureBuilder().getCollectionExample();
TypeFactory tf = new TypeFactory();
System.out.println("\n\n----- GrArg Test -----");
System.out.println("GrArg(List<T>) = " + fc.grArg(tf.getSimpleType("List", "T")));
System.out.println("GrArg(? extends List<T>) = " + fc.grArg(tf.getExtendsType(tf.getSimpleType("List", "T"))));
System.out.println("GrArg(? super List<T>) = " + fc.grArg(tf.getSuperType(tf.getSimpleType("List", "T"))));
}
@Test
public void testSmaller() {
IFiniteClosure fc = new FiniteClosureBuilder().getCollectionExample();
TypeFactory tf = new TypeFactory();
System.out.println("\n\n----- Smaller Test -----");
System.out.println("Smaller(List<T>) = " + fc.smaller(tf.getSimpleType("List", "T")));
System.out.println("Smaller(TreeSet<T>) = " + fc.smaller(tf.getSimpleType("TreeSet", "T")));
System.out.println("Smaller(Collection) = " + fc.smaller(tf.getSimpleType("Collection")));
}
@Test
public void testSmArg() {
IFiniteClosure fc = new FiniteClosureBuilder().getCollectionExample();
TypeFactory tf = new TypeFactory();
System.out.println("\n\n----- SmArg Test -----");
System.out.println("SmArg(List<T>) = " + fc.smArg(tf.getSimpleType("List", "T")));
System.out.println("SmArg(? extends List<T>) = " + fc.smArg(tf.getExtendsType(tf.getSimpleType("List", "T"))));
System.out.println("SmArg(? super List<T>) = " + fc.smArg(tf.getSuperType(tf.getSimpleType("List", "T"))));
}
}

686
test/unify/RuleSetTest.java Normal file
View File

@ -0,0 +1,686 @@
package unify;
import java.util.Optional;
import java.util.Set;
import junit.framework.Assert;
import org.junit.Test;
import de.dhbwstuttgart.typeinference.unify.interfaces.IRuleSet;
import de.dhbwstuttgart.typeinference.unifynew.RuleSet;
import de.dhbwstuttgart.typinference.unify.model.ExtendsType;
import de.dhbwstuttgart.typinference.unify.model.MPair;
import de.dhbwstuttgart.typinference.unify.model.MPair.PairOperator;
import de.dhbwstuttgart.typinference.unify.model.SimpleType;
import de.dhbwstuttgart.typinference.unify.model.SuperType;
public class RuleSetTest {
@Test
public void testReduceUp() {
IRuleSet rules = new RuleSet(new FiniteClosureBuilder().getFiniteClosure());
TypeFactory tf = new TypeFactory();
/*
* Positive Tests
*/
MPair reduce1 = new MPair(tf.getSimpleType("type"), tf.getSuperType(tf.getSimpleType("type")), PairOperator.SMALLERDOT);
MPair reduce2 = new MPair(tf.getPlaceholderType("T"), tf.getSuperType(tf.getSimpleType("type")), PairOperator.SMALLERDOT);
MPair expected1 = new MPair(tf.getSimpleType("type"), tf.getSimpleType("type"), PairOperator.SMALLERDOT);
MPair expected2 = new MPair(tf.getPlaceholderType("T"), tf.getSimpleType("type"), PairOperator.SMALLERDOT);
Optional<MPair> opt1 = rules.reduceUp(reduce1);
Optional<MPair> opt2 = rules.reduceUp(reduce2);
Assert.assertTrue(opt1.isPresent());
Assert.assertTrue(opt2.isPresent());
Assert.assertEquals(opt1.get(), expected1);
Assert.assertEquals(opt2.get(), expected2);
/*
* Negative Tests
*/
MPair noreduce1 = new MPair(tf.getSuperType(tf.getSimpleType("type")), tf.getSuperType(tf.getSimpleType("type")), PairOperator.SMALLERDOT);
MPair noreduce2 = new MPair(tf.getPlaceholderType("T"), tf.getSimpleType("type"), PairOperator.SMALLERDOT);
MPair noreduce3 = new MPair(tf.getPlaceholderType("T"), tf.getExtendsType(tf.getSimpleType("type")), PairOperator.SMALLERDOT);
MPair noreduce4 = new MPair(tf.getPlaceholderType("T"), tf.getSuperType(tf.getSimpleType("type")), PairOperator.EQUALSDOT);
Assert.assertFalse(rules.reduceUp(noreduce1).isPresent());
Assert.assertFalse(rules.reduceUp(noreduce2).isPresent());
Assert.assertFalse(rules.reduceUp(noreduce3).isPresent());
Assert.assertFalse(rules.reduceUp(noreduce4).isPresent());
}
@Test
public void testReduceLow() {
IRuleSet rules = new RuleSet(new FiniteClosureBuilder().getFiniteClosure());
TypeFactory tf = new TypeFactory();
/*
* Positive Tests
*/
MPair reduce1 = new MPair(tf.getExtendsType(tf.getSimpleType("type")), tf.getSimpleType("type"), PairOperator.SMALLERDOT);
MPair reduce2 = new MPair(tf.getExtendsType(tf.getSimpleType("type")), tf.getPlaceholderType("T"), PairOperator.SMALLERDOT);
MPair expected1 = new MPair(tf.getSimpleType("type"), tf.getSimpleType("type"), PairOperator.SMALLERDOT);
MPair expected2 = new MPair(tf.getSimpleType("type"), tf.getPlaceholderType("T"), PairOperator.SMALLERDOT);
Optional<MPair> opt1 = rules.reduceLow(reduce1);
Optional<MPair> opt2 = rules.reduceLow(reduce2);
Assert.assertTrue(opt1.isPresent());
Assert.assertTrue(opt2.isPresent());
Assert.assertEquals(opt1.get(), expected1);
Assert.assertEquals(opt2.get(), expected2);
/*
* Negative Tests
*/
MPair noreduce1 = new MPair(tf.getExtendsType(tf.getSimpleType("type")), tf.getExtendsType(tf.getSimpleType("type")), PairOperator.SMALLERDOT);
MPair noreduce2 = new MPair(tf.getPlaceholderType("T"), tf.getSimpleType("type"), PairOperator.SMALLERDOT);
MPair noreduce3 = new MPair(tf.getSuperType(tf.getPlaceholderType("T")), tf.getSimpleType("type"), PairOperator.SMALLERDOT);
MPair noreduce4 = new MPair(tf.getExtendsType(tf.getPlaceholderType("T")), tf.getSimpleType("type"), PairOperator.EQUALSDOT);
Assert.assertFalse(rules.reduceLow(noreduce1).isPresent());
Assert.assertFalse(rules.reduceLow(noreduce2).isPresent());
Assert.assertFalse(rules.reduceLow(noreduce3).isPresent());
Assert.assertFalse(rules.reduceLow(noreduce4).isPresent());
}
@Test
public void testReduceUpLow() {
IRuleSet rules = new RuleSet(new FiniteClosureBuilder().getFiniteClosure());
TypeFactory tf = new TypeFactory();
/*
* Positive Tests
*/
MPair reduce1 = new MPair(tf.getExtendsType(tf.getSimpleType("type")), tf.getSuperType(tf.getSimpleType("type")), PairOperator.SMALLERDOT);
MPair reduce2 = new MPair(tf.getExtendsType(tf.getSimpleType("type")), tf.getSuperType(tf.getPlaceholderType("T")), PairOperator.SMALLERDOT);
MPair expected1 = new MPair(tf.getSimpleType("type"), tf.getSimpleType("type"), PairOperator.SMALLERDOT);
MPair expected2 = new MPair(tf.getSimpleType("type"), tf.getPlaceholderType("T"), PairOperator.SMALLERDOT);
Optional<MPair> opt1 = rules.reduceUpLow(reduce1);
Optional<MPair> opt2 = rules.reduceUpLow(reduce2);
Assert.assertTrue(opt1.isPresent());
Assert.assertTrue(opt2.isPresent());
Assert.assertEquals(opt1.get(), expected1);
Assert.assertEquals(opt2.get(), expected2);
/*
* Negative Tests
*/
MPair noreduce1 = new MPair(tf.getExtendsType(tf.getSimpleType("type")), tf.getExtendsType(tf.getSimpleType("type")), PairOperator.SMALLERDOT);
MPair noreduce2 = new MPair(tf.getSuperType(tf.getPlaceholderType("T")), tf.getExtendsType(tf.getSimpleType("type")), PairOperator.SMALLERDOT);
MPair noreduce3 = new MPair(tf.getSuperType(tf.getPlaceholderType("T")), tf.getSimpleType("type"), PairOperator.SMALLERDOT);
MPair noreduce4 = new MPair(tf.getExtendsType(tf.getPlaceholderType("T")), tf.getSimpleType("type"), PairOperator.EQUALSDOT);
Assert.assertFalse(rules.reduceUpLow(noreduce1).isPresent());
Assert.assertFalse(rules.reduceUpLow(noreduce2).isPresent());
Assert.assertFalse(rules.reduceUpLow(noreduce3).isPresent());
Assert.assertFalse(rules.reduceUpLow(noreduce4).isPresent());
}
@Test
public void testReduce1() {
TypeFactory tf = new TypeFactory();
FiniteClosureBuilder fcb = new FiniteClosureBuilder();
/*
* Positive Tests
*/
// C<T1, T2, T3, T4>
SimpleType c1 = tf.getSimpleType("C", "T1", "T2", "T3", "T4");
// D<T4, T1, T2, T3>
SimpleType d1 = tf.getSimpleType("D", "T4", "T1", "T2", "T3");
SimpleType buffer = tf.getSimpleType("Buffer");
//C<Int, ? extends Double, M, N>
SimpleType c2 = tf.getSimpleType("C", tf.getSimpleType("Int"), tf.getExtendsType(tf.getSimpleType("Double")), tf.getPlaceholderType("M"), tf.getPlaceholderType("N"));
//D<? super HashSet<Int>, Number, Double, N>
SimpleType d2 = tf.getSimpleType("D", tf.getSuperType(tf.getSimpleType("HashSet", "Int")), tf.getSimpleType("Number"), tf.getSimpleType("Double"), tf.getPlaceholderType("N"));
// C<...> < buffer < D<...>
fcb.add(c1, buffer);
fcb.add(buffer, d1);
IRuleSet rules = new RuleSet(fcb.getFiniteClosure());
MPair pair = new MPair(c2, d2, PairOperator.SMALLERDOT);
System.out.println("------ Reduce1 ------");
Optional<Set<MPair>> res = rules.reduce1(pair);
System.out.println(res);
pair = new MPair(c2, c2, PairOperator.SMALLERDOT);
res = rules.reduce1(pair);
System.out.println(res);
/*
* Negative Tests
*/
// Case 1: D <. C and C <* D
pair = new MPair(d2, c2, PairOperator.SMALLERDOT);
Assert.assertFalse(rules.reduce1(pair).isPresent());
// Case 2: D =. C
pair = new MPair(c2, d2, PairOperator.EQUALSDOT);
Assert.assertFalse(rules.reduce1(pair).isPresent());
// Case 3: C <. D and !(C <* D)
fcb.clear();
rules = new RuleSet(fcb.getFiniteClosure());
pair = new MPair(c1, d1, PairOperator.SMALLERDOT);
Assert.assertFalse(rules.reduce1(pair).isPresent());
}
@Test
public void testReduce2() {
TypeFactory tf = new TypeFactory();
FiniteClosureBuilder fcb = new FiniteClosureBuilder();
IRuleSet rules = new RuleSet(fcb.getFiniteClosure());
/*
* Positive Tests
*/
System.out.println("----- Reduce2 ------");
// C<T1, SType1, ? extends SType1>
SimpleType c1 = tf.getSimpleType("C", tf.getPlaceholderType("T1"), tf.getSimpleType("SType1"), tf.getExtendsType(tf.getSimpleType("SType1")));
// C<T2, SType2, ? extends SType2>
SimpleType c2 = tf.getSimpleType("C", tf.getPlaceholderType("T2"), tf.getSimpleType("SType2"), tf.getExtendsType(tf.getSimpleType("SType2")));
MPair pair1 = new MPair(c1, c2, PairOperator.EQUALSDOT);
MPair pair2 = new MPair(tf.getExtendsType(c1), tf.getExtendsType(c2), PairOperator.EQUALSDOT);
MPair pair3 = new MPair(tf.getSuperType(c1), tf.getSuperType(c2), PairOperator.EQUALSDOT);
Optional<Set<MPair>> opt1 = rules.reduce2(pair1);
System.out.println(opt1);
Optional<Set<MPair>> opt2 = rules.reduce2(pair2);
System.out.println(opt2);
Optional<Set<MPair>> opt3 = rules.reduce2(pair3);
System.out.println(opt3);
/*
* Negative Tests
*/
SimpleType d1 = tf.getSimpleType("D", tf.getPlaceholderType("T2"), tf.getSimpleType("SType2"), tf.getExtendsType(tf.getSimpleType("SType2")));
pair1 = new MPair(d1, c1, PairOperator.EQUALSDOT); // Case 1: D =. C
pair2 = new MPair(tf.getExtendsType(c1), c2, PairOperator.EQUALSDOT); // Case 2: ? extends C =. C
pair3 = new MPair(tf.getExtendsType(c1), tf.getSuperType(c2), PairOperator.EQUALSDOT); // Case 3: ? extends C =. ? super C
MPair pair4 = new MPair(c1, c2, PairOperator.SMALLERDOT); // Case 4: C <. C
Assert.assertFalse(rules.reduceEq(pair1).isPresent());
Assert.assertFalse(rules.reduceEq(pair2).isPresent());
Assert.assertFalse(rules.reduceEq(pair3).isPresent());
Assert.assertFalse(rules.reduceEq(pair4).isPresent());
}
@Test
public void testReduceExt() {
TypeFactory tf = new TypeFactory();
FiniteClosureBuilder fcb = new FiniteClosureBuilder();
/*
* Positive Tests
*/
// X<T1, T2, T3, T4>
SimpleType x1 = tf.getSimpleType("X", "T1", "T2", "T3", "T4");
// Y<T4, T1, T2, T3>
SimpleType y1 = tf.getSimpleType("Y", "T4", "T1", "T2", "T3");
SimpleType buffer = tf.getSimpleType("Buffer");
//X<Int, ? extends Double, M, N>
SimpleType x2 = tf.getSimpleType("X", tf.getSimpleType("Int"), tf.getExtendsType(tf.getSimpleType("Double")), tf.getPlaceholderType("M"), tf.getPlaceholderType("N"));
//? extends Y<? super HashSet<Int>, Number, Double, N>
ExtendsType extY1 = tf.getExtendsType(tf.getSimpleType("Y", tf.getSuperType(tf.getSimpleType("HashSet", "Int")), tf.getSimpleType("Number"), tf.getSimpleType("Double"), tf.getPlaceholderType("N")));
// Y<...> < buffer < X<...>
fcb.add(x1, buffer);
fcb.add(buffer, y1);
IRuleSet rules = new RuleSet(fcb.getFiniteClosure());
MPair pair1 = new MPair(x2, extY1, PairOperator.SMALLERDOTWC);
MPair pair2 = new MPair(tf.getExtendsType(x2), extY1, PairOperator.SMALLERDOTWC);
MPair pair3 = new MPair(extY1, extY1, PairOperator.SMALLERDOTWC);
System.out.println("------ ReduceExt ------");
Optional<Set<MPair>> opt1 = rules.reduceExt(pair1);
System.out.println(opt1);
Optional<Set<MPair>> opt2 = rules.reduceExt(pair2);
System.out.println(opt2);
Optional<Set<MPair>> opt3 = rules.reduceExt(pair3);
System.out.println(opt3);
/*
* Negative Tests
*/
// Case 1: X <.? Y
pair1 = new MPair(x2, extY1.getExtendedType(), PairOperator.SMALLERDOTWC);
Assert.assertFalse(rules.reduceExt(pair1).isPresent());
// Case 2: X =. ? super Y
pair2 = new MPair(x2, extY1, PairOperator.EQUALSDOT);
Assert.assertFalse(rules.reduceExt(pair2).isPresent());
// Case 3: ? extends Y <.? ? extends X
pair3 = new MPair(extY1, tf.getExtendsType(x2), PairOperator.SMALLERDOTWC);
Assert.assertFalse(rules.reduceExt(pair3).isPresent());
// Case 4: X <. ? extends Y and ? extends Y not in grArg(X)
fcb.clear();
rules = new RuleSet(fcb.getFiniteClosure());
pair1 = new MPair(x2, extY1, PairOperator.SMALLERDOTWC);
Assert.assertFalse(rules.reduceExt(pair1).isPresent());
}
@Test
public void testReduceSup() {
TypeFactory tf = new TypeFactory();
FiniteClosureBuilder fcb = new FiniteClosureBuilder();
/*
* Positive Tests
*/
// X<T1, T2, T3, T4>
SimpleType x1 = tf.getSimpleType("X", "T1", "T2", "T3", "T4");
// Y<T4, T1, T2, T3>
SimpleType y1 = tf.getSimpleType("Y", "T4", "T1", "T2", "T3");
SimpleType buffer = tf.getSimpleType("Buffer");
//X<Int, ? extends Double, M, N>
SimpleType x2 = tf.getSimpleType("X", tf.getSimpleType("Int"), tf.getExtendsType(tf.getSimpleType("Double")), tf.getPlaceholderType("M"), tf.getPlaceholderType("N"));
//? super Y<? super HashSet<Int>, Number, Double, N>
SuperType supY1 = tf.getSuperType(tf.getSimpleType("Y", tf.getSuperType(tf.getSimpleType("HashSet", "Int")), tf.getSimpleType("Number"), tf.getSimpleType("Double"), tf.getPlaceholderType("N")));
// Y<...> < buffer < X<...>
fcb.add(y1, buffer);
fcb.add(buffer, x1);
IRuleSet rules = new RuleSet(fcb.getFiniteClosure());
MPair pair1 = new MPair(x2, supY1, PairOperator.SMALLERDOTWC);
MPair pair2 = new MPair(tf.getSuperType(x2), supY1, PairOperator.SMALLERDOTWC);
MPair pair3 = new MPair(supY1, supY1, PairOperator.SMALLERDOTWC);
System.out.println("------ ReduceSup ------");
Optional<Set<MPair>> opt1 = rules.reduceSup(pair1);
System.out.println(opt1);
Optional<Set<MPair>> opt2 = rules.reduceSup(pair2);
System.out.println(opt2);
Optional<Set<MPair>> opt3 = rules.reduceSup(pair3);
System.out.println(opt3);
/*
* Negative Tests
*/
// Case 1: X <.? Y
pair1 = new MPair(x2, supY1.getSuperedType(), PairOperator.SMALLERDOTWC);
Assert.assertFalse(rules.reduceSup(pair1).isPresent());
// Case 2: X =. ? super Y
pair2 = new MPair(x2, supY1, PairOperator.EQUALSDOT);
Assert.assertFalse(rules.reduceSup(pair2).isPresent());
// Case 3: ? super Y <.? ? super X
pair3 = new MPair(supY1, tf.getSuperType(x2), PairOperator.SMALLERDOTWC);
Assert.assertFalse(rules.reduceSup(pair3).isPresent());
// Case 4: X <. ? super Y and ? super Y not in grArg(X)
fcb.clear();
rules = new RuleSet(fcb.getFiniteClosure());
pair1 = new MPair(x2, supY1, PairOperator.SMALLERDOTWC);
Assert.assertFalse(rules.reduceSup(pair1).isPresent());
}
@Test
public void testReduceEq() {
TypeFactory tf = new TypeFactory();
FiniteClosureBuilder fcb = new FiniteClosureBuilder();
IRuleSet rules = new RuleSet(fcb.getFiniteClosure());
/*
* Positive Tests
*/
System.out.println("----- ReduceEq ------");
// C<T1, SType1, ? extends SType1>
SimpleType c1 = tf.getSimpleType("C", tf.getPlaceholderType("T1"), tf.getSimpleType("SType1"), tf.getExtendsType(tf.getSimpleType("SType1")));
// C<T2, SType2, ? extends SType2>
SimpleType c2 = tf.getSimpleType("C", tf.getPlaceholderType("T2"), tf.getSimpleType("SType2"), tf.getExtendsType(tf.getSimpleType("SType2")));
MPair pair = new MPair(c1, c2, PairOperator.SMALLERDOTWC);
Optional<Set<MPair>> res = rules.reduceEq(pair);
System.out.println(res);
/*
* Negative Tests
*/
// Case 1: D <.? C
SimpleType d1 = tf.getSimpleType("D", tf.getPlaceholderType("T2"), tf.getSimpleType("SType2"), tf.getExtendsType(tf.getSimpleType("SType2")));
pair = new MPair(d1, c1, PairOperator.SMALLERDOTWC);
Assert.assertFalse(rules.reduceEq(pair).isPresent());
// Case 2: C <. C
pair = new MPair(c1, c2, PairOperator.SMALLERDOT);
Assert.assertFalse(rules.reduceEq(pair).isPresent());
}
@Test
public void testErase1() {
TypeFactory tf = new TypeFactory();
IRuleSet rules = new RuleSet(new FiniteClosureBuilder().getCollectionExample());
/*
* Positive Tests
*/
MPair erase1 = new MPair(tf.getSimpleType("List", "T"), tf.getSimpleType("Collection"), PairOperator.SMALLERDOT);
MPair erase2 = new MPair(tf.getSimpleType("HashSet", "T"), tf.getSimpleType("Collection"), PairOperator.SMALLERDOT);
MPair erase3 = new MPair(tf.getSimpleType("List", "T"), tf.getSimpleType("List", "T"), PairOperator.SMALLERDOT);
Assert.assertTrue(rules.erase1(erase1));
Assert.assertTrue(rules.erase1(erase2));
Assert.assertTrue(rules.erase1(erase3));
/*
* Negative Tests
*/
MPair noerase1 = new MPair(tf.getSimpleType("Collection"), tf.getSimpleType("List", "T"), PairOperator.SMALLERDOT);
MPair noerase2 = new MPair(tf.getSimpleType("List", "T"), tf.getSimpleType("Collection"), PairOperator.EQUALSDOT);
MPair noerase3 = new MPair(tf.getSimpleType("List", "T"), tf.getSimpleType("Collection"), PairOperator.SMALLERDOTWC);
Assert.assertFalse(rules.erase1(noerase1));
Assert.assertFalse(rules.erase1(noerase2));
Assert.assertFalse(rules.erase1(noerase3));
}
@Test
public void testErase2() {
TypeFactory tf = new TypeFactory();
IRuleSet rules = new RuleSet(new FiniteClosureBuilder().getCollectionExample());
/*
* Positive Tests
*/
MPair erase1 = new MPair(tf.getSimpleType("List", "T"), tf.getExtendsType(tf.getSimpleType("Collection")), PairOperator.SMALLERDOTWC);
MPair erase2 = new MPair(tf.getSimpleType("Collection"), tf.getSuperType(tf.getSimpleType("HashSet", "T")), PairOperator.SMALLERDOTWC);
MPair erase3 = new MPair(tf.getSimpleType("List", "T"), tf.getSimpleType("List", "T"), PairOperator.SMALLERDOTWC);
MPair erase4 = new MPair(tf.getExtendsType(tf.getSimpleType("LinkedList", "T")), tf.getExtendsType(tf.getSimpleType("List", "T")), PairOperator.SMALLERDOTWC);
MPair erase5 = new MPair(tf.getSuperType(tf.getSimpleType("List", "T")), tf.getSuperType(tf.getSimpleType("Stack", "T")), PairOperator.SMALLERDOTWC);
Assert.assertTrue(rules.erase2(erase1));
Assert.assertTrue(rules.erase2(erase2));
Assert.assertTrue(rules.erase2(erase3));
Assert.assertTrue(rules.erase2(erase4));
Assert.assertTrue(rules.erase2(erase5));
/*
* Negative Tests
*/
MPair noerase1 = new MPair(tf.getSimpleType("Collection"), tf.getSimpleType("List", "T"), PairOperator.SMALLERDOTWC);
MPair noerase2 = new MPair(tf.getSuperType(tf.getSimpleType("List", "T")), tf.getSimpleType("ArrayList", "T"), PairOperator.SMALLERDOTWC);
MPair noerase3 = new MPair(tf.getExtendsType(tf.getSimpleType("List", "T")), tf.getSuperType(tf.getSimpleType("List", "T")), PairOperator.SMALLERDOTWC);
MPair noerase4 = new MPair(tf.getSimpleType("List", "T"), tf.getSimpleType("List", "T"), PairOperator.SMALLERDOT);
Assert.assertFalse(rules.erase2(noerase1));
Assert.assertFalse(rules.erase2(noerase2));
Assert.assertFalse(rules.erase2(noerase3));
Assert.assertFalse(rules.erase2(noerase4));
}
@Test
public void testErase3() {
TypeFactory tf = new TypeFactory();
IRuleSet rules = new RuleSet(new FiniteClosureBuilder().getFiniteClosure());
/*
* Positive Tests
*/
MPair erase1 = new MPair(tf.getSimpleType("List", "T"), tf.getSimpleType("List", "T"), PairOperator.EQUALSDOT);
MPair erase2 = new MPair(tf.getPlaceholderType("W"), tf.getPlaceholderType("W"), PairOperator.EQUALSDOT);
Assert.assertTrue(rules.erase3(erase1));
Assert.assertTrue(rules.erase3(erase2));
/*
* Negative Tests
*/
MPair noerase1 = new MPair(tf.getSimpleType("Collection"), tf.getSimpleType("List", "T"), PairOperator.EQUALSDOT);
MPair noerase2 = new MPair(tf.getSimpleType("List", "T"), tf.getSimpleType("List", "T"), PairOperator.SMALLERDOT);
Assert.assertFalse(rules.erase3(noerase1));
Assert.assertFalse(rules.erase3(noerase2));
}
@Test
public void testSwap() {
TypeFactory tf = new TypeFactory();
IRuleSet rules = new RuleSet(new FiniteClosureBuilder().getFiniteClosure());
/*
* Positive Tests
*/
MPair swap1 = new MPair(tf.getExtendsType(tf.getSimpleType("MyClass")), tf.getPlaceholderType("P"), PairOperator.EQUALSDOT);
MPair swap2 = new MPair(tf.getSimpleType("MyClass"), tf.getPlaceholderType("X"), PairOperator.EQUALSDOT);
MPair expected1 = new MPair(tf.getPlaceholderType("P"), tf.getExtendsType(tf.getSimpleType("MyClass")), PairOperator.EQUALSDOT);
MPair expected2 = new MPair(tf.getPlaceholderType("X"), tf.getSimpleType("MyClass"), PairOperator.EQUALSDOT);
Optional<MPair> opt1 = rules.swap(swap1);
Optional<MPair> opt2 = rules.swap(swap2);
// swap((? extends MyClass =. P)) = (P =. MyClass)
Assert.assertEquals(opt1.get(), expected1);
// swap((MyClass =. X)) = (X =. MyClass)
Assert.assertEquals(opt2.get(), expected2);
/*
* Negative Tests
*/
MPair noswap1 = new MPair(tf.getPlaceholderType("Z"), tf.getPlaceholderType("X"), PairOperator.EQUALSDOT);
MPair noswap2 = new MPair(tf.getSimpleType("MyClass"), tf.getExtendsType(tf.getPlaceholderType("X")), PairOperator.EQUALSDOT);
MPair noswap3 = new MPair( tf.getPlaceholderType("X"), tf.getSimpleType("MyClass"), PairOperator.EQUALSDOT);
MPair noswap4 = new MPair(tf.getSimpleType("MyClass"), tf.getPlaceholderType("X"), PairOperator.SMALLERDOT);
opt1 = rules.swap(noswap1);
opt2 = rules.swap(noswap2);
Optional<MPair> opt3 = rules.swap(noswap3);
Optional<MPair> opt4 = rules.swap(noswap4);
Assert.assertFalse(opt1.isPresent());
Assert.assertFalse(opt2.isPresent());
Assert.assertFalse(opt3.isPresent());
Assert.assertFalse(opt4.isPresent());
}
@Test
public void testAdapt() {
TypeFactory tf = new TypeFactory();
FiniteClosureBuilder fcb = new FiniteClosureBuilder();
SimpleType t1 = tf.getSimpleType("Type1", "T", "U");
SimpleType t2 = tf.getSimpleType("Type2", "T");
SimpleType t3 = tf.getSimpleType("Type3", tf.getPlaceholderType("T"), tf.getSimpleType("Integer"));
fcb.add(t1, t2);
fcb.add(t2, t3);
IRuleSet rules = new RuleSet(fcb.getFiniteClosure());
/*
* Positive Tests
*/
SimpleType c1 = tf.getSimpleType("Type1", "String", "Double");
SimpleType c2 = tf.getSimpleType("Type2", "Object");
SimpleType c3 = tf.getSimpleType("Type3", "Object", "Number");
MPair pair1 = new MPair(c1, c2, PairOperator.SMALLERDOT);
MPair pair2 = new MPair(c2, c3, PairOperator.SMALLERDOT);
MPair pair3 = new MPair(c1, c3, PairOperator.SMALLERDOT);
System.out.println("------ Adapt ------");
System.out.println(rules.adapt(pair1));
System.out.println(rules.adapt(pair2));
System.out.println(rules.adapt(pair3));
/*
* Negative Tests
*/
MPair noAdapt1 = new MPair(c2, c1, PairOperator.SMALLERDOT);
MPair noAdapt2 = new MPair(c1, c1, PairOperator.SMALLERDOT);
MPair noAdapt3 = new MPair(c1, c2, PairOperator.SMALLERDOTWC);
Assert.assertFalse(rules.adapt(noAdapt1).isPresent());
Assert.assertFalse(rules.adapt(noAdapt2).isPresent());
Assert.assertFalse(rules.adapt(noAdapt3).isPresent());
}
@Test
public void testAdaptExt() {
TypeFactory tf = new TypeFactory();
FiniteClosureBuilder fcb = new FiniteClosureBuilder();
SimpleType t1 = tf.getSimpleType("Type1", "T", "U");
SimpleType t2 = tf.getSimpleType("Type2", "T");
SimpleType t3 = tf.getSimpleType("Type3", tf.getPlaceholderType("T"), tf.getSimpleType("Integer"));
SimpleType t32 = tf.getSimpleType("Type3", "T", "U");
SimpleType t4 = tf.getSimpleType("Object");
fcb.add(t1, t2);
fcb.add(t2, t3);
fcb.add(t32, t4);
IRuleSet rules = new RuleSet(fcb.getFiniteClosure());
/*
* Positive Tests
*/
SimpleType c1 = tf.getSimpleType("Type1", "String", "Double");
SimpleType c2 = tf.getSimpleType("Type2", "Object");
SimpleType c3 = tf.getSimpleType("Type3", "Object", "Number");
ExtendsType extc1 = new ExtendsType(c1);
ExtendsType extc2 = new ExtendsType(c2);
ExtendsType extc3 = new ExtendsType(c3);
MPair pair1 = new MPair(c1, extc2, PairOperator.SMALLERDOTWC);
MPair pair2 = new MPair(c2, extc3, PairOperator.SMALLERDOTWC);
MPair pair3 = new MPair(c1, extc3, PairOperator.SMALLERDOTWC);
MPair pair4 = new MPair(extc1, extc2, PairOperator.SMALLERDOTWC);
MPair pair5 = new MPair(extc2, extc3, PairOperator.SMALLERDOTWC);
MPair pair6 = new MPair(extc1, extc3, PairOperator.SMALLERDOTWC);
MPair pair7 = new MPair(extc1, extc1, PairOperator.SMALLERDOTWC);
System.out.println("------ AdaptExt ------");
System.out.println(rules.adaptExt(pair1));
System.out.println(rules.adaptExt(pair2));
System.out.println(rules.adaptExt(pair3));
System.out.println(rules.adaptExt(pair4));
System.out.println(rules.adaptExt(pair5));
System.out.println(rules.adaptExt(pair6));
System.out.println(rules.adaptExt(pair7));
/*
* Negative Tests
*/
MPair noAdapt1 = new MPair(extc2, extc1, PairOperator.SMALLERDOTWC);
MPair noAdapt2 = new MPair(extc1, c2, PairOperator.SMALLERDOTWC);
MPair noAdapt3 = new MPair(tf.getSuperType(c1), extc2, PairOperator.SMALLERDOTWC);
MPair noAdapt4 = new MPair(extc3, extc1, PairOperator.SMALLERDOTWC);
MPair noAdapt5 = new MPair(c1, extc2, PairOperator.SMALLERDOT);
Assert.assertFalse(rules.adaptExt(noAdapt1).isPresent());
Assert.assertFalse(rules.adaptExt(noAdapt2).isPresent());
Assert.assertFalse(rules.adaptExt(noAdapt3).isPresent());
Assert.assertFalse(rules.adaptExt(noAdapt4).isPresent());
Assert.assertFalse(rules.adaptExt(noAdapt5).isPresent());
}
@Test
public void testAdaptSup() {
TypeFactory tf = new TypeFactory();
FiniteClosureBuilder fcb = new FiniteClosureBuilder();
SimpleType t1 = tf.getSimpleType("Type1", "T", "U");
SimpleType t2 = tf.getSimpleType("Type2", "T");
SimpleType t3 = tf.getSimpleType("Type3", tf.getPlaceholderType("T"), tf.getSimpleType("Integer"));
SimpleType t32 = tf.getSimpleType("Type3", "T", "U");
SimpleType t4 = tf.getSimpleType("Object");
fcb.add(t1, t2);
fcb.add(t2, t3);
fcb.add(t32, t4);
IRuleSet rules = new RuleSet(fcb.getFiniteClosure());
/*
* Positive Tests
*/
SimpleType c1 = tf.getSimpleType("Type1", "String", "Double");
SimpleType c2 = tf.getSimpleType("Type2", "Object");
SimpleType c3 = tf.getSimpleType("Type3", "Object", "Number");
SuperType supc1 = new SuperType(c1);
SuperType supc2 = new SuperType(c2);
SuperType supc3 = new SuperType(c3);
MPair pair1 = new MPair(c2, supc1, PairOperator.SMALLERDOTWC);
MPair pair2 = new MPair(c3, supc2, PairOperator.SMALLERDOTWC);
MPair pair3 = new MPair(c3, supc1, PairOperator.SMALLERDOTWC);
MPair pair4 = new MPair(supc2, supc1, PairOperator.SMALLERDOTWC);
MPair pair5 = new MPair(supc3, supc2, PairOperator.SMALLERDOTWC);
MPair pair6 = new MPair(supc3, supc1, PairOperator.SMALLERDOTWC);
MPair pair7 = new MPair(supc1, supc1, PairOperator.SMALLERDOTWC);
System.out.println("------ AdaptSup ------");
System.out.println(rules.adaptSup(pair1));
System.out.println(rules.adaptSup(pair2));
System.out.println(rules.adaptSup(pair3));
System.out.println(rules.adaptSup(pair4));
System.out.println(rules.adaptSup(pair5));
System.out.println(rules.adaptSup(pair6));
System.out.println(rules.adaptSup(pair7));
/*
* Negative Tests
*/
MPair noAdapt1 = new MPair(supc2, supc1, PairOperator.SMALLERDOTWC);
MPair noAdapt2 = new MPair(supc1, c2, PairOperator.SMALLERDOTWC);
MPair noAdapt3 = new MPair(tf.getExtendsType(c1), supc2, PairOperator.SMALLERDOTWC);
MPair noAdapt4 = new MPair(supc3, supc1, PairOperator.SMALLERDOTWC);
MPair noAdapt5 = new MPair(c1, supc2, PairOperator.SMALLERDOT);
Assert.assertFalse(rules.adaptExt(noAdapt1).isPresent());
Assert.assertFalse(rules.adaptExt(noAdapt2).isPresent());
Assert.assertFalse(rules.adaptExt(noAdapt3).isPresent());
Assert.assertFalse(rules.adaptExt(noAdapt4).isPresent());
Assert.assertFalse(rules.adaptExt(noAdapt5).isPresent());
}
}

View File

@ -0,0 +1,37 @@
package unify;
import java.util.Arrays;
import java.util.stream.Collectors;
import de.dhbwstuttgart.typinference.unify.model.ExtendsType;
import de.dhbwstuttgart.typinference.unify.model.PlaceholderType;
import de.dhbwstuttgart.typinference.unify.model.SimpleType;
import de.dhbwstuttgart.typinference.unify.model.SuperType;
import de.dhbwstuttgart.typinference.unify.model.Type;
public class TypeFactory {
public ExtendsType getExtendsType(Type extendedType) {
return new ExtendsType(extendedType);
}
public SuperType getSuperType(Type superedType) {
return new SuperType(superedType);
}
public SimpleType getSimpleType(String name) {
return new SimpleType(name);
}
public SimpleType getSimpleType(String name, Type... typeParams) {
return new SimpleType(name, typeParams);
}
public SimpleType getSimpleType(String name, String... typeParams) {
return new SimpleType(name, Arrays.stream(typeParams).map(x -> getPlaceholderType(x)).collect(Collectors.toList()).toArray(new Type[0]));
}
public PlaceholderType getPlaceholderType(String name) {
return new PlaceholderType(name);
}
}

View File

@ -0,0 +1,303 @@
package unify;
import junit.framework.Assert;
import org.junit.Test;
import de.dhbwstuttgart.syntaxtree.factory.UnifyPairMengenBuilder;
import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory;
import de.dhbwstuttgart.syntaxtree.factory.Unify_FC_TTO_Builder;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.typeinference.Pair;
import de.dhbwstuttgart.typeinference.Pair.PairOperator;
import de.dhbwstuttgart.typeinference.unify.Unify;
public class UnifyOldTest {
@Test
public void unifyTestSimpleTypes() {
// Init Factories and Builders
UnifyTypeFactory typeFactory = new UnifyTypeFactory();
Unify_FC_TTO_Builder fcBuilder = new Unify_FC_TTO_Builder();
UnifyPairMengenBuilder assumptionBuilder = new UnifyPairMengenBuilder();
UnifyPairMengenBuilder resultBuilder = new UnifyPairMengenBuilder();
/*
* Test a <. Boolean
*/
// Init Types
RefType boolT = typeFactory.GetSimpleType("java.lang.Boolean");
TypePlaceholder aTph = typeFactory.GetTypePlaceholder("a");
// Expected Result
resultBuilder.clear();
resultBuilder.addPair(aTph, boolT, PairOperator.Equal);
resultBuilder.addPair(aTph, typeFactory.GetExtendsType(boolT),
PairOperator.Equal);
Menge<Menge<Pair>> expectedResult = resultBuilder.getNestedPairMenge();
// Actual Result
assumptionBuilder.clear();
assumptionBuilder.addPair(aTph, boolT);
Menge<Menge<Pair>> actualResult = Unify.unify(
assumptionBuilder.getPairMenge(), fcBuilder.Get_FC_TTO());
// System.out.println(expectedResult);
// System.out.println(actualResult);
Assert.assertTrue(mengeEquals(expectedResult, actualResult));
/*
* Test b <. a, a <. Boolean
*/
// Init Types
boolT = typeFactory.GetSimpleType("java.lang.Boolean");
aTph = typeFactory.GetTypePlaceholder("a");
TypePlaceholder bTph = typeFactory.GetTypePlaceholder("b");
// Expected Result
resultBuilder.clear();
resultBuilder.addPair(aTph, boolT, PairOperator.Equal);
resultBuilder.addPair(aTph, typeFactory.GetExtendsType(boolT),
PairOperator.Equal);
resultBuilder.addPair(bTph, boolT, PairOperator.Equal);
resultBuilder.addPair(bTph, typeFactory.GetExtendsType(boolT),
PairOperator.Equal);
expectedResult = resultBuilder.getNestedPairMenge();
// Actual Result
assumptionBuilder.clear();
assumptionBuilder.addPair(bTph, aTph);
assumptionBuilder.addPair(aTph, boolT);
actualResult = Unify.unify(assumptionBuilder.getPairMenge(),
fcBuilder.Get_FC_TTO());
// System.out.println(expectedResult);
// System.out.println(actualResult);
// NOTE: Elemente im actualResult sind nicht unique
// Assert.assertTrue(mengeEquals(expectedResult, actualResult));
/*
* Test b <. a, a <. b
*/
aTph = typeFactory.GetTypePlaceholder("a");
bTph = typeFactory.GetTypePlaceholder("b");
// Expected Result
resultBuilder.clear();
resultBuilder.addPair(bTph, aTph);
resultBuilder.addPair(aTph, bTph);
Menge<Pair> buffer = resultBuilder.getPairMenge();
expectedResult = new Menge<Menge<Pair>>();
expectedResult.add(buffer);
// Actual Result
assumptionBuilder.clear();
assumptionBuilder.addPair(bTph, aTph);
assumptionBuilder.addPair(aTph, bTph);
actualResult = Unify.unify(assumptionBuilder.getPairMenge(),
fcBuilder.Get_FC_TTO());
// System.out.println(expectedResult);
// System.out.println(actualResult);
Assert.assertTrue(mengeEquals(expectedResult, actualResult));
/*
* Test Integer <. a, a <. Boolean
*/
RefType intT = typeFactory.GetSimpleType("java.lang.Integer");
boolT = typeFactory.GetSimpleType("java.lang.Boolean");
aTph = typeFactory.GetTypePlaceholder("a");
bTph = typeFactory.GetTypePlaceholder("b");
// Expected Result
resultBuilder.clear();
expectedResult = resultBuilder.getNestedPairMenge();
// Actual Result
assumptionBuilder.clear();
assumptionBuilder.addPair(intT, aTph);
assumptionBuilder.addPair(aTph, boolT);
actualResult = Unify.unify(assumptionBuilder.getPairMenge(),
fcBuilder.Get_FC_TTO());
// System.out.println(expectedResult);
// System.out.println(actualResult);
Assert.assertTrue(mengeEquals(expectedResult, actualResult));
}
@Test
public void unifyTestGenerics() {
// Init Factories and Builders
UnifyTypeFactory typeFactory = new UnifyTypeFactory();
Unify_FC_TTO_Builder fcBuilder = new Unify_FC_TTO_Builder();
UnifyPairMengenBuilder assumptionBuilder = new UnifyPairMengenBuilder();
UnifyPairMengenBuilder resultBuilder = new UnifyPairMengenBuilder();
/*
* Test a <. MyClass<T, F>
*/
TypePlaceholder aTph = typeFactory.GetTypePlaceholder("a");
RefType myType = typeFactory.GetSimpleType("MyClass",
typeFactory.GetTypePlaceholder("T"),
typeFactory.GetTypePlaceholder("F"));
// Expected Result
resultBuilder.clear();
resultBuilder.addPair(aTph, myType, PairOperator.Equal);
resultBuilder.addPair(aTph, typeFactory.GetExtendsType(myType));
Menge<Menge<Pair>> expectedResult = resultBuilder.getNestedPairMenge();
// Actual Result
assumptionBuilder.clear();
assumptionBuilder.addPair(aTph, myType);
Menge<Menge<Pair>> actualResult = Unify.unify(
assumptionBuilder.getPairMenge(), fcBuilder.Get_FC_TTO());
// System.out.println(expectedResult);
// System.out.println(actualResult);
Assert.assertTrue(mengeEquals(expectedResult, actualResult));
/*
* Test List<List<T>> <. List<T>
*/
TypePlaceholder tTph = typeFactory.GetTypePlaceholder("T");
RefType list = typeFactory.GetSimpleType("List", tTph);
RefType listlist = typeFactory.GetSimpleType("List", list);
// Expected Result
resultBuilder.clear();
resultBuilder.addPair(typeFactory.GetExtendsType(list), tTph,
PairOperator.Equal);
expectedResult = resultBuilder.getNestedPairMenge();
// Actual Result
assumptionBuilder.clear();
assumptionBuilder.addPair(listlist, list);
actualResult = Unify.unify(assumptionBuilder.getPairMenge(),
fcBuilder.Get_FC_TTO());
System.out.println(expectedResult);
System.out.println(actualResult);
Assert.assertTrue(mengeEquals(expectedResult, actualResult));
/*
* Test List<T> <. List<List<T>>
*/
}
@Test
public void unifyTestInheritance() {
// Init Factories and Builders
UnifyTypeFactory typeFactory = new UnifyTypeFactory();
Unify_FC_TTO_Builder fcBuilder = new Unify_FC_TTO_Builder();
UnifyPairMengenBuilder assumptionBuilder = new UnifyPairMengenBuilder();
UnifyPairMengenBuilder resultBuilder = new UnifyPairMengenBuilder();
// Init Types
RefType tBool = typeFactory.GetSimpleType("java.lang.Boolean");
RefType tString = typeFactory.GetSimpleType("java.lang.String");
RefType tInt = typeFactory.GetSimpleType("java.lang.Integer");
TypePlaceholder tphA = typeFactory.GetTypePlaceholder("a");
// Build inheritance hierachy
// Bool <. String <. Int
fcBuilder.AddInheritance(tBool, tString);
fcBuilder.AddInheritance(tString, tInt);
// Build Assumptions
assumptionBuilder.addPair(tphA, tString);
// Build expected result
resultBuilder.addPair(tphA, tBool, PairOperator.Equal);
resultBuilder.addPair(tphA, typeFactory.GetExtendsType(tBool),
PairOperator.Equal);
resultBuilder.addPair(tphA, tString, PairOperator.Equal);
resultBuilder.addPair(tphA, typeFactory.GetExtendsType(tString),
PairOperator.Equal);
// Assert
Menge<Menge<Pair>> actualResult = Unify.unify(
assumptionBuilder.getPairMenge(), fcBuilder.Get_FC_TTO());
// System.out.println(actualResult);
// System.out.println("-------------------");
// System.out.println(resultBuilder.getNestedPairMenge());
Assert.assertTrue(mengeEquals(resultBuilder.getNestedPairMenge(),
actualResult));
}
@Test
public void unifyTestWildcards() {
}
private static boolean mengeEquals(Menge<Menge<Pair>> m1,
Menge<Menge<Pair>> m2) {
if (m1.size() != m2.size())
return false;
return containsAll(m1, m2) && containsAll(m2, m1);
}
private static boolean containsAll(Menge<Menge<Pair>> m1,
Menge<Menge<Pair>> m2) {
for (Menge<Pair> elem : m2)
if (!contains(m1, elem))
return false;
return true;
}
private static boolean contains(Menge<Menge<Pair>> m1, Menge<Pair> m2) {
for (Menge<Pair> elem : m1)
if (mengePairEquals(elem, m2))
return true;
return false;
}
private static boolean mengePairEquals(Menge<Pair> m1, Menge<Pair> m2) {
if (m1.size() != m2.size())
return false;
return containsAllPair(m1, m2) && containsAllPair(m2, m1);
}
private static boolean containsAllPair(Menge<Pair> m1, Menge<Pair> m2) {
for (Pair elem : m1)
if (contains(m2, elem))
return true;
return false;
}
private static boolean contains(Menge<Pair> m, Pair p) {
for (Pair elem : m)
if (pairEquals(elem, p))
return true;
return false;
}
private static boolean pairEquals(Pair p1, Pair p2) {
return (p1.TA1.equals(p2.TA1) && p1.TA2.equals(p2.TA2))
|| (p1.TA1.equals(p2.TA2) && p1.TA2.equals(p2.TA1));
}
}

View File

@ -1,304 +1,51 @@
package unify;
import junit.framework.Assert;
import java.util.HashSet;
import java.util.Set;
import org.junit.Test;
import de.dhbwstuttgart.syntaxtree.factory.UnifyPairMengenBuilder;
import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory;
import de.dhbwstuttgart.syntaxtree.factory.Unify_FC_TTO_Builder;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.typeinference.Pair;
import de.dhbwstuttgart.typeinference.Pair.PairOperator;
import de.dhbwstuttgart.typeinference.unify.Unify;
public class UnifyTest {
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unifynew.Unify;
import de.dhbwstuttgart.typinference.unify.model.MPair;
import de.dhbwstuttgart.typinference.unify.model.MPair.PairOperator;
public class UnifyTest extends Unify {
@Test
public void unifyTest() {
TypeFactory tf = new TypeFactory();
FiniteClosureBuilder fcb = new FiniteClosureBuilder();
Set<MPair> eq = new HashSet<MPair>();
fcb.add(tf.getSimpleType("Number"), tf.getSimpleType("Object"));
fcb.add(tf.getSimpleType("Integer"), tf.getSimpleType("Number"));
fcb.add(tf.getSimpleType("Double"), tf.getSimpleType("Number"));
IFiniteClosure fc = fcb.getCollectionExample();
// Vector<Integer> <. Vector<A>
// A <. Number
// Double <. B
// B <. Object
eq.add(new MPair(tf.getSimpleType("Vector", tf.getSimpleType("Integer")), tf.getSimpleType("Vector", "A"), PairOperator.SMALLERDOT));
eq.add(new MPair(tf.getPlaceholderType("A"), tf.getSimpleType("Number"), PairOperator.SMALLERDOT));
eq.add(new MPair(tf.getPlaceholderType("A"), tf.getPlaceholderType("C"), PairOperator.SMALLERDOT));
eq.add(new MPair(tf.getSimpleType("Double"), tf.getPlaceholderType("B"), PairOperator.SMALLERDOT));
eq.add(new MPair(tf.getPlaceholderType("B"), tf.getSimpleType("Object"), PairOperator.EQUALSDOT));
this.unify(eq, fc);
}
@Test
public void unifyTestSimpleTypes() {
// Init Factories and Builders
UnifyTypeFactory typeFactory = new UnifyTypeFactory();
Unify_FC_TTO_Builder fcBuilder = new Unify_FC_TTO_Builder();
UnifyPairMengenBuilder assumptionBuilder = new UnifyPairMengenBuilder();
UnifyPairMengenBuilder resultBuilder = new UnifyPairMengenBuilder();
/*
* Test a <. Boolean
*/
// Init Types
RefType boolT = typeFactory.GetSimpleType("java.lang.Boolean");
TypePlaceholder aTph = typeFactory.GetTypePlaceholder("a");
// Expected Result
resultBuilder.clear();
resultBuilder.addPair(aTph, boolT, PairOperator.Equal);
resultBuilder.addPair(aTph, typeFactory.GetExtendsType(boolT),
PairOperator.Equal);
Menge<Menge<Pair>> expectedResult = resultBuilder.getNestedPairMenge();
// Actual Result
assumptionBuilder.clear();
assumptionBuilder.addPair(aTph, boolT);
Menge<Menge<Pair>> actualResult = Unify.unify(
assumptionBuilder.getPairMenge(), fcBuilder.Get_FC_TTO());
// System.out.println(expectedResult);
// System.out.println(actualResult);
Assert.assertTrue(mengeEquals(expectedResult, actualResult));
/*
* Test b <. a, a <. Boolean
*/
// Init Types
boolT = typeFactory.GetSimpleType("java.lang.Boolean");
aTph = typeFactory.GetTypePlaceholder("a");
TypePlaceholder bTph = typeFactory.GetTypePlaceholder("b");
// Expected Result
resultBuilder.clear();
resultBuilder.addPair(aTph, boolT, PairOperator.Equal);
resultBuilder.addPair(aTph, typeFactory.GetExtendsType(boolT),
PairOperator.Equal);
resultBuilder.addPair(bTph, boolT, PairOperator.Equal);
resultBuilder.addPair(bTph, typeFactory.GetExtendsType(boolT),
PairOperator.Equal);
expectedResult = resultBuilder.getNestedPairMenge();
// Actual Result
assumptionBuilder.clear();
assumptionBuilder.addPair(bTph, aTph);
assumptionBuilder.addPair(aTph, boolT);
actualResult = Unify.unify(assumptionBuilder.getPairMenge(),
fcBuilder.Get_FC_TTO());
// System.out.println(expectedResult);
// System.out.println(actualResult);
// NOTE: Elemente im actualResult sind nicht unique
// Assert.assertTrue(mengeEquals(expectedResult, actualResult));
/*
* Test b <. a, a <. b
*/
aTph = typeFactory.GetTypePlaceholder("a");
bTph = typeFactory.GetTypePlaceholder("b");
// Expected Result
resultBuilder.clear();
resultBuilder.addPair(bTph, aTph);
resultBuilder.addPair(aTph, bTph);
Menge<Pair> buffer = resultBuilder.getPairMenge();
expectedResult = new Menge<Menge<Pair>>();
expectedResult.add(buffer);
// Actual Result
assumptionBuilder.clear();
assumptionBuilder.addPair(bTph, aTph);
assumptionBuilder.addPair(aTph, bTph);
actualResult = Unify.unify(assumptionBuilder.getPairMenge(),
fcBuilder.Get_FC_TTO());
// System.out.println(expectedResult);
// System.out.println(actualResult);
Assert.assertTrue(mengeEquals(expectedResult, actualResult));
/*
* Test Integer <. a, a <. Boolean
*/
RefType intT = typeFactory.GetSimpleType("java.lang.Integer");
boolT = typeFactory.GetSimpleType("java.lang.Boolean");
aTph = typeFactory.GetTypePlaceholder("a");
bTph = typeFactory.GetTypePlaceholder("b");
// Expected Result
resultBuilder.clear();
expectedResult = resultBuilder.getNestedPairMenge();
// Actual Result
assumptionBuilder.clear();
assumptionBuilder.addPair(intT, aTph);
assumptionBuilder.addPair(aTph, boolT);
actualResult = Unify.unify(assumptionBuilder.getPairMenge(),
fcBuilder.Get_FC_TTO());
// System.out.println(expectedResult);
// System.out.println(actualResult);
Assert.assertTrue(mengeEquals(expectedResult, actualResult));
public void applyTypeUnificationRulesTest() {
}
@Test
public void unifyTestGenerics() {
// Init Factories and Builders
UnifyTypeFactory typeFactory = new UnifyTypeFactory();
Unify_FC_TTO_Builder fcBuilder = new Unify_FC_TTO_Builder();
UnifyPairMengenBuilder assumptionBuilder = new UnifyPairMengenBuilder();
UnifyPairMengenBuilder resultBuilder = new UnifyPairMengenBuilder();
/*
* Test a <. MyClass<T, F>
*/
TypePlaceholder aTph = typeFactory.GetTypePlaceholder("a");
RefType myType = typeFactory.GetSimpleType("MyClass",
typeFactory.GetTypePlaceholder("T"),
typeFactory.GetTypePlaceholder("F"));
// Expected Result
resultBuilder.clear();
resultBuilder.addPair(aTph, myType, PairOperator.Equal);
resultBuilder.addPair(aTph, typeFactory.GetExtendsType(myType));
Menge<Menge<Pair>> expectedResult = resultBuilder.getNestedPairMenge();
// Actual Result
assumptionBuilder.clear();
assumptionBuilder.addPair(aTph, myType);
Menge<Menge<Pair>> actualResult = Unify.unify(
assumptionBuilder.getPairMenge(), fcBuilder.Get_FC_TTO());
// System.out.println(expectedResult);
// System.out.println(actualResult);
Assert.assertTrue(mengeEquals(expectedResult, actualResult));
/*
* Test List<List<T>> <. List<T>
*/
TypePlaceholder tTph = typeFactory.GetTypePlaceholder("T");
RefType list = typeFactory.GetSimpleType("List", tTph);
RefType listlist = typeFactory.GetSimpleType("List", list);
// Expected Result
resultBuilder.clear();
resultBuilder.addPair(typeFactory.GetExtendsType(list), tTph,
PairOperator.Equal);
expectedResult = resultBuilder.getNestedPairMenge();
// Actual Result
assumptionBuilder.clear();
assumptionBuilder.addPair(listlist, list);
actualResult = Unify.unify(assumptionBuilder.getPairMenge(),
fcBuilder.Get_FC_TTO());
System.out.println(expectedResult);
System.out.println(actualResult);
Assert.assertTrue(mengeEquals(expectedResult, actualResult));
/*
* Test List<T> <. List<List<T>>
*/
public void calculatePairSetsTest() {
}
@Test
public void unifyTestInheritance() {
// Init Factories and Builders
UnifyTypeFactory typeFactory = new UnifyTypeFactory();
Unify_FC_TTO_Builder fcBuilder = new Unify_FC_TTO_Builder();
UnifyPairMengenBuilder assumptionBuilder = new UnifyPairMengenBuilder();
UnifyPairMengenBuilder resultBuilder = new UnifyPairMengenBuilder();
// Init Types
RefType tBool = typeFactory.GetSimpleType("java.lang.Boolean");
RefType tString = typeFactory.GetSimpleType("java.lang.String");
RefType tInt = typeFactory.GetSimpleType("java.lang.Integer");
TypePlaceholder tphA = typeFactory.GetTypePlaceholder("a");
// Build inheritance hierachy
// Bool <. String <. Int
fcBuilder.AddInheritance(tBool, tString);
fcBuilder.AddInheritance(tString, tInt);
// Build Assumptions
assumptionBuilder.addPair(tphA, tString);
// Build expected result
resultBuilder.addPair(tphA, tBool, PairOperator.Equal);
resultBuilder.addPair(tphA, typeFactory.GetExtendsType(tBool),
PairOperator.Equal);
resultBuilder.addPair(tphA, tString, PairOperator.Equal);
resultBuilder.addPair(tphA, typeFactory.GetExtendsType(tString),
PairOperator.Equal);
// Assert
Menge<Menge<Pair>> actualResult = Unify.unify(
assumptionBuilder.getPairMenge(), fcBuilder.Get_FC_TTO());
// System.out.println(actualResult);
// System.out.println("-------------------");
// System.out.println(resultBuilder.getNestedPairMenge());
Assert.assertTrue(mengeEquals(resultBuilder.getNestedPairMenge(),
actualResult));
}
@Test
public void unifyTestWildcards() {
}
private static boolean mengeEquals(Menge<Menge<Pair>> m1,
Menge<Menge<Pair>> m2) {
if (m1.size() != m2.size())
return false;
return containsAll(m1, m2) && containsAll(m2, m1);
}
private static boolean containsAll(Menge<Menge<Pair>> m1,
Menge<Menge<Pair>> m2) {
for (Menge<Pair> elem : m2)
if (!contains(m1, elem))
return false;
return true;
}
private static boolean contains(Menge<Menge<Pair>> m1, Menge<Pair> m2) {
for (Menge<Pair> elem : m1)
if (mengePairEquals(elem, m2))
return true;
return false;
}
private static boolean mengePairEquals(Menge<Pair> m1, Menge<Pair> m2) {
if (m1.size() != m2.size())
return false;
return containsAllPair(m1, m2) && containsAllPair(m2, m1);
}
private static boolean containsAllPair(Menge<Pair> m1, Menge<Pair> m2) {
for (Pair elem : m1)
if (contains(m2, elem))
return true;
return false;
}
private static boolean contains(Menge<Pair> m, Pair p) {
for (Pair elem : m)
if (pairEquals(elem, p))
return true;
return false;
}
private static boolean pairEquals(Pair p1, Pair p2) {
return (p1.TA1.equals(p2.TA1) && p1.TA2.equals(p2.TA2))
|| (p1.TA1.equals(p2.TA2) && p1.TA2.equals(p2.TA1));
}
}