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