This commit is contained in:
Florian Steurer 2016-03-13 23:01:28 +01:00
parent 27acee3385
commit 6778160315
14 changed files with 103 additions and 75 deletions

View File

@ -4,7 +4,6 @@ import java.util.Optional;
import java.util.Set;
import de.dhbwstuttgart.typeinference.unify.model.MPair;
import de.dhbwstuttgart.typeinference.unifynew.Unifier;
public interface IRuleSet {

View File

@ -6,7 +6,7 @@ import java.util.Set;
import java.util.stream.Collectors;
import de.dhbwstuttgart.typeinference.unify.model.Type;
import de.dhbwstuttgart.typeinference.unifynew.Unifier;
import de.dhbwstuttgart.typeinference.unify.model.Unifier;
/**
* Standard unification algorithm (e.g. Robinson, Paterson-Wegman, Martelli-Montanari)

View File

@ -3,16 +3,30 @@ package de.dhbwstuttgart.typeinference.unify.model;
import java.util.Set;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unifynew.Unifier;
/**
* An extends wildcard type "? extends T".
*/
public final class ExtendsType extends Type {
/**
* The extended type
*/
private Type extendedType;
/**
* Creates a new extends wildcard type.
* @param extendedType The extended type e.g. Integer in "? extends Integer"
*/
public ExtendsType(Type extendedType) {
super("? extends " + extendedType.getName(), extendedType.getTypeParams());
this.extendedType = extendedType;
}
/**
* Gets the type extended by this wildcard e.g. "Integer" for "? extends Integer"
* @return The extended type.
*/
public Type getExtendedType() {
return extendedType;
}
@ -21,21 +35,21 @@ public final class ExtendsType extends Type {
public TypeParams getTypeParams() {
return extendedType.getTypeParams();
}
@Override
public String toString() {
return "? extends " + extendedType;
}
@Override
public Set<Type> smArg(IFiniteClosure fc) {
Set<Type> smArg(IFiniteClosure fc) {
return fc.smArg(this);
}
@Override
public Set<Type> grArg(IFiniteClosure fc) {
Set<Type> grArg(IFiniteClosure fc) {
return fc.grArg(this);
}
@Override
Type apply(Unifier unif) {
return new ExtendsType(extendedType.apply(unif));
}
@Override
public int hashCode() {
@ -50,9 +64,9 @@ public final class ExtendsType extends Type {
ExtendsType other = (ExtendsType) obj;
return other.getExtendedType().equals(extendedType);
}
@Override
public Type apply(Unifier unif) {
return new ExtendsType(extendedType.apply(unif));
public String toString() {
return "? extends " + extendedType;
}
}

View File

@ -3,7 +3,6 @@ package de.dhbwstuttgart.typeinference.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{
@ -12,12 +11,12 @@ public final class PlaceholderType extends Type{
}
@Override
public Set<Type> smArg(IFiniteClosure fc) {
Set<Type> smArg(IFiniteClosure fc) {
return fc.smArg(this);
}
@Override
public Set<Type> grArg(IFiniteClosure fc) {
Set<Type> grArg(IFiniteClosure fc) {
return fc.grArg(this);
}
@ -26,6 +25,13 @@ public final class PlaceholderType extends Type{
return typeName.hashCode();
}
@Override
Type apply(Unifier unif) {
if(unif.hasSubstitute(this))
return unif.getSubstitute(this);
return this;
}
@Override
public boolean equals(Object obj) {
if(!(obj instanceof PlaceholderType))
@ -33,11 +39,4 @@ public final class PlaceholderType extends Type{
return ((PlaceholderType) obj).getName().equals(typeName);
}
@Override
public Type apply(Unifier unif) {
if(unif.hasSubstitute(this))
return unif.getSubstitute(this);
return this;
}
}

View File

@ -3,7 +3,6 @@ package de.dhbwstuttgart.typeinference.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) {
@ -15,15 +14,20 @@ public final class SimpleType extends Type {
}
@Override
public Set<Type> smArg(IFiniteClosure fc) {
Set<Type> smArg(IFiniteClosure fc) {
return fc.smArg(this);
}
@Override
public Set<Type> grArg(IFiniteClosure fc) {
Set<Type> grArg(IFiniteClosure fc) {
return fc.grArg(this);
}
@Override
Type apply(Unifier unif) {
return new SimpleType(typeName, typeParams.apply(unif));
}
@Override
public int hashCode() {
return typeName.hashCode();
@ -41,9 +45,4 @@ public final class SimpleType extends Type {
return other.getTypeParams().equals(typeParams);
}
@Override
public Type apply(Unifier unif) {
return new SimpleType(typeName, typeParams.apply(unif));
}
}

View File

@ -3,7 +3,6 @@ package de.dhbwstuttgart.typeinference.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 {
@ -29,15 +28,20 @@ public final class SuperType extends Type {
}
@Override
public Set<Type> smArg(IFiniteClosure fc) {
Set<Type> smArg(IFiniteClosure fc) {
return fc.smArg(this);
}
@Override
public Set<Type> grArg(IFiniteClosure fc) {
Set<Type> grArg(IFiniteClosure fc) {
return fc.grArg(this);
}
@Override
Type apply(Unifier unif) {
return new SuperType(superedType.apply(unif));
}
@Override
public int hashCode() {
return superedType.hashCode() + 17;
@ -51,9 +55,4 @@ public final class SuperType extends Type {
SuperType other = (SuperType) obj;
return other.getSuperedType().equals(superedType);
}
@Override
public Type apply(Unifier unif) {
return new SuperType(superedType.apply(unif));
}
}

View File

@ -3,7 +3,6 @@ package de.dhbwstuttgart.typeinference.unify.model;
import java.util.Set;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unifynew.Unifier;
public abstract class Type {
@ -28,11 +27,11 @@ public abstract class Type {
return typeParams;
}
public abstract Set<Type> smArg(IFiniteClosure fc);
abstract Set<Type> smArg(IFiniteClosure fc);
public abstract Set<Type> grArg(IFiniteClosure fc);
abstract Set<Type> grArg(IFiniteClosure fc);
public abstract Type apply(Unifier unif);
abstract Type apply(Unifier unif);
@Override
public String toString() {

View File

@ -3,8 +3,6 @@ package de.dhbwstuttgart.typeinference.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;
@ -42,6 +40,20 @@ public final class TypeParams implements Iterable<Type>{
return new TypeParams(newParams);
}
public boolean occurs(PlaceholderType t) {
for(Type p : typeParams) {
if(p instanceof PlaceholderType) {
if(p.equals(t))
return true;
} else {
if(p.getTypeParams().occurs(t))
return true;
}
}
return false;
}
public boolean contains(Type t) {
for(Type t1 : typeParams)
if(t1.equals(t1))

View File

@ -1,13 +1,9 @@
package de.dhbwstuttgart.typeinference.unifynew;
package de.dhbwstuttgart.typeinference.unify.model;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.function.Function;
import de.dhbwstuttgart.typeinference.unify.model.MPair;
import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType;
import de.dhbwstuttgart.typeinference.unify.model.Type;
public class Unifier implements Function<Type, Type> {
private HashMap<PlaceholderType, Type> substitutions = new HashMap<>();

View File

@ -15,6 +15,7 @@ import de.dhbwstuttgart.typeinference.unify.model.MPair.PairOperator;
import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType;
import de.dhbwstuttgart.typeinference.unify.model.Type;
import de.dhbwstuttgart.typeinference.unify.model.TypeParams;
import de.dhbwstuttgart.typeinference.unify.model.Unifier;
/**
* Implementation of the Martelli-Montanari unification algorithm.

View File

@ -20,6 +20,7 @@ import de.dhbwstuttgart.typeinference.unify.model.SimpleType;
import de.dhbwstuttgart.typeinference.unify.model.SuperType;
import de.dhbwstuttgart.typeinference.unify.model.Type;
import de.dhbwstuttgart.typeinference.unify.model.TypeParams;
import de.dhbwstuttgart.typeinference.unify.model.Unifier;
import de.dhbwstuttgart.typeinference.unify.model.MPair.PairOperator;
public class RuleSet implements IRuleSet{
@ -534,35 +535,28 @@ public class RuleSet implements IRuleSet{
typeMap.put(t2, typeMap.get(t2)+1);
}
Queue<MPair> result = new LinkedList<MPair>(pairs);
ArrayList<MPair> result = new ArrayList<MPair>(pairs);
boolean applied = false;
for(int i = 0; i < result.size(); i++) {
MPair pair = result.poll();
Type lhsType;
MPair pair = result.get(i);
PlaceholderType lhsType = null;
Type rhsType;
if(pair.getPairOp() == PairOperator.EQUALSDOT
&& ((lhsType = pair.getLhsType()) instanceof PlaceholderType)
if(pair.getPairOp() == PairOperator.EQUALSDOT
&& pair.getLhsType() instanceof PlaceholderType)
lhsType = (PlaceholderType) pair.getLhsType();
if(lhsType != null
&& !((rhsType = pair.getRhsType()) instanceof PlaceholderType)
&& typeMap.get(lhsType) > 1 // The type occurs in more pairs in the set than just the recent pair.
&& !occurs(lhsType, rhsType)) {
Unifier uni = new Unifier((PlaceholderType) lhsType, rhsType);
result = result.stream().map(uni::apply).collect(Collectors.toCollection(LinkedList::new));
&& !rhsType.getTypeParams().occurs(lhsType)) {
Unifier uni = new Unifier(lhsType, rhsType);
result = result.stream().map(uni::apply).collect(Collectors.toCollection(ArrayList::new));
applied = true;
}
result.add(pair);
}
return applied ? Optional.of(new HashSet<>(result)) : Optional.empty();
}
private boolean occurs(Type t1, Type t2) {
TypeParams t2Params = t2.getTypeParams();
for(Type t2Param : t2Params)
if(t1.equals(t2Param) || occurs(t1, t2Param))
return true;
return false;
}
}

View File

@ -70,8 +70,8 @@ public class Unify {
// Sets that originate from pair pattern matching
// Sets of the "second level"
sets.addAll(calculatePairSets(eq2s, fc));
sets.addAll(calculatePairSets(eq2s, fc));
/* Up to here, no cartesian products are calculated.
* Around here, filters for pairs and sets can be applied */
@ -105,7 +105,7 @@ public class Unify {
else
unchanged.add(eqss);
}
/*
* Step 6 a) Restart for pairs where subst was applied
@ -116,7 +116,7 @@ public class Unify {
unchanged.addAll(this.unify(eqss, fc));
/*
* Step 7: Filter result for solved pairs
* Step 7: Filter result for solved pairs TODO wie?
*/
return unchanged;
@ -228,13 +228,21 @@ public class Unify {
IUnify unify = new MartelliMontanariUnify();
Set<Type> possibleCs = fc.getAllTypes(rhsType.getName());
/*IUnify unify = new MartelliMontanariUnify();
Set<Type> possibleCs = fc.getAllTypes(rhsType.getName());
Set<Type> possibleThetas = possibleCs.stream()
.flatMap(x -> fc.smaller(x).stream())
.collect(Collectors.toCollection(HashSet::new));
Set<Type> possibleThetaPrimes = possibleThetas.stream()
.flatMap(x -> getAllInstantiations(x, fc).stream())
.collect(Collectors.toCollection(HashSet::new));
*/
// TODO
/*Set<Unifier> unifiers = possibleThetaPrimes.stream()
@ -263,7 +271,7 @@ public class Unify {
// Case 2: (a <.? ? ext Theta')
else if(pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof PlaceholderType && rhsType instanceof ExtendsType){
// TODO
throw new NotImplementedException(); // TODO
}
// Case 3: (a <.? ? sup Theta')
@ -299,7 +307,7 @@ public class Unify {
// Case 7: (? sup Theta <.? a)
else if(pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof SuperType && rhsType instanceof PlaceholderType) {
// TODO
throw new NotImplementedException(); // TODO
}
// Case 8: (Theta <.? a)

View File

@ -7,6 +7,7 @@ import org.junit.Test;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unify.model.MPair;
import de.dhbwstuttgart.typeinference.unify.model.MPair.PairOperator;
import de.dhbwstuttgart.typeinference.unify.model.Type;
public class FiniteClosureTest {
@ -54,4 +55,10 @@ public class FiniteClosureTest {
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
}
}

View File

@ -31,8 +31,9 @@ public class UnifyTest extends Unify {
// 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.getSimpleType("Vector", tf.getSimpleType("Number")), tf.getSimpleType("Vector", "A"), PairOperator.SMALLERDOT));
//eq.add(new MPair(tf.getSimpleType("Vector", tf.getSimpleType("Integer")), tf.getSimpleType("Vector", "C"), PairOperator.SMALLERDOT));
eq.add(new MPair(tf.getPlaceholderType("A"), tf.getSimpleType("Integer"), PairOperator.SMALLERDOT));
//eq.add(new MPair(tf.getPlaceholderType("A"), tf.getSimpleType("Integer"), PairOperator.SMALLERDOT));
//eq.add(new MPair(tf.getSimpleType("Number"), tf.getPlaceholderType("A"), 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));