Fixes for TPH4
This commit is contained in:
parent
99c46bf37f
commit
b58b6c2288
@ -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<ResultPair<?, ?>> generics) {
|
||||
TypePlaceholder finalName = equality.getOrDefault(name, name);
|
||||
return generics.stream().anyMatch(generic -> generic.getLeft().equals(finalName));
|
||||
}
|
||||
|
||||
boolean containsRelation(Set<ResultPair<?, ?>> 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<ResultPair<?, ?>> transitiveClosure(Set<ResultPair<?, ?>> generics) {
|
||||
Set<ResultPair<?, ?>> all = new HashSet<>(generics);
|
||||
HashSet<ResultPair<?, ?>> 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<ResultPair<?, ?>> generics(ClassOrInterface owner, Method method) {
|
||||
if (computedGenericsOfMethods.containsKey(method))
|
||||
@ -129,10 +145,10 @@ public class ASTToTargetAST {
|
||||
var simplifiedConstraints = new HashSet<>(this.simplifiedConstraints);
|
||||
|
||||
HashSet<TypePlaceholder> typeVariables = new HashSet<>();
|
||||
HashSet<TypePlaceholder> typeVariablesOfFields = new HashSet<>();
|
||||
HashSet<TypePlaceholder> 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<ResultPair<?, ?>> all = new HashSet<>(generics);
|
||||
|
||||
// Reflexive and Transitive closure
|
||||
HashSet<ResultPair<?, ?>> 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<ResultPair<?, ?>>();
|
||||
for (var generic : all) {
|
||||
toAdd.add(new PairTPHsmallerTPH((TypePlaceholder) generic.getLeft(), (TypePlaceholder) generic.getLeft()));
|
||||
}
|
||||
all.addAll(toAdd);
|
||||
|
||||
HashSet<PairTPHsmallerTPH> 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<arglist.getArguments().size();i++){
|
||||
superType = arglist.getArguments().get(i).getType();
|
||||
arglist.getArguments().get(i).accept(this);
|
||||
superType = arglist.getArguments().get(i).getType();
|
||||
arglist.getArguments().get(i).accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
// Type variables with bounds that are also type variables of fields
|
||||
var closure = transitiveClosure((Set) simplifiedConstraints);
|
||||
// Type variables with bounds that are also type variables of the class
|
||||
for (var typeVariable : new HashSet<>(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<PairTPHsmallerTPH>();
|
||||
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<TypePlaceholder>();
|
||||
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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user