forked from JavaTX/JavaCompilerCore
Merge mit Unify und Bytecode
This commit is contained in:
commit
ac42bdf0a2
@ -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
|
||||
|
||||
|
@ -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 {
|
||||
|
||||
|
@ -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 f�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 )
|
||||
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package de.dhbwstuttgart.typeinference.unify.interfaces;
|
||||
|
||||
import de.dhbwstuttgart.typeinference.Menge;
|
||||
|
||||
public interface ITypeMapper<T> {
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
69
src/de/dhbwstuttgart/typeinference/unifynew/Mapping.java
Normal file
69
src/de/dhbwstuttgart/typeinference/unifynew/Mapping.java
Normal 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())
|
||||
}
|
||||
|
||||
}
|
524
src/de/dhbwstuttgart/typeinference/unifynew/RuleSet.java
Normal file
524
src/de/dhbwstuttgart/typeinference/unifynew/RuleSet.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
29
src/de/dhbwstuttgart/typeinference/unifynew/Unifier.java
Normal file
29
src/de/dhbwstuttgart/typeinference/unifynew/Unifier.java
Normal 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;
|
||||
}
|
||||
}
|
257
src/de/dhbwstuttgart/typeinference/unifynew/Unify.java
Normal file
257
src/de/dhbwstuttgart/typeinference/unifynew/Unify.java
Normal 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());
|
||||
}
|
||||
}
|
@ -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));
|
||||
}
|
||||
}
|
208
src/de/dhbwstuttgart/typinference/unify/model/FiniteClosure.java
Normal file
208
src/de/dhbwstuttgart/typinference/unify/model/FiniteClosure.java
Normal 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();
|
||||
}
|
||||
}
|
97
src/de/dhbwstuttgart/typinference/unify/model/MPair.java
Normal file
97
src/de/dhbwstuttgart/typinference/unify/model/MPair.java
Normal 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 + ")";
|
||||
}
|
||||
}
|
||||
|
||||
|
57
src/de/dhbwstuttgart/typinference/unify/model/Node.java
Normal file
57
src/de/dhbwstuttgart/typinference/unify/model/Node.java
Normal 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() + ")";
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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));
|
||||
}
|
||||
}
|
59
src/de/dhbwstuttgart/typinference/unify/model/SuperType.java
Normal file
59
src/de/dhbwstuttgart/typinference/unify/model/SuperType.java
Normal 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));
|
||||
}
|
||||
}
|
48
src/de/dhbwstuttgart/typinference/unify/model/Type.java
Normal file
48
src/de/dhbwstuttgart/typinference/unify/model/Type.java
Normal 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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
64
test/unify/FiniteClosureBuilder.java
Normal file
64
test/unify/FiniteClosureBuilder.java
Normal 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;
|
||||
}
|
||||
}
|
57
test/unify/FiniteClosureTest.java
Normal file
57
test/unify/FiniteClosureTest.java
Normal 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
686
test/unify/RuleSetTest.java
Normal 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());
|
||||
}
|
||||
}
|
37
test/unify/TypeFactory.java
Normal file
37
test/unify/TypeFactory.java
Normal 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);
|
||||
}
|
||||
}
|
303
test/unify/UnifyOldTest.java
Normal file
303
test/unify/UnifyOldTest.java
Normal 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));
|
||||
}
|
||||
|
||||
}
|
@ -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));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user