From 27f6abefe85d140d8dc6b062d03b8d6f832d8cfd Mon Sep 17 00:00:00 2001 From: Florian Steurer Date: Tue, 12 Apr 2016 15:43:32 +0200 Subject: [PATCH] commenting and refactoring --- .../unify/model/FiniteClosure.java | 161 +++++++++++------- 1 file changed, 95 insertions(+), 66 deletions(-) diff --git a/src/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java b/src/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java index 1ad6f28b..17fbb240 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java +++ b/src/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java @@ -8,20 +8,35 @@ import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; -import de.dhbwstuttgart.typeinference.exceptions.NotImplementedException; import de.dhbwstuttgart.typeinference.unify.MartelliMontanariUnify; import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; import de.dhbwstuttgart.typeinference.unify.interfaces.IUnify; +/** + * The finite closure for the type unification + * @author Florian Steurer + */ public class FiniteClosure implements IFiniteClosure { - - private HashMap> inheritanceGraph; - private HashMap>> strInheritanceGraph; - private Set pairs; - //private Set 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) + /** + * A map that maps every type to the node in the inheritance graph that contains that type. + */ + private HashMap> inheritanceGraph; + + /** + * A map that maps every typename to the nodes of the inheritance graph that contain a type with that name. + */ + private HashMap>> strInheritanceGraph; + + /** + * The initial pairs of that define the inheritance tree + */ + private Set pairs; + + //TODO Prüfen: Typen ohne Kante im Graph als extra Menge im Konstruktor mitgeben? + /** + * Creates a new instance using the inheritance tree defined in the pairs. + */ public FiniteClosure(Set pairs) { this.pairs = new HashSet<>(pairs); inheritanceGraph = new HashMap>(); @@ -49,7 +64,6 @@ public class FiniteClosure implements IFiniteClosure { } // Build the alternative representation with strings as keys - strInheritanceGraph = new HashMap<>(); for(UnifyType key : inheritanceGraph.keySet()) { if(!strInheritanceGraph.containsKey(key.getName())) @@ -71,7 +85,12 @@ public class FiniteClosure implements IFiniteClosure { return computeSmaller(type); } + /** + * Computes the smaller functions for every type except FunNTypes. + */ private Set computeSmaller(UnifyType type) { + // Base Case: The type is in the inheritance tree. Add all children. + // This is Case 1 in the definition of the subtyping relation. if(inheritanceGraph.containsKey(type)) { Set result = new HashSet<>(); result.add(type); @@ -85,22 +104,22 @@ public class FiniteClosure implements IFiniteClosure { // if T = T' then T <=* T' result1.add(type); + // Permute all params with values that are in smArg() of that type. + // This corresponds to Case 3 in the definition of the subtyping relation. {ArrayList> paramCandidates = new ArrayList<>(); for (UnifyType param : type.getTypeParams()) paramCandidates.add(smArg(param)); - - Set permResult = permuteParams(paramCandidates); - - for (TypeParams newParams : permResult) - result1.add(type.setTypeParams(newParams));} - + permuteParams(paramCandidates).forEach(x -> result1.add(type.setTypeParams(x)));} + + // This is case 2 of the definition of the subtyping relation. Set result2 = new HashSet<>(); if (strInheritanceGraph.containsKey(type.getName())) { HashSet candidates = new HashSet<>(); + // All types with the same name strInheritanceGraph.get(type.getName()).forEach(x -> candidates.add(x.getContent())); - for(UnifyType typePrime : result1) { for (UnifyType theta2 : candidates) { + // Find the substitution Optional sigma2Opt = unify.unify(typePrime, theta2); if (!sigma2Opt.isPresent()) continue; @@ -120,6 +139,8 @@ public class FiniteClosure implements IFiniteClosure { else result2 = result1; + // Permute the params again. + // This corresponds again to Case 3 of the definition of the subtyping relation. Set result3 = new HashSet<>(); for(UnifyType t : result2) { ArrayList> paramCandidates = new ArrayList<>(); @@ -141,22 +162,23 @@ public class FiniteClosure implements IFiniteClosure { return result3; } + /** + * Computes the smaller-Function for FunNTypes. + */ private Set computeSmallerFunN(FunNType type) { Set result = new HashSet<>(); // if T = T' then T <=* T' result.add(type); + // Because real function types are implicitly variant + // it is enough to permute the params with the values of greater / smaller. ArrayList> paramCandidates = new ArrayList<>(); paramCandidates.add(smaller(type.getTypeParams().get(0))); for (int i = 1; i < type.getTypeParams().size(); i++) - paramCandidates.add(greater(type.getTypeParams().get(i))); + paramCandidates.add(greater(type.getTypeParams().get(i))); - Set permResult = permuteParams(paramCandidates); - - for (TypeParams newParams : permResult) - result.add(type.setTypeParams(newParams)); - + permuteParams(paramCandidates).forEach(x -> result.add(type.setTypeParams(x))); return result; } @@ -170,40 +192,44 @@ public class FiniteClosure implements IFiniteClosure { return computeGreaterFunN((FunNType) type); return computeGreater(type); } - + + /** + * Computes the greater function for all types except function types. + */ protected Set computeGreater(UnifyType type) { IUnify unify = new MartelliMontanariUnify(); Set result1 = new HashSet<>(); + // The type is in the inheritance tree. Add all children. + // This is Case 1 in the definition of the subtyping relation. if(inheritanceGraph.containsKey(type)) result1.addAll(inheritanceGraph.get(type).getContentOfPredecessors()); // if T = T' then T <=* T' result1.add(type); + // Permute all params with values that are in smArg() of that type. + // This corresponds to Case 3 in the definition of the subtyping relation. {ArrayList> paramCandidates = new ArrayList<>(); for (UnifyType param : type.getTypeParams()) paramCandidates.add(grArg(param)); - - Set permResult = new HashSet<>(); - permuteParams(paramCandidates, 0, permResult, new UnifyType[paramCandidates.size()]); - - for (TypeParams newParams : permResult) - result1.add(type.setTypeParams(newParams));} + permuteParams(paramCandidates).forEach(x -> result1.add(type.setTypeParams(x)));} + // This is case 2 of the definition of the subtyping relation. Set result2 = new HashSet<>(); if (strInheritanceGraph.containsKey(type.getName()) && !inheritanceGraph.containsKey(type)) { HashSet candidates = new HashSet<>(); + // All types with the same name strInheritanceGraph.get(type.getName()).forEach(x -> candidates.add(x.getContent())); for(UnifyType typePrime : result1) { for (UnifyType theta2 : candidates) { + // Find the substitution Optional sigma2Opt = unify.unify(typePrime, theta2); if (!sigma2Opt.isPresent()) continue; if(type.equals(theta2)) continue; - Unifier sigma2 = sigma2Opt.get(); sigma2.swapPlaceholderSubstitutions(typePrime.getTypeParams()); Set theta1s = greater(theta2); @@ -216,18 +242,17 @@ public class FiniteClosure implements IFiniteClosure { } } - result2.addAll(result1); + result2.addAll(result1); + // Permute the params again. + // This corresponds again to Case 3 of the definition of the subtyping relation. Set result3 = new HashSet<>(); for(UnifyType t : result2) { ArrayList> paramCandidates = new ArrayList<>(); for (UnifyType param : t.getTypeParams()) paramCandidates.add(grArg(param)); - Set permResult = new HashSet<>(); - permuteParams(paramCandidates, 0, permResult, new UnifyType[paramCandidates.size()]); - - for (TypeParams newParams : permResult) { + for (TypeParams newParams : permuteParams(paramCandidates)) { UnifyType tPrime = t.setTypeParams(newParams); if(tPrime.equals(t)) result3.add(t); @@ -240,22 +265,22 @@ public class FiniteClosure implements IFiniteClosure { return result3; } + /** + * Computes the greater function for FunN-Types + */ protected Set computeGreaterFunN(FunNType type) { Set result = new HashSet<>(); // if T = T' then T <=* T' result.add(type); + // Because real function types are implicitly variant + // it is enough to permute the params with the values of greater / smaller. ArrayList> 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 permResult = permuteParams(paramCandidates); - - for (TypeParams newParams : permResult) - result.add(type.setTypeParams(newParams)); - + permuteParams(paramCandidates).forEach(x -> result.add(type.setTypeParams(x))); return result; } @@ -267,29 +292,29 @@ public class FiniteClosure implements IFiniteClosure { @Override public Set grArg(ReferenceType type) { - Set result = new HashSet(); - + Set result = new HashSet(); 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 grArg(FunNType type) { - throw new NotImplementedException(); + // TODO ist das richtig? + Set result = new HashSet(); + 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 grArg(ExtendsType type) { Set result = new HashSet(); - result.add(type); - + result.add(type); UnifyType t = type.getExtendedType(); - greater(t).forEach(x -> result.add(new ExtendsType(x))); - return result; } @@ -297,20 +322,15 @@ public class FiniteClosure implements IFiniteClosure { public Set grArg(SuperType type) { Set result = new HashSet(); result.add(type); - - UnifyType t = type.getSuperedType(); - + UnifyType t = type.getSuperedType(); smaller(t).forEach(x -> result.add(new SuperType(x))); - return result; } @Override public Set grArg(PlaceholderType type) { HashSet result = new HashSet<>(); - result.add(type); - //result.add(new SuperType(type)); - //result.add(new ExtendsType(type)); + result.add(type); return result; } @@ -321,30 +341,29 @@ public class FiniteClosure implements IFiniteClosure { @Override public Set smArg(ReferenceType type) { - Set result = new HashSet(); - + Set result = new HashSet(); result.add(type); return result; } @Override public Set smArg(FunNType type) { - throw new NotImplementedException(); + // TODO ist das richtig? + Set result = new HashSet(); + result.add(type); + return result; } @Override public Set smArg(ExtendsType type) { Set result = new HashSet(); result.add(type); - UnifyType t = type.getExtendedType(); - result.add(t); smaller(t).forEach(x -> { result.add(new ExtendsType(x)); result.add(x); }); - return result; } @@ -352,16 +371,13 @@ public class FiniteClosure implements IFiniteClosure { @Override public Set smArg(SuperType type) { Set result = new HashSet(); - result.add(type); - + result.add(type); UnifyType t = type.getSuperedType(); - result.add(t); greater(t).forEach(x -> { result.add(new SuperType(x)); result.add(x); }); - return result; } @@ -409,12 +425,25 @@ public class FiniteClosure implements IFiniteClosure { return result; } + /** + * Takes a set of candidates for each position and computes all possible permutations. + * @param candidates The length of the list determines the number of type params. Each set + * contains the candidates for the corresponding position. + */ protected Set permuteParams(ArrayList> candidates) { Set result = new HashSet<>(); permuteParams(candidates, 0, result, new UnifyType[candidates.size()]); return result; } + /** + * Takes a set of candidates for each position and computes all possible permutations. + * @param candidates The length of the list determines the number of type params. Each set + * contains the candidates for the corresponding position. + * @param idx Idx for the current permutatiton. + * @param result Set of all permutations found so far + * @param current The permutation of type params that is currently explored + */ protected void permuteParams(ArrayList> candidates, int idx, Set result, UnifyType[] current) { if(candidates.size() == idx) { result.add(new TypeParams(Arrays.copyOf(current, current.length)));