Merge branch 'unify' into refactoring

This commit is contained in:
JanUlrich 2016-04-11 18:35:50 +02:00
commit 6cc0d462ab
24 changed files with 820 additions and 677 deletions

View File

@ -7,10 +7,16 @@ import com.google.common.collect.Sets;
import de.dhbwstuttgart.typeinference.unify.interfaces.ISetOperations;
/**
* Implements set operations using google guava.
* @author DH10STF
*
*/
public class GuavaSetOperations implements ISetOperations {
@Override
public <B> Set<List<B>> cartesianProduct(List<? extends Set<? extends B>> sets) {
// Wraps the call to google guava
return Sets.cartesianProduct(sets);
}

View File

@ -1,21 +1,19 @@
package de.dhbwstuttgart.typeinference.unify;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import de.dhbwstuttgart.typeinference.unify.interfaces.IUnify;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
import de.dhbwstuttgart.typeinference.unify.model.PairOperator;
import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType;
import de.dhbwstuttgart.typeinference.unify.model.UnifyType;
import de.dhbwstuttgart.typeinference.unify.model.TypeParams;
import de.dhbwstuttgart.typeinference.unify.model.Unifier;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
import de.dhbwstuttgart.typeinference.unify.model.UnifyType;
/**
* Implementation of the Martelli-Montanari unification algorithm.
@ -25,60 +23,77 @@ public class MartelliMontanariUnify implements IUnify {
@Override
public Optional<Unifier> unify(Set<UnifyType> terms) {
// Sets with less than 2 terms are trivially unified
if(terms.size() < 2)
return Optional.of(Unifier.Identity());
ArrayList<UnifyPair> termsQ = new ArrayList<UnifyPair>();
// For the the set of terms {t1,...,tn},
// build a list of equations {(t1 = t2), (t2 = t3), (t3 = t4), ....}
ArrayList<UnifyPair> termsList = new ArrayList<UnifyPair>();
Iterator<UnifyType> iter = terms.iterator();
UnifyType prev = iter.next();
while(iter.hasNext()) {
UnifyType next = iter.next();
termsQ.add(new UnifyPair(prev, next, PairOperator.EQUALSDOT));
termsList.add(new UnifyPair(prev, next, PairOperator.EQUALSDOT));
prev = next;
}
// Start with the identity unifier. Substitutions will be added later.
Unifier mgu = Unifier.Identity();
// Apply rules while possible
int idx = 0;
while(idx < termsQ.size()) {
UnifyPair pair = termsQ.get(idx);
while(idx < termsList.size()) {
UnifyPair pair = termsList.get(idx);
UnifyType rhsType = pair.getRhsType();
UnifyType lhsType = pair.getLhsType();
TypeParams rhsTypeParams = rhsType.getTypeParams();
TypeParams lhsTypeParams = lhsType.getTypeParams();
if(delete(pair)) {
termsQ.remove(idx);
// DELETE - Rule
if(pair.getRhsType().equals(pair.getLhsType())) {
termsList.remove(idx);
continue;
}
// REDUCE - Rule
if(!(rhsType instanceof PlaceholderType) && !(lhsType instanceof PlaceholderType)
&& (rhsTypeParams.size() != 0 || lhsTypeParams.size() != 0)) {
Set<UnifyPair> result = new HashSet<>();
// f<...> = g<...> with f != g are not unifiable
if(!rhsType.getName().equals(lhsType.getName()))
return Optional.empty(); // conflict
// f<t1,...,tn> = f<s1,...,sm> are not unifiable
if(rhsTypeParams.size() != lhsTypeParams.size())
return Optional.empty(); // conflict
// Unpack the arguments
for(int i = 0; i < rhsTypeParams.size(); i++)
result.add(new UnifyPair(rhsTypeParams.get(i), lhsTypeParams.get(i), PairOperator.EQUALSDOT));
termsList.remove(idx);
termsList.addAll(result);
continue;
}
// SWAP - Rule
if(!(lhsType instanceof PlaceholderType) && (rhsType instanceof PlaceholderType)) {
termsList.remove(idx);
termsList.add(new UnifyPair(rhsType, lhsType, PairOperator.EQUALSDOT));
continue;
}
Optional<Set<UnifyPair>> optSet = decompose(pair);
if(optSet == null)
return Optional.empty(); // Unification failed
if(optSet.isPresent()) {
termsQ.addAll(optSet.get());
idx = idx+1 == termsQ.size() ? 0 : idx+1;
continue;
}
Optional<UnifyPair> optPair = swap(pair);
if(optPair.isPresent()) {
termsQ.add(optPair.get());
idx = idx+1 == termsQ.size() ? 0 : idx+1;
continue;
}
// Occurs-Check
// OCCURS-CHECK
if(pair.getLhsType() instanceof PlaceholderType
&& pair.getRhsType().getTypeParams().occurs((PlaceholderType) pair.getLhsType()))
return Optional.empty();
Optional<Entry<PlaceholderType, UnifyType>> optUni = eliminate(pair);
if(optUni.isPresent()) {
Entry<PlaceholderType, UnifyType> substitution = optUni.get();
mgu.Add(substitution.getKey(), substitution.getValue());
termsQ = termsQ.stream().map(mgu::apply).collect(Collectors.toCollection(ArrayList::new));
idx = idx+1 == termsQ.size() ? 0 : idx+1;
// SUBST - Rule
if(lhsType instanceof PlaceholderType) {
mgu.Add((PlaceholderType) lhsType, rhsType);
termsList = termsList.stream().map(mgu::apply).collect(Collectors.toCollection(ArrayList::new));
idx = idx+1 == termsList.size() ? 0 : idx+1;
continue;
}
@ -87,55 +102,4 @@ public class MartelliMontanariUnify implements IUnify {
return Optional.of(mgu);
}
private boolean delete(UnifyPair pair) {
return pair.getRhsType().equals(pair.getLhsType());
}
private Optional<Set<UnifyPair>> decompose(UnifyPair pair) {
Set<UnifyPair> result = new HashSet<>();
UnifyType rhs = pair.getRhsType();
UnifyType lhs = pair.getLhsType();
TypeParams rhsTypeParams = rhs.getTypeParams();
TypeParams lhsTypeParams = lhs.getTypeParams();
if(!(rhs instanceof PlaceholderType) && !(lhs instanceof PlaceholderType)) {
if(!rhs.getName().equals(lhs.getName()))
return null; // conflict
if(rhsTypeParams.size() != lhsTypeParams.size())
return null; // conflict;
}
if(rhsTypeParams.size() == 0 || lhsTypeParams.size() == 0)
return Optional.empty();
for(int i = 0; i < rhsTypeParams.size(); i++)
result.add(new UnifyPair(rhsTypeParams.get(i), lhsTypeParams.get(i), PairOperator.EQUALSDOT));
return Optional.of(result);
}
private Optional<UnifyPair> swap(UnifyPair pair) {
UnifyType rhs = pair.getRhsType();
UnifyType lhs = pair.getLhsType();
if(!(lhs instanceof PlaceholderType) && (rhs instanceof PlaceholderType))
return Optional.of(new UnifyPair(rhs, lhs, PairOperator.EQUALSDOT));
return Optional.empty();
}
private Optional<Entry<PlaceholderType, UnifyType>> eliminate(UnifyPair pair) {
UnifyType rhs = pair.getRhsType();
UnifyType lhs = pair.getLhsType();
// TODO only apply when lhs is element of vars(termsQ)?
if(!(lhs instanceof PlaceholderType))
return Optional.empty();
return Optional.of(new AbstractMap.SimpleImmutableEntry<PlaceholderType, UnifyType>((PlaceholderType) lhs, rhs));
}
}

View File

@ -25,16 +25,26 @@ import de.dhbwstuttgart.typeinference.unify.model.TypeParams;
import de.dhbwstuttgart.typeinference.unify.model.Unifier;
import de.dhbwstuttgart.typeinference.unify.model.PairOperator;
/**
* Implementation of the type inference rules.
* @author Florian Steurer
*
*/
public class RuleSet implements IRuleSet{
protected IFiniteClosure finiteClosure;
/**
* Creates a new instance that uses the specified FC for greater, grArg, etc.
* @param fc The FC that is used for greater, grArg, etc.
*/
public RuleSet(IFiniteClosure fc) {
finiteClosure = fc;
}
@Override
public Optional<UnifyPair> reduceUp(UnifyPair pair) {
// Check if reduce up is applicable
if(pair.getPairOp() != PairOperator.SMALLERDOT)
return Optional.empty();
@ -46,11 +56,13 @@ public class RuleSet implements IRuleSet{
if(!(lhsType instanceof ReferenceType) && !(lhsType instanceof PlaceholderType))
return Optional.empty();
// Rule is applicable, unpack the SuperType
return Optional.of(new UnifyPair(lhsType, ((SuperType) rhsType).getSuperedType(), PairOperator.SMALLERDOT));
}
@Override
public Optional<UnifyPair> reduceLow(UnifyPair pair) {
// Check if rule is applicable
if(pair.getPairOp() != PairOperator.SMALLERDOT)
return Optional.empty();
@ -62,11 +74,13 @@ public class RuleSet implements IRuleSet{
if(!(rhsType instanceof ReferenceType) && !(rhsType instanceof PlaceholderType))
return Optional.empty();
// Rule is applicable, unpack the ExtendsType
return Optional.of(new UnifyPair(((ExtendsType) lhsType).getExtendedType(), rhsType, PairOperator.SMALLERDOT));
}
@Override
public Optional<UnifyPair> reduceUpLow(UnifyPair pair) {
// Check if rule is applicable
if(pair.getPairOp() != PairOperator.SMALLERDOT)
return Optional.empty();
@ -78,6 +92,7 @@ public class RuleSet implements IRuleSet{
if(!(rhsType instanceof SuperType))
return Optional.empty();
// Rule is applicable, unpack both sides
return Optional.of(new UnifyPair(((ExtendsType) lhsType).getExtendedType(),((SuperType) rhsType).getSuperedType(), PairOperator.SMALLERDOT));
}
@ -104,7 +119,7 @@ public class RuleSet implements IRuleSet{
if(x.getTypeParams().empty() || extY.getTypeParams().size() != x.getTypeParams().size())
return Optional.empty();
UnifyType xFromFc = finiteClosure.getLeftHandedType(sTypeX).orElse(null);
UnifyType xFromFc = finiteClosure.getLeftHandedType(sTypeX.getName()).orElse(null);
if(xFromFc == null || !xFromFc.getTypeParams().arePlaceholders())
return Optional.empty();
@ -156,7 +171,7 @@ public class RuleSet implements IRuleSet{
if(x.getTypeParams().empty() || supY.getTypeParams().size() != x.getTypeParams().size())
return Optional.empty();
UnifyType xFromFc = finiteClosure.getLeftHandedType(sTypeX).orElse(null);
UnifyType xFromFc = finiteClosure.getLeftHandedType(sTypeX.getName()).orElse(null);
if(xFromFc == null || !xFromFc.getTypeParams().arePlaceholders())
return Optional.empty();
@ -234,7 +249,7 @@ public class RuleSet implements IRuleSet{
if(lhsSType.getTypeParams().empty() || lhsSType.getTypeParams().size() != rhsSType.getTypeParams().size())
return Optional.empty();
UnifyType cFromFc = finiteClosure.getLeftHandedType(c).orElse(null);
UnifyType cFromFc = finiteClosure.getLeftHandedType(c.getName()).orElse(null);
if(cFromFc == null || !cFromFc.getTypeParams().arePlaceholders())
return Optional.empty();
@ -383,7 +398,7 @@ public class RuleSet implements IRuleSet{
return Optional.empty();
Optional<UnifyType> opt = finiteClosure.getLeftHandedType(typeD);
Optional<UnifyType> opt = finiteClosure.getLeftHandedType(typeD.getName());
if(!opt.isPresent())
return Optional.empty();
@ -427,9 +442,9 @@ public class RuleSet implements IRuleSet{
UnifyType typeDgen;
if(typeD instanceof ReferenceType)
typeDgen = finiteClosure.getLeftHandedType(typeD).orElse(null);
typeDgen = finiteClosure.getLeftHandedType(typeD.getName()).orElse(null);
else {
Optional<UnifyType> opt = finiteClosure.getLeftHandedType(((ExtendsType) typeD).getExtendedType());
Optional<UnifyType> opt = finiteClosure.getLeftHandedType(((ExtendsType) typeD).getExtendedType().getName());
typeDgen = opt.isPresent() ? new ExtendsType(opt.get()) : null;
}
@ -472,7 +487,7 @@ public class RuleSet implements IRuleSet{
return Optional.empty();
Optional<UnifyType> opt = finiteClosure.getLeftHandedType(((SuperType) typeSupD).getSuperedType());
Optional<UnifyType> opt = finiteClosure.getLeftHandedType(((SuperType) typeSupD).getSuperedType().getName());
if(!opt.isPresent())
return Optional.empty();

View File

@ -32,6 +32,8 @@ import de.dhbwstuttgart.typeinference.unify.model.Unifier;
*/
public class Unify {
protected ISetOperations setOps = new GuavaSetOperations();
public Set<Set<UnifyPair>> unify(Set<UnifyPair> eq, IFiniteClosure fc) {
/*
* Step 1: Repeated application of reduce, adapt, erase, swap
@ -89,8 +91,6 @@ public class Unify {
/* Up to here, no cartesian products are calculated.
* filters for pairs and sets can be applied here */
ISetOperations setOps = new GuavaSetOperations();
// Sub cartesian products of the second level (pattern matched) sets
for(Set<Set<Set<UnifyPair>>> secondLevelSet : secondLevelSets) {
List<Set<Set<UnifyPair>>> secondLevelSetList = new ArrayList<>(secondLevelSet);
@ -119,22 +119,26 @@ public class Unify {
}
IRuleSet rules = new RuleSet(fc);
Set<Set<UnifyPair>> changed = new HashSet<>();
Set<Set<UnifyPair>> restartSet = new HashSet<>();
Set<Set<UnifyPair>> eqPrimePrimeSet = new HashSet<>();
for(Set<UnifyPair> eqPrime : eqPrimeSetFlat) {
Optional<Set<UnifyPair>> eqPrimePrime = rules.subst(eqPrime);
if(eqPrime.equals(eq))
/*if (eqPrime.equals(eq))
eqPrimePrimeSet.add(eqPrime);
else if(eqPrimePrime.isPresent())
eqPrimePrimeSet.addAll(this.unify(eqPrimePrime.get(), fc));
else if(eqPrimePrime.isPresent()) {
Set<Set<UnifyPair>> subUnifyResult = unify(eqPrimePrime.get(), fc);
eqPrimePrimeSet.addAll(subUnifyResult);
}
else
eqPrimePrimeSet.addAll(this.unify(eqPrime, fc));
/*if(eqPrimePrime.isPresent())
changed.add(eqPrimePrime.get());
eqPrimePrimeSet.addAll(this.unify(eqPrime, fc));*/
if(eqPrimePrime.isPresent())
restartSet.add(eqPrimePrime.get());
else if(!isSolvedForm(eqPrime))
restartSet.add(eqPrime);
else
eqPrimePrimeSet.add(eqPrime);*/
eqPrimePrimeSet.add(eqPrime);
}
/*
@ -142,7 +146,7 @@ public class Unify {
* b) Build the union over everything
*/
for(Set<UnifyPair> eqss : changed)
for(Set<UnifyPair> eqss : restartSet)
eqPrimePrimeSet.addAll(this.unify(eqss, fc));
/*
@ -326,12 +330,11 @@ public class Unify {
IUnify unify = new MartelliMontanariUnify();
Set<UnifyType> cs = fc.getAllTypesByName(thetaPrime.getName());
cs.add(thetaPrime);
for(UnifyType c : cs) {
// Wenn die fc nach spezifikation funktioniert ist das hier nicht mehr nötig?
Set<UnifyType> thetaQs = fc.getChildren(c).stream().filter(x -> x.getTypeParams().arePlaceholders()).collect(Collectors.toCollection(HashSet::new));
thetaQs.add(c); // reflexive
for(UnifyType c : cs) {
Set<UnifyType> thetaQs = fc.getChildren(c).stream().collect(Collectors.toCollection(HashSet::new));
thetaQs.add(thetaPrime);
Set<UnifyType> thetaQPrimes = new HashSet<>();
TypeParams cParams = c.getTypeParams();
@ -339,6 +342,26 @@ public class Unify {
thetaQPrimes.add(c);
else {
ArrayList<Set<UnifyType>> candidateParams = new ArrayList<>();
/*
* TODO Optimierungsmöglichkeit:
*
* An dieser Stelle gibt es Raum für Optimierung.
* Z.B. resultiert (a <. C<Integer>) durch Permutation der Parameter mit grArg und smaller in:
* (a = C<b'>, b' <.? ? extends Number)
* (a = C<b'>, b' <.? ? extends Integer)
* (a = C<b'>, b' <.? Integer)
* usw...
*
* Der erste Fall ist am allgemeinsten und schließt alle anderen Fälle mit ein. Jeder Fall resultiert in einem
* rekursiven Aufruf des Unify. Es würde reichen nur den allgemeinsten Fall zu betrachten da dieser den Lösungraum
* der anderen Fälle miteinschließt.
*
* Prüfen:
* Gibt es einen einzigen maximalen Fall?
* Wahrscheinlich gibt es 2: ? super x (x möglichst klein) und ? ext y (y möglichst groß))
*/
for(UnifyType param : cParams)
candidateParams.add(fc.grArg(param));
@ -352,15 +375,26 @@ public class Unify {
continue;
Unifier unifier = opt.get();
unifier.swapPlaceholderSubstitutions(thetaPrime.getTypeParams().toArray());
Set<UnifyPair> substitutionSet = new HashSet<>();
for (Entry<PlaceholderType, UnifyType> sigma : unifier.getSubstitutions())
substitutionSet.add(new UnifyPair(sigma.getKey(), sigma.getValue(), PairOperator.EQUALSDOT));
List<UnifyType> freshTphs = new ArrayList<>();
for (UnifyType tq : thetaQs) {
Set<UnifyType> smaller = fc.smaller(unifier.apply(tq));
for(UnifyType theta : smaller) {
Set<UnifyPair> resultPrime = new HashSet<>();
resultPrime.add(new UnifyPair(a, theta, PairOperator.EQUALSDOT));
//UnifyType[] freshTphs = new UnifyType[theta.getTypeParams().size()];
for(int i = 0; i < theta.getTypeParams().size(); i++) {
if(freshTphs.size()-1 < i)
freshTphs.add(PlaceholderType.freshPlaceholder());
resultPrime.add(new UnifyPair(freshTphs.get(i), theta.getTypeParams().get(i), PairOperator.SMALLERDOTWC));
}
UnifyType freshTheta = theta.setTypeParams(new TypeParams(freshTphs.toArray(new UnifyType[0])));
resultPrime.add(new UnifyPair(a, freshTheta, PairOperator.EQUALSDOT));
resultPrime.addAll(substitutionSet);
result.add(resultPrime);
}
@ -374,56 +408,74 @@ public class Unify {
protected Set<Set<UnifyPair>> unifyCase2(PlaceholderType a, ExtendsType extThetaPrime, IFiniteClosure fc) {
Set<Set<UnifyPair>> result = new HashSet<>();
IUnify unify = new MartelliMontanariUnify();
UnifyType aPrime = PlaceholderType.freshPlaceholder();
UnifyType extAPrime = new ExtendsType(aPrime);
UnifyType thetaPrime = extThetaPrime.getExtendedType();
Set<UnifyType> cs = fc.getAllTypesByName(thetaPrime.getName());
for(UnifyType c : cs) {
//for(UnifyType theta : fc.smArg(subThetaPrime)) {
Set<UnifyPair> resultPrime = new HashSet<>();
resultPrime.add(new UnifyPair(a, aPrime, PairOperator.EQUALSDOT));
resultPrime.add(new UnifyPair(aPrime, thetaPrime, PairOperator.SMALLERDOT));
result.add(resultPrime);
// Wenn die fc nach spezifikation funktioniert ist das hier nicht mehr nötig?
Set<UnifyType> thetaQs = fc.getChildren(c).stream().filter(x -> x.getTypeParams().arePlaceholders()).collect(Collectors.toCollection(HashSet::new));
thetaQs.add(c); // reflexive
Set<UnifyType> thetaQPrimes = new HashSet<>();
TypeParams cParams = c.getTypeParams();
if(cParams.size() == 0)
thetaQPrimes.add(c);
else {
ArrayList<Set<UnifyType>> candidateParams = new ArrayList<>();
for(UnifyType param : cParams)
candidateParams.add(fc.grArg(param));
for(TypeParams tp : permuteParams(candidateParams))
thetaQPrimes.add(c.setTypeParams(tp));
}
for(UnifyType tqp : thetaQPrimes) {
Optional<Unifier> opt = unify.unify(tqp, thetaPrime);
if (!opt.isPresent())
continue;
Unifier unifier = opt.get();
Set<UnifyPair> substitutionSet = new HashSet<>();
for (Entry<PlaceholderType, UnifyType> sigma : unifier.getSubstitutions())
substitutionSet.add(new UnifyPair(sigma.getKey(), sigma.getValue(), PairOperator.EQUALSDOT));
for (UnifyType tq : thetaQs) {
ExtendsType extTq = new ExtendsType(tq);
Set<UnifyType> smArg = fc.smArg(unifier.apply(extTq));
for(UnifyType theta : smArg) {
Set<UnifyPair> resultPrime = new HashSet<>();
resultPrime.add(new UnifyPair(a, theta, PairOperator.EQUALSDOT));
resultPrime.addAll(substitutionSet);
result.add(resultPrime);
}
}
}
}
resultPrime = new HashSet<>();
resultPrime.add(new UnifyPair(a, extAPrime, PairOperator.EQUALSDOT));
resultPrime.add(new UnifyPair(aPrime, thetaPrime, PairOperator.SMALLERDOT));
result.add(resultPrime);
//}
return result;
// Set<Set<UnifyPair>> result = new HashSet<>();
// IUnify unify = new MartelliMontanariUnify();
//
// UnifyType thetaPrime = extThetaPrime.getExtendedType();
// Set<UnifyType> cs = fc.getAllTypesByName(thetaPrime.getName());
// cs.add(thetaPrime);
//
// for(UnifyType c : cs) {
// Set<UnifyType> thetaQs = fc.getChildren(c).stream().collect(Collectors.toCollection(HashSet::new));
// thetaQs.add(thetaPrime);
//
// Set<UnifyType> thetaQPrimes = new HashSet<>();
// TypeParams cParams = c.getTypeParams();
// if(cParams.size() == 0)
// thetaQPrimes.add(c);
// else {
// ArrayList<Set<UnifyType>> candidateParams = new ArrayList<>();
// for(UnifyType param : cParams)
// candidateParams.add(fc.grArg(param));
//
// for(TypeParams tp : permuteParams(candidateParams))
// thetaQPrimes.add(c.setTypeParams(tp));
// }
//
// for(UnifyType tqp : thetaQPrimes) {
// Optional<Unifier> opt = unify.unify(tqp, thetaPrime);
// if (!opt.isPresent())
// continue;
//
// Unifier unifier = opt.get();
//
// Set<UnifyPair> substitutionSet = new HashSet<>();
// for (Entry<PlaceholderType, UnifyType> sigma : unifier.getSubstitutions())
// substitutionSet.add(new UnifyPair(sigma.getKey(), sigma.getValue(), PairOperator.EQUALSDOT));
//
// for (UnifyType tq : thetaQs) {
// ExtendsType extTq = new ExtendsType(tq);
// Set<UnifyType> smArg = fc.smArg(unifier.apply(extTq));
// for(UnifyType theta : smArg) {
// Set<UnifyPair> resultPrime = new HashSet<>();
// resultPrime.add(new UnifyPair(a, theta, PairOperator.EQUALSDOT));
// resultPrime.addAll(substitutionSet);
// result.add(resultPrime);
// }
// }
//
// }
// }
//
// return result;
}
protected Set<Set<UnifyPair>> unifyCase3(PlaceholderType a, SuperType subThetaPrime, IFiniteClosure fc) {
@ -460,7 +512,14 @@ public class Unify {
Set<Set<UnifyPair>> result = new HashSet<>();
for(UnifyType thetaS : fc.greater(theta)) {
Set<UnifyPair> resultPrime = new HashSet<>();
resultPrime.add(new UnifyPair(a, thetaS, PairOperator.EQUALSDOT));
UnifyType[] freshTphs = new UnifyType[thetaS.getTypeParams().size()];
for(int i = 0; i < freshTphs.length; i++) {
freshTphs[i] = PlaceholderType.freshPlaceholder();
resultPrime.add(new UnifyPair(thetaS.getTypeParams().get(i), freshTphs[i], PairOperator.SMALLERDOTWC));
}
resultPrime.add(new UnifyPair(a, thetaS.setTypeParams(new TypeParams(freshTphs)), PairOperator.EQUALSDOT));
result.add(resultPrime);
}
@ -469,76 +528,104 @@ public class Unify {
protected Set<Set<UnifyPair>> unifyCase6(ExtendsType extTheta, PlaceholderType a, IFiniteClosure fc) {
Set<Set<UnifyPair>> result = new HashSet<>();
for(UnifyType thetaS : fc.grArg(extTheta)) {
Set<UnifyPair> resultPrime = new HashSet<>();
resultPrime.add(new UnifyPair(a, thetaS, PairOperator.EQUALSDOT));
result.add(resultPrime);
}
//for(UnifyType thetaS : fc.smaller(extTheta.getExtendedType())) {
UnifyType freshTph = PlaceholderType.freshPlaceholder();
UnifyType extFreshTph = new ExtendsType(freshTph);
Set<UnifyPair> resultPrime = new HashSet<>();
resultPrime.add(new UnifyPair(a, extFreshTph, PairOperator.EQUALSDOT));
resultPrime.add(new UnifyPair(extTheta.getExtendedType(), freshTph, PairOperator.SMALLERDOT));
result.add(resultPrime);
//}
return result;
}
protected Set<Set<UnifyPair>> unifyCase7(SuperType supTheta, PlaceholderType a, IFiniteClosure fc) {
Set<Set<UnifyPair>> result = new HashSet<>();
IUnify unify = new MartelliMontanariUnify();
UnifyType aPrime = PlaceholderType.freshPlaceholder();
UnifyType supAPrime = new SuperType(aPrime);
UnifyType theta = supTheta.getSuperedType();
Set<UnifyType> cs = fc.getAllTypesByName(theta.getName());
for(UnifyType c : cs) {
// Wenn die fc nach spezifikation funktioniert ist das hier nicht mehr nötig?
Set<UnifyType> thetaQs = fc.getChildren(c).stream().filter(x -> x.getTypeParams().arePlaceholders()).collect(Collectors.toCollection(HashSet::new));
thetaQs.add(c); // reflexive
Set<UnifyType> thetaQPrimes = new HashSet<>();
TypeParams cParams = c.getTypeParams();
if(cParams.size() == 0)
thetaQPrimes.add(c);
else {
ArrayList<Set<UnifyType>> candidateParams = new ArrayList<>();
for(UnifyType param : cParams)
candidateParams.add(fc.grArg(param));
for(TypeParams tp : permuteParams(candidateParams))
thetaQPrimes.add(c.setTypeParams(tp));
}
for(UnifyType tqp : thetaQPrimes) {
Optional<Unifier> opt = unify.unify(tqp, theta);
if (!opt.isPresent())
continue;
Unifier unifier = opt.get();
Set<UnifyPair> substitutionSet = new HashSet<>();
for (Entry<PlaceholderType, UnifyType> sigma : unifier.getSubstitutions())
substitutionSet.add(new UnifyPair(sigma.getKey(), sigma.getValue(), PairOperator.EQUALSDOT));
for (UnifyType tq : thetaQs) {
Set<UnifyType> smaller = fc.smaller(unifier.apply(tq));
for(UnifyType thetaPrime : smaller) {
Set<UnifyPair> resultPrime = new HashSet<>();
resultPrime.add(new UnifyPair(a, new SuperType(thetaPrime), PairOperator.EQUALSDOT));
resultPrime.addAll(substitutionSet);
result.add(resultPrime);
}
}
}
}
//for(UnifyType theta : fc.smArg(subThetaPrime)) {
Set<UnifyPair> resultPrime = new HashSet<>();
resultPrime.add(new UnifyPair(a, supAPrime, PairOperator.EQUALSDOT));
resultPrime.add(new UnifyPair(aPrime, theta, PairOperator.SMALLERDOT));
result.add(resultPrime);
//}
return result;
// Set<Set<UnifyPair>> result = new HashSet<>();
// IUnify unify = new MartelliMontanariUnify();
//
// UnifyType theta = supTheta.getSuperedType();
// Set<UnifyType> cs = fc.getAllTypesByName(theta.getName());
// cs.add(theta);
//
// for(UnifyType c : cs) {
// Set<UnifyType> thetaQs = fc.getChildren(c).stream().collect(Collectors.toCollection(HashSet::new));
// thetaQs.add(theta);
//
// Set<UnifyType> thetaQPrimes = new HashSet<>();
// TypeParams cParams = c.getTypeParams();
// if(cParams.size() == 0)
// thetaQPrimes.add(c);
// else {
// ArrayList<Set<UnifyType>> candidateParams = new ArrayList<>();
// for(UnifyType param : cParams)
// candidateParams.add(fc.grArg(param));
//
// for(TypeParams tp : permuteParams(candidateParams))
// thetaQPrimes.add(c.setTypeParams(tp));
// }
//
// for(UnifyType tqp : thetaQPrimes) {
// Optional<Unifier> opt = unify.unify(tqp, theta);
// if (!opt.isPresent())
// continue;
//
// Unifier unifier = opt.get();
//
// Set<UnifyPair> substitutionSet = new HashSet<>();
// for (Entry<PlaceholderType, UnifyType> sigma : unifier.getSubstitutions())
// substitutionSet.add(new UnifyPair(sigma.getKey(), sigma.getValue(), PairOperator.EQUALSDOT));
//
// for (UnifyType tq : thetaQs) {
// Set<UnifyType> smaller = fc.smaller(unifier.apply(tq));
//
// for(UnifyType thetaPrime : smaller) {
// Set<UnifyPair> resultPrime = new HashSet<>();
// resultPrime.add(new UnifyPair(a, new SuperType(thetaPrime), PairOperator.EQUALSDOT));
// resultPrime.addAll(substitutionSet);
// result.add(resultPrime);
// }
// }
//
// }
// }
//
// return result;
}
protected Set<Set<UnifyPair>> unifyCase8(UnifyType theta, PlaceholderType a, IFiniteClosure fc) {
Set<Set<UnifyPair>> result = new HashSet<>();
for(UnifyType thetaS : fc.grArg(theta)) {
Set<UnifyPair> resultPrime = new HashSet<>();
resultPrime.add(new UnifyPair(a, thetaS, PairOperator.EQUALSDOT));
result.add(resultPrime);
}
//for(UnifyType thetaS : fc.grArg(theta)) {
Set<UnifyPair> resultPrime = new HashSet<>();
resultPrime.add(new UnifyPair(a, theta, PairOperator.EQUALSDOT));
result.add(resultPrime);
UnifyType freshTph = PlaceholderType.freshPlaceholder();
resultPrime = new HashSet<>();
resultPrime.add(new UnifyPair(a, new ExtendsType(freshTph), PairOperator.EQUALSDOT));
resultPrime.add(new UnifyPair(theta, freshTph, PairOperator.SMALLERDOT));
result.add(resultPrime);
resultPrime = new HashSet<>();
resultPrime.add(new UnifyPair(a, new SuperType(freshTph), PairOperator.EQUALSDOT));
resultPrime.add(new UnifyPair(freshTph, theta, PairOperator.SMALLERDOT));
result.add(resultPrime);
//}
return result;
}

View File

@ -10,6 +10,10 @@ import de.dhbwstuttgart.typeinference.unify.model.ReferenceType;
import de.dhbwstuttgart.typeinference.unify.model.SuperType;
import de.dhbwstuttgart.typeinference.unify.model.UnifyType;
/**
*
* @author Florian Steurer
*/
public interface IFiniteClosure {
/**
@ -53,7 +57,7 @@ public interface IFiniteClosure {
public Set<UnifyType> grArg(FunNType type);
public Set<UnifyType> smArg(FunNType type);
public Optional<UnifyType> getLeftHandedType(UnifyType t);
public Optional<UnifyType> getLeftHandedType(String typeName);
public Set<UnifyType> getAncestors(UnifyType t);
public Set<UnifyType> getChildren(UnifyType t);
public Set<UnifyType> getAllTypesByName(String typeName);

View File

@ -5,6 +5,10 @@ import java.util.Set;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
/**
* Contains the inference rules that are applied to the set Eq.
* @author Florian Steurer
*/
public interface IRuleSet {
public Optional<UnifyPair> reduceUp(UnifyPair pair);
@ -17,7 +21,7 @@ public interface IRuleSet {
public Optional<Set<UnifyPair>> reduce2(UnifyPair pair);
/*
* Missing Rules
* Missing Reduce-Rules for Wildcards
*/
public Optional<UnifyPair> reduceWildcardLow(UnifyPair pair);
public Optional<UnifyPair> reduceWildcardLowRight(UnifyPair pair);
@ -34,8 +38,22 @@ public interface IRuleSet {
public Optional<Set<UnifyPair>> greaterFunN(UnifyPair pair);
public Optional<Set<UnifyPair>> smallerFunN(UnifyPair pair);
/**
* Checks whether the erase1-Rule applies to the pair.
* @return True if the pair is erasable, false otherwise.
*/
public boolean erase1(UnifyPair pair);
/**
* Checks whether the erase2-Rule applies to the pair.
* @return True if the pair is erasable, false otherwise.
*/
public boolean erase2(UnifyPair pair);
/**
* Checks whether the erase3-Rule applies to the pair.
* @return True if the pair is erasable, false otherwise.
*/
public boolean erase3(UnifyPair pair);
public Optional<UnifyPair> swap(UnifyPair pair);
@ -44,5 +62,10 @@ public interface IRuleSet {
public Optional<UnifyPair> adaptExt(UnifyPair pair);
public Optional<UnifyPair> adaptSup(UnifyPair pair);
public Optional<Set<UnifyPair>> subst(Set<UnifyPair> pair);
/**
* Applies the subst-Rule to a set of pairs (usually Eq').
* @param pairs The set of pairs where the subst rule should apply.
* @return An optional of the modified set, if there were any substitutions. An empty optional if there were no substitutions.
*/
public Optional<Set<UnifyPair>> subst(Set<UnifyPair> pairs);
}

View File

@ -3,6 +3,14 @@ package de.dhbwstuttgart.typeinference.unify.interfaces;
import java.util.List;
import java.util.Set;
/**
* Contains operations on sets.
* @author Florian Steurer
*/
public interface ISetOperations {
/**
* Calculates the cartesian product of the sets.
* @return The cartesian product
*/
<B> Set<List<B>> cartesianProduct(List<? extends Set<? extends B>> sets);
}

View File

@ -14,8 +14,20 @@ import de.dhbwstuttgart.typeinference.unify.model.Unifier;
*/
public interface IUnify {
/**
* Finds the most general unifier sigma of the set {t1,...,tn} so that
* sigma(t1) = sigma(t2) = ... = sigma(tn).
* @param terms The set of terms to be unified
* @return An optional of the most general unifier if it exists or an empty optional if there is no unifier.
*/
public Optional<Unifier> unify(Set<UnifyType> terms);
/**
* Finds the most general unifier sigma of the set {t1,...,tn} so that
* sigma(t1) = sigma(t2) = ... = sigma(tn).
* @param terms The set of terms to be unified
* @return An optional of the most general unifier if it exists or an empty optional if there is no unifier.
*/
default public Optional<Unifier> unify(UnifyType... terms) {
return unify(Arrays.stream(terms).collect(Collectors.toSet()));
}

View File

@ -14,7 +14,7 @@ public final class ExtendsType extends WildcardType {
* @param extendedType The extended type e.g. Integer in "? extends Integer"
*/
public ExtendsType(UnifyType extendedType) {
super("? extends " + extendedType.getName(), extendedType, extendedType.getTypeParams());
super("? extends " + extendedType.getName(), extendedType);
}
public UnifyType getExtendedType() {

View File

@ -18,7 +18,7 @@ public class FiniteClosure implements IFiniteClosure {
private HashMap<UnifyType, Node<UnifyType>> inheritanceGraph;
private HashMap<String, HashSet<Node<UnifyType>>> strInheritanceGraph;
private Set<UnifyPair> pairs;
private Set<UnifyType> basicTypes;
//private Set<UnifyType> basicTypes;
//TODO im konstruktor mitgeben um typenabzuhandeln die keine extends beziehung haben. (Damit die FC diese Typen auch kennt)
//(ALternative: immer die extends zu object beziehung einfügen)
@ -65,6 +65,13 @@ public class FiniteClosure implements IFiniteClosure {
*/
@Override
public Set<UnifyType> smaller(UnifyType type) {
if(type instanceof FunNType)
return computeSmallerFunN((FunNType) type);
return computeSmaller(type);
}
private Set<UnifyType> computeSmaller(UnifyType type) {
if(inheritanceGraph.containsKey(type)) {
Set<UnifyType> result = new HashSet<>();
result.add(type);
@ -82,8 +89,7 @@ public class FiniteClosure implements IFiniteClosure {
for (UnifyType param : type.getTypeParams())
paramCandidates.add(smArg(param));
Set<TypeParams> permResult = new HashSet<>();
permuteParams(paramCandidates, 0, permResult, new UnifyType[paramCandidates.size()]);
Set<TypeParams> permResult = permuteParams(paramCandidates);
for (TypeParams newParams : permResult)
result1.add(type.setTypeParams(newParams));}
@ -94,16 +100,18 @@ public class FiniteClosure implements IFiniteClosure {
strInheritanceGraph.get(type.getName()).forEach(x -> candidates.add(x.getContent()));
for(UnifyType typePrime : result1) {
for (UnifyType theta2 : candidates) {
Optional<Unifier> sigma2 = unify.unify(typePrime, theta2);
if (!sigma2.isPresent())
for (UnifyType theta2 : candidates) {
Optional<Unifier> sigma2Opt = unify.unify(typePrime, theta2);
if (!sigma2Opt.isPresent())
continue;
Unifier sigma2 = sigma2Opt.get();
sigma2.swapPlaceholderSubstitutions(typePrime.getTypeParams().toArray());
if(type.equals(theta2))
continue;
Set<UnifyType> theta1s = smaller(theta2);
for (UnifyType theta1 : theta1s) {
// Because only the most general type is calculated, sigma1 = sigma2
UnifyType sigma1Theta1 = sigma2.get().apply(theta1);
UnifyType sigma1Theta1 = sigma2.apply(theta1);
result2.add(sigma1Theta1);
}
}
@ -118,8 +126,7 @@ public class FiniteClosure implements IFiniteClosure {
for (UnifyType param : t.getTypeParams())
paramCandidates.add(smArg(param));
Set<TypeParams> permResult = new HashSet<>();
permuteParams(paramCandidates, 0, permResult, new UnifyType[paramCandidates.size()]);
Set<TypeParams> permResult = permuteParams(paramCandidates);
for (TypeParams newParams : permResult) {
UnifyType tPrime = t.setTypeParams(newParams);
@ -127,19 +134,44 @@ public class FiniteClosure implements IFiniteClosure {
result3.add(t);
else
result3.addAll(smaller(tPrime));
}
}
}
return result3;
}
private Set<UnifyType> computeSmallerFunN(FunNType type) {
Set<UnifyType> result = new HashSet<>();
// if T = T' then T <=* T'
result.add(type);
ArrayList<Set<UnifyType>> paramCandidates = new ArrayList<>();
paramCandidates.add(smaller(type.getTypeParams().get(0)));
for (int i = 1; i < type.getTypeParams().size(); i++)
paramCandidates.add(greater(type.getTypeParams().get(i)));
Set<TypeParams> permResult = permuteParams(paramCandidates);
for (TypeParams newParams : permResult)
result.add(type.setTypeParams(newParams));
return result;
}
/**
* Returns all types of the finite closure that are supertypes of the argument.
* @return The set of supertypes of the argument.
*/
@Override
public Set<UnifyType> greater(UnifyType type) {
public Set<UnifyType> greater(UnifyType type) {
if(type instanceof FunNType)
return computeGreaterFunN((FunNType) type);
return computeGreater(type);
}
protected Set<UnifyType> computeGreater(UnifyType type) {
IUnify unify = new MartelliMontanariUnify();
Set<UnifyType> result1 = new HashSet<>();
@ -166,22 +198,25 @@ public class FiniteClosure implements IFiniteClosure {
for(UnifyType typePrime : result1) {
for (UnifyType theta2 : candidates) {
Optional<Unifier> sigma2 = unify.unify(typePrime, theta2);
if (!sigma2.isPresent())
Optional<Unifier> sigma2Opt = unify.unify(typePrime, theta2);
if (!sigma2Opt.isPresent())
continue;
if(type.equals(theta2))
continue;
Unifier sigma2 = sigma2Opt.get();
sigma2.swapPlaceholderSubstitutions(typePrime.getTypeParams().toArray());
Set<UnifyType> theta1s = greater(theta2);
for (UnifyType theta1 : theta1s) {
// Because only the most general type is calculated, sigma1 = sigma2
UnifyType sigma1Theta1 = sigma2.get().apply(theta1);
UnifyType sigma1Theta1 = sigma2.apply(theta1);
result2.add(sigma1Theta1);
}
}
}
}
result2.addAll(result1);
result2.addAll(result1);
Set<UnifyType> result3 = new HashSet<>();
for(UnifyType t : result2) {
@ -203,8 +238,27 @@ public class FiniteClosure implements IFiniteClosure {
}
return result3;
}
protected Set<UnifyType> computeGreaterFunN(FunNType type) {
Set<UnifyType> result = new HashSet<>();
// if T = T' then T <=* T'
result.add(type);
ArrayList<Set<UnifyType>> paramCandidates = new ArrayList<>();
paramCandidates.add(greater(type.getTypeParams().get(0)));
for (int i = 1; i < type.getTypeParams().size(); i++)
paramCandidates.add(smaller(type.getTypeParams().get(i)));
Set<TypeParams> permResult = permuteParams(paramCandidates);
for (TypeParams newParams : permResult)
result.add(type.setTypeParams(newParams));
return result;
}
@Override
public Set<UnifyType> grArg(UnifyType type) {
@ -341,12 +395,12 @@ public class FiniteClosure implements IFiniteClosure {
}
@Override
public Optional<UnifyType> getLeftHandedType(UnifyType t) {
if(!strInheritanceGraph.containsKey(t.getName()))
public Optional<UnifyType> getLeftHandedType(String typeName) {
if(!strInheritanceGraph.containsKey(typeName))
return Optional.empty();
for(UnifyPair pair : pairs)
if(pair.getLhsType().getName().equals(t.getName()))
if(pair.getLhsType().getName().equals(typeName))
return Optional.of(pair.getLhsType());
return Optional.empty();
@ -370,6 +424,12 @@ public class FiniteClosure implements IFiniteClosure {
return result;
}
protected Set<TypeParams> permuteParams(ArrayList<Set<UnifyType>> candidates) {
Set<TypeParams> result = new HashSet<>();
permuteParams(candidates, 0, result, new UnifyType[candidates.size()]);
return result;
}
protected void permuteParams(ArrayList<Set<UnifyType>> candidates, int idx, Set<TypeParams> result, UnifyType[] current) {
if(candidates.size() == idx) {
result.add(new TypeParams(Arrays.copyOf(current, current.length)));

View File

@ -43,13 +43,26 @@ public class FunNType extends UnifyType {
Set<UnifyType> grArg(IFiniteClosure fc) {
return fc.grArg(this);
}
@Override
UnifyType apply(Unifier unif) {
// TODO Auto-generated method stub
return null;
}
// TODO equals und hashcode
@Override
public int hashCode() {
return 31 + typeParams.hashCode();
}
@Override
public boolean equals(Object obj) {
if(!(obj instanceof FunNType))
return false;
FunNType other = (FunNType) obj;
return other.getTypeParams().equals(typeParams);
}
}

View File

@ -16,13 +16,13 @@ public final class PlaceholderType extends UnifyType{
private final boolean IsGenerated;
public PlaceholderType(String name) {
super(name);
super(name, new TypeParams());
EXISTING_PLACEHOLDERS.add(name);
IsGenerated = false;
}
protected PlaceholderType(String name, boolean isGenerated) {
super(name);
super(name, new TypeParams());
EXISTING_PLACEHOLDERS.add(name);
IsGenerated = isGenerated;
}
@ -31,7 +31,7 @@ public final class PlaceholderType extends UnifyType{
String name = nextName + randomChar();
while(EXISTING_PLACEHOLDERS.contains(name));
nextName += randomChar();
name += randomChar();
return new PlaceholderType(name, true);
}

View File

@ -22,7 +22,7 @@ public final class ReferenceType extends UnifyType {
Set<UnifyType> grArg(IFiniteClosure fc) {
return fc.grArg(this);
}
@Override
UnifyType apply(Unifier unif) {
return new ReferenceType(typeName, typeParams.apply(unif));
@ -35,7 +35,7 @@ public final class ReferenceType extends UnifyType {
@Override
public int hashCode() {
return typeName.hashCode();
return 31 + 17 * typeName.hashCode() + 17 * typeParams.hashCode();
}
@Override

View File

@ -5,10 +5,8 @@ import java.util.Set;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
public final class SuperType extends WildcardType {
public SuperType(UnifyType superedType) {
super("? super " + superedType.getName(), superedType, superedType.getTypeParams());
super("? super " + superedType.getName(), superedType);
}
public UnifyType getSuperedType() {

View File

@ -77,6 +77,9 @@ public final class TypeParams implements Iterable<UnifyType>{
return new TypeParams(newparams);
}
public UnifyType[] toArray() {
return Arrays.copyOf(typeParams, typeParams.length);
}
@Override
public Iterator<UnifyType> iterator() {

View File

@ -17,7 +17,7 @@ public class Unifier implements Function<UnifyType, UnifyType> /*, Set<MPair>*/
/**
* Identity function as an "unifier".
*/
public Unifier() {
protected Unifier() {
}
@ -52,6 +52,18 @@ public class Unifier implements Function<UnifyType, UnifyType> /*, Set<MPair>*/
public Set<Entry<PlaceholderType, UnifyType>> getSubstitutions() {
return substitutions.entrySet();
}
public void swapPlaceholderSubstitutions(UnifyType... targetParams) {
for(UnifyType tph : targetParams) {
if(!(tph instanceof PlaceholderType))
continue;
if(substitutions.containsKey(tph) && substitutions.get(tph) instanceof PlaceholderType) {
PlaceholderType newLhs = (PlaceholderType) substitutions.get(tph);
substitutions.remove(tph);
substitutions.put(newLhs, tph);
}
}
}
@Override
public String toString() {

View File

@ -1,31 +1,55 @@
package de.dhbwstuttgart.typeinference.unify.model;
/**
* A pair which contains two types and an operator, e.q. (Integer <. a).
* @author Florian Steurer
*/
public class UnifyPair {
/**
* The type on the left hand side of the pair.
*/
private UnifyType lhs;
/**
* The type on the right hand side of the pair.
*/
private UnifyType rhs;
/**
* The operator that determines the relation between the left and right hand side type.
*/
private PairOperator pairOp;
/*public MPair(Type t1, Type t2) {
lhs = t1;
rhs = t2;
pairOp = PairOperator.SMALLER;
}*/
public UnifyPair(UnifyType t1, UnifyType t2, PairOperator op) {
lhs = t1;
rhs = t2;
/**
* Creates a new instance of the pair.
* @param lhs The type on the left hand side of the pair.
* @param rhs The type on the right hand side of the pair.
* @param op The operator that determines the relation between the left and right hand side type.
*/
public UnifyPair(UnifyType lhs, UnifyType rhs, PairOperator op) {
this.lhs = lhs;
this.rhs = rhs;
pairOp = op;
}
/**
* Returns the type on the left hand side of the pair.
*/
public UnifyType getLhsType() {
return lhs;
}
/**
* Returns the type on the right hand side of the pair.
*/
public UnifyType getRhsType() {
return rhs;
}
/**
* Returns the operator that determines the relation between the left and right hand side type.
*/
public PairOperator getPairOp() {
return pairOp;
}

View File

@ -4,35 +4,76 @@ import java.util.Set;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
/**
* Represents a java type.
* @author Florian Steurer
*/
public abstract class UnifyType {
/**
* The name of the type e.q. "Integer", "? extends Integer" or "List" for (List<T>)
*/
protected final String typeName;
/**
* The type parameters of the type.
*/
protected final TypeParams typeParams;
protected UnifyType(String name, UnifyType... typeParams) {
typeName = name;
this.typeParams = new TypeParams(typeParams);
}
/**
* Creates a new instance
* @param name Name of the type (e.q. List for List<T>, Integer or ? extends Integer)
* @param typeParams Parameters of the type (e.q. <T> for List<T>)
*/
protected UnifyType(String name, TypeParams p) {
typeName = name;
typeParams = p;
}
/**
* Returns the name of the type.
* @return The name e.q. List for List<T>, Integer or ? extends Integer
*/
public String getName() {
return typeName;
}
/**
* The parameters of the type.
* @return Parameters of the type, e.q. <T> for List<T>.
*/
public TypeParams getTypeParams() {
return typeParams;
}
/**
* Returns a new type that equals this type except for the type parameters.
* @param newTp The type params of the new type.
* @return A new type object.
*/
public abstract UnifyType setTypeParams(TypeParams newTp);
/**
* Implementation of the visitor-pattern. Returns the set of smArg
* by calling the most specific overload in the FC.
* @param fc The FC that is called.
* @return The set that is smArg(this)
*/
abstract Set<UnifyType> smArg(IFiniteClosure fc);
/**
* Implementation of the visitor-pattern. Returns the set of grArg
* by calling the most specific overload in the FC.
* @param fc The FC that is called.
* @return The set that is grArg(this)
*/
abstract Set<UnifyType> grArg(IFiniteClosure fc);
/**
* Applies a unifier to this object.
* @param unif The unifier
* @return A UnifyType, that may or may not be a new object, that has its subtypes substituted.
*/
abstract UnifyType apply(Unifier unif);
@Override

View File

@ -1,19 +1,30 @@
package de.dhbwstuttgart.typeinference.unify.model;
/**
* A wildcard type that is either a ExtendsType or a SuperType.
* @author Florian Steurer
*/
public abstract class WildcardType extends UnifyType {
/**
* The wildcarded type, e.q. Integer for ? extends Integer. Never a wildcard type itself.
*/
protected UnifyType wildcardedType;
protected WildcardType(String name, UnifyType wildcardedType, UnifyType[] typeParams) {
super(name, typeParams);
this.wildcardedType = wildcardedType;
}
protected WildcardType(String name, UnifyType wildcardedType, TypeParams p) {
super(name, p);
/**
* Creates a new instance.
* @param name The name of the type, e.q. ? extends Integer
* @param wildcardedType The wildcarded type, e.q. Integer for ? extends Integer. Never a wildcard type itself.
*/
protected WildcardType(String name, UnifyType wildcardedType) {
super(name, wildcardedType.getTypeParams());
this.wildcardedType = wildcardedType;
}
/**
* Returns the wildcarded type, e.q. Integer for ? extends Integer.
* @return The wildcarded type. Never a wildcard type itself.
*/
public UnifyType getWildcardedType() {
return wildcardedType;
}

View File

@ -2,17 +2,13 @@ package unify;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.junit.Assert;
import org.junit.Test;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
import de.dhbwstuttgart.typeinference.unify.model.PairOperator;
import de.dhbwstuttgart.typeinference.unify.model.FiniteClosure;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unify.model.UnifyType;
public class FiniteClosureTest {
@ -169,6 +165,7 @@ public class FiniteClosureTest {
setExtT1, hashSetExtT1, treeSetExtT1, linkedHashSetExtT1
}).collect(Collectors.toSet()));
//System.out.println(fc.smaller(setExtT1));
Assert.assertEquals(expectedResult, fc.smaller(setExtT1));
/*
@ -395,7 +392,37 @@ public class FiniteClosureTest {
Assert.assertEquals(82, actual.size());
Assert.assertTrue(actual.contains(myMapExtInt));
Assert.assertTrue(actual.contains(myMapInt));
Assert.assertTrue(actual.contains(myMapInt));
/*
* Test Case 16:
*
* smaller(FunN<Number, Number, Number>) =
* { FunN<Number, Number, Number>, FunN<Number, Object, Number>,
* FunN<Number, Number, Object>, FunN<Number, Object, Object>,
* FunN<Integer, Number, Number>, FunN<Integer, Object, Number>,
* FunN<Integer, Number, Object>, FunN<Integer, Object, Object> }
*/
UnifyType object = tf.getSimpleType("Object");
fcb = new FiniteClosureBuilder();
fcb.add(integer, number);
fcb.add(number, object);
fc = fcb.getCollectionExample();
UnifyType funNNumber = tf.getFunNType(number, number, number);
expectedResult = new HashSet<>(Arrays.stream(new UnifyType[] {
tf.getFunNType(number, number, number), tf.getFunNType(number, object, number),
tf.getFunNType(number, number, object), tf.getFunNType(number, object, object),
tf.getFunNType(integer, number, number), tf.getFunNType(integer, object, number),
tf.getFunNType(integer, number, object), tf.getFunNType(integer, object, object),
}).collect(Collectors.toSet()));
actual = fc.smaller(funNNumber);
//System.out.println(actual);
Assert.assertEquals(expectedResult, actual);
}
@Test
@ -633,41 +660,33 @@ public class FiniteClosureTest {
* greater(SortedMap<? super Number>, ? super List<? extends Integer>>) =
*
*/
}
@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 testSmArg() {
IFiniteClosure fc = new FiniteClosureBuilder().getCollectionExample();
TypeFactory tf = new TypeFactory();
/*
* Test Case 14:
*
* greater(FunN<Number, Number, Number>) =
* { FunN<Number, Number, Number>, FunN<Number, Object, Number>,
* FunN<Number, Number, Object>, FunN<Number, Object, Object>,
* FunN<Integer, Number, Number>, FunN<Integer, Object, Number>,
* FunN<Integer, Number, Object>, FunN<Integer, Object, Object> }
*/
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"))));
}
@Test
public void testGetGenericType() {
// TODO
}
private void printDiff(Set<UnifyType> expected, Set<UnifyType> actual) {
System.out.println("Diff:");
System.out.println("In expected but not in actual:");
Set<UnifyType> expected1 = new HashSet<>(expected);
expected1.removeAll(actual);
System.out.println(expected1);
UnifyType object = tf.getSimpleType("Object");
fcb = new FiniteClosureBuilder();
fcb.add(integer, number);
fcb.add(number, object);
fc = fcb.getCollectionExample();
UnifyType funNNumber = tf.getFunNType(number, number, number);
expectedResult = new HashSet<>(Arrays.stream(new UnifyType[] {
tf.getFunNType(number, number, number), tf.getFunNType(number, integer, number),
tf.getFunNType(number, number, integer), tf.getFunNType(number, integer, integer),
tf.getFunNType(object, number, number), tf.getFunNType(object, integer, number),
tf.getFunNType(object, number, integer), tf.getFunNType(object, integer, integer)
}).collect(Collectors.toSet()));
actual = fc.greater(funNNumber);
Assert.assertEquals(expectedResult, actual);
}
}

View File

@ -32,8 +32,6 @@ public class StandardUnifyTest {
System.out.println(unify.unify(f, y).get());
// TODO ist das ergebnis { (x -> ? extends a), (y -> g<x>) } in der richtigen form oder
// muss es { (x -> ? extends a), (y -> g<? extends a>) } sein?
// {f<g<x>,x> = f<y, ? extends a>}
UnifyType g = tf.getSimpleType("g", "x");
UnifyType f1 = tf.getSimpleType("f", g, x);

View File

@ -4,9 +4,11 @@ import java.util.Arrays;
import java.util.stream.Collectors;
import de.dhbwstuttgart.typeinference.unify.model.ExtendsType;
import de.dhbwstuttgart.typeinference.unify.model.FunNType;
import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType;
import de.dhbwstuttgart.typeinference.unify.model.ReferenceType;
import de.dhbwstuttgart.typeinference.unify.model.SuperType;
import de.dhbwstuttgart.typeinference.unify.model.TypeParams;
import de.dhbwstuttgart.typeinference.unify.model.UnifyType;
public class TypeFactory {
@ -34,4 +36,9 @@ public class TypeFactory {
public PlaceholderType getPlaceholderType(String name) {
return new PlaceholderType(name);
}
public FunNType getFunNType(UnifyType... typeParams) {
return FunNType.getFunNType(new TypeParams(typeParams));
}
}

View File

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

View File

@ -129,6 +129,8 @@ public class UnifyTest extends Unify {
addAsSet(expected, new UnifyPair(tphA, supObject, PairOperator.EQUALSDOT));
actual = unify(eq, fc);
System.out.println("? super Integer");
System.out.println(actual);
actual = filterGeneratedTPHsMultiple(actual);
Assert.assertEquals(expected, actual);
@ -155,6 +157,7 @@ public class UnifyTest extends Unify {
addAsSet(expected, new UnifyPair(tphA, supNumber, PairOperator.EQUALSDOT));
actual = unify(eq, fc);
actual = filterGeneratedTPHsMultiple(actual);
Assert.assertEquals(expected, actual);
@ -172,7 +175,7 @@ public class UnifyTest extends Unify {
addAsSet(expected, new UnifyPair(tphA, extObject, PairOperator.EQUALSDOT));
actual = unify(eq, fc);
actual = filterGeneratedTPHsMultiple(actual);
Assert.assertEquals(expected, actual);
@ -197,6 +200,7 @@ public class UnifyTest extends Unify {
addAsSet(expected, new UnifyPair(tphA, number, PairOperator.EQUALSDOT));
actual = unify(eq, fc);
actual = filterGeneratedTPHsMultiple(actual);
Assert.assertEquals(expected, actual);
@ -278,9 +282,9 @@ public class UnifyTest extends Unify {
UnifyType integer = tf.getSimpleType("Integer");
UnifyType doubl = tf.getSimpleType("Double");
fcb.add(number, object);
//fcb.add(number, object);
fcb.add(integer, number);
fcb.add(doubl, number);
//fcb.add(doubl, number);
IFiniteClosure fc = fcb.getCollectionExample();
@ -289,6 +293,10 @@ public class UnifyTest extends Unify {
*
* (Vector<a> <. Vector<? extends b>)
* (List<b> <. List<? extends Number>)
*
* Expected:
* {(b = Number), (a = Number)}, {(b = Number), (a = Integer)}, {(b = Number), (a = Integer)}
* (b = Integer),
*/
UnifyType tphA = tf.getPlaceholderType("a");
@ -303,28 +311,9 @@ public class UnifyTest extends Unify {
Set<Set<UnifyPair>> expected = new HashSet<>();
Set<Set<UnifyPair>> actual = unify(eq, fc);
System.out.println(actual);
//System.out.println(actual);
//Assert.assertEquals(actual, expected);
/*
* Test 8:
*
* (a <.? ? sup b)
* (b = Number)
*/
UnifyType supB = tf.getSuperType(tphB);
eq = new HashSet<>();
eq.add(new UnifyPair(tphA, supB, PairOperator.SMALLERDOTWC));
eq.add(new UnifyPair(tphB, number, PairOperator.EQUALSDOT));
expected = new HashSet<>();
actual = unify(eq, fc);
System.out.println(actual);
//Assert.assertEquals(expected, actual);
/*
* Test 2:
@ -356,8 +345,8 @@ public class UnifyTest extends Unify {
expected = new HashSet<>();
actual = unify(eq, fc);
//System.out.println(actual);
System.out.println(actual);
//Assert.assertEquals(actual, expected);
/*
@ -382,6 +371,194 @@ public class UnifyTest extends Unify {
//Assert.assertEquals(actual, expected);
}
/**
* These are tests that specifically test cases where the old unify algorithm was incomplete.
*/
@Test
public void unifyTestExtension() {
/*
* INIT
*/
TypeFactory tf = new TypeFactory();
FiniteClosureBuilder fcb = new FiniteClosureBuilder();
UnifyType number = tf.getSimpleType("Number");
UnifyType object = tf.getSimpleType("Object");
UnifyType integer = tf.getSimpleType("Integer");
UnifyType doubl = tf.getSimpleType("Double");
UnifyType mygeneric = tf.getSimpleType("MyGeneric", "T");
fcb.add(mygeneric, object);
fcb.add(integer, number);
//fcb.add(doubl, number);
IFiniteClosure fc = fcb.getCollectionExample();
/*
* Test 1:
* This is a Test for the extension of case 1 in the cartesian product of step 4.
*
* (a <. Vector<b>)
* (List<Integer> <. List<b>)
*
* Expected:
* (b = Integer), (a = Vector<Integer>)
* (b = ? extends Integer), (a = Vector<Integer>),
* (b = ? extends Integer), (a = Vector<? extends Integer>),
* (b = ? super Integer), (a = Vector<Integer>)
* (b = ? super Integer), (a = Vector<Number>)
* (b = ? super Integer), (a = Vector<? super Integer>)
* (b = ? super Integer), (a = Vector<? super Number>)
* (b = ? extends Number), (a = Vector<Integer>)
* (b = ? extends Number), (a = Vector<Number>)
* (b = ? extends Number), (a = Vector<? extends Integer>)
* (b = ? extends Number), (a = Vector<? extends Number>)
*/
UnifyType tphA = tf.getPlaceholderType("a");
UnifyType tphB = tf.getPlaceholderType("b");
UnifyType extB = tf.getExtendsType(tphB);
UnifyType extNum = tf.getExtendsType(number);
Set<UnifyPair> eq = new HashSet<UnifyPair>();
eq.add(new UnifyPair(tphA, tf.getSimpleType("Stack", tphB), PairOperator.SMALLERDOT));
eq.add(new UnifyPair(tf.getSimpleType("List", integer), tf.getSimpleType("List", tphB), PairOperator.SMALLERDOT));
Set<Set<UnifyPair>> expected = new HashSet<>();
Set<Set<UnifyPair>> actual = unify(eq, fc);
System.out.println(actual);
//Assert.assertEquals(actual, expected);
/*
* Test 2:
*
* This is a test for th extension of case 2 of the cartesian product of step 4.
*
* (a <.? ? ext b)
* (b =. Number)
*/
eq = new HashSet<>();
eq.add(new UnifyPair(tphA, extB, PairOperator.SMALLERDOTWC));
eq.add(new UnifyPair(tphB, number, PairOperator.EQUALSDOT));
expected = new HashSet<>();
actual = unify(eq, fc);
System.out.println("Case 2");
System.out.println(actual);
/*
* Test 3:
* This is a test for the extension of case 3 of the cartesian product of step 4.
*
* (a <.? ? sup b)
* (b = Number)
*/
UnifyType supB = tf.getSuperType(tphB);
eq = new HashSet<>();
eq.add(new UnifyPair(tphA, supB, PairOperator.SMALLERDOTWC));
eq.add(new UnifyPair(tphB, number, PairOperator.EQUALSDOT));
expected = new HashSet<>();
actual = unify(eq, fc);
System.out.println("Case 3");
System.out.println(actual);
//Assert.assertEquals(expected, actual);
/*
* Case 4 has no extension
*/
/*
* Test 5:
* This is a test for the extension of case 5 of the cartesian product of step 4.
*
* Vector<b> <. a
* b =. Number
*/
eq = new HashSet<>();
eq.add(new UnifyPair(tf.getSimpleType("HashSet", tphB), tphA, PairOperator.SMALLERDOT));
eq.add(new UnifyPair(tphB, number, PairOperator.EQUALSDOT));
expected = new HashSet<>();
actual = unify(eq, fc);
System.out.println(actual);
//Assert.assertEquals(expected, actual);
/*
* Test 6:
* This is a test for the extension of case 6 of the cartesian product of step 4.
*
* ? extends b <.? a
* b =. Integer
*/
eq = new HashSet<>();
eq.add(new UnifyPair(extB, tphA, PairOperator.SMALLERDOTWC));
eq.add(new UnifyPair(tphB, integer, PairOperator.EQUALSDOT));
expected = new HashSet<>();
actual = unify(eq, fc);
System.out.println(actual);
//Assert.assertEquals(expected, actual);
/*
* Test 7:
* This is a test for the extension of case 7 of the cartesian product of step 4.
*
* ? sup b <.? a
* b =. Number
*/
eq = new HashSet<>();
eq.add(new UnifyPair(supB, tphA, PairOperator.SMALLERDOTWC));
eq.add(new UnifyPair(tphB, number, PairOperator.EQUALSDOT));
expected = new HashSet<>();
actual = unify(eq, fc);
System.out.println("Case 7");
System.out.println(actual);
//Assert.assertEquals(expected, actual);
/*
* Test 8:
* This is a test for the extension of case 8 of the cartesian product of step 4.
*
* MyGeneric<? extends b> <.? a
* b =. Integer
*/
eq = new HashSet<>();
eq.add(new UnifyPair(tf.getSimpleType("MyGeneric", extB), tphA, PairOperator.SMALLERDOTWC));
eq.add(new UnifyPair(tphB, number, PairOperator.EQUALSDOT));
expected = new HashSet<>();
actual = unify(eq, fc);
System.out.println("Case 8:");
System.out.println(actual);
//Assert.assertEquals(expected, actual);
}
@Test
public void unifyTestComplex() {
/*