diff --git a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java index 3ebd5430..841858dd 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java @@ -18,6 +18,7 @@ import de.dhbwstuttgart.typeinference.constraints.Pair; import de.dhbwstuttgart.typeinference.result.*; import java.util.*; +import java.util.concurrent.CyclicBarrier; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -170,7 +171,6 @@ public class ASTToTargetAST { for (var pair : simplifiedConstraints) { if (pair.left.equals(typeVariable) && typeVariables.contains(pair.right)) { addToPairs(result, new PairTPHsmallerTPH(pair.left, equality.getOrDefault(pair.right, pair.right))); - typeVariables.add(pair.right); } } } @@ -196,7 +196,7 @@ public class ASTToTargetAST { RefTypeOrTPHOrWildcardOrGeneric T2 = superType; if (T2 instanceof TypePlaceholder tph) T2 = equality.getOrDefault(tph, tph); - System.out.println("T1s: " + T1s + "\nT2: " + T2); + System.out.println("T1s: " + T1s + " T2: " + T2); //Ende superType = methodCall.receiverType; @@ -211,7 +211,7 @@ public class ASTToTargetAST { var optMethod = findMethod(owner, methodCall.name, methodCall.getArgumentList()); if (optMethod.isEmpty()) return; var method = optMethod.get(); - var generics = generics(owner, method).javaGenerics(); + var generics = generics(owner, method).txGenerics(); // transitive and var all = transitiveClosure(generics); @@ -226,24 +226,24 @@ public class ASTToTargetAST { // Loop from hell outer: - for (var tph : typeVariables) { - if (typeVariablesOfClass.contains(tph)) continue; + for (var R1 : typeVariables) { + if (typeVariablesOfClass.contains(R1)) continue; for (var generic : all) { if (!(generic.getRight() instanceof TypePlaceholder type)) continue; for (var pair : simplifiedConstraints) { - if (!(pair.left.equals(tph) && pair.right.equals(generic.getLeft()))) + if (!(pair.left.equals(R1) && pair.right.equals(generic.getLeft()))) continue; - for (var tph2 : typeVariables) { + for (var R2 : typeVariables) { for (var pair2 : simplifiedConstraints) { - if (!(pair2.right.equals(tph2) && pair2.left.equals(type))) + if (!(pair2.right.equals(R2) && pair2.left.equals(type))) continue; - if (tph.equals(tph2)) continue; - if (!T1s.contains(tph) || !tph2.equals(T2)) continue; + if (R1.equals(R2)) continue; + if (!T1s.contains(R1) || !R2.equals(T2)) continue; - var newPair = new PairTPHsmallerTPH(tph, tph2); + var newPair = new PairTPHsmallerTPH(R1, R2); newPairs.add(newPair); if (!containsRelation(result, newPair)) @@ -268,7 +268,7 @@ public class ASTToTargetAST { @Override public void visit(Assign assign) { - superType = assign.lefSide.getType(); + superType = assign.rightSide.getType(); assign.rightSide.accept(this); } @@ -521,9 +521,6 @@ public class ASTToTargetAST { super.visit(methodCall); typeVariables.addAll(findTypeVariables(methodCall.getType(), equality)); } - - @Override - public void visit(Assign assign) {} }); } @@ -557,7 +554,7 @@ public class ASTToTargetAST { var referenced = new HashSet(); eliminateCycles(javaResult, equality, referenced); - eliminateInfima(javaResult, equality, referenced); + eliminateInfima(javaResult, equality); var usedTphs = new HashSet(); // For eliminating inner type variables we need to figure out which ones are actually used @@ -575,7 +572,7 @@ public class ASTToTargetAST { { var referenced = new HashSet(); // JavaTX Generics - eliminateInfima(txResult, txEquality, referenced); + eliminateInfima(txResult, txEquality); for (var param : method.getParameterList().getFormalparalist()) { referenced.addAll(findTypeVariables(param.getType(), txEquality)); @@ -636,9 +633,9 @@ public class ASTToTargetAST { var referenced = new HashSet(); eliminateCycles(javaResult, equality, referenced); - eliminateInfima(javaResult, equality, referenced); + eliminateInfima(javaResult, equality); var txReferenced = new HashSet(); - eliminateInfima(txResult, txEquality, txReferenced); + eliminateInfima(txResult, txEquality); eliminateInnerTypeVariablesOfClass(classOrInterface, javaResult, equality, referenced); equalizeTypeVariables(javaResult, equality); @@ -649,19 +646,52 @@ public class ASTToTargetAST { } void equalizeTypeVariables(Set> input, Map equality) { - System.out.println(input); for (var pair : new HashSet<>(input)) { if (pair instanceof PairTPHsmallerTPH ptph) { - System.out.println(pair + " " + ptph.left.getVariance() + " " + ptph.right.getVariance()); - if (ptph.left.getVariance() == 1 && ptph.right.getVariance() == -1) { - addToEquality(equality, ptph.left, ptph.right); - input.remove(ptph); - for (var pair2 : new HashSet<>(simplifiedConstraints)) { - if (pair2.right.equals(ptph.left)) { - simplifiedConstraints.remove(pair2); - simplifiedConstraints.add(new PairTPHsmallerTPH(pair2.left, ptph.right)); + var chain = new ArrayList(); + chain.add(ptph.left); + chain.add(ptph.right); + + outer: while (true) { + var added = false; + for (var pair2 : input) { + if (pair2 instanceof PairTPHsmallerTPH ptph2 && ptph2.left.equals(chain.get(chain.size() - 1))) { + if (chain.contains(ptph2.right)) break outer; + chain.add(ptph2.right); + added = true; } } + if (!added) break; + } + + var variance = chain.get(0).getVariance(); + if (variance != 1) continue; + var index = 0; + for (var tph : chain) { + if (variance == 1 && tph.getVariance() == -1) { + variance = -1; + } + if (variance == -1 && tph.getVariance() == 1) { + break; + } + index++; + } + if (variance == 1) continue; + + var start = chain.get(0); + var prev = start; + for (var i = 1; i < index; i++) { + var cur = chain.get(i); + addToEquality(equality, cur, start); + input.remove(new PairTPHsmallerTPH(prev, chain.get(i))); + for (var pair2 : new HashSet<>(input)) { + // TODO Maybe this would be unnecessary if we were to add the = constraints later on + if (pair2 instanceof PairTPHequalRefTypeOrWildcardType && pair2.getLeft().equals(cur)) { + input.remove(pair2); + input.add(new PairTPHequalRefTypeOrWildcardType(start, pair2.getRight())); + } + } + prev = chain.get(i); } } } @@ -739,6 +769,15 @@ public class ASTToTargetAST { var cycles = findCycles(input); for (var cycle : cycles) { var newTph = TypePlaceholder.fresh(new NullToken()); + var variance = cycle.get(0).getVariance(); + for (var tph : cycle) { + if (tph.getVariance() != variance) { + variance = 0; + break; + } + } + newTph.setVariance(variance); + referenced.add(newTph); addToPairs(input, new PairTPHequalRefTypeOrWildcardType(newTph, OBJECT)); cycle.add(cycle.get(0)); // Make it a complete cycle @@ -752,7 +791,7 @@ public class ASTToTargetAST { } } - void eliminateInfima(Set> input, Map equality, Set referenced) { + void eliminateInfima(Set> input, Map equality) { var foundInfima = false; do { foundInfima = false; @@ -767,7 +806,16 @@ public class ASTToTargetAST { if (infima.size() > 1) { foundInfima = true; var newTph = TypePlaceholder.fresh(new NullToken()); - referenced.add(newTph); + var variance = infima.stream().findFirst().get().right.getVariance(); + for (var pair : infima) { + if (pair.right.getVariance() != variance) { + variance = 0; + break; + } + } + newTph.setVariance(variance); + + //referenced.add(newTph); addToPairs(input, new PairTPHsmallerTPH(left, newTph)); input.removeAll(infima); for (var infimum : infima) {