From b58b6c228834ac13245e7d6275ec72b04c6dcb11 Mon Sep 17 00:00:00 2001 From: Victorious3 Date: Tue, 21 Feb 2023 10:28:00 +0100 Subject: [PATCH] Fixes for TPH4 --- .../target/generate/ASTToTargetAST.java | 146 +++++++++++------- 1 file changed, 89 insertions(+), 57 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java index d82d658d..b33f4ea4 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java @@ -14,6 +14,7 @@ import de.dhbwstuttgart.target.tree.*; import de.dhbwstuttgart.target.tree.expression.TargetBlock; import de.dhbwstuttgart.target.tree.expression.TargetExpression; import de.dhbwstuttgart.target.tree.type.*; +import de.dhbwstuttgart.typeinference.constraints.Pair; import de.dhbwstuttgart.typeinference.result.*; import java.util.*; @@ -80,11 +81,6 @@ public class ASTToTargetAST { return result; } - boolean hasBound(TypePlaceholder name, Set> generics) { - TypePlaceholder finalName = equality.getOrDefault(name, name); - return generics.stream().anyMatch(generic -> generic.getLeft().equals(finalName)); - } - boolean containsRelation(Set> result, PairTPHsmallerTPH pair) { // Check if both the right and the left are already part of a relation var containsLeft = false; @@ -117,6 +113,26 @@ public class ASTToTargetAST { input.add(pair); } + static Set> transitiveClosure(Set> generics) { + Set> all = new HashSet<>(generics); + HashSet> toAdd = new HashSet<>(); + int sizeBefore; + do { + sizeBefore = all.size(); + toAdd.clear(); + for (var g1 : all) { + for (var g2 : all) { + if (g1 instanceof PairTPHsmallerTPH pair) { + if (g2.getLeft().equals(pair.getRight()) && g2.getRight() instanceof TypePlaceholder right) + toAdd.add(new PairTPHsmallerTPH(pair.left, right)); + } + } + } + all.addAll(toAdd); + } while (sizeBefore < all.size()); + return all; + } + // Family of generated Generics Set> generics(ClassOrInterface owner, Method method) { if (computedGenericsOfMethods.containsKey(method)) @@ -129,10 +145,10 @@ public class ASTToTargetAST { var simplifiedConstraints = new HashSet<>(this.simplifiedConstraints); HashSet typeVariables = new HashSet<>(); - HashSet typeVariablesOfFields = new HashSet<>(); + HashSet typeVariablesOfClass = new HashSet<>(); - for (var field : owner.getFieldDecl()) { - typeVariablesOfFields.addAll(findTypeVariables(field.getType())); + for (var pair : genericsOfClass) { + typeVariablesOfClass.add((TypePlaceholder) pair.getLeft()); } typeVariables.addAll(findTypeVariables(method.getReturnType())); @@ -159,6 +175,7 @@ public class ASTToTargetAST { // Type variables with bounds that are also type variables of the method for (var typeVariable : new HashSet<>(typeVariables)) { + if (typeVariablesOfClass.contains(typeVariable)) continue; 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))); @@ -167,7 +184,6 @@ public class ASTToTargetAST { } } - method.block.accept(new TracingStatementVisitor() { private RefTypeOrTPHOrWildcardOrGeneric superType = new Void(new NullToken()); @@ -206,33 +222,22 @@ public class ASTToTargetAST { var method = optMethod.get(); var generics = generics(owner, method); - Set> all = new HashSet<>(generics); - // Reflexive and Transitive closure - HashSet> toAdd = new HashSet<>(); - int sizeBefore; - do { - sizeBefore = all.size(); - toAdd.clear(); - for (var g1 : all) { - for (var g2 : all) { - if (g1 instanceof PairTPHsmallerTPH pair) { - if (g2.getLeft().equals(pair.getLeft()) && generics.stream().anyMatch(generic -> generic.getLeft().equals(pair.getRight()))) - toAdd.add(new PairTPHsmallerTPH(pair.left, pair.right)); - } - } - } - all.addAll(toAdd); - } while (sizeBefore < all.size()); + // transitive and + var all = transitiveClosure(generics); + // reflexive + var toAdd = new HashSet>(); for (var generic : all) { toAdd.add(new PairTPHsmallerTPH((TypePlaceholder) generic.getLeft(), (TypePlaceholder) generic.getLeft())); } all.addAll(toAdd); + HashSet newPairs = new HashSet<>(); // Loop from hell outer: for (var tph : typeVariables) { + if (typeVariablesOfClass.contains(tph)) continue; for (var generic : all) { if (!(generic.getRight() instanceof TypePlaceholder type)) continue; @@ -267,19 +272,19 @@ public class ASTToTargetAST { @Override public void visit(LambdaExpression lambdaExpression) { - superType = new Void(new NullToken()); + superType = new Void(new NullToken()); lambdaExpression.methodBody.accept(this); } @Override public void visit(Assign assign) { - superType = assign.lefSide.getType(); + superType = assign.lefSide.getType(); assign.rightSide.accept(this); } @Override public void visit(BinaryExpr binary) { - superType = new Void(new NullToken()); + superType = new Void(new NullToken()); binary.lexpr.accept(this); superType = new Void(new NullToken()); binary.rexpr.accept(this); @@ -288,7 +293,7 @@ public class ASTToTargetAST { @Override public void visit(Block block) { for (var expr : block.statements) { - superType = new Void(new NullToken()); + superType = new Void(new NullToken()); expr.accept(this); } } @@ -315,9 +320,9 @@ public class ASTToTargetAST { @Override public void visit(IfStmt ifStmt) { - superType = new Void(new NullToken()); - ifStmt.expr.accept(this); - superType = new Void(new NullToken()); + superType = new Void(new NullToken()); + ifStmt.expr.accept(this); + superType = new Void(new NullToken()); ifStmt.then_block.accept(this); superType = new Void(new NullToken()); ifStmt.else_block.accept(this); @@ -350,7 +355,7 @@ public class ASTToTargetAST { @Override public void visit(Return aReturn) { - superType = aReturn.getType(); + superType = aReturn.getType(); aReturn.retexpr.accept(this); } @@ -376,9 +381,9 @@ public class ASTToTargetAST { @Override public void visit(WhileStmt whileStmt) { - superType = new Void(new NullToken()); - whileStmt.expr.accept(this); - superType = new Void(new NullToken()); + superType = new Void(new NullToken()); + whileStmt.expr.accept(this); + superType = new Void(new NullToken()); whileStmt.loopBlock.accept(this); } @@ -416,36 +421,67 @@ public class ASTToTargetAST { public void visit(Literal literal) { } - @Override + @Override public void visit(ArgumentList arglist) { for(int i = 0;i(typeVariables)) { - for (var pair : simplifiedConstraints) { - if (pair.left.equals(typeVariable) && typeVariablesOfFields.contains(pair.right)) { - addToPairs(result, new PairTPHsmallerTPH(pair.left, equality.getOrDefault(pair.right, pair.right))); - typeVariables.add(pair.right); + if (typeVariablesOfClass.contains(typeVariable)) continue; + + var pairs = new HashSet(); + for (var pair : closure) { + if (!(pair instanceof PairTPHsmallerTPH ptph)) continue; + if (ptph.left.equals(typeVariable) && typeVariablesOfClass.contains(ptph.right)) { + pairs.add(new PairTPHsmallerTPH(ptph.left, equality.getOrDefault(ptph.right, ptph.right))); } } + + // Find the closest pair with the minimum amount of steps + PairTPHsmallerTPH minimalPair = null; + var minSteps = Integer.MAX_VALUE; + for (var pair : pairs) { + var left = pair.left; + var visited = new HashSet(); + var steps = 0; + while (!left.equals(pair.right)) { + visited.add(left); + var found = false; + for (var pair2 : simplifiedConstraints) { + if (left.equals(pair2.left) && !visited.contains(pair2.right)) { + left = pair2.right; + steps += 1; + found = true; + break; + } + } + if (!found) break; + } + if (steps < minSteps) { + minSteps = steps; + minimalPair = pair; + } + } + + if (minimalPair != null) + addToPairs(result, minimalPair); } // All unbounded type variables (bounds not in method) outer: for (var typeVariable : typeVariables) { - for (var pair : simplifiedConstraints) { - if (pair.left.equals(typeVariable) && typeVariables.contains(pair.right)) + if (typeVariablesOfClass.contains(typeVariable)) continue; + for (var pair : result) { + if (pair.getLeft().equals(typeVariable)) continue outer; } - if (!hasBound(typeVariable, genericsOfClass)) - addToPairs(result, new PairTPHequalRefTypeOrWildcardType(typeVariable, OBJECT)); + addToPairs(result, new PairTPHequalRefTypeOrWildcardType(typeVariable, OBJECT)); } // All unbounded bounds @@ -455,7 +491,7 @@ public class ASTToTargetAST { if (pair.right.equals(pair2.left)) continue outer; } - if (!hasBound(pair.right, genericsOfClass) && typeVariables.contains(pair.right)) { + if (!typeVariablesOfClass.contains(pair.right) && typeVariables.contains(pair.right)) { addToPairs(result, new PairTPHequalRefTypeOrWildcardType(pair.right, OBJECT)); } } @@ -468,10 +504,7 @@ public class ASTToTargetAST { referenced.addAll(findTypeVariables(param.getType())); } referenced.addAll(findTypeVariables(method.getReturnType())); - for (var g : genericsOfClass) { - if (g.getLeft() instanceof TypePlaceholder left) - referenced.add(left); - } + referenced.addAll(typeVariablesOfClass); eliminateInnerTypeVariables(referenced, result); usedTPHsOfMethods.put(method, referenced); @@ -524,7 +557,6 @@ public class ASTToTargetAST { eliminateInnerTypeVariablesOfClass(classOrInterface, result); equalizeTypeVariables(result); - System.out.println("Class " + classOrInterface.getClassName().getClassName() + ": " + result); return result; }