Split up equality

This commit is contained in:
Victorious3 2023-03-01 14:55:13 +01:00
parent 3de89a5cfa
commit 11eb03cdf0
2 changed files with 214 additions and 194 deletions

View File

@ -36,7 +36,7 @@ public class ASTToTargetAST {
return all.stream().map(GenericsResult::new).toList(); return all.stream().map(GenericsResult::new).toList();
} }
record Generics(Set<ResultPair<?, ?>> javaGenerics, Set<TargetGeneric> txGenerics) {} record Generics(Set<ResultPair<?, ?>> javaGenerics, Set<ResultPair<?, ?>> txGenerics) {}
class Sigma { class Sigma {
Map<Method, Generics> computedGenericsOfMethods = new HashMap<>(); Map<Method, Generics> computedGenericsOfMethods = new HashMap<>();
@ -46,6 +46,7 @@ public class ASTToTargetAST {
Set<PairTPHsmallerTPH> simplifiedConstraints = new HashSet<>(); Set<PairTPHsmallerTPH> simplifiedConstraints = new HashSet<>();
Map<TypePlaceholder, RefTypeOrTPHOrWildcardOrGeneric> concreteTypes = new HashMap<>(); Map<TypePlaceholder, RefTypeOrTPHOrWildcardOrGeneric> concreteTypes = new HashMap<>();
Map<TypePlaceholder, TypePlaceholder> equality = new HashMap<>(); Map<TypePlaceholder, TypePlaceholder> equality = new HashMap<>();
Map<TypePlaceholder, TypePlaceholder> txEquality = new HashMap<>();
Sigma(ResultSet constraints) { Sigma(ResultSet constraints) {
ASTToTargetAST.this.sigma = this; ASTToTargetAST.this.sigma = this;
@ -55,6 +56,7 @@ public class ASTToTargetAST {
simplifiedConstraints.add(p); simplifiedConstraints.add(p);
} else if (constraint instanceof PairTPHEqualTPH p) { } else if (constraint instanceof PairTPHEqualTPH p) {
equality.put(p.getLeft(), p.getRight()); equality.put(p.getLeft(), p.getRight());
txEquality.put(p.getLeft(), p.getRight());
} else if (constraint instanceof PairTPHequalRefTypeOrWildcardType p) { } else if (constraint instanceof PairTPHequalRefTypeOrWildcardType p) {
concreteTypes.put(this.equality.getOrDefault(p.left, p.left), p.right); concreteTypes.put(this.equality.getOrDefault(p.left, p.left), p.right);
} }
@ -63,22 +65,22 @@ public class ASTToTargetAST {
System.out.println("Simplified constraints: " + simplifiedConstraints); System.out.println("Simplified constraints: " + simplifiedConstraints);
} }
Set<TypePlaceholder> findTypeVariables(RefTypeOrTPHOrWildcardOrGeneric type) { Set<TypePlaceholder> findTypeVariables(RefTypeOrTPHOrWildcardOrGeneric type, Map<TypePlaceholder, TypePlaceholder> equality) {
var result = new HashSet<TypePlaceholder>(); var result = new HashSet<TypePlaceholder>();
if (type instanceof TypePlaceholder tph) { if (type instanceof TypePlaceholder tph) {
tph = equality.getOrDefault(tph, tph); tph = equality.getOrDefault(tph, tph);
if (concreteTypes.containsKey(tph)) { if (concreteTypes.containsKey(tph)) {
result.addAll(findTypeVariables(concreteTypes.get(tph))); result.addAll(findTypeVariables(concreteTypes.get(tph), equality));
return result; return result;
} }
result.add(tph); result.add(tph);
} else if (type instanceof RefType refType) { } else if (type instanceof RefType refType) {
for (var t : refType.getParaList()) for (var t : refType.getParaList())
result.addAll(findTypeVariables(t)); result.addAll(findTypeVariables(t, equality));
} else if (type instanceof ExtendsWildcardType wildcardType) { } else if (type instanceof ExtendsWildcardType wildcardType) {
result.addAll(findTypeVariables(wildcardType.getInnerType())); result.addAll(findTypeVariables(wildcardType.getInnerType(), equality));
} else if (type instanceof SuperWildcardType wildcardType) { } else if (type instanceof SuperWildcardType wildcardType) {
result.addAll(findTypeVariables(wildcardType.getInnerType())); result.addAll(findTypeVariables(wildcardType.getInnerType(), equality));
} }
return result; return result;
} }
@ -135,144 +137,115 @@ public class ASTToTargetAST {
return all; return all;
} }
// Family of generated Generics private void methodFindConstraints(
Generics generics(ClassOrInterface owner, Method method) { ClassOrInterface owner, Method method,
if (computedGenericsOfMethods.containsKey(method)) Set<PairTPHsmallerTPH> simplifiedConstraints,
return computedGenericsOfMethods.get(method); HashSet<TypePlaceholder> typeVariables,
HashSet<TypePlaceholder> typeVariablesOfClass,
Set<ResultPair<?, ?>> txResult = new HashSet<>(); Set<ResultPair<?, ?>> result,
Set<ResultPair<?, ?>> javaResult = new HashSet<>(); Map<TypePlaceholder, TypePlaceholder> equality
Set<TargetGeneric> generatedTxGenerics = new HashSet<>(); ) {
var generics = new Generics(javaResult, generatedTxGenerics);
computedGenericsOfMethods.put(method, generics);
var genericsOfClass = generics(owner).javaGenerics();
var simplifiedConstraints = new HashSet<>(this.simplifiedConstraints);
HashSet<TypePlaceholder> typeVariables = new HashSet<>();
HashSet<TypePlaceholder> typeVariablesOfClass = new HashSet<>();
for (var pair : genericsOfClass) {
typeVariablesOfClass.add((TypePlaceholder) pair.getLeft());
}
typeVariables.addAll(findTypeVariables(method.getReturnType()));
for (var arg : method.getParameterList().getFormalparalist()) {
typeVariables.addAll(findTypeVariables(arg.getType()));
}
method.block.accept(new TracingStatementVisitor() {
@Override
public void visit(LocalVarDecl localVarDecl) {
typeVariables.addAll(findTypeVariables(localVarDecl.getType()));
}
@Override
public void visit(MethodCall methodCall) {
super.visit(methodCall);
typeVariables.addAll(findTypeVariables(methodCall.getType()));
}
@Override
public void visit(Assign assign) {}
});
// Type variables with bounds that are also type variables of the method // Type variables with bounds that are also type variables of the method
for (var typeVariable : new HashSet<>(typeVariables)) { for (var typeVariable : new HashSet<>(typeVariables)) {
if (typeVariablesOfClass.contains(typeVariable)) continue; if (typeVariablesOfClass.contains(typeVariable)) continue;
for (var pair : simplifiedConstraints) { for (var pair : simplifiedConstraints) {
if (pair.left.equals(typeVariable) && typeVariables.contains(pair.right)) { if (pair.left.equals(typeVariable) && typeVariables.contains(pair.right)) {
addToPairs(txResult, new PairTPHsmallerTPH(pair.left, equality.getOrDefault(pair.right, pair.right))); addToPairs(result, new PairTPHsmallerTPH(pair.left, equality.getOrDefault(pair.right, pair.right)));
typeVariables.add(pair.right); typeVariables.add(pair.right);
} }
} }
} }
method.block.accept(new TracingStatementVisitor() { method.block.accept(new TracingStatementVisitor() {
private RefTypeOrTPHOrWildcardOrGeneric superType = new Void(new NullToken()); private RefTypeOrTPHOrWildcardOrGeneric superType = new Void(new NullToken());
@Override @Override
public void visit(MethodCall methodCall) { public void visit(MethodCall methodCall) {
//Anfang es werden Paare von TPHs gespeichert, die bei den Generated Generics ueber die Methodengrenzen hinweg //Anfang es werden Paare von TPHs gespeichert, die bei den Generated Generics ueber die Methodengrenzen hinweg
//betrachtet werden muessen //betrachtet werden muessen
//Definition 7.2 (Family of generated generics). T1 <. R1 <.^ R2 <. T2 //Definition 7.2 (Family of generated generics). T1 <. R1 <.^ R2 <. T2
Set<RefTypeOrTPHOrWildcardOrGeneric> T1s = Set<RefTypeOrTPHOrWildcardOrGeneric> T1s =
methodCall.getArgumentList() methodCall.getArgumentList()
.getArguments() .getArguments()
.stream() .stream()
.map(TypableStatement::getType) .map(TypableStatement::getType)
.collect(Collectors.toCollection(HashSet::new)) .collect(Collectors.toCollection(HashSet::new))
.stream().filter(x -> x instanceof TypePlaceholder) .stream().filter(x -> x instanceof TypePlaceholder)
.map(tph -> equality.getOrDefault(tph, (TypePlaceholder) tph)) .map(tph -> equality.getOrDefault(tph, (TypePlaceholder) tph))
.collect(Collectors.toCollection(HashSet::new)); .collect(Collectors.toCollection(HashSet::new));
RefTypeOrTPHOrWildcardOrGeneric T2 = superType; RefTypeOrTPHOrWildcardOrGeneric T2 = superType;
if (T2 instanceof TypePlaceholder tph) T2 = equality.getOrDefault(tph, tph); if (T2 instanceof TypePlaceholder tph) T2 = equality.getOrDefault(tph, tph);
System.out.println("T1s: " + T1s + "\nT2: " + T2); System.out.println("T1s: " + T1s + "\nT2: " + T2);
//Ende //Ende
superType = methodCall.receiverType; superType = methodCall.receiverType;
methodCall.receiver.accept(this); methodCall.receiver.accept(this);
for(int i = 0;i<methodCall.arglist.getArguments().size();i++){ for(int i = 0;i<methodCall.arglist.getArguments().size();i++){
superType = methodCall.signature.get(i); superType = methodCall.signature.get(i);
methodCall.arglist.getArguments().get(i).accept(this); methodCall.arglist.getArguments().get(i).accept(this);
} }
if (methodCall.receiver instanceof ExpressionReceiver expressionReceiver) { if (methodCall.receiver instanceof ExpressionReceiver expressionReceiver) {
if (expressionReceiver.expr instanceof This) { if (expressionReceiver.expr instanceof This) {
var optMethod = findMethod(owner, methodCall.name, methodCall.getArgumentList()); var optMethod = findMethod(owner, methodCall.name, methodCall.getArgumentList());
if (optMethod.isEmpty()) return; if (optMethod.isEmpty()) return;
var method = optMethod.get(); var method = optMethod.get();
var generics = generics(owner, method).javaGenerics(); var generics = generics(owner, method).javaGenerics();
// transitive and // transitive and
var all = transitiveClosure(generics); var all = transitiveClosure(generics);
// reflexive // reflexive
var toAdd = new HashSet<ResultPair<?, ?>>(); var toAdd = new HashSet<ResultPair<?, ?>>();
for (var generic : all) { for (var generic : all) {
toAdd.add(new PairTPHsmallerTPH((TypePlaceholder) generic.getLeft(), (TypePlaceholder) generic.getLeft())); toAdd.add(new PairTPHsmallerTPH((TypePlaceholder) generic.getLeft(), (TypePlaceholder) generic.getLeft()));
} }
all.addAll(toAdd); all.addAll(toAdd);
HashSet<PairTPHsmallerTPH> newPairs = new HashSet<>(); HashSet<PairTPHsmallerTPH> newPairs = new HashSet<>();
// Loop from hell System.out.println("XXXX");
outer: System.out.println(typeVariables);
for (var tph : typeVariables) { System.out.println(typeVariablesOfClass);
if (typeVariablesOfClass.contains(tph)) continue; System.out.println(simplifiedConstraints);
for (var generic : all) { System.out.println(result);
if (!(generic.getRight() instanceof TypePlaceholder type)) System.out.println("XXXX");
continue; // Loop from hell
outer:
for (var tph : typeVariables) {
if (typeVariablesOfClass.contains(tph)) continue;
for (var generic : all) {
if (!(generic.getRight() instanceof TypePlaceholder type))
continue;
for (var pair : simplifiedConstraints) { for (var pair : simplifiedConstraints) {
if (!(pair.left.equals(tph) && pair.right.equals(generic.getLeft()))) if (!(pair.left.equals(tph) && pair.right.equals(generic.getLeft())))
continue; continue;
for (var tph2 : typeVariables) { for (var tph2 : typeVariables) {
for (var pair2 : simplifiedConstraints) { for (var pair2 : simplifiedConstraints) {
if (!(pair2.right.equals(tph2) && pair2.left.equals(type))) if (!(pair2.right.equals(tph2) && pair2.left.equals(type)))
continue; continue;
if (tph.equals(tph2)) continue; if (tph.equals(tph2)) continue;
if (!T1s.contains(tph) || !tph2.equals(T2)) continue; if (!T1s.contains(tph) || !tph2.equals(T2)) continue;
var newPair = new PairTPHsmallerTPH(tph, tph2); var newPair = new PairTPHsmallerTPH(tph, tph2);
newPairs.add(newPair); newPairs.add(newPair);
if (!containsRelation(txResult, newPair)) if (!containsRelation(result, newPair))
addToPairs(txResult, newPair); addToPairs(result, newPair);
continue outer; continue outer;
} }
} }
} }
} }
} }
simplifiedConstraints.addAll(newPairs); simplifiedConstraints.addAll(newPairs);
} }
} }
} }
@Override @Override
@ -475,18 +448,19 @@ public class ASTToTargetAST {
} }
if (minimalPair != null) if (minimalPair != null)
addToPairs(txResult, minimalPair); addToPairs(result, minimalPair);
} }
// All unbounded type variables (bounds not in method) // All unbounded type variables (bounds not in method)
outer: outer:
for (var typeVariable : typeVariables) { for (var typeVariable : typeVariables) {
if (typeVariablesOfClass.contains(typeVariable)) continue; if (typeVariablesOfClass.contains(typeVariable)) continue;
for (var pair : txResult) { for (var pair : result) {
if (pair.getLeft().equals(typeVariable)) if (pair.getLeft().equals(typeVariable))
continue outer; continue outer;
} }
addToPairs(txResult, new PairTPHequalRefTypeOrWildcardType(typeVariable, OBJECT)); addToPairs(result, new PairTPHequalRefTypeOrWildcardType(typeVariable, OBJECT));
} }
// All unbounded bounds // All unbounded bounds
@ -497,63 +471,112 @@ public class ASTToTargetAST {
continue outer; continue outer;
} }
if (!typeVariablesOfClass.contains(pair.right) && typeVariables.contains(pair.right)) { if (!typeVariablesOfClass.contains(pair.right) && typeVariables.contains(pair.right)) {
addToPairs(txResult, new PairTPHequalRefTypeOrWildcardType(pair.right, OBJECT)); addToPairs(result, new PairTPHequalRefTypeOrWildcardType(pair.right, OBJECT));
} }
} }
}
javaResult.addAll(txResult); // Same result until here private void methodFindTypeVariables(
Method method,
Set<ResultPair<?, ?>> genericsOfClass,
Set<TypePlaceholder> typeVariablesOfClass,
Set<TypePlaceholder> typeVariables,
Map<TypePlaceholder, TypePlaceholder> equality
) {
for (var pair : genericsOfClass) {
typeVariablesOfClass.add((TypePlaceholder) pair.getLeft());
}
typeVariables.addAll(findTypeVariables(method.getReturnType(), equality));
for (var arg : method.getParameterList().getFormalparalist()) {
typeVariables.addAll(findTypeVariables(arg.getType(), equality));
}
method.block.accept(new TracingStatementVisitor() {
@Override
public void visit(LocalVarDecl localVarDecl) {
typeVariables.addAll(findTypeVariables(localVarDecl.getType(), equality));
}
@Override
public void visit(MethodCall methodCall) {
super.visit(methodCall);
typeVariables.addAll(findTypeVariables(methodCall.getType(), equality));
}
@Override
public void visit(Assign assign) {}
});
}
// Family of generated Generics
Generics generics(ClassOrInterface owner, Method method) {
if (computedGenericsOfMethods.containsKey(method))
return computedGenericsOfMethods.get(method);
Set<ResultPair<?, ?>> txResult = new HashSet<>();
Set<ResultPair<?, ?>> javaResult = new HashSet<>();
var generics = new Generics(javaResult, txResult);
computedGenericsOfMethods.put(method, generics);
var genericsOfClass = generics(owner).javaGenerics();
var simplifiedConstraints = new HashSet<>(this.simplifiedConstraints);
HashSet<TypePlaceholder> txTypeVariables = new HashSet<>();
HashSet<TypePlaceholder> javaTypeVariables = new HashSet<>();
HashSet<TypePlaceholder> txTypeVariablesOfClass = new HashSet<>();
HashSet<TypePlaceholder> javaTypeVariablesOfClass = new HashSet<>();
methodFindTypeVariables(method, genericsOfClass, javaTypeVariablesOfClass, javaTypeVariables, equality);
methodFindTypeVariables(method, genericsOfClass, txTypeVariablesOfClass, txTypeVariables, txEquality);
methodFindConstraints(owner, method, simplifiedConstraints, javaTypeVariables, javaTypeVariablesOfClass, javaResult, equality);
methodFindConstraints(owner, method, simplifiedConstraints, txTypeVariables, txTypeVariablesOfClass, txResult, txEquality);
var eq = new HashMap<>(equality);
{ // Java Generics { // Java Generics
eliminateCycles(javaResult); eliminateCycles(javaResult, equality);
eliminateInfima(javaResult); eliminateInfima(javaResult, equality);
var usedTphs = new HashSet<TypePlaceholder>(); var usedTphs = new HashSet<TypePlaceholder>();
// For eliminating inner type variables we need to figure out which ones are actually used // For eliminating inner type variables we need to figure out which ones are actually used
// TODO Maybe don't do this twice? // TODO Maybe don't do this twice?
for (var param : method.getParameterList().getFormalparalist()) { for (var param : method.getParameterList().getFormalparalist()) {
usedTphs.addAll(findTypeVariables(param.getType())); usedTphs.addAll(findTypeVariables(param.getType(), equality));
} }
usedTphs.addAll(findTypeVariables(method.getReturnType())); usedTphs.addAll(findTypeVariables(method.getReturnType(), equality));
var referenced = new HashSet<>(usedTphs); var referenced = new HashSet<>(usedTphs);
referenced.addAll(typeVariablesOfClass); referenced.addAll(javaTypeVariablesOfClass);
eliminateInnerTypeVariables(referenced, javaResult); eliminateInnerTypeVariables(referenced, javaResult);
equalizeTypeVariables(javaResult); equalizeTypeVariables(javaResult, equality);
usedTPHsOfMethods.put(method, usedTphs); usedTPHsOfMethods.put(method, usedTphs);
} }
var storedEq = equality; //TODO Hack: pass equality as parameter instead
equality = eq;
{ // JavaTX Generics { // JavaTX Generics
eliminateInfima(txResult); eliminateInfima(txResult, txEquality);
var referenced = new HashSet<TypePlaceholder>(); var referenced = new HashSet<TypePlaceholder>();
for (var param : method.getParameterList().getFormalparalist()) { for (var param : method.getParameterList().getFormalparalist()) {
referenced.addAll(findTypeVariables(param.getType())); referenced.addAll(findTypeVariables(param.getType(), txEquality));
} }
referenced.addAll(findTypeVariables(method.getReturnType())); referenced.addAll(findTypeVariables(method.getReturnType(), txEquality));
referenced.addAll(typeVariablesOfClass); referenced.addAll(txTypeVariablesOfClass);
eliminateInnerTypeVariables(referenced, txResult); eliminateInnerTypeVariables(referenced, txResult);
// Generate generics with current equality
generatedTxGenerics.addAll(convert(txResult));
} }
equality = storedEq;
System.out.println(method.name + ": " + txResult + " & " + javaResult); System.out.println(method.name + ": " + txResult + " & " + javaResult);
return generics; return generics;
} }
void findAllBounds(RefTypeOrTPHOrWildcardOrGeneric type, Set<ResultPair<?, ?>> generics) { void findAllBounds(RefTypeOrTPHOrWildcardOrGeneric type, Set<ResultPair<?, ?>> generics, Map<TypePlaceholder, TypePlaceholder> equality) {
if (type instanceof TypePlaceholder tph) { if (type instanceof TypePlaceholder tph) {
tph = equality.getOrDefault(tph, tph); tph = equality.getOrDefault(tph, tph);
var concreteType = concreteTypes.get(tph); var concreteType = concreteTypes.get(tph);
if (concreteType != null) { if (concreteType != null) {
findAllBounds(concreteType, generics); findAllBounds(concreteType, generics, equality);
return; return;
} }
@ -565,7 +588,7 @@ public class ASTToTargetAST {
var pair = new PairTPHsmallerTPH(tph, right); var pair = new PairTPHsmallerTPH(tph, right);
if (!generics.contains(pair)) { if (!generics.contains(pair)) {
generics.add(pair); generics.add(pair);
findAllBounds(right, generics); findAllBounds(right, generics, equality);
found = true; found = true;
} }
} }
@ -573,7 +596,7 @@ public class ASTToTargetAST {
if (!found) if (!found)
generics.add(new PairTPHequalRefTypeOrWildcardType(tph, OBJECT)); generics.add(new PairTPHequalRefTypeOrWildcardType(tph, OBJECT));
} else if (type instanceof RefType refType) { } else if (type instanceof RefType refType) {
refType.getParaList().forEach(t -> findAllBounds(t, generics)); refType.getParaList().forEach(t -> findAllBounds(t, generics, equality));
} }
} }
@ -583,38 +606,30 @@ public class ASTToTargetAST {
Set<ResultPair<?, ?>> txResult = new HashSet<>(); Set<ResultPair<?, ?>> txResult = new HashSet<>();
Set<ResultPair<?, ?>> javaResult = new HashSet<>(); Set<ResultPair<?, ?>> javaResult = new HashSet<>();
Set<TargetGeneric> generatedTxGenerics = new HashSet<>(); var generics = new Generics(javaResult, txResult);
var generics = new Generics(javaResult, generatedTxGenerics);
for (var field : classOrInterface.getFieldDecl()) {
findAllBounds(field.getType(), txResult);
}
computedGenericsOfClasses.put(classOrInterface, generics); computedGenericsOfClasses.put(classOrInterface, generics);
javaResult.addAll(txResult); for (var field : classOrInterface.getFieldDecl()) {
findAllBounds(field.getType(), javaResult, equality);
findAllBounds(field.getType(), txResult, txEquality);
}
var eq = new HashMap<>(equality);
{ // Java Generics { // Java Generics
eliminateCycles(javaResult); eliminateCycles(javaResult, equality);
eliminateInfima(javaResult); eliminateInfima(javaResult, equality);
eliminateInnerTypeVariablesOfClass(classOrInterface, javaResult); eliminateInnerTypeVariablesOfClass(classOrInterface, javaResult, equality);
equalizeTypeVariables(javaResult); equalizeTypeVariables(javaResult, equality);
} }
var storedEq = equality; //TODO Hack: pass equality as parameter instead { // TX Generics
equality = eq; eliminateInfima(txResult, txEquality);
{ eliminateInnerTypeVariablesOfClass(classOrInterface, txResult, txEquality);
eliminateInfima(txResult);
eliminateInnerTypeVariablesOfClass(classOrInterface, txResult);
} }
equality = storedEq;
generatedTxGenerics.addAll(convert(txResult));
System.out.println("Class " + classOrInterface.getClassName().getClassName() + ": " + txResult); System.out.println("Class " + classOrInterface.getClassName().getClassName() + ": " + txResult);
return generics; return generics;
} }
void equalizeTypeVariables(Set<ResultPair<?, ?>> input) { void equalizeTypeVariables(Set<ResultPair<?, ?>> input, Map<TypePlaceholder, TypePlaceholder> equality) {
for (var pair : new HashSet<>(input)) { for (var pair : new HashSet<>(input)) {
if (pair instanceof PairTPHsmallerTPH ptph) { if (pair instanceof PairTPHsmallerTPH ptph) {
if (ptph.left.getVariance() == 1 && ptph.right.getVariance() == -1) { if (ptph.left.getVariance() == 1 && ptph.right.getVariance() == -1) {
@ -631,24 +646,24 @@ public class ASTToTargetAST {
} }
} }
void findTphs(RefTypeOrTPHOrWildcardOrGeneric type, Set<TypePlaceholder> tphs) { void findTphs(RefTypeOrTPHOrWildcardOrGeneric type, Set<TypePlaceholder> tphs, Map<TypePlaceholder, TypePlaceholder> equality) {
if (type instanceof RefType refType) { if (type instanceof RefType refType) {
refType.getParaList().forEach(t -> findTphs(t, tphs)); refType.getParaList().forEach(t -> findTphs(t, tphs, equality));
} else if (type instanceof TypePlaceholder tph) { } else if (type instanceof TypePlaceholder tph) {
tph = equality.getOrDefault(tph, tph); tph = equality.getOrDefault(tph, tph);
var concreteType = concreteTypes.get(tph); var concreteType = concreteTypes.get(tph);
if (concreteType != null) { if (concreteType != null) {
findTphs(concreteType, tphs); findTphs(concreteType, tphs, equality);
return; return;
} }
tphs.add(tph); tphs.add(tph);
} }
} }
void eliminateInnerTypeVariablesOfClass(ClassOrInterface classOrInterface, Set<ResultPair<?, ?>> input) { void eliminateInnerTypeVariablesOfClass(ClassOrInterface classOrInterface, Set<ResultPair<?, ?>> input, Map<TypePlaceholder, TypePlaceholder> equality) {
Set<TypePlaceholder> referenced = new HashSet<>(); Set<TypePlaceholder> referenced = new HashSet<>();
for (var field : classOrInterface.getFieldDecl()) { for (var field : classOrInterface.getFieldDecl()) {
findTphs(field.getType(), referenced); findTphs(field.getType(), referenced, equality);
} }
for (var method : classOrInterface.getMethods()) { for (var method : classOrInterface.getMethods()) {
generics(classOrInterface, method); generics(classOrInterface, method);
@ -700,7 +715,7 @@ public class ASTToTargetAST {
input.addAll(output); input.addAll(output);
} }
void eliminateCycles(Set<ResultPair<?, ?>> input) { void eliminateCycles(Set<ResultPair<?, ?>> input, Map<TypePlaceholder, TypePlaceholder> equality) {
var cycles = findCycles(input); var cycles = findCycles(input);
for (var cycle : cycles) { for (var cycle : cycles) {
var newTph = TypePlaceholder.fresh(new NullToken()); var newTph = TypePlaceholder.fresh(new NullToken());
@ -716,7 +731,7 @@ public class ASTToTargetAST {
} }
} }
void eliminateInfima(Set<ResultPair<?, ?>> input) { void eliminateInfima(Set<ResultPair<?, ?>> input, Map<TypePlaceholder, TypePlaceholder> equality) {
var foundInfima = false; var foundInfima = false;
do { do {
foundInfima = false; foundInfima = false;
@ -758,19 +773,19 @@ public class ASTToTargetAST {
} while (foundInfima); } while (foundInfima);
} }
RefTypeOrTPHOrWildcardOrGeneric getType(RefTypeOrTPHOrWildcardOrGeneric type) { RefTypeOrTPHOrWildcardOrGeneric getType(RefTypeOrTPHOrWildcardOrGeneric type, Map<TypePlaceholder, TypePlaceholder> equality) {
if (type instanceof TypePlaceholder tph) { if (type instanceof TypePlaceholder tph) {
if (equality.containsKey(tph)) { if (equality.containsKey(tph)) {
return getType(equality.get(tph)); return getType(equality.get(tph), equality);
} }
return concreteTypes.getOrDefault(tph, tph); return concreteTypes.getOrDefault(tph, tph);
} }
return type; return type;
} }
TargetType getTargetType(TypePlaceholder tph) { TargetType getTargetType(TypePlaceholder tph, Map<TypePlaceholder, TypePlaceholder> equality) {
if (equality.containsKey(tph)) { if (equality.containsKey(tph)) {
return getTargetType(equality.get(tph)); return getTargetType(equality.get(tph), equality);
} }
var type = concreteTypes.get(tph); var type = concreteTypes.get(tph);
if (type == null) return new TargetGenericType(tph.getName()); if (type == null) return new TargetGenericType(tph.getName());
@ -944,7 +959,7 @@ public class ASTToTargetAST {
// Generate generics only if there are no user defined ones // Generate generics only if there are no user defined ones
var generics = sigma.generics(input); var generics = sigma.generics(input);
javaGenerics = convert(generics.javaGenerics()); javaGenerics = convert(generics.javaGenerics());
txGenerics = generics.txGenerics(); txGenerics = convert(generics.txGenerics());
} }
TargetBlock fieldInitializer = null; TargetBlock fieldInitializer = null;
@ -970,8 +985,8 @@ public class ASTToTargetAST {
return generics.stream().anyMatch(g -> g.name().equals(type.getParsedName())); return generics.stream().anyMatch(g -> g.name().equals(type.getParsedName()));
} }
private Set<TargetGeneric> collectMethodGenerics(Set<TargetGeneric> generics, Method input) { private Set<TargetGeneric> collectMethodGenerics(Set<ResultPair<?, ?>> generics, Map<TypePlaceholder, TypePlaceholder> equality, Method input) {
var convertedGenerics = new HashSet<>(generics); var convertedGenerics = new HashSet<>(convert(generics));
outer: outer:
for (GenericTypeVar typeVar : input.getGenerics()) { for (GenericTypeVar typeVar : input.getGenerics()) {
for (var classGeneric : currentClass.getGenerics()) { for (var classGeneric : currentClass.getGenerics()) {
@ -981,12 +996,12 @@ public class ASTToTargetAST {
} }
convertedGenerics.addAll(convert(typeVar)); convertedGenerics.addAll(convert(typeVar));
} }
var returnType = sigma.getType(input.getReturnType()); var returnType = sigma.getType(input.getReturnType(), equality);
if ((returnType instanceof GenericRefType refType) && !hasGeneric(convertedGenerics, refType)) { if ((returnType instanceof GenericRefType refType) && !hasGeneric(convertedGenerics, refType)) {
convertedGenerics.add(new TargetGeneric(refType.getParsedName(), convert(OBJECT))); convertedGenerics.add(new TargetGeneric(refType.getParsedName(), convert(OBJECT)));
} }
for (var param : input.getParameterList()) { for (var param : input.getParameterList()) {
var type = sigma.getType(param.getType()); var type = sigma.getType(param.getType(), equality);
if (type instanceof GenericRefType refType && !hasGeneric(convertedGenerics, refType)) { if (type instanceof GenericRefType refType && !hasGeneric(convertedGenerics, refType)) {
convertedGenerics.add(new TargetGeneric(refType.getParsedName(), convert(OBJECT))); convertedGenerics.add(new TargetGeneric(refType.getParsedName(), convert(OBJECT)));
} }
@ -1005,8 +1020,8 @@ public class ASTToTargetAST {
var generics = sigma.generics(currentClass, input); var generics = sigma.generics(currentClass, input);
List<MethodParameter> params = convert(input.getParameterList()); List<MethodParameter> params = convert(input.getParameterList());
if (parameterSet.stream().noneMatch(p -> p.equals(params))) { if (parameterSet.stream().noneMatch(p -> p.equals(params))) {
var javaGenerics = collectMethodGenerics(convert(generics.javaGenerics()), input); var javaGenerics = collectMethodGenerics(generics.javaGenerics(), sigma.equality, input);
var txGenerics = collectMethodGenerics(generics.txGenerics(), input); var txGenerics = collectMethodGenerics(generics.txGenerics(), sigma.txEquality, input);
result.add(new TargetConstructor(input.modifier, javaGenerics, txGenerics, params, convert(input.block), fieldInitializer)); result.add(new TargetConstructor(input.modifier, javaGenerics, txGenerics, params, convert(input.block), fieldInitializer));
parameterSet.add(params); parameterSet.add(params);
@ -1026,8 +1041,8 @@ public class ASTToTargetAST {
var generics = sigma.generics(currentClass, input); var generics = sigma.generics(currentClass, input);
List<MethodParameter> params = convert(input.getParameterList()); List<MethodParameter> params = convert(input.getParameterList());
if (parameterSet.stream().noneMatch(p -> p.equals(params))) { if (parameterSet.stream().noneMatch(p -> p.equals(params))) {
var javaGenerics = collectMethodGenerics(convert(generics.javaGenerics()), input); var javaGenerics = collectMethodGenerics(generics.javaGenerics(), sigma.equality, input);
var txGenerics = collectMethodGenerics(generics.txGenerics(), input); var txGenerics = collectMethodGenerics(generics.txGenerics(), sigma.txEquality, input);
result.add(new TargetMethod( result.add(new TargetMethod(
input.modifier, input.modifier,
@ -1099,7 +1114,7 @@ public class ASTToTargetAST {
@Override @Override
public TargetType visit(TypePlaceholder typePlaceholder) { public TargetType visit(TypePlaceholder typePlaceholder) {
return sigma.getTargetType(typePlaceholder); return sigma.getTargetType(typePlaceholder, sigma.equality);
} }
@Override @Override

View File

@ -18,15 +18,14 @@ public class GenericsResult {
public Set<ResultPair<?, ?>> get(ClassOrInterface clazz) { public Set<ResultPair<?, ?>> get(ClassOrInterface clazz) {
var generics = this.sigma.computedGenericsOfClasses.get(clazz); var generics = this.sigma.computedGenericsOfClasses.get(clazz);
if (generics == null) return Set.of(); if (generics == null) return Set.of();
return generics.javaGenerics(); return generics.txGenerics();
} }
// TODO Compute generics if not present? // TODO Compute generics if not present?
// TODO Maybe use tx Generics here (two equalities)
public Set<ResultPair<?, ?>> get(Method method) { public Set<ResultPair<?, ?>> get(Method method) {
var generics = this.sigma.computedGenericsOfMethods.get(method); var generics = this.sigma.computedGenericsOfMethods.get(method);
if (generics == null) return Set.of(); if (generics == null) return Set.of();
return generics.javaGenerics(); return generics.txGenerics();
} }
public BoundsList getBounds(RefTypeOrTPHOrWildcardOrGeneric type, ClassOrInterface clazz) { public BoundsList getBounds(RefTypeOrTPHOrWildcardOrGeneric type, ClassOrInterface clazz) {
@ -68,7 +67,13 @@ public class GenericsResult {
public RefTypeOrTPHOrWildcardOrGeneric resolve(RefTypeOrTPHOrWildcardOrGeneric type) { public RefTypeOrTPHOrWildcardOrGeneric resolve(RefTypeOrTPHOrWildcardOrGeneric type) {
if (type instanceof TypePlaceholder tph) if (type instanceof TypePlaceholder tph)
return this.sigma.getType(tph); return this.sigma.getType(tph, sigma.equality);
return type;
}
public RefTypeOrTPHOrWildcardOrGeneric resolveTx(RefTypeOrTPHOrWildcardOrGeneric type) {
if (type instanceof TypePlaceholder tph)
return this.sigma.getType(tph, sigma.txEquality);
return type; return type;
} }
} }