Iteration

This commit is contained in:
Daniel Holle 2023-06-15 14:13:15 +02:00
parent bb0ee7d517
commit 9eb0dd1cf5
2 changed files with 54 additions and 24 deletions

View File

@ -23,7 +23,7 @@ public abstract class GenerateGenerics {
private final ASTToTargetAST astToTargetAST;
public class TPH {
final TypePlaceholder wrap;
private final TypePlaceholder wrap;
TPH(TypePlaceholder wrap) {
this.wrap = wrap;
@ -212,6 +212,7 @@ public abstract class GenerateGenerics {
equality.put(entry.getKey(), to);
}
}
to.setVariance(from.getVariance());
equality.put(from, to);
referenced.remove(new TPH(from));
referenced.add(new TPH(to));
@ -292,8 +293,10 @@ public abstract class GenerateGenerics {
if (expressionReceiver.expr instanceof This) {
var optMethod = astToTargetAST.findMethod(owner, methodCall.name, methodCall.getArgumentList());
if (optMethod.isEmpty()) return;
var method = optMethod.get();
var generics = generics(owner, method);
var method2 = optMethod.get();
System.out.println("In: " + method.getName() + " Method: " + method2.getName());
System.out.println(simplifiedConstraints);
var generics = family(owner, method2);
// transitive and
var all = transitiveClosure(generics);
@ -325,6 +328,7 @@ public abstract class GenerateGenerics {
if (!T1s.contains(R1) || !T2s.contains(R2)) continue;
var newPair = new PairLT(R1, R2);
System.out.println("New pair: " + newPair);
newPairs.add(newPair);
if (!containsRelation(result, newPair))
@ -501,10 +505,10 @@ public abstract class GenerateGenerics {
abstract void generics(ClassOrInterface owner, Method method, Set<Pair> result, Set<TPH> javaTypeVariablesOfClass);
Set<Pair> family(ClassOrInterface owner, Method method) {
Set<Pair> result = new HashSet<>();
if (familyOfMethods.containsKey(method))
return familyOfMethods.get(method);
var result = new HashSet<Pair>();
familyOfMethods.put(method, result);
var classGenerics = generics(owner);
@ -524,19 +528,22 @@ public abstract class GenerateGenerics {
}
Set<Pair> generics(ClassOrInterface owner, Method method) {
if (computedGenericsOfMethods.containsKey(method))
return computedGenericsOfMethods.get(method);
if (computedGenericsOfMethods.containsKey(method)) {
var cached = computedGenericsOfMethods.get(method);
System.out.println("Cached " + method.getName() + ": " + cached);
return cached;
}
var result = new HashSet<Pair>();
computedGenericsOfMethods.put(method, result);
var classGenerics = generics(owner);
HashSet<TPH> typeVariablesOfClass = new HashSet<>();
for (var pair : classGenerics) {
typeVariablesOfClass.add(pair.left);
}
var result = new HashSet<>(family(owner, method));
computedGenericsOfMethods.put(method, result);
result.addAll(family(owner, method));
var referenced = new HashSet<TPH>();
@ -552,7 +559,7 @@ public abstract class GenerateGenerics {
generics(owner, method, result, referenced);
usedTPHsOfMethods.put(method, usedTphs);
addMissingObjectBounds(result, classGenerics, usedTphs);
normalize(result, classGenerics, usedTphs);
System.out.println(this.getClass().getSimpleName() + " " + method.name + ": " + result);
return result;
@ -631,16 +638,18 @@ public abstract class GenerateGenerics {
findTphs(field.getType(), referencedByClass);
}
addMissingObjectBounds(javaResult, null, referencedByClass);
normalize(javaResult, null, referencedByClass);
System.out.println(this.getClass().getSimpleName() + " Class " + classOrInterface.getClassName().getClassName() + ": " + javaResult);
return javaResult;
}
void addMissingObjectBounds(Set<Pair> result, Set<Pair> classGenerics, Set<TPH> usedTphs) {
void normalize(Set<Pair> result, Set<Pair> classGenerics, Set<TPH> usedTphs) {
outer:
for (var tph : usedTphs) {
for (var p1 : new HashSet<>(result)) {
if (p1 instanceof PairLT ptph && ptph.left.equals(ptph.right))
result.remove(p1); // TODO This is a bit strange
if (p1.left.equals(tph)) continue outer;
}
@ -683,12 +692,13 @@ public abstract class GenerateGenerics {
}
if (variance == 1) continue;
var start = chain.get(0);
var prev = start;
for (var i = 1; i < index; i++) {
var cur = chain.get(i);
if (!referenced.contains(cur)) continue;
addToEquality(cur.wrap, start.resolve(), referenced);
addToEquality(cur.resolve(), start.resolve(), referenced);
TPH finalPrev = prev;
input.removeIf(p -> p.equals(new PairLT(finalPrev, cur)));
for (var pair2 : new HashSet<>(input)) {
@ -722,13 +732,32 @@ public abstract class GenerateGenerics {
for (var field : classOrInterface.getFieldDecl()) {
findTphs(field.getType(), referenced);
}
doIterationForMethods(classOrInterface);
for (var method : classOrInterface.getMethods()) {
generics(classOrInterface, method);
referenced.addAll(usedTPHsOfMethods.get(method));
}
eliminateInnerTypeVariables(referenced, input);
}
void doIterationForMethods(ClassOrInterface classOrInterface) {
familyOfMethods.clear();
var oldFamily = new HashMap<Method, Set<Pair>>();
do {
oldFamily.clear();
oldFamily.putAll(familyOfMethods);
familyOfMethods.clear();
for (var method : classOrInterface.getMethods()) {
family(classOrInterface, method);
}
System.out.println(familyOfMethods);
} while(!oldFamily.equals(familyOfMethods));
for (var method : classOrInterface.getMethods()) {
generics(classOrInterface, method);
}
}
private void findChain(Set<TPH> referenced, Set<Pair> input, Set<Pair> output, TPH start, TPH end, Set<TPH> chain) {
if (referenced.contains(end)) {
var pair = new PairLT(start, end);
@ -793,7 +822,7 @@ public abstract class GenerateGenerics {
var right = cycle.get(i + 1);
var pair = new PairLT(left, right);
input.remove(pair);
addToEquality(left.wrap, newTph, referenced);
addToEquality(left.resolve(), newTph, referenced);
}
}
}
@ -806,9 +835,10 @@ public abstract class GenerateGenerics {
var left = constraint.left;
Set<PairLT> infima = new HashSet<>();
for (var pair : input) {
if (pair instanceof PairLT stph)
if (pair.left.wrap.equals(constraint.left.wrap))
if (pair instanceof PairLT stph) {
if (pair.left.equals(constraint.left))
infima.add(stph);
}
}
if (infima.size() > 1) {
foundInfima = true;
@ -826,19 +856,19 @@ public abstract class GenerateGenerics {
addToPairs(input, new PairLT(left, new TPH(newTph)));
input.removeAll(infima);
for (var infimum : infima) {
addToEquality(infimum.right.wrap, newTph, referenced);
addToEquality(infimum.right.resolve(), newTph, referenced);
new HashSet<>(input).forEach(pair -> {
if (pair.left.wrap.equals(infimum.right.wrap)) {
if (pair.left.equals(infimum.right)) {
input.remove(pair);
if (pair instanceof PairLT stph) {
if (!newTph.equals(stph.right.wrap))
if (!newTph.equals(stph.right.resolve()))
addToPairs(input, new PairLT(new TPH(newTph), stph.right));
} else if (pair instanceof PairEQ rtph) {
addToPairs(input, new PairEQ(new TPH(newTph), rtph.right));
}
} else if (pair instanceof PairLT stph && stph.right.wrap.equals(infimum.right.wrap)) {
} else if (pair instanceof PairLT stph && stph.right.equals(infimum.right)) {
input.remove(pair);
if (!newTph.equals(stph.left.wrap))
if (!newTph.equals(stph.left.resolve()))
addToPairs(input, new PairLT(stph.left, new TPH(newTph)));
}
});

View File

@ -15,7 +15,7 @@ final class JavaGenerics extends GenerateGenerics {
void generics(ClassOrInterface owner, Method method, Set<Pair> result, Set<TPH> referenced) {
eliminateCycles(result, referenced);
eliminateInfima(result, referenced);
//equalizeTypeVariables(result, referenced);
equalizeTypeVariables(result, referenced);
eliminateInnerTypeVariables(referenced, result);
}