Compare commits

...

8 Commits

Author SHA1 Message Date
a4f18e91fb List append works
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 1m26s
2025-08-13 13:52:14 +02:00
3516cd93f4 Refactoring
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 1m58s
2025-08-12 13:33:42 +02:00
4c42983bb5 Refactor
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 1m41s
2025-08-08 17:59:41 +02:00
6569fb4dc1 Add overlay class to be used later
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 1m37s
2025-08-08 11:49:40 +02:00
f04c3bc01e Use signatures instead of methods to do the grouping so that we can generate the correct target method later
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 1m37s
2025-08-06 16:42:44 +02:00
a3f6365b07 Wrong branch
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 1m30s
2025-07-31 11:47:28 +02:00
b808c85722 Sonar
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Has been cancelled
2025-07-31 11:46:50 +02:00
8d41ed2328 Continue working on pattern matching
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 1m47s
2025-07-30 14:34:10 +02:00
11 changed files with 373 additions and 286 deletions

View File

@@ -1739,7 +1739,7 @@ public class Codegen {
methodName = fromMethod.name;
fromReturn = converter.convert(fromMethod.getReturnType());
var fromParams = converter.convert(fromMethod.getParameterList(), converter.generics.javaGenerics()).stream().map(m -> m.pattern().type()).toArray(TargetType[]::new);
var fromParams = converter.convert(fromMethod.getParameterList()).stream().map(m -> m.pattern().type()).toArray(TargetType[]::new);
fromDescriptor = TargetMethod.getDescriptor(fromReturn, fromParams);
} else {
fromReturn = funNType.returnArguments() > 0 ? TargetType.Object : null;
@@ -1749,7 +1749,7 @@ public class Codegen {
var toClass = compiler.getClass(new JavaClassName(pair.to.name()));
var toMethod = toClass.getMethods().stream().filter(m -> (m.modifier & ACC_ABSTRACT) != 0).findFirst().orElseThrow();
var toReturn = converter.convert(toMethod.getReturnType());
var toParams = converter.convert(toMethod.getParameterList(), converter.generics.javaGenerics()).stream().map(m -> m.pattern().type()).toArray(TargetType[]::new);
var toParams = converter.convert(toMethod.getParameterList()).stream().map(m -> m.pattern().type()).toArray(TargetType[]::new);
var toDescriptor = TargetMethod.getDescriptor(toReturn, toParams);
// Generate wrapper method

View File

@@ -18,6 +18,7 @@ import de.dhbwstuttgart.target.tree.expression.*;
import de.dhbwstuttgart.target.tree.type.*;
import de.dhbwstuttgart.typeinference.result.*;
import java.lang.annotation.Target;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -32,9 +33,9 @@ public class ASTToTargetAST {
public static RefType OBJECT = ASTFactory.createObjectType(); // TODO It would be better if I could call this directly but the hashcode seems to change
protected List<Generics> all;
public Generics generics;
public List<Generics> currentMethodOverloads;
public List<Generics> all;
//public Generics generics;
//public List<Generics> currentMethodOverloads;
final Map<ClassOrInterface, Set<GenericTypeVar>> userDefinedGenerics = new HashMap<>();
final Map<Method, Set<SignaturePair>> tphsInMethods = new HashMap<>();
@@ -54,13 +55,13 @@ public class ASTToTargetAST {
return all.stream().map(generics -> new GenericsResult(generics.javaGenerics)).toList();
}
public TargetExpression convert(Pattern pattern) {
var converter = new StatementToTargetExpression(this);
public TargetExpression convert(Pattern pattern, IGenerics generics) {
var converter = new StatementToTargetExpression(this, generics);
pattern.accept(converter);
return converter.result;
}
public record Generics(JavaGenerics javaGenerics, TxGenerics txGenerics) {
public record Generics(IGenerics javaGenerics, IGenerics txGenerics) {
}
@@ -83,7 +84,6 @@ public class ASTToTargetAST {
for (var set : resultSets) {
all.add(new Generics(new JavaGenerics(this, set), new TxGenerics(this, set)));
}
this.generics = all.get(0);
}
public void addSignaturePair(TypePlaceholder signature, RefTypeOrTPHOrWildcardOrGeneric parameter) {
@@ -112,20 +112,23 @@ public class ASTToTargetAST {
return false;
for (var i = 0; i < pars.size(); i++) {
var type1 = convert(pars.get(i).getType(), generics.javaGenerics);
var type1 = pars.get(i).getType();
var type2 = arguments.get(i);
if (type1 instanceof TargetGenericType)
return true;
if (TargetType.toPrimitive(type2).equals(type1))
return true;
if (!type1.equals(type2))
//if (type1 instanceof GenericRefType)
// return true;
//if (TargetType.toPrimitive(type2).equals(type1))
// return true;
if (type1 instanceof RefType rt) {
if (type2 instanceof TargetRefType rt2 && !rt2.name().equals(rt.getName().toString())) {
return false;
}
}
}
return true;
}
Set<TargetGeneric> convert(Set<GenerateGenerics.Pair> result, GenerateGenerics generics) {
Set<TargetGeneric> convert(Set<GenerateGenerics.Pair> result, IGenerics generics) {
return result.stream().map(p -> {
if (p instanceof GenerateGenerics.PairLT pair) {
return new TargetGeneric(pair.left.resolve().getName(), convert(pair.right.resolve(), generics));
@@ -137,7 +140,7 @@ public class ASTToTargetAST {
}).collect(Collectors.toSet());
}
public List<TargetGeneric> convert(GenericTypeVar typeVar, GenerateGenerics generics) {
public List<TargetGeneric> convert(GenericTypeVar typeVar, IGenerics generics) {
var ret = new ArrayList<TargetGeneric>();
for (var bound : typeVar.getBounds()) {
ret.add(new TargetGeneric(typeVar.getName(), generics.getTargetType(bound)));
@@ -146,6 +149,7 @@ public class ASTToTargetAST {
}
// This finds a common sealed interface type to group together methods that use different records
// This function should do matching or unification
private List<ClassOrInterface> commonSuperInterfaceTypes(TargetType a, TargetType b) {
if (a instanceof TargetGenericType && b instanceof TargetGenericType) return List.of(ASTFactory.createObjectClass());
if (a instanceof TargetRefType ta && b instanceof TargetGenericType)
@@ -183,44 +187,28 @@ public class ASTToTargetAST {
return List.of();
}
// TODO This is ugly and probably doesn't work right
private boolean patternStrictlyEquals(TargetComplexPattern a, TargetComplexPattern b) {
if (!a.name().equals(b.name())) return false;
if (a.subPatterns().size() != b.subPatterns().size()) return false;
for (var i = 0; i < a.subPatterns().size(); i++) {
var p1 = a.subPatterns().get(i);
var p2 = b.subPatterns().get(i);
if (p1 instanceof TargetComplexPattern pc1 && p2 instanceof TargetComplexPattern pc2 &&
patternStrictlyEquals(pc1, pc2)) return false;
if (p1 instanceof TargetTypePattern pt1 && p2 instanceof TargetTypePattern pt2) {
if (pt1.type() instanceof TargetGenericType && pt2.type() instanceof TargetGenericType) continue;
}
if (!p1.type().equals(p2.type()) && commonSuperInterfaceTypes(p1.type(), p2.type()).isEmpty()) return false;
}
return true;
}
private boolean canCombine(TargetMethod m1, TargetMethod m2) {
if (!m1.name().equals(m2.name())) return false;
var s1 = m1.signature();
var s2 = m2.signature();
if (s1.parameters().size() != s2.parameters().size()) return false;
if (s1.parameters().isEmpty()) return false;
for (var i = 0; i < s1.parameters().size(); i++) {
var p1 = s1.parameters().get(i).pattern();
var p2 = s2.parameters().get(i).pattern();
private boolean canCombine(Signature m1, Signature m2) {
var pl1 = m1.java.parameters();
var pl2 = m2.java.parameters();
if (pl1.size() != pl2.size()) return false;
if (pl1.isEmpty()) return false;
for (var i = 0; i < pl1.size(); i++) {
var p1 = pl1.get(i).pattern();
var p2 = pl2.get(i).pattern();
// TPH <> RefType sind nicht unterscheidbar
if (p1.type() instanceof TargetGenericType || p2.type() instanceof TargetGenericType) continue;
// Pattern(X) <> Pattern(Y) ist nicht unterscheidbar
if (p1 instanceof TargetComplexPattern pc1 && p2 instanceof TargetComplexPattern pc2 &&
patternStrictlyEquals(pc1, pc2)) return false;
if (!p1.equals(p2) && commonSuperInterfaceTypes(p1.type(), p2.type()).isEmpty()) return false;
pc1.type().equals(pc2.type())) continue;
if (!p1.equals(p2)) return false;
}
return true;
}
private record Combination(TargetMethod a, TargetMethod b) {
private record Combination(MethodWithTphs a, MethodWithTphs b) {
@Override
public boolean equals(Object o) {
if (!(o instanceof Combination(TargetMethod a1, TargetMethod b1))) return false;
if (!(o instanceof Combination(MethodWithTphs a1, MethodWithTphs b1))) return false;
return this.a.equals(a1) && this.b.equals(b1) ||
this.a.equals(b1) && this.b.equals(a1);
}
@@ -231,10 +219,10 @@ public class ASTToTargetAST {
}
}
public List<List<TargetMethod>> groupOverloads(ClassOrInterface input, List<Method> methods) {
var mapOfTargetMethods = new HashMap<Generics, TargetMethod[]>();
for (var generics : all) {
mapOfTargetMethods.put(generics, new TargetMethod[methods.size()]);
private List<List<MethodWithTphs>> groupOverloads(ClassOrInterface input, List<Method> methods) {
var mapOfTargetMethods = new HashMap<Generics, MethodWithTphs[]>();
for (var gen : all) {
mapOfTargetMethods.put(gen, new MethodWithTphs[methods.size()]);
}
for (var i = 0; i < methods.size(); i++) {
@@ -243,14 +231,14 @@ public class ASTToTargetAST {
var methodsWithTphs = convert(input, method);
for (var m : methodsWithTphs) {
var resultMethods = mapOfTargetMethods.get(m.generics);
resultMethods[i] = m.method;
resultMethods[i] = new MethodWithTphs(m.method, m.generics, m.signature);
}
}
/*System.out.println("============== INPUT ==============");
System.out.println("============== INPUT ==============");
for (var m : mapOfTargetMethods.values()) {
for (var v : m) System.out.println(v.name() + " " + v.getSignature());
for (var v : m) if (v != null) System.out.println(v.method.name + " " + v.signature.java.getSignature());
System.out.println();
}*/
}
var allCombinations = new HashSet<Set<Combination>>();
// Combine methods based on their signature and position in the result set
@@ -268,8 +256,8 @@ public class ASTToTargetAST {
var combinations = new HashSet<Combination>();
if (canCombine(m1, m2)) {
//System.out.println(" Combining " + m1.getSignature() + " and " + m2.getSignature());
if (canCombine(m1.signature, m2.signature)) {
System.out.println(" Combining " + m1.signature.java.getSignature() + " and " + m2.signature.java.getSignature());
combinations.add(new Combination(m1, m2));
for (var j = 0; j < methods.size(); j++) {
if (j == i) continue;
@@ -278,10 +266,10 @@ public class ASTToTargetAST {
var m4 = resMeth1[j];
if (m4 == null) continue;
combinations.add(new Combination(m4, m3));
//System.out.println("Also Combining " + m4.getSignature() + " and " + m3.getSignature());
System.out.println("Also Combining " + m4.signature.java.getSignature() + " and " + m3.signature.java.getSignature());
}
} else {
//System.out.println(" Not Combining " + m1.getSignature() + " and " + m2.getSignature());
System.out.println(" Not Combining " + m1.signature.java.getSignature() + " and " + m2.signature.java.getSignature());
}
if (!combinations.isEmpty()) allCombinations.add(combinations);
}
@@ -291,14 +279,14 @@ public class ASTToTargetAST {
if (allCombinations.isEmpty()) allCombinations.add(new HashSet<>());
// Combine back into output format
var r0 = new HashSet<Set<TargetMethod>>();
var r0 = new HashSet<Set<MethodWithTphs>>();
for (var combinations : allCombinations) {
var r1 = new HashSet<Set<TargetMethod>>();
var r1 = new HashSet<Set<MethodWithTphs>>();
// This is used to weed out duplicates
var uniqued = new HashSet<TargetMethod>();
var uniqued = new HashSet<MethodWithTphs>();
// We go over all methods in the result
for (var g : all) for (var i = 0; i < methods.size(); i++) {
var r2 = new HashSet<TargetMethod>();
var r2 = new HashSet<MethodWithTphs>();
var m = mapOfTargetMethods.get(g)[i];
if (m == null) continue;
if (!uniqued.contains(m)) {
@@ -340,13 +328,14 @@ public class ASTToTargetAST {
System.out.println("============== OUTPUT ==============");
for (var l : result) {
for (var m : l) System.out.println(m.name() + " " + m.getSignature());
for (var m : l) System.out.println(m.method.name + " " + m.signature.java.getSignature());
System.out.println();
}
return result;
}
public TargetStructure convert(ClassOrInterface input) {
var generics = all.getFirst();
Set<TargetGeneric> javaGenerics = new HashSet<>();
Set<TargetGeneric> txGenerics = new HashSet<>();
@@ -359,7 +348,7 @@ public class ASTToTargetAST {
var next = genericsIter.next();
userDefinedGenerics.add(next);
// TODO Support multiple bounds
javaGenerics.add(new TargetGeneric(next.getName(), convert(next.getBounds().get(0))));
javaGenerics.add(new TargetGeneric(next.getName(), convert(next.getBounds().getFirst(), generics.javaGenerics)));
}
} else {
this.userDefinedGenerics.put(input, new HashSet<>());
@@ -370,18 +359,20 @@ public class ASTToTargetAST {
TargetBlock fieldInitializer = null;
if (input.getfieldInitializations().isPresent())
fieldInitializer = convert(input.getfieldInitializations().get().block);
fieldInitializer = convert(input.getfieldInitializations().get().block, generics.javaGenerics);
TargetBlock finalFieldInitializer = fieldInitializer;
var superInterfaces = input.getSuperInterfaces().stream().map(clazz -> convert(clazz, generics.javaGenerics)).toList();
var constructors = input.getConstructors().stream().map(constructor -> this.convert(input, constructor, finalFieldInitializer)).flatMap(List::stream).toList();
var fields = input.getFieldDecl().stream().map(this::convert).toList();
var constructors = input.getConstructors().stream().map(constructor -> this.convert(input, constructor, finalFieldInitializer, generics)).flatMap(List::stream).toList();
var fields = input.getFieldDecl().stream().map(f -> convert(f, generics.javaGenerics)).toList();
var methods = groupOverloads(input, input.getMethods()).stream().map(m -> generatePatternOverloads(input, m)).flatMap(List::stream)
.collect(Collectors.toSet()).stream().toList(); // Unique generated methods
TargetMethod staticConstructor = null;
if (input.getStaticInitializer().isPresent())
staticConstructor = this.convert(input, input.getStaticInitializer().get()).stream().findFirst().orElseThrow().method;
if (input.getStaticInitializer().isPresent()) {
var init = this.convert(input, input.getStaticInitializer().get()).stream().findFirst().orElseThrow();
staticConstructor = this.convert(init, init.generics.javaGenerics);
}
if (input instanceof Record)
return new TargetRecord(input.getModifiers(), input.getClassName(), javaGenerics, txGenerics, superInterfaces, constructors, staticConstructor, fields, methods);
@@ -390,11 +381,16 @@ public class ASTToTargetAST {
else return new TargetClass(input.getModifiers(), input.getClassName(), convert(input.getSuperClass(), generics.javaGenerics), javaGenerics, txGenerics, superInterfaces, constructors, staticConstructor, fields, methods);
}
public List<MethodParameter> convert(ParameterList input, GenerateGenerics generics) {
@Deprecated
public List<MethodParameter> convert(ParameterList input) {
return convert(input, all.getFirst().javaGenerics);
}
public List<MethodParameter> convert(ParameterList input, IGenerics generics) {
var res = new ArrayList<MethodParameter>();
for (var i = 0; i < input.getFormalparalist().size(); i++) {
var param = input.getFormalparalist().get(i);
var pattern = (TargetPattern) convert(param);
var pattern = (TargetPattern) convert(param, generics);
if (pattern instanceof TargetComplexPattern) pattern = pattern.withName("__var" + i);
res.add(new MethodParameter(pattern));
}
@@ -405,7 +401,7 @@ public class ASTToTargetAST {
return generics.stream().anyMatch(g -> g.name().equals(type.getParsedName()));
}
private Set<TargetGeneric> collectMethodGenerics(ClassOrInterface clazz, GenerateGenerics generateGenerics, Set<GenerateGenerics.Pair> generics, Method input) {
private Set<TargetGeneric> collectMethodGenerics(ClassOrInterface clazz, IGenerics generateGenerics, Set<GenerateGenerics.Pair> generics, Method input) {
var convertedGenerics = new HashSet<>(convert(generics, generateGenerics));
outer: for (GenericTypeVar typeVar : input.getGenerics()) {
for (var classGeneric : clazz.getGenerics()) {
@@ -423,7 +419,7 @@ public class ASTToTargetAST {
return convertedGenerics;
}
private List<TargetConstructor> convert(ClassOrInterface currentClass, Constructor input, TargetBlock fieldInitializer) {
private List<TargetConstructor> convert(ClassOrInterface currentClass, Constructor input, TargetBlock fieldInitializer, Generics generics) {
generics = all.get(0);
List<TargetConstructor> result = new ArrayList<>();
Set<List<MethodParameter>> parameterSet = new HashSet<>();
@@ -431,15 +427,15 @@ public class ASTToTargetAST {
for (var s : all) {
generics = s;
var javaGenerics = this.generics.javaGenerics.generics(currentClass, input);
var txGenerics = this.generics.txGenerics.generics(currentClass, input);
List<MethodParameter> params = convert(input.getParameterList(), this.generics.javaGenerics);
var javaGenerics = generics.javaGenerics.generics(currentClass, input);
var txGenerics = generics.txGenerics.generics(currentClass, input);
List<MethodParameter> params = convert(input.getParameterList(), generics.javaGenerics);
if (parameterSet.stream().noneMatch(p -> p.equals(params))) {
List<MethodParameter> txParams = convert(input.getParameterList(), this.generics.txGenerics);
List<MethodParameter> txParams = convert(input.getParameterList(), generics.txGenerics);
var javaMethodGenerics = collectMethodGenerics(currentClass, generics.javaGenerics(), javaGenerics, input);
var txMethodGenerics = collectMethodGenerics(currentClass, generics.txGenerics(), txGenerics, input);
result.add(new TargetConstructor(input.modifier, javaMethodGenerics, txMethodGenerics, params, txParams, convert(input.block), fieldInitializer));
result.add(new TargetConstructor(input.modifier, javaMethodGenerics, txMethodGenerics, params, txParams, convert(input.block, generics.javaGenerics), fieldInitializer));
parameterSet.add(params);
}
}
@@ -447,10 +443,13 @@ public class ASTToTargetAST {
return result;
}
private static int counter = 0;
private String encodeName(String name, TargetMethod.Signature params) {
var res = new StringBuilder();
res.append(name);
res.append('$');
res.append(counter++);
res.append('$');
for (var param : params.parameters()) {
encodeName(param.pattern(), res);
}
@@ -526,12 +525,14 @@ public class ASTToTargetAST {
var j = 0;
for (var param : m.signature().parameters()) {
if (j >= patternsRec.size()) return true;
if (!patternsRec.get(j).type().equals(param.pattern().type())) return false;
if (!patternsRec.get(j).equals(param.pattern())) return false;
j++;
}
return true;
}).toList();
//System.out.println(offset + " -> " + lastPattern);
//candidates.forEach(m -> System.out.println(m.getSignature()));
var caseBody = generatePatternOverloadsRec(offset + 1, expr, params, patternsRec, candidates, classType);
var body = new TargetBlock(List.of(caseBody));
var case_ = new TargetSwitch.Case(List.of(lastPattern), body);
@@ -542,19 +543,14 @@ public class ASTToTargetAST {
return new TargetSwitch(switchExpr, cases, null, true);
}
private List<TargetMethod> generatePatternOverloads(ClassOrInterface clazz, List<TargetMethod> overloadedMethods) {
if (overloadedMethods.size() <= 1) return overloadedMethods;
private List<TargetMethod> generatePatternOverloads(ClassOrInterface clazz, List<MethodWithTphs> overloadedMethods) {
if (overloadedMethods.isEmpty()) return List.of();
// Check if we have a pattern as a parameter
var firstMethod = overloadedMethods.getFirst();
var secondMethod = overloadedMethods.get(1);
if (firstMethod.signature().parameters().stream().noneMatch(mp -> mp.pattern() instanceof TargetComplexPattern)) return overloadedMethods;
// Rename existing methods
var res = new ArrayList<TargetMethod>();
for (var method : overloadedMethods) {
var name = encodeName(method.name(), method.signature());
res.add(new TargetMethod(method.access(), name, method.block(), method.signature(), method.txSignature()));
}
var firstMethod = convert(overloadedMethods.getFirst(), overloadedMethods.getFirst().generics.javaGenerics);
if (overloadedMethods.size() == 1) return List.of(firstMethod);
var secondMethod = convert(overloadedMethods.get(1), overloadedMethods.get(1).generics.javaGenerics);
if (firstMethod.signature().parameters().stream().noneMatch(mp -> mp.pattern() instanceof TargetComplexPattern))
return overloadedMethods.stream().map(m -> convert(m, m.generics.javaGenerics)).toList();
var signatureParams = new ArrayList<MethodParameter>();
for (var i = 0; i < firstMethod.signature().parameters().size(); i++) {
@@ -563,7 +559,7 @@ public class ASTToTargetAST {
var t2 = secondMethod.signature().parameters().get(i).pattern().type();
var commonSubTypes = new HashSet<>(commonSuperInterfaceTypes(t1, t2));
for (var m : overloadedMethods.subList(2, overloadedMethods.size())) {
var t3 = m.signature().parameters().get(i).pattern().type();
var t3 = m.signature().java.parameters().get(i).pattern().type();
commonSubTypes.retainAll(commonSuperInterfaceTypes(t1, t3));
}
if (commonSubTypes.size() > 1) throw new DebugException("Invalid overload");
@@ -578,9 +574,28 @@ public class ASTToTargetAST {
signatureParams.add(new MethodParameter(new TargetRefType(superType.getClassName().toString()), name));
}
// Rename existing methods
var res = new ArrayList<TargetMethod>();
for (var method : overloadedMethods) {
var name = encodeName(method.method.name, method.signature.java);
var generics = new OverlayGenerics(method.generics.javaGenerics, this);
var m = overloadedMethods.getFirst();
var params = m.method.getParameterList().getFormalparalist();
for (var i = 0; i < params.size(); i++) {
var param = params.get(i);
if (param.getType() instanceof TypePlaceholder tph) {
generics.addOverlay(tph, signatureParams.get(i).pattern().type());
}
}
var tMethod = convert(method, generics);
res.add(new TargetMethod(tMethod.access(), name, tMethod.block(), tMethod.signature(), tMethod.txSignature()));
}
var commonSubTypes = new HashSet<>(commonSuperInterfaceTypes(firstMethod.signature().returnType(), secondMethod.signature().returnType()));
for (var m : overloadedMethods.subList(2, overloadedMethods.size())) {
commonSubTypes.retainAll(commonSuperInterfaceTypes(firstMethod.signature().returnType(), m.signature().returnType()));
commonSubTypes.retainAll(commonSuperInterfaceTypes(firstMethod.signature().returnType(), m.signature().java.returnType()));
}
var returnType = commonSubTypes.isEmpty() ? TargetType.Object : new TargetRefType(commonSubTypes.iterator().next().getClassName().toString());
@@ -601,7 +616,7 @@ public class ASTToTargetAST {
}
private Expression makeRecordSwitch(RefTypeOrTPHOrWildcardOrGeneric returnType, ParameterList params, List<Method> overloadedMethods) {
var param = params.getFormalparalist().get(0);
var param = params.getFormalparalist().getFirst();
assert param instanceof RecordPattern; // TODO
var cases = new ArrayList<SwitchBlock>();
@@ -621,7 +636,7 @@ public class ASTToTargetAST {
return swtch;
}
private Optional<Method> findSuperMethodToOverride(ClassOrInterface currentClass, String name, List<MethodParameter> params) {
private Optional<Method> findSuperMethodToOverride(ClassOrInterface currentClass, String name, List<MethodParameter> params, IGenerics generics) {
var superClass = compiler.getClass(currentClass.getSuperClass().getName());
var methodStream = superClass.getMethods().stream();
for (var superInterface : currentClass.getSuperInterfaces()) {
@@ -634,115 +649,106 @@ public class ASTToTargetAST {
if (sParams.getFormalparalist().size() != params.size()) return false;
for (var i = 0; i < params.size(); i++) {
var a = TargetType.toPrimitive(params.get(i).pattern().type());
var b = convert(sParams.getFormalparalist().get(i).getType());
var b = convert(sParams.getFormalparalist().get(i).getType(), generics);
if (!Objects.equals(a, b)) return false;
}
return true;
}).findFirst();
}
record MethodWithTphs(TargetMethod method, Generics generics, List<SignaturePairTarget> args) {
record MethodWithTphs(Method method, Generics generics, Signature signature) {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof MethodWithTphs that)) return false;
return Objects.equals(method, that.method) && Objects.equals(args, that.args);
return Objects.equals(method, that.method) && Objects.equals(signature, that.signature);
}
@Override
public int hashCode() {
return Objects.hash(method, args);
return Objects.hash(method, signature);
}
}
private TargetMethod convert(MethodWithTphs mtph, IGenerics generics) {
return new TargetMethod(mtph.method.modifier, mtph.method.name, convert(mtph.method.block, generics), mtph.signature.java(), mtph.signature.tx());
}
record Signature(TargetMethod.Signature java, TargetMethod.Signature tx, Generics generics) {}
private List<MethodWithTphs> convert(ClassOrInterface currentClass, Method method) {
generics = all.getFirst();
List<MethodWithTphs> result = new ArrayList<>();
this.currentMethod = method;
List<Signature> signatures = new ArrayList<>();
HashMap<TargetMethod.Signature, List<Generics>> collectedGenerics = new HashMap<>();
for (var s : all) {
generics = s;
var javaGenerics = this.generics.javaGenerics.generics(currentClass, method);
var txGenerics = this.generics.txGenerics.generics(currentClass, method);
List<MethodParameter> params = convert(method.getParameterList(), this.generics.javaGenerics);
var returnType = convert(method.getReturnType(), this.generics.javaGenerics);
var superMethod = findSuperMethodToOverride(currentClass, method.getName(), params);
for (var generics : all) {
var javaGenerics = generics.javaGenerics.generics(currentClass, method);
var txGenerics = generics.txGenerics.generics(currentClass, method);
List<MethodParameter> params = convert(method.getParameterList(), generics.javaGenerics);
var returnType = convert(method.getReturnType(), generics.javaGenerics);
var superMethod = findSuperMethodToOverride(currentClass, method.getName(), params, generics.javaGenerics);
if (superMethod.isPresent()) {
// If we find a super method to override, use its parameters and return types
var newReturnType = convert(superMethod.get().getReturnType(), this.generics.javaGenerics);
var newReturnType = convert(superMethod.get().getReturnType(), generics.javaGenerics);
if (newReturnType instanceof TargetPrimitiveType && TargetType.toPrimitive(returnType).equals(newReturnType)) {
returnType = newReturnType;
params = convert(superMethod.get().getParameterList(), method.getParameterList(), this.generics.javaGenerics);
params = convert(superMethod.get().getParameterList(), method.getParameterList(), generics.javaGenerics);
}
}
List<MethodParameter> txParams = convert(method.getParameterList(), this.generics.txGenerics);
List<MethodParameter> txParams = convert(method.getParameterList(), generics.txGenerics);
var javaMethodGenerics = collectMethodGenerics(currentClass, generics.javaGenerics(), javaGenerics, method);
var txMethodGenerics = collectMethodGenerics(currentClass, generics.txGenerics(), txGenerics, method);
var javaSignature = new TargetMethod.Signature(javaMethodGenerics, params, returnType);
var txSignature = new TargetMethod.Signature(txMethodGenerics, txParams, convert(method.getReturnType(), this.generics.txGenerics));
var txSignature = new TargetMethod.Signature(txMethodGenerics, txParams, convert(method.getReturnType(), generics.txGenerics));
signatures.add(new Signature(javaSignature, txSignature, generics));
var listOfGenerics = collectedGenerics.getOrDefault(javaSignature, new ArrayList<>());
listOfGenerics.add(generics);
collectedGenerics.put(javaSignature, listOfGenerics);
}
for (var signature : signatures) {
generics = signature.generics;
currentMethodOverloads = collectedGenerics.get(signature.java);
var newMethod = new TargetMethod(method.modifier, method.name, convert(method.block), signature.java, signature.tx);
var concreteParams = tphsInMethods.getOrDefault(method, new HashSet<>()).stream().map(sig -> new SignaturePairTarget(convert(sig.signature), convert(sig.parameter))).toList();
result.add(new MethodWithTphs(newMethod, generics, concreteParams));
result.add(new MethodWithTphs(method, signature.generics, signature));
}
return result;
}
private List<MethodParameter> convert(ParameterList superList, ParameterList paraList, JavaGenerics generics) {
private List<MethodParameter> convert(ParameterList superList, ParameterList paraList, IGenerics generics) {
var list = new ArrayList<MethodParameter>();
for (var i = 0; i < paraList.getFormalparalist().size(); i++) {
var param = paraList.getParameterAt(i);
var pattern = (TargetPattern) convert(param);
var pattern = (TargetPattern) convert(param, generics);
if (pattern instanceof TargetComplexPattern) pattern = pattern.withName("__var" + i);
list.add(new MethodParameter(pattern).withType(convert(superList.getParameterAt(i).getType(), generics)));
}
return list;
}
protected TargetSwitch.Case convert(SwitchBlock block) {
return new TargetSwitch.Case(block.getLabels().stream().map(this::convert).toList(), convert((Block) block), block.isExpression);
protected TargetSwitch.Case convert(SwitchBlock block, IGenerics generics) {
return new TargetSwitch.Case(block.getLabels().stream().map(s -> convert(s, generics)).toList(), convert((Block) block, generics), block.isExpression);
}
protected TargetBlock convert(Block block) {
protected TargetBlock convert(Block block, IGenerics generics) {
if (block == null) return null;
return new TargetBlock(block.statements.stream().map(this::convert).toList());
return new TargetBlock(block.statements.stream().map(s -> convert(s, generics)).toList());
}
protected TargetBlock convertWrapInBlock(Expression expression) {
var res = convert(expression);
protected TargetBlock convertWrapInBlock(Expression expression, IGenerics generics) {
var res = convert(expression, generics);
if (!(res instanceof TargetBlock))
return new TargetBlock(List.of(res));
return (TargetBlock) res;
}
protected TargetExpression convert(Expression expr) {
var converter = new StatementToTargetExpression(this);
protected TargetExpression convert(Expression expr, IGenerics generics) {
var converter = new StatementToTargetExpression(this, generics);
expr.accept(converter);
return converter.result;
}
private TargetField convert(Field input) {
return new TargetField(input.modifier, convert(input.getType(), generics.javaGenerics), input.getName());
private TargetField convert(Field input, IGenerics generics) {
return new TargetField(input.modifier, convert(input.getType(), generics), input.getName());
}
private final Map<String, FunNGenerator.GenericParameters> usedFunN = new HashMap<>();
@@ -750,9 +756,6 @@ public class ASTToTargetAST {
public Map<String, byte[]> auxiliaries = new HashMap<>();
public TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input) {
return convert(input, generics.javaGenerics);
}
private static void collectArguments(TargetSpecializedType tspec, List<TargetType> newParams) {
for (var i = 0; i < tspec.params().size(); i++) {
@@ -831,7 +834,13 @@ public class ASTToTargetAST {
}
}
protected TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input, GenerateGenerics generics) {
// FIXME This method shouldn't be used
@Deprecated
public TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input) {
return convert(input, all.getFirst().javaGenerics);
}
public TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input, IGenerics generics) {
return input.acceptTV(new TypeVisitor<>() {
@Override
public TargetType visit(RefType refType) {

View File

@@ -16,7 +16,7 @@ import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public abstract class GenerateGenerics {
public abstract class GenerateGenerics implements IGenerics {
private final ASTToTargetAST astToTargetAST;
@@ -151,22 +151,6 @@ public abstract class GenerateGenerics {
System.out.println("Simplified constraints: " + simplifiedConstraints);
}
/*public record GenericsState(Map<TPH, RefTypeOrTPHOrWildcardOrGeneric> concreteTypes, Map<TypePlaceholder, TypePlaceholder> equality) {}
public GenericsState store() {
return new GenericsState(new HashMap<>(concreteTypes), new HashMap<>(equality));
}
public void restore(GenericsState state) {
this.concreteTypes = state.concreteTypes;
this.equality = state.equality;
}
public void addOverlay(TypePlaceholder from, RefTypeOrTPHOrWildcardOrGeneric to) {
if (to instanceof TypePlaceholder t) equality.put(from, t);
else if (to instanceof RefType t) concreteTypes.put(new TPH(from), t);
}*/
Set<TPH> findTypeVariables(ParameterList params) {
var res = new HashSet<TPH>();
for (var param : params.getFormalparalist()) {
@@ -282,6 +266,7 @@ public abstract class GenerateGenerics {
Set<Pair> result
) {
var userDefinedGenericsOfClass = astToTargetAST.userDefinedGenerics.get(owner);
var generics = this;
// Type variables with bounds that are also type variables of the method
for (var typeVariable : new HashSet<>(typeVariables)) {
@@ -329,7 +314,7 @@ public abstract class GenerateGenerics {
if (methodCall.receiver instanceof ExpressionReceiver expressionReceiver) {
if (expressionReceiver.expr instanceof This) {
var optMethod = astToTargetAST.findMethod(owner, methodCall.name, methodCall.signatureArguments().stream().map(astToTargetAST::convert).toList());
var optMethod = astToTargetAST.findMethod(owner, methodCall.name, methodCall.signatureArguments().stream().map(sa -> astToTargetAST.convert(sa, generics)).toList());
if (optMethod.isEmpty()) return;
var method2 = optMethod.get();
System.out.println("In: " + method.getName() + " Method: " + method2.getName());
@@ -539,8 +524,6 @@ public abstract class GenerateGenerics {
});
}
abstract void generics(ClassOrInterface owner, Method method, Set<Pair> result, Set<TPH> javaTypeVariablesOfClass);
Set<Pair> family(ClassOrInterface owner, Method method) {
Set<Pair> result = new HashSet<>();
if (familyOfMethods.containsKey(method))
@@ -564,7 +547,8 @@ public abstract class GenerateGenerics {
return result;
}
Set<Pair> generics(ClassOrInterface owner, Method method) {
@Override
public Set<Pair> generics(ClassOrInterface owner, Method method) {
if (computedGenericsOfMethods.containsKey(method)) {
var cached = computedGenericsOfMethods.get(method);
System.out.println("Cached " + method.getName() + ": " + cached);
@@ -652,8 +636,10 @@ public abstract class GenerateGenerics {
}
abstract void generics(ClassOrInterface classOrInterface, Set<Pair> result, Set<TPH> referenced);
abstract void generics(ClassOrInterface owner, Method method, Set<Pair> result, Set<TPH> referenced);
Set<Pair> generics(ClassOrInterface classOrInterface) {
@Override
public Set<Pair> generics(ClassOrInterface classOrInterface) {
if (computedGenericsOfClasses.containsKey(classOrInterface))
return computedGenericsOfClasses.get(classOrInterface);
@@ -988,7 +974,13 @@ public abstract class GenerateGenerics {
} while (foundInfima);
}
RefTypeOrTPHOrWildcardOrGeneric getType(RefTypeOrTPHOrWildcardOrGeneric type) {
@Override
public TypePlaceholder getEqualType(TypePlaceholder tph) {
return this.equality.getOrDefault(tph, tph);
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric getType(RefTypeOrTPHOrWildcardOrGeneric type) {
if (type instanceof TypePlaceholder tph) {
if (equality.containsKey(tph)) {
return getType(equality.get(tph));
@@ -998,7 +990,8 @@ public abstract class GenerateGenerics {
return type;
}
TargetType getTargetType(RefTypeOrTPHOrWildcardOrGeneric in) {
@Override
public TargetType getTargetType(RefTypeOrTPHOrWildcardOrGeneric in) {
if (in instanceof TypePlaceholder tph) {
if (equality.containsKey(tph)) {
return getTargetType(equality.get(tph));

View File

@@ -9,21 +9,20 @@ import de.dhbwstuttgart.target.tree.type.TargetType;
import java.util.*;
public class GenericsResult {
private final GenerateGenerics generics;
private final IGenerics generics;
GenericsResult(GenerateGenerics generics) {
GenericsResult(IGenerics generics) {
this.generics = generics;
}
public GenericsResultSet get(ClassOrInterface clazz) {
var generics = this.generics.computedGenericsOfClasses.get(clazz);
return new GenericsResultSet(generics, this.generics.equality);
var generics = this.generics.generics(clazz);
return new GenericsResultSet(generics, this.generics);
}
// TODO Compute generics if not present?
public GenericsResultSet get(Method method) {
var generics = this.generics.computedGenericsOfMethods.get(method);
return new GenericsResultSet(generics, this.generics.equality);
public GenericsResultSet get(ClassOrInterface clazz, Method method) {
var generics = this.generics.generics(clazz, method);
return new GenericsResultSet(generics, this.generics);
}
public BoundsList getBounds(RefTypeOrTPHOrWildcardOrGeneric type, ClassOrInterface clazz) {
@@ -34,7 +33,7 @@ public class GenericsResult {
var resolvedType = resolve(type);
type = resolvedType;
if (type instanceof TypePlaceholder) {
var methodGenerics = get(method);
var methodGenerics = get(clazz, method);
var classGenerics = get(clazz);
List<Bound> result = new ArrayList<>();

View File

@@ -4,17 +4,18 @@ import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.result.PairTPHequalRefTypeOrWildcardType;
import de.dhbwstuttgart.typeinference.result.PairTPHsmallerTPH;
import de.dhbwstuttgart.typeinference.result.ResultPair;
import org.antlr.v4.codegen.model.decl.ContextRuleListIndexedGetterDecl;
import java.util.*;
public class GenericsResultSet extends AbstractSet<GenerateGenerics.Pair> {
final Set<GenerateGenerics.Pair> backing;
final Map<TypePlaceholder, TypePlaceholder> equality;
final IGenerics generics;
public GenericsResultSet(Set<GenerateGenerics.Pair> backing, Map<TypePlaceholder, TypePlaceholder> equality) {
public GenericsResultSet(Set<GenerateGenerics.Pair> backing, IGenerics generics) {
this.backing = backing == null ? new HashSet<>() : new HashSet<>(backing);
this.equality = equality;
this.generics = generics;
}
@Override
@@ -28,7 +29,7 @@ public class GenericsResultSet extends AbstractSet<GenerateGenerics.Pair> {
}
public Optional<ResultPair<?, ?>> getResultPairFor(TypePlaceholder tph) {
var tph2 = equality.getOrDefault(tph, tph);
var tph2 = generics.getEqualType(tph);
return this.stream().filter(pair -> {
return pair.left.resolve().equals(tph2);
}).findFirst().map(pair -> {

View File

@@ -0,0 +1,22 @@
package de.dhbwstuttgart.target.generate;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.target.tree.type.TargetType;
import java.util.Set;
public interface IGenerics {
Set<GenerateGenerics.Pair> generics(ClassOrInterface classOrInterface);
Set<GenerateGenerics.Pair> generics(ClassOrInterface owner, Method method);
RefTypeOrTPHOrWildcardOrGeneric getType(RefTypeOrTPHOrWildcardOrGeneric type);
TypePlaceholder getEqualType(TypePlaceholder tph);
TargetType getTargetType(RefTypeOrTPHOrWildcardOrGeneric in);
}

View File

@@ -0,0 +1,60 @@
package de.dhbwstuttgart.target.generate;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.target.tree.type.TargetGenericType;
import de.dhbwstuttgart.target.tree.type.TargetType;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class OverlayGenerics implements IGenerics {
private final IGenerics wrapped;
private final ASTToTargetAST converter;
private final Map<TypePlaceholder, TargetType> overlay;
public OverlayGenerics(IGenerics wrapped, ASTToTargetAST converter) {
this.wrapped = wrapped;
this.converter = converter;
this.overlay = new HashMap<>();
}
public void addOverlay(TypePlaceholder tph, TargetType type) {
this.overlay.put(tph, type);
}
@Override
public Set<GenerateGenerics.Pair> generics(ClassOrInterface classOrInterface) {
return wrapped.generics(classOrInterface);
}
@Override
public Set<GenerateGenerics.Pair> generics(ClassOrInterface owner, Method method) {
return wrapped.generics(owner, method);
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric getType(RefTypeOrTPHOrWildcardOrGeneric type) {
return wrapped.getType(type);
}
@Override
public TypePlaceholder getEqualType(TypePlaceholder tph) {
return wrapped.getEqualType(tph);
}
@Override
public TargetType getTargetType(RefTypeOrTPHOrWildcardOrGeneric in) {
if (in instanceof TypePlaceholder tph) {
var overlay = this.overlay.get(tph);
if (overlay != null) return overlay;
var type = getType(tph);
if (type == null) return new TargetGenericType(tph.getName());
return wrapped.getTargetType(type);
}
return converter.convert(in, this);
}
}

View File

@@ -21,11 +21,13 @@ import java.util.stream.StreamSupport;
public class StatementToTargetExpression implements ASTVisitor {
public StatementToTargetExpression(ASTToTargetAST converter) {
public StatementToTargetExpression(ASTToTargetAST converter, IGenerics generics) {
this.converter = converter;
this.generics = generics;
}
public TargetExpression result;
private final IGenerics generics;
private final ASTToTargetAST converter;
@Override
@@ -64,7 +66,7 @@ public class StatementToTargetExpression implements ASTVisitor {
@Override
public void visit(LocalVar localVar) {
super.visit(localVar);
var capture = new MethodParameter(new TargetTypePattern(converter.convert(localVar.getType()), localVar.name));
var capture = new MethodParameter(new TargetTypePattern(converter.convert(localVar.getType(), generics), localVar.name));
if (!hasLocalVar(localVar.name) && !parameters.contains(capture) && !captures.contains(capture))
captures.add(capture);
}
@@ -88,7 +90,7 @@ public class StatementToTargetExpression implements ASTVisitor {
private List<MethodParameter> createParameters(LambdaExpression lambda) {
return StreamSupport.stream(lambda.params.spliterator(), false)
.map(p -> (FormalParameter) p)
.map(p -> new MethodParameter(new TargetTypePattern(converter.convert(p.getType()), p.getName())))
.map(p -> new MethodParameter(new TargetTypePattern(converter.convert(p.getType(), generics), p.getName())))
.toList();
}
@@ -99,59 +101,59 @@ public class StatementToTargetExpression implements ASTVisitor {
var visitor = new LambdaCaptureFinder(parameters, captures);
lambdaExpression.methodBody.accept(visitor);
TargetMethod.Signature signature = new TargetMethod.Signature(Set.of(), parameters, converter.convert(lambdaExpression.getReturnType()));;
var tpe = converter.convert(lambdaExpression.getType());
result = new TargetLambdaExpression(tpe, captures, signature, converter.convert(lambdaExpression.methodBody));
TargetMethod.Signature signature = new TargetMethod.Signature(Set.of(), parameters, converter.convert(lambdaExpression.getReturnType(), generics));;
var tpe = converter.convert(lambdaExpression.getType(), generics);
result = new TargetLambdaExpression(tpe, captures, signature, converter.convert(lambdaExpression.methodBody, this.generics));
}
@Override
public void visit(Assign assign) {
TargetExpression left;
if (assign.lefSide instanceof AssignToLocal) {
left = converter.convert(((AssignToLocal) assign.lefSide).localVar);
left = converter.convert(((AssignToLocal) assign.lefSide).localVar, this.generics);
} else {
left = converter.convert(((AssignToField) assign.lefSide).field);
left = converter.convert(((AssignToField) assign.lefSide).field, this.generics);
}
result = new TargetAssign(converter.convert(assign.getType()), left, converter.convert(assign.rightSide));
result = new TargetAssign(converter.convert(assign.getType(), generics), left, converter.convert(assign.rightSide, this.generics));
}
@Override
public void visit(BinaryExpr binary) {
result = switch (binary.operation) {
case ADD -> new TargetBinaryOp.Add(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
case SUB -> new TargetBinaryOp.Sub(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
case MUL -> new TargetBinaryOp.Mul(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
case MOD -> new TargetBinaryOp.Rem(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
case AND -> new TargetBinaryOp.BAnd(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
case OR -> new TargetBinaryOp.BOr(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
case XOR -> new TargetBinaryOp.XOr(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
case DIV -> new TargetBinaryOp.Div(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
case LESSTHAN -> new TargetBinaryOp.Less(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
case BIGGERTHAN -> new TargetBinaryOp.Greater(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
case LESSEQUAL -> new TargetBinaryOp.LessOrEqual(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
case BIGGEREQUAL -> new TargetBinaryOp.GreaterOrEqual(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
case EQUAL -> new TargetBinaryOp.Equal(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
case NOTEQUAL -> new TargetBinaryOp.NotEqual(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
case ADD -> new TargetBinaryOp.Add(converter.convert(binary.getType(), generics), converter.convert(binary.lexpr, this.generics), converter.convert(binary.rexpr, this.generics));
case SUB -> new TargetBinaryOp.Sub(converter.convert(binary.getType(), generics), converter.convert(binary.lexpr, this.generics), converter.convert(binary.rexpr, this.generics));
case MUL -> new TargetBinaryOp.Mul(converter.convert(binary.getType(), generics), converter.convert(binary.lexpr, this.generics), converter.convert(binary.rexpr, this.generics));
case MOD -> new TargetBinaryOp.Rem(converter.convert(binary.getType(), generics), converter.convert(binary.lexpr, this.generics), converter.convert(binary.rexpr, this.generics));
case AND -> new TargetBinaryOp.BAnd(converter.convert(binary.getType(), generics), converter.convert(binary.lexpr, this.generics), converter.convert(binary.rexpr, this.generics));
case OR -> new TargetBinaryOp.BOr(converter.convert(binary.getType(), generics), converter.convert(binary.lexpr, this.generics), converter.convert(binary.rexpr, this.generics));
case XOR -> new TargetBinaryOp.XOr(converter.convert(binary.getType(), generics), converter.convert(binary.lexpr, this.generics), converter.convert(binary.rexpr, this.generics));
case DIV -> new TargetBinaryOp.Div(converter.convert(binary.getType(), generics), converter.convert(binary.lexpr, this.generics), converter.convert(binary.rexpr, this.generics));
case LESSTHAN -> new TargetBinaryOp.Less(converter.convert(binary.getType(), generics), converter.convert(binary.lexpr, this.generics), converter.convert(binary.rexpr, this.generics));
case BIGGERTHAN -> new TargetBinaryOp.Greater(converter.convert(binary.getType(), generics), converter.convert(binary.lexpr, this.generics), converter.convert(binary.rexpr, this.generics));
case LESSEQUAL -> new TargetBinaryOp.LessOrEqual(converter.convert(binary.getType(), generics), converter.convert(binary.lexpr, this.generics), converter.convert(binary.rexpr, this.generics));
case BIGGEREQUAL -> new TargetBinaryOp.GreaterOrEqual(converter.convert(binary.getType(), generics), converter.convert(binary.lexpr, this.generics), converter.convert(binary.rexpr, this.generics));
case EQUAL -> new TargetBinaryOp.Equal(converter.convert(binary.getType(), generics), converter.convert(binary.lexpr, this.generics), converter.convert(binary.rexpr, this.generics));
case NOTEQUAL -> new TargetBinaryOp.NotEqual(converter.convert(binary.getType(), generics), converter.convert(binary.lexpr, this.generics), converter.convert(binary.rexpr, this.generics));
};
}
@Override
public void visit(BoolExpression bool) {
result = switch(bool.operation) {
case OR -> new TargetBinaryOp.Or(converter.convert(bool.getType()), converter.convert(bool.lexpr), converter.convert(bool.rexpr));
case AND -> new TargetBinaryOp.And(converter.convert(bool.getType()), converter.convert(bool.lexpr), converter.convert(bool.rexpr));
case OR -> new TargetBinaryOp.Or(converter.convert(bool.getType(), generics), converter.convert(bool.lexpr, generics), converter.convert(bool.rexpr, generics));
case AND -> new TargetBinaryOp.And(converter.convert(bool.getType(), generics), converter.convert(bool.lexpr, generics), converter.convert(bool.rexpr, generics));
};
}
@Override
public void visit(Block block) {
result = converter.convert(block);
result = converter.convert(block, generics);
}
@Override
public void visit(CastExpr castExpr) {
result = new TargetCast(converter.convert(castExpr.getType()), converter.convert(castExpr.expr));
result = new TargetCast(converter.convert(castExpr.getType(), generics), converter.convert(castExpr.expr, generics));
}
@Override
@@ -162,46 +164,46 @@ public class StatementToTargetExpression implements ASTVisitor {
@Override
public void visit(FieldVar fieldVar) {
var isStatic = false;
var type = converter.convert(fieldVar.receiver.getType());
var type = converter.convert(fieldVar.receiver.getType(), generics);
var clazz = converter.compiler.getClass(new JavaClassName(type.name()));
var field = clazz.getField(fieldVar.fieldVarName).orElseThrow();
result = new TargetFieldVar(converter.convert(fieldVar.getType()), type, Modifier.isStatic(field.modifier), converter.convert(fieldVar.receiver), fieldVar.fieldVarName);
result = new TargetFieldVar(converter.convert(fieldVar.getType(), generics), type, Modifier.isStatic(field.modifier), converter.convert(fieldVar.receiver, this.generics), fieldVar.fieldVarName);
}
@Override
public void visit(ForStmt forStmt) {
result = new TargetFor(
forStmt.initializer.stream().map(converter::convert).toList(),
forStmt.condition != null ? converter.convert(forStmt.condition) : null,
forStmt.loopExpr.stream().map(converter::convert).toList(),
converter.convertWrapInBlock(forStmt.block)
forStmt.initializer.stream().map(c -> converter.convert(c, generics)).toList(),
forStmt.condition != null ? converter.convert(forStmt.condition, generics) : null,
forStmt.loopExpr.stream().map(e -> converter.convert(e, generics)).toList(),
converter.convertWrapInBlock(forStmt.block, generics)
);
}
@Override
public void visit(ForEachStmt forEachStmt) {
result = new TargetForEach(converter.convert(forEachStmt.statement), converter.convert(forEachStmt.expression), converter.convertWrapInBlock(forEachStmt.block));
result = new TargetForEach(converter.convert(forEachStmt.statement, generics), converter.convert(forEachStmt.expression, generics), converter.convertWrapInBlock(forEachStmt.block, generics));
}
@Override
public void visit(IfStmt ifStmt) {
result = new TargetIf(converter.convert(ifStmt.expr), converter.convertWrapInBlock(ifStmt.then_block), ifStmt.else_block != null ? converter.convertWrapInBlock(ifStmt.else_block) : null);
result = new TargetIf(converter.convert(ifStmt.expr, generics), converter.convertWrapInBlock(ifStmt.then_block, generics), ifStmt.else_block != null ? converter.convertWrapInBlock(ifStmt.else_block, generics) : null);
}
@Override
public void visit(InstanceOf instanceOf) {
result = new TargetInstanceOf(converter.convert(instanceOf.getExpression()), converter.convert(instanceOf.getPattern()));
result = new TargetInstanceOf(converter.convert(instanceOf.getExpression(), generics), converter.convert(instanceOf.getPattern(), this.generics));
}
@Override
public void visit(LocalVar localVar) {
result = new TargetLocalVar(converter.convert(localVar.getType()), localVar.name);
result = new TargetLocalVar(converter.convert(localVar.getType(), generics), localVar.name);
}
@Override
public void visit(LocalVarDecl localVarDecl) {
// TODO No value, is this correct?
result = new TargetVarDecl(converter.convert(localVarDecl.getType()), localVarDecl.getName(), null);
result = new TargetVarDecl(converter.convert(localVarDecl.getType(), generics), localVarDecl.getName(), null);
}
static boolean convertsTo(TargetType from, TargetType to) {
@@ -216,19 +218,19 @@ public class StatementToTargetExpression implements ASTVisitor {
@Override
public void visit(MethodCall methodCall) {
var receiverType = converter.convert(methodCall.receiver.getType());
var receiverType = converter.convert(methodCall.receiver.getType(), generics);
var isFunNType = receiverType instanceof TargetFunNType;
var returnType = isFunNType ? TargetType.Object : converter.convert(methodCall.signature.get(methodCall.signature.size() - 1));
var receiverName = new JavaClassName(converter.convert(methodCall.receiver.getType()).name());
var argList = methodCall.signature.stream().map(converter::convert).toList();
var returnType = isFunNType ? TargetType.Object : converter.convert(methodCall.signature.getLast(), generics);
var receiverName = new JavaClassName(converter.convert(methodCall.receiver.getType(), generics).name());
var argList = methodCall.signature.stream().map(sig -> converter.convert(sig, generics)).toList();
argList = argList.subList(0, argList.size() - 1);
Method foundMethod = null;
var isStatic = false;
var isInterface = true;
var isPrivate = false;
var signature = methodCall.signatureArguments().stream().map(converter::convert).toList();
var signature = methodCall.signatureArguments().stream().map(sig -> converter.convert(sig, generics)).toList();
// Add used TPHs to containing method
for (var i = 0; i < methodCall.signatureArguments().size(); i++) {
@@ -248,23 +250,28 @@ public class StatementToTargetExpression implements ASTVisitor {
}
if (!isFunNType) {
returnType = converter.convert(foundMethod.getReturnType());
argList = foundMethod.getParameterList().getFormalparalist().stream().map(e -> converter.convert(e.getType())).toList();
returnType = converter.convert(foundMethod.getReturnType(), generics);
argList = foundMethod.getParameterList().getFormalparalist().stream().map(e -> converter.convert(e.getType(), generics)).toList();
isStatic = Modifier.isStatic(foundMethod.modifier);
isPrivate = Modifier.isPrivate(foundMethod.modifier);
isInterface = receiverClass.isInterface();
}
System.out.println(argList);
result = new TargetMethodCall(converter.convert(methodCall.getType()), returnType, argList, converter.convert(methodCall.receiver), methodCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), receiverType, methodCall.name, isStatic, isInterface, isPrivate);
result = new TargetMethodCall(
converter.convert(methodCall.getType(), generics), returnType, argList,
converter.convert(methodCall.receiver, generics),
methodCall.getArgumentList().getArguments().stream().map(arg -> converter.convert(arg, generics)).toList(),
receiverType, methodCall.name, isStatic, isInterface, isPrivate
);
}
@Override
public void visit(NewClass newClass) {
var receiverName = new JavaClassName(newClass.name);
var ctor = converter.findConstructor(converter.compiler.getClass(receiverName), newClass.signatureArguments().stream().map(converter::convert).toList());
var signature = ctor.orElseThrow().getParameterList().getFormalparalist().stream().map(e -> converter.convert(e.getType())).toList();
result = new TargetNew(new TargetRefType(newClass.name), signature, newClass.getArgumentList().getArguments().stream().map(converter::convert).toList());
var ctor = converter.findConstructor(converter.compiler.getClass(receiverName), newClass.signatureArguments().stream().map(arg -> converter.convert(arg, generics)).toList());
var signature = ctor.orElseThrow().getParameterList().getFormalparalist().stream().map(e -> converter.convert(e.getType(), generics)).toList();
result = new TargetNew(new TargetRefType(newClass.name), signature, newClass.getArgumentList().getArguments().stream().map(arg -> converter.convert(arg, generics)).toList());
}
@Override
@@ -275,7 +282,7 @@ public class StatementToTargetExpression implements ASTVisitor {
@Override
public void visit(Return aReturn) {
result = new TargetReturn(converter.convert(aReturn.retexpr));
result = new TargetReturn(converter.convert(aReturn.retexpr, generics));
}
@Override
@@ -295,53 +302,53 @@ public class StatementToTargetExpression implements ASTVisitor {
@Override
public void visit(StaticClassName staticClassName) {
result = new TargetClassName(converter.convert(staticClassName.getType()));
result = new TargetClassName(converter.convert(staticClassName.getType(), generics));
}
@Override
public void visit(Super aSuper) {
result = new TargetSuper(converter.convert(aSuper.getType()));
result = new TargetSuper(converter.convert(aSuper.getType(), generics));
}
@Override
public void visit(This aThis) {
result = new TargetThis(converter.convert(aThis.getType()));
result = new TargetThis(converter.convert(aThis.getType(), generics));
}
@Override
public void visit(WhileStmt whileStmt) {
result = new TargetWhile(converter.convert(whileStmt.expr), converter.convert(whileStmt.loopBlock));
result = new TargetWhile(converter.convert(whileStmt.expr, generics), converter.convert(whileStmt.loopBlock, generics));
}
@Override
public void visit(DoStmt whileStmt) {
result = new TargetDo(converter.convert(whileStmt.expr), converter.convert(whileStmt.loopBlock));
result = new TargetDo(converter.convert(whileStmt.expr, generics), converter.convert(whileStmt.loopBlock, generics));
}
// TODO These two might not be necessary
@Override
public void visit(AssignToField assignLeftSide) {
result = converter.convert(assignLeftSide.field);
result = converter.convert(assignLeftSide.field, generics);
}
@Override
public void visit(AssignToLocal assignLeftSide) {
result = converter.convert(assignLeftSide.localVar);
result = converter.convert(assignLeftSide.localVar, generics);
}
@Override
public void visit(SuperCall superCall) {
var aSuper = converter.convert(superCall.receiver.getType());
var type = converter.convert(superCall.getType());
var receiverName = new JavaClassName(converter.convert(superCall.receiver.getType()).name());
var aSuper = converter.convert(superCall.receiver.getType(), generics);
var type = converter.convert(superCall.getType(), generics);
var receiverName = new JavaClassName(converter.convert(superCall.receiver.getType(), generics).name());
var clazz = converter.compiler.getClass(receiverName);
var signature = superCall.signatureArguments().stream().map(converter::convert).toList();
var signature = superCall.signatureArguments().stream().map(arg -> converter.convert(arg, generics)).toList();
var method = converter.findConstructor(clazz, signature);
var params = superCall.getArgumentList().getArguments().stream().map(converter::convert).toList();
var params = superCall.getArgumentList().getArguments().stream().map(arg -> converter.convert(arg, generics)).toList();
List<TargetType> argList;
if (method.isPresent()) {
argList = method.get().getParameterList().getFormalparalist().stream().map(e -> converter.convert(e.getType())).toList();
argList = method.get().getParameterList().getFormalparalist().stream().map(e -> converter.convert(e.getType(), generics)).toList();
} else {
argList = params.stream().map(TargetExpression::type).toList();
}
@@ -351,28 +358,28 @@ public class StatementToTargetExpression implements ASTVisitor {
@Override
public void visit(ThisCall thisCall) {
var aThis = converter.convert(thisCall.receiver.getType());
var type = converter.convert(thisCall.getType());
var parameters = thisCall.arglist.getArguments().stream().map(par -> converter.convert(par.getType())).toList();
var aThis = converter.convert(thisCall.receiver.getType(), generics);
var type = converter.convert(thisCall.getType(), generics);
var parameters = thisCall.arglist.getArguments().stream().map(par -> converter.convert(par.getType(), generics)).toList();
result = new TargetMethodCall(type, type, parameters, new TargetThis(aThis), thisCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), aThis, thisCall.name, false, false, false);
result = new TargetMethodCall(type, type, parameters, new TargetThis(aThis), thisCall.getArgumentList().getArguments().stream().map(arg -> converter.convert(arg, generics)).toList(), aThis, thisCall.name, false, false, false);
}
@Override
public void visit(ExpressionReceiver expressionReceiver) {
result = converter.convert(expressionReceiver.expr);
result = converter.convert(expressionReceiver.expr, generics);
}
@Override
public void visit(UnaryExpr unaryExpr) {
result = switch (unaryExpr.operation) {
case NOT -> new TargetUnaryOp.Not(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr));
case MINUS -> new TargetUnaryOp.Negate(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr));
case PREINCREMENT -> new TargetUnaryOp.PreIncrement(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr));
case PREDECREMENT -> new TargetUnaryOp.PreDecrement(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr));
case POSTINCREMENT -> new TargetUnaryOp.PostIncrement(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr));
case PLUS -> new TargetUnaryOp.Add(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr));
case POSTDECREMENT -> new TargetUnaryOp.PostDecrement(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr));
case NOT -> new TargetUnaryOp.Not(converter.convert(unaryExpr.getType(), generics), converter.convert(unaryExpr.expr, generics));
case MINUS -> new TargetUnaryOp.Negate(converter.convert(unaryExpr.getType(), generics), converter.convert(unaryExpr.expr, generics));
case PREINCREMENT -> new TargetUnaryOp.PreIncrement(converter.convert(unaryExpr.getType(), generics), converter.convert(unaryExpr.expr, generics));
case PREDECREMENT -> new TargetUnaryOp.PreDecrement(converter.convert(unaryExpr.getType(), generics), converter.convert(unaryExpr.expr, generics));
case POSTINCREMENT -> new TargetUnaryOp.PostIncrement(converter.convert(unaryExpr.getType(), generics), converter.convert(unaryExpr.expr, generics));
case PLUS -> new TargetUnaryOp.Add(converter.convert(unaryExpr.getType(), generics), converter.convert(unaryExpr.expr, generics));
case POSTDECREMENT -> new TargetUnaryOp.PostDecrement(converter.convert(unaryExpr.getType(), generics), converter.convert(unaryExpr.expr, generics));
};
}
@@ -400,12 +407,12 @@ public class StatementToTargetExpression implements ASTVisitor {
@Override
public void visit(Throw aThrow) {
result = new TargetThrow(converter.convert(aThrow.expr));
result = new TargetThrow(converter.convert(aThrow.expr, generics));
}
@Override
public void visit(Ternary ternary) {
result = new TargetTernary(converter.convert(ternary.getType()), converter.convert(ternary.cond), converter.convert(ternary.iftrue), converter.convert(ternary.iffalse));
result = new TargetTernary(converter.convert(ternary.getType(), generics), converter.convert(ternary.cond, generics), converter.convert(ternary.iftrue, generics), converter.convert(ternary.iffalse, generics));
}
record TypeVariants(RefTypeOrTPHOrWildcardOrGeneric in, List<RefTypeOrTPHOrWildcardOrGeneric> types) {}
@@ -469,10 +476,8 @@ public class StatementToTargetExpression implements ASTVisitor {
var product = cartesianProduct(extractAllPatterns(label.getPattern()));
for (var l : product) {
var oldGenerics = converter.generics;
// Set the generics to matching result set
for (var generics : converter.currentMethodOverloads) {
/*for (var generics : converter.currentMethodOverloads) {
var java = generics.javaGenerics();
var equals = true;
for (var pair : l) {
@@ -481,17 +486,15 @@ public class StatementToTargetExpression implements ASTVisitor {
}
}
if (equals) {
converter.generics = generics;
break;
}
}
}*/
overloads.add(converter.convert(case_));
converter.generics = oldGenerics;
overloads.add(converter.convert(case_, generics));
}
}
} else {
overloads.add(converter.convert(case_));
overloads.add(converter.convert(case_, generics));
}
return overloads;
@@ -500,10 +503,10 @@ public class StatementToTargetExpression implements ASTVisitor {
TargetSwitch.Case default_ = null;
for (var block : switchStmt.getBlocks()) {
if (block.isDefault()) {
default_ = new TargetSwitch.Case(converter.convert((Block) block), block.isExpression);
default_ = new TargetSwitch.Case(converter.convert((Block) block, generics), block.isExpression);
}
}
result = new TargetSwitch(converter.convert(switchStmt.getSwitch()), cases, default_ , converter.convert(switchStmt.getType()), !switchStmt.getStatement());
result = new TargetSwitch(converter.convert(switchStmt.getSwitch(), generics), cases, default_ , converter.convert(switchStmt.getType(), generics), !switchStmt.getStatement());
}
@Override
@@ -511,12 +514,12 @@ public class StatementToTargetExpression implements ASTVisitor {
@Override
public void visit(SwitchLabel switchLabel) {
result = converter.convert(switchLabel.getPattern());
result = converter.convert(switchLabel.getPattern(), this.generics);
}
@Override
public void visit(Yield aYield) {
result = new TargetYield(converter.convert(aYield.retexpr));
result = new TargetYield(converter.convert(aYield.retexpr, generics));
}
@Override
@@ -586,30 +589,30 @@ public class StatementToTargetExpression implements ASTVisitor {
@Override
public void visit(FormalParameter aPattern) {
result = new TargetTypePattern(converter.convert(aPattern.getType()), aPattern.getName());
result = new TargetTypePattern(converter.convert(aPattern.getType(), generics), aPattern.getName());
}
@Override
public void visit(LiteralPattern literalPattern) {
result = new TargetExpressionPattern(converter.convert(literalPattern.value));
result = new TargetExpressionPattern(converter.convert(literalPattern.value, generics));
}
@Override
public void visit(ExpressionPattern aPattern) {
result = converter.convert(aPattern.getExpression());
result = converter.convert(aPattern.getExpression(), generics);
}
@Override
public void visit(RecordPattern aRecordPattern) {
result = new TargetComplexPattern(
converter.convert(aRecordPattern.getType()),
converter.convert(aRecordPattern.getType(), generics),
aRecordPattern.getName(),
aRecordPattern.getSubPattern().stream().map(x -> (TargetPattern) converter.convert(x)).toList()
aRecordPattern.getSubPattern().stream().map(x -> (TargetPattern) converter.convert(x, generics)).toList()
);
}
@Override
public void visit(GuardedPattern aGuardedPattern) {
result = new TargetGuard((TargetPattern) converter.convert(aGuardedPattern.getNestedPattern()), converter.convert(aGuardedPattern.getCondition()));
result = new TargetGuard((TargetPattern) converter.convert(aGuardedPattern.getNestedPattern(), generics), converter.convert(aGuardedPattern.getCondition(), generics));
}
}

View File

@@ -55,7 +55,7 @@ class TypeInsertPlacerClass extends AbstractASTWalker{
@Override
public void visit(Method method) {
this.method = method;
constraints = generatedGenerics.get(method);
constraints = generatedGenerics.get(cl, method);
classConstraints = generatedGenerics.get(cl);
if(method.getReturnType() instanceof TypePlaceholder)
inserts.add(TypeInsertFactory.createInsertPoints(

View File

@@ -931,7 +931,7 @@ public class TestComplete {
}
@Disabled("Not implemented")
//@Disabled("Not implemented")
@Test
public void testPatternMatchingListAppend() throws Exception {
var classFiles = generateClassFiles(createClassLoader(), "PatternMatchingListAppend.jav");

View File

@@ -65,7 +65,7 @@ public class TestGenerics {
var b = result.findField("b");
var generics = result.genericsResults.get(0);
assertEquals(1, generics.get(anyMethod).size());
assertEquals(1, generics.get(result.clazz, anyMethod).size());
assertEquals(2, generics.get(result.clazz).size());
var ECK1 = generics.getBounds(otherMethod.getParameterList().getParameterAt(0).getType(), result.clazz, anyMethod);
@@ -86,7 +86,7 @@ public class TestGenerics {
var generics = result.genericsResults.get(0);
assertEquals(1, generics.get(result.clazz).size());
assertEquals(0, generics.get(fReturn).size());
assertEquals(0, generics.get(result.clazz, fReturn).size());
var N = generics.getBounds(fReturn.getReturnType(), result.clazz);
var NChain = new BoundsList(onClass(OBJECT));
@@ -101,8 +101,8 @@ public class TestGenerics {
var generics = result.genericsResults.get(0);
assertEquals(0, generics.get(result.clazz).size());
assertEquals(3, generics.get(m).size());
assertEquals(3, generics.get(main).size());
assertEquals(3, generics.get(result.clazz, m).size());
assertEquals(3, generics.get(result.clazz, main).size());
{
var AJ = generics.getBounds(m.getParameterList().getParameterAt(0).getType(), result.clazz, m);
@@ -143,9 +143,9 @@ public class TestGenerics {
var generics = result.genericsResults.get(0);
assertEquals(1, generics.get(result.clazz).size());
assertEquals(2, generics.get(id).size());
assertEquals(1, generics.get(setA).size());
assertEquals(2, generics.get(m).size());
assertEquals(2, generics.get(result.clazz, id).size());
assertEquals(1, generics.get(result.clazz, setA).size());
assertEquals(2, generics.get(result.clazz, m).size());
var R = generics.getBounds(a.getType(), result.clazz);
var RChain = new BoundsList(onClass(OBJECT));
@@ -183,9 +183,9 @@ public class TestGenerics {
var generics = result.genericsResults.get(0);
assertEquals(1, generics.get(result.clazz).size());
assertEquals(2, generics.get(id).size());
assertEquals(2, generics.get(m).size());
assertEquals(3, generics.get(main).size());
assertEquals(2, generics.get(result.clazz, id).size());
assertEquals(2, generics.get(result.clazz, m).size());
assertEquals(3, generics.get(result.clazz, main).size());
var N = generics.getBounds(a.getType(), result.clazz);
assertEquals(N, new BoundsList(onClass(OBJECT)));
@@ -215,7 +215,7 @@ public class TestGenerics {
var anyMethod = result.findMethod("anyMethod");
var generics = result.genericsResults.get(0);
assertEquals(1, generics.get(anyMethod).size());
assertEquals(1, generics.get(result.clazz, anyMethod).size());
var M = generics.getBounds(anyMethod.getReturnType(), result.clazz, anyMethod);
assertEquals(M, new BoundsList(onMethod(OBJECT)));