Fix removing inner type variables

This commit is contained in:
Victorious3 2023-02-07 12:22:37 +01:00
parent d39fd64f0f
commit 1c2e868589
2 changed files with 42 additions and 33 deletions

View File

@ -218,7 +218,7 @@ public class ASTToTargetAST {
for (var g2 : all) { for (var g2 : all) {
if (g1 instanceof PairTPHsmallerTPH pair) { if (g1 instanceof PairTPHsmallerTPH pair) {
if (g2.getLeft().equals(pair.getLeft()) && generics.stream().anyMatch(generic -> generic.getLeft().equals(pair.getRight()))) if (g2.getLeft().equals(pair.getLeft()) && generics.stream().anyMatch(generic -> generic.getLeft().equals(pair.getRight())))
toAdd.add(new PairTPHsmallerTPH((TypePlaceholder) g1.getLeft(), (TypePlaceholder) g2.getRight())); toAdd.add(new PairTPHsmallerTPH(pair.left, pair.right));
} }
} }
} }
@ -460,17 +460,22 @@ public class ASTToTargetAST {
} }
} }
eliminateCyclesAndInfima(result); eliminateCyclesAndInfima(result);
usedTPHsOfMethods.put(method, typeVariables);
// 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?
var typeVariablesOfSignature = new HashSet<TypePlaceholder>(); var referenced = new HashSet<TypePlaceholder>();
for (var param : method.getParameterList().getFormalparalist()) { for (var param : method.getParameterList().getFormalparalist()) {
typeVariablesOfSignature.addAll(findTypeVariables(param.getType())); referenced.addAll(findTypeVariables(param.getType()));
}
referenced.addAll(findTypeVariables(method.getReturnType()));
for (var g : genericsOfClass) {
if (g.getLeft() instanceof TypePlaceholder left)
referenced.add(left);
} }
typeVariablesOfSignature.addAll(findTypeVariables(method.getReturnType()));
eliminateInnerTypeVariables(typeVariablesOfSignature, result); eliminateInnerTypeVariables(referenced, result);
usedTPHsOfMethods.put(method, referenced);
System.out.println(method.name + ": " + result); System.out.println(method.name + ": " + result);
return result; return result;
@ -567,37 +572,42 @@ public class ASTToTargetAST {
eliminateInnerTypeVariables(referenced, input); eliminateInnerTypeVariables(referenced, input);
} }
private void findChain(Set<TypePlaceholder> referenced, Set<ResultPair<?, ?>> input, Set<ResultPair<?, ?>> output, TypePlaceholder start, TypePlaceholder end, Set<TypePlaceholder> chain) {
if (referenced.contains(end)) {
var pair = new PairTPHsmallerTPH(start, end);
if (input.contains(pair)) output.add(pair);
}
for (var pair : input) {
if (pair instanceof PairTPHsmallerTPH ptph && ptph.left.equals(end)) {
if (chain.contains(ptph.right)) return;
chain = new HashSet<>(chain);
chain.add(ptph.right);
findChain(referenced, input, output, start, ptph.right, chain);
}
}
}
void eliminateInnerTypeVariables(Set<TypePlaceholder> referenced, Set<ResultPair<?, ?>> input) { void eliminateInnerTypeVariables(Set<TypePlaceholder> referenced, Set<ResultPair<?, ?>> input) {
// Remove type variables that are part of a relation A < B < C where B is not in referenced var output = new HashSet<ResultPair<?, ?>>();
// Add new pair A < C for (var tph : referenced) {
var oldInput = new HashSet<>(input); for (var pair : input) {
for (var pair : oldInput) { if (pair instanceof PairTPHsmallerTPH pthp && pthp.left.equals(tph)) {
if (pair instanceof PairTPHsmallerTPH ptph && !referenced.contains(ptph.left)) { var chain = new HashSet<TypePlaceholder>();
input.remove(pair); chain.add(tph);
equality.put(ptph.left, ptph.right); chain.add(pthp.right);
for (var pair2 : oldInput) { findChain(referenced, input, output, tph, pthp.right, chain);
if (pair2.getRight().equals(pair.getLeft())) {
input.remove(pair2);
addToPairs(input, new PairTPHsmallerTPH((TypePlaceholder) pair2.getLeft(), (TypePlaceholder) pair.getRight()));
}
} }
} }
} }
for (var pair : input) {
if (pair instanceof PairTPHequalRefTypeOrWildcardType rtph) {
if (referenced.contains(rtph.left))
output.add(rtph);
}
}
// Remove lone type variables, A = RefType where A is in no relation X < A or A < X and A is not in referenced input.clear();
oldInput = new HashSet<>(input); input.addAll(output);
outer:
for (var pair : oldInput) {
if (pair instanceof PairTPHequalRefTypeOrWildcardType ptph) {
if (!referenced.contains(ptph.left)) {
for (var pair2 : oldInput) {
if (pair != pair2 && (pair2.getLeft().equals(ptph.left) || pair2.getRight().equals(ptph.left)))
continue outer;
}
input.remove(pair);
}
}
}
} }
void eliminateCycles(Set<ResultPair<?, ?>> input) { void eliminateCycles(Set<ResultPair<?, ?>> input) {

View File

@ -14,7 +14,6 @@ import static org.junit.Assert.*;
import static targetast.TestCodegen.generateClassFiles; import static targetast.TestCodegen.generateClassFiles;
public class TestComplete { public class TestComplete {
@Test @Test
public void applyLambdaTest() throws Exception { public void applyLambdaTest() throws Exception {
var classFiles = generateClassFiles("applyLambda.jav", new ByteArrayClassLoader()); var classFiles = generateClassFiles("applyLambda.jav", new ByteArrayClassLoader());