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
18 changed files with 379 additions and 366 deletions

View File

@@ -1,8 +1,5 @@
name: Build and Test with Maven name: Build and Test with Maven
on: on: [push]
push:
branches-ignore:
- master
jobs: jobs:
Build-and-test-with-Maven: Build-and-test-with-Maven:

View File

@@ -1,45 +0,0 @@
on:
push:
branches:
- master
pull_request:
types: [opened, synchronize, reopened]
name: SonarQube Scan
jobs:
sonarqube:
name: SonarQube Trigger
runs-on: ubuntu-latest
steps:
- name: Checking out
uses: actions/checkout@v4
with:
# Disabling shallow clone is recommended for improving relevancy of reporting
fetch-depth: 0
- name: Install maven
run: |
apt update
apt install -y maven
- name: Install java
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '24'
cache: 'maven'
- name: Compile project
run: |
mvn clean dependency:copy-dependencies verify
- name: SonarQube Scan
uses: SonarSource/sonarqube-scan-action@v5.3.0
env:
SONAR_HOST_URL: ${{ secrets.SONARQUBE_HOST }}
SONAR_TOKEN: ${{ secrets.SONARQUBE_TOKEN }}
with:
args: >
-Dsonar.projectKey=Java-TX
-Dsonar.sources=src/main/java
-Dsonar.tests=src/test/java
-Dsonar.junit.reportPaths=target/test-reports
-Dsonar.java.binaries=target/classes
-Dsonar.java.libraries=target/dependency/*.jar
-Dsonar.coverage.jacoco.xmlReportPaths=target/site/jacoco/jacoco.xml

View File

@@ -1,7 +0,0 @@
## Java-TX Compiler
[![Lines of Code](https://gitea.hb.dhbw-stuttgart.de/sonarqube/api/project_badges/measure?project=Java-TX&metric=ncloc&token=sqb_d4a372fca7a6b86441243728a6ea5f88183db5eb)](https://gitea.hb.dhbw-stuttgart.de/sonarqube/dashboard?id=Java-TX)
[![Coverage](https://gitea.hb.dhbw-stuttgart.de/sonarqube/api/project_badges/measure?project=Java-TX&metric=coverage&token=sqb_d4a372fca7a6b86441243728a6ea5f88183db5eb)](https://gitea.hb.dhbw-stuttgart.de/sonarqube/dashboard?id=Java-TX)
[![Quality Gate Status](https://gitea.hb.dhbw-stuttgart.de/sonarqube/api/project_badges/measure?project=Java-TX&metric=alert_status&token=sqb_d4a372fca7a6b86441243728a6ea5f88183db5eb)](https://gitea.hb.dhbw-stuttgart.de/sonarqube/dashboard?id=Java-TX)
Work in Progress Java-TX Compiler repository!

21
pom.xml
View File

@@ -48,25 +48,6 @@ http://maven.apache.org/maven-v4_0_0.xsd">
<build> <build>
<plugins> <plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.13</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
@@ -84,7 +65,7 @@ http://maven.apache.org/maven-v4_0_0.xsd">
<configuration> <configuration>
<redirectTestOutputToFile>true</redirectTestOutputToFile> <redirectTestOutputToFile>true</redirectTestOutputToFile>
<reportsDirectory>${project.build.directory}/test-reports</reportsDirectory> <reportsDirectory>${project.build.directory}/test-reports</reportsDirectory>
<argLine>${argLine} --enable-preview</argLine> <argLine>--enable-preview</argLine>
<trimStackTrace>false</trimStackTrace> <trimStackTrace>false</trimStackTrace>
<excludes> <excludes>
<exclude>**/JavaTXCompilerTest.java</exclude> <exclude>**/JavaTXCompilerTest.java</exclude>

View File

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

View File

@@ -30,7 +30,7 @@ public class CompilationEnvironment {
public final PackageCrawler packageCrawler; public final PackageCrawler packageCrawler;
/** /**
* Imitiert die Environment beim Aufruf des JavaCompilers auf einer Menge von java-Dateien Die Environment enthält automatisch die Java Standard Library * Imitiert die Environment beim Aufruf des JavaCompilers auf einer Menge von java-Dateien Die Environment enth<EFBFBD>lt automatisch die Java Standard Library
* *
* @param sourceFiles die zu kompilierenden Dateien * @param sourceFiles die zu kompilierenden Dateien
*/ */

View File

@@ -41,7 +41,7 @@ public class JavaClassName {
} }
/** /**
* Gibt von einem Klassennamen nur den Namen der Klasse zurück * Gibt von einem Klassennamen nur den Namen der Klasse zur<EFBFBD>ck
* Beispiel: * Beispiel:
* java.lang.Object wird zu: Object * java.lang.Object wird zu: Object
*/ */

View File

@@ -5,7 +5,7 @@ import de.dhbwstuttgart.exceptions.NotImplementedException;
import java.util.*; import java.util.*;
/** /**
* Speichert die Klassen für einen bestimmten Projektscope * Speichert die Klassen f<EFBFBD>r einen bestimmten Projektscope
*/ */
public class JavaClassRegistry{ public class JavaClassRegistry{
final Map<JavaClassName, Integer> existingClasses = new HashMap<>(); final Map<JavaClassName, Integer> existingClasses = new HashMap<>();

View File

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

View File

@@ -16,7 +16,7 @@ import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
public abstract class GenerateGenerics { public abstract class GenerateGenerics implements IGenerics {
private final ASTToTargetAST astToTargetAST; private final ASTToTargetAST astToTargetAST;
@@ -151,22 +151,6 @@ public abstract class GenerateGenerics {
System.out.println("Simplified constraints: " + simplifiedConstraints); 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) { Set<TPH> findTypeVariables(ParameterList params) {
var res = new HashSet<TPH>(); var res = new HashSet<TPH>();
for (var param : params.getFormalparalist()) { for (var param : params.getFormalparalist()) {
@@ -282,6 +266,7 @@ public abstract class GenerateGenerics {
Set<Pair> result Set<Pair> result
) { ) {
var userDefinedGenericsOfClass = astToTargetAST.userDefinedGenerics.get(owner); var userDefinedGenericsOfClass = astToTargetAST.userDefinedGenerics.get(owner);
var generics = this;
// 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)) {
@@ -329,7 +314,7 @@ public abstract class GenerateGenerics {
if (methodCall.receiver instanceof ExpressionReceiver expressionReceiver) { if (methodCall.receiver instanceof ExpressionReceiver expressionReceiver) {
if (expressionReceiver.expr instanceof This) { 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; if (optMethod.isEmpty()) return;
var method2 = optMethod.get(); var method2 = optMethod.get();
System.out.println("In: " + method.getName() + " Method: " + method2.getName()); 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> family(ClassOrInterface owner, Method method) {
Set<Pair> result = new HashSet<>(); Set<Pair> result = new HashSet<>();
if (familyOfMethods.containsKey(method)) if (familyOfMethods.containsKey(method))
@@ -564,7 +547,8 @@ public abstract class GenerateGenerics {
return result; return result;
} }
Set<Pair> generics(ClassOrInterface owner, Method method) { @Override
public Set<Pair> generics(ClassOrInterface owner, Method method) {
if (computedGenericsOfMethods.containsKey(method)) { if (computedGenericsOfMethods.containsKey(method)) {
var cached = computedGenericsOfMethods.get(method); var cached = computedGenericsOfMethods.get(method);
System.out.println("Cached " + method.getName() + ": " + cached); 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 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)) if (computedGenericsOfClasses.containsKey(classOrInterface))
return computedGenericsOfClasses.get(classOrInterface); return computedGenericsOfClasses.get(classOrInterface);
@@ -988,7 +974,13 @@ public abstract class GenerateGenerics {
} while (foundInfima); } 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 (type instanceof TypePlaceholder tph) {
if (equality.containsKey(tph)) { if (equality.containsKey(tph)) {
return getType(equality.get(tph)); return getType(equality.get(tph));
@@ -998,7 +990,8 @@ public abstract class GenerateGenerics {
return type; return type;
} }
TargetType getTargetType(RefTypeOrTPHOrWildcardOrGeneric in) { @Override
public TargetType getTargetType(RefTypeOrTPHOrWildcardOrGeneric in) {
if (in instanceof TypePlaceholder tph) { if (in instanceof TypePlaceholder tph) {
if (equality.containsKey(tph)) { if (equality.containsKey(tph)) {
return getTargetType(equality.get(tph)); return getTargetType(equality.get(tph));

View File

@@ -9,21 +9,20 @@ import de.dhbwstuttgart.target.tree.type.TargetType;
import java.util.*; import java.util.*;
public class GenericsResult { public class GenericsResult {
private final GenerateGenerics generics; private final IGenerics generics;
GenericsResult(GenerateGenerics generics) { GenericsResult(IGenerics generics) {
this.generics = generics; this.generics = generics;
} }
public GenericsResultSet get(ClassOrInterface clazz) { public GenericsResultSet get(ClassOrInterface clazz) {
var generics = this.generics.computedGenericsOfClasses.get(clazz); var generics = this.generics.generics(clazz);
return new GenericsResultSet(generics, this.generics.equality); return new GenericsResultSet(generics, this.generics);
} }
// TODO Compute generics if not present? public GenericsResultSet get(ClassOrInterface clazz, Method method) {
public GenericsResultSet get(Method method) { var generics = this.generics.generics(clazz, method);
var generics = this.generics.computedGenericsOfMethods.get(method); return new GenericsResultSet(generics, this.generics);
return new GenericsResultSet(generics, this.generics.equality);
} }
public BoundsList getBounds(RefTypeOrTPHOrWildcardOrGeneric type, ClassOrInterface clazz) { public BoundsList getBounds(RefTypeOrTPHOrWildcardOrGeneric type, ClassOrInterface clazz) {
@@ -34,7 +33,7 @@ public class GenericsResult {
var resolvedType = resolve(type); var resolvedType = resolve(type);
type = resolvedType; type = resolvedType;
if (type instanceof TypePlaceholder) { if (type instanceof TypePlaceholder) {
var methodGenerics = get(method); var methodGenerics = get(clazz, method);
var classGenerics = get(clazz); var classGenerics = get(clazz);
List<Bound> result = new ArrayList<>(); 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.PairTPHequalRefTypeOrWildcardType;
import de.dhbwstuttgart.typeinference.result.PairTPHsmallerTPH; import de.dhbwstuttgart.typeinference.result.PairTPHsmallerTPH;
import de.dhbwstuttgart.typeinference.result.ResultPair; import de.dhbwstuttgart.typeinference.result.ResultPair;
import org.antlr.v4.codegen.model.decl.ContextRuleListIndexedGetterDecl;
import java.util.*; import java.util.*;
public class GenericsResultSet extends AbstractSet<GenerateGenerics.Pair> { public class GenericsResultSet extends AbstractSet<GenerateGenerics.Pair> {
final Set<GenerateGenerics.Pair> backing; 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.backing = backing == null ? new HashSet<>() : new HashSet<>(backing);
this.equality = equality; this.generics = generics;
} }
@Override @Override
@@ -28,7 +29,7 @@ public class GenericsResultSet extends AbstractSet<GenerateGenerics.Pair> {
} }
public Optional<ResultPair<?, ?>> getResultPairFor(TypePlaceholder tph) { public Optional<ResultPair<?, ?>> getResultPairFor(TypePlaceholder tph) {
var tph2 = equality.getOrDefault(tph, tph); var tph2 = generics.getEqualType(tph);
return this.stream().filter(pair -> { return this.stream().filter(pair -> {
return pair.left.resolve().equals(tph2); return pair.left.resolve().equals(tph2);
}).findFirst().map(pair -> { }).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 class StatementToTargetExpression implements ASTVisitor {
public StatementToTargetExpression(ASTToTargetAST converter) { public StatementToTargetExpression(ASTToTargetAST converter, IGenerics generics) {
this.converter = converter; this.converter = converter;
this.generics = generics;
} }
public TargetExpression result; public TargetExpression result;
private final IGenerics generics;
private final ASTToTargetAST converter; private final ASTToTargetAST converter;
@Override @Override
@@ -64,7 +66,7 @@ public class StatementToTargetExpression implements ASTVisitor {
@Override @Override
public void visit(LocalVar localVar) { public void visit(LocalVar localVar) {
super.visit(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)) if (!hasLocalVar(localVar.name) && !parameters.contains(capture) && !captures.contains(capture))
captures.add(capture); captures.add(capture);
} }
@@ -88,7 +90,7 @@ public class StatementToTargetExpression implements ASTVisitor {
private List<MethodParameter> createParameters(LambdaExpression lambda) { private List<MethodParameter> createParameters(LambdaExpression lambda) {
return StreamSupport.stream(lambda.params.spliterator(), false) return StreamSupport.stream(lambda.params.spliterator(), false)
.map(p -> (FormalParameter) p) .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(); .toList();
} }
@@ -99,59 +101,59 @@ public class StatementToTargetExpression implements ASTVisitor {
var visitor = new LambdaCaptureFinder(parameters, captures); var visitor = new LambdaCaptureFinder(parameters, captures);
lambdaExpression.methodBody.accept(visitor); lambdaExpression.methodBody.accept(visitor);
TargetMethod.Signature signature = new TargetMethod.Signature(Set.of(), parameters, converter.convert(lambdaExpression.getReturnType()));; TargetMethod.Signature signature = new TargetMethod.Signature(Set.of(), parameters, converter.convert(lambdaExpression.getReturnType(), generics));;
var tpe = converter.convert(lambdaExpression.getType()); var tpe = converter.convert(lambdaExpression.getType(), generics);
result = new TargetLambdaExpression(tpe, captures, signature, converter.convert(lambdaExpression.methodBody)); result = new TargetLambdaExpression(tpe, captures, signature, converter.convert(lambdaExpression.methodBody, this.generics));
} }
@Override @Override
public void visit(Assign assign) { public void visit(Assign assign) {
TargetExpression left; TargetExpression left;
if (assign.lefSide instanceof AssignToLocal) { if (assign.lefSide instanceof AssignToLocal) {
left = converter.convert(((AssignToLocal) assign.lefSide).localVar); left = converter.convert(((AssignToLocal) assign.lefSide).localVar, this.generics);
} else { } 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 @Override
public void visit(BinaryExpr binary) { public void visit(BinaryExpr binary) {
result = switch (binary.operation) { result = switch (binary.operation) {
case ADD -> new TargetBinaryOp.Add(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()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); 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()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); 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()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); 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()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); 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()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); 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()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); 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()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); 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()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); 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()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); 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()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); 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()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); 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()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); 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()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); case NOTEQUAL -> new TargetBinaryOp.NotEqual(converter.convert(binary.getType(), generics), converter.convert(binary.lexpr, this.generics), converter.convert(binary.rexpr, this.generics));
}; };
} }
@Override @Override
public void visit(BoolExpression bool) { public void visit(BoolExpression bool) {
result = switch(bool.operation) { result = switch(bool.operation) {
case OR -> new TargetBinaryOp.Or(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()), converter.convert(bool.lexpr), converter.convert(bool.rexpr)); case AND -> new TargetBinaryOp.And(converter.convert(bool.getType(), generics), converter.convert(bool.lexpr, generics), converter.convert(bool.rexpr, generics));
}; };
} }
@Override @Override
public void visit(Block block) { public void visit(Block block) {
result = converter.convert(block); result = converter.convert(block, generics);
} }
@Override @Override
public void visit(CastExpr castExpr) { 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 @Override
@@ -162,46 +164,46 @@ public class StatementToTargetExpression implements ASTVisitor {
@Override @Override
public void visit(FieldVar fieldVar) { public void visit(FieldVar fieldVar) {
var isStatic = false; 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 clazz = converter.compiler.getClass(new JavaClassName(type.name()));
var field = clazz.getField(fieldVar.fieldVarName).orElseThrow(); 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 @Override
public void visit(ForStmt forStmt) { public void visit(ForStmt forStmt) {
result = new TargetFor( result = new TargetFor(
forStmt.initializer.stream().map(converter::convert).toList(), forStmt.initializer.stream().map(c -> converter.convert(c, generics)).toList(),
forStmt.condition != null ? converter.convert(forStmt.condition) : null, forStmt.condition != null ? converter.convert(forStmt.condition, generics) : null,
forStmt.loopExpr.stream().map(converter::convert).toList(), forStmt.loopExpr.stream().map(e -> converter.convert(e, generics)).toList(),
converter.convertWrapInBlock(forStmt.block) converter.convertWrapInBlock(forStmt.block, generics)
); );
} }
@Override @Override
public void visit(ForEachStmt forEachStmt) { 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 @Override
public void visit(IfStmt ifStmt) { 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 @Override
public void visit(InstanceOf instanceOf) { 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 @Override
public void visit(LocalVar localVar) { 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 @Override
public void visit(LocalVarDecl localVarDecl) { public void visit(LocalVarDecl localVarDecl) {
// TODO No value, is this correct? // 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) { static boolean convertsTo(TargetType from, TargetType to) {
@@ -216,19 +218,19 @@ public class StatementToTargetExpression implements ASTVisitor {
@Override @Override
public void visit(MethodCall methodCall) { 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 isFunNType = receiverType instanceof TargetFunNType;
var returnType = isFunNType ? TargetType.Object : converter.convert(methodCall.signature.get(methodCall.signature.size() - 1)); var returnType = isFunNType ? TargetType.Object : converter.convert(methodCall.signature.getLast(), generics);
var receiverName = new JavaClassName(converter.convert(methodCall.receiver.getType()).name()); var receiverName = new JavaClassName(converter.convert(methodCall.receiver.getType(), generics).name());
var argList = methodCall.signature.stream().map(converter::convert).toList(); var argList = methodCall.signature.stream().map(sig -> converter.convert(sig, generics)).toList();
argList = argList.subList(0, argList.size() - 1); argList = argList.subList(0, argList.size() - 1);
Method foundMethod = null; Method foundMethod = null;
var isStatic = false; var isStatic = false;
var isInterface = true; var isInterface = true;
var isPrivate = false; 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 // Add used TPHs to containing method
for (var i = 0; i < methodCall.signatureArguments().size(); i++) { for (var i = 0; i < methodCall.signatureArguments().size(); i++) {
@@ -248,23 +250,28 @@ public class StatementToTargetExpression implements ASTVisitor {
} }
if (!isFunNType) { if (!isFunNType) {
returnType = converter.convert(foundMethod.getReturnType()); returnType = converter.convert(foundMethod.getReturnType(), generics);
argList = foundMethod.getParameterList().getFormalparalist().stream().map(e -> converter.convert(e.getType())).toList(); argList = foundMethod.getParameterList().getFormalparalist().stream().map(e -> converter.convert(e.getType(), generics)).toList();
isStatic = Modifier.isStatic(foundMethod.modifier); isStatic = Modifier.isStatic(foundMethod.modifier);
isPrivate = Modifier.isPrivate(foundMethod.modifier); isPrivate = Modifier.isPrivate(foundMethod.modifier);
isInterface = receiverClass.isInterface(); isInterface = receiverClass.isInterface();
} }
System.out.println(argList); 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 @Override
public void visit(NewClass newClass) { public void visit(NewClass newClass) {
var receiverName = new JavaClassName(newClass.name); var receiverName = new JavaClassName(newClass.name);
var ctor = converter.findConstructor(converter.compiler.getClass(receiverName), newClass.signatureArguments().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())).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(converter::convert).toList()); result = new TargetNew(new TargetRefType(newClass.name), signature, newClass.getArgumentList().getArguments().stream().map(arg -> converter.convert(arg, generics)).toList());
} }
@Override @Override
@@ -275,7 +282,7 @@ public class StatementToTargetExpression implements ASTVisitor {
@Override @Override
public void visit(Return aReturn) { public void visit(Return aReturn) {
result = new TargetReturn(converter.convert(aReturn.retexpr)); result = new TargetReturn(converter.convert(aReturn.retexpr, generics));
} }
@Override @Override
@@ -295,53 +302,53 @@ public class StatementToTargetExpression implements ASTVisitor {
@Override @Override
public void visit(StaticClassName staticClassName) { public void visit(StaticClassName staticClassName) {
result = new TargetClassName(converter.convert(staticClassName.getType())); result = new TargetClassName(converter.convert(staticClassName.getType(), generics));
} }
@Override @Override
public void visit(Super aSuper) { public void visit(Super aSuper) {
result = new TargetSuper(converter.convert(aSuper.getType())); result = new TargetSuper(converter.convert(aSuper.getType(), generics));
} }
@Override @Override
public void visit(This aThis) { public void visit(This aThis) {
result = new TargetThis(converter.convert(aThis.getType())); result = new TargetThis(converter.convert(aThis.getType(), generics));
} }
@Override @Override
public void visit(WhileStmt whileStmt) { 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 @Override
public void visit(DoStmt whileStmt) { 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 // TODO These two might not be necessary
@Override @Override
public void visit(AssignToField assignLeftSide) { public void visit(AssignToField assignLeftSide) {
result = converter.convert(assignLeftSide.field); result = converter.convert(assignLeftSide.field, generics);
} }
@Override @Override
public void visit(AssignToLocal assignLeftSide) { public void visit(AssignToLocal assignLeftSide) {
result = converter.convert(assignLeftSide.localVar); result = converter.convert(assignLeftSide.localVar, generics);
} }
@Override @Override
public void visit(SuperCall superCall) { public void visit(SuperCall superCall) {
var aSuper = converter.convert(superCall.receiver.getType()); var aSuper = converter.convert(superCall.receiver.getType(), generics);
var type = converter.convert(superCall.getType()); var type = converter.convert(superCall.getType(), generics);
var receiverName = new JavaClassName(converter.convert(superCall.receiver.getType()).name()); var receiverName = new JavaClassName(converter.convert(superCall.receiver.getType(), generics).name());
var clazz = converter.compiler.getClass(receiverName); 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 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; List<TargetType> argList;
if (method.isPresent()) { 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 { } else {
argList = params.stream().map(TargetExpression::type).toList(); argList = params.stream().map(TargetExpression::type).toList();
} }
@@ -351,28 +358,28 @@ public class StatementToTargetExpression implements ASTVisitor {
@Override @Override
public void visit(ThisCall thisCall) { public void visit(ThisCall thisCall) {
var aThis = converter.convert(thisCall.receiver.getType()); var aThis = converter.convert(thisCall.receiver.getType(), generics);
var type = converter.convert(thisCall.getType()); var type = converter.convert(thisCall.getType(), generics);
var parameters = thisCall.arglist.getArguments().stream().map(par -> converter.convert(par.getType())).toList(); 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 @Override
public void visit(ExpressionReceiver expressionReceiver) { public void visit(ExpressionReceiver expressionReceiver) {
result = converter.convert(expressionReceiver.expr); result = converter.convert(expressionReceiver.expr, generics);
} }
@Override @Override
public void visit(UnaryExpr unaryExpr) { public void visit(UnaryExpr unaryExpr) {
result = switch (unaryExpr.operation) { result = switch (unaryExpr.operation) {
case NOT -> new TargetUnaryOp.Not(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()), converter.convert(unaryExpr.expr)); case MINUS -> new TargetUnaryOp.Negate(converter.convert(unaryExpr.getType(), generics), converter.convert(unaryExpr.expr, generics));
case PREINCREMENT -> new TargetUnaryOp.PreIncrement(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr)); case PREINCREMENT -> new TargetUnaryOp.PreIncrement(converter.convert(unaryExpr.getType(), generics), converter.convert(unaryExpr.expr, generics));
case PREDECREMENT -> new TargetUnaryOp.PreDecrement(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr)); case PREDECREMENT -> new TargetUnaryOp.PreDecrement(converter.convert(unaryExpr.getType(), generics), converter.convert(unaryExpr.expr, generics));
case POSTINCREMENT -> new TargetUnaryOp.PostIncrement(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr)); case POSTINCREMENT -> new TargetUnaryOp.PostIncrement(converter.convert(unaryExpr.getType(), generics), converter.convert(unaryExpr.expr, generics));
case PLUS -> new TargetUnaryOp.Add(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr)); case PLUS -> new TargetUnaryOp.Add(converter.convert(unaryExpr.getType(), generics), converter.convert(unaryExpr.expr, generics));
case POSTDECREMENT -> new TargetUnaryOp.PostDecrement(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr)); 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 @Override
public void visit(Throw aThrow) { public void visit(Throw aThrow) {
result = new TargetThrow(converter.convert(aThrow.expr)); result = new TargetThrow(converter.convert(aThrow.expr, generics));
} }
@Override @Override
public void visit(Ternary ternary) { 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) {} record TypeVariants(RefTypeOrTPHOrWildcardOrGeneric in, List<RefTypeOrTPHOrWildcardOrGeneric> types) {}
@@ -469,10 +476,8 @@ public class StatementToTargetExpression implements ASTVisitor {
var product = cartesianProduct(extractAllPatterns(label.getPattern())); var product = cartesianProduct(extractAllPatterns(label.getPattern()));
for (var l : product) { for (var l : product) {
var oldGenerics = converter.generics;
// Set the generics to matching result set // Set the generics to matching result set
for (var generics : converter.currentMethodOverloads) { /*for (var generics : converter.currentMethodOverloads) {
var java = generics.javaGenerics(); var java = generics.javaGenerics();
var equals = true; var equals = true;
for (var pair : l) { for (var pair : l) {
@@ -481,17 +486,15 @@ public class StatementToTargetExpression implements ASTVisitor {
} }
} }
if (equals) { if (equals) {
converter.generics = generics;
break; break;
} }
} }*/
overloads.add(converter.convert(case_)); overloads.add(converter.convert(case_, generics));
converter.generics = oldGenerics;
} }
} }
} else { } else {
overloads.add(converter.convert(case_)); overloads.add(converter.convert(case_, generics));
} }
return overloads; return overloads;
@@ -500,10 +503,10 @@ public class StatementToTargetExpression implements ASTVisitor {
TargetSwitch.Case default_ = null; TargetSwitch.Case default_ = null;
for (var block : switchStmt.getBlocks()) { for (var block : switchStmt.getBlocks()) {
if (block.isDefault()) { 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 @Override
@@ -511,12 +514,12 @@ public class StatementToTargetExpression implements ASTVisitor {
@Override @Override
public void visit(SwitchLabel switchLabel) { public void visit(SwitchLabel switchLabel) {
result = converter.convert(switchLabel.getPattern()); result = converter.convert(switchLabel.getPattern(), this.generics);
} }
@Override @Override
public void visit(Yield aYield) { public void visit(Yield aYield) {
result = new TargetYield(converter.convert(aYield.retexpr)); result = new TargetYield(converter.convert(aYield.retexpr, generics));
} }
@Override @Override
@@ -586,30 +589,30 @@ public class StatementToTargetExpression implements ASTVisitor {
@Override @Override
public void visit(FormalParameter aPattern) { 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 @Override
public void visit(LiteralPattern literalPattern) { public void visit(LiteralPattern literalPattern) {
result = new TargetExpressionPattern(converter.convert(literalPattern.value)); result = new TargetExpressionPattern(converter.convert(literalPattern.value, generics));
} }
@Override @Override
public void visit(ExpressionPattern aPattern) { public void visit(ExpressionPattern aPattern) {
result = converter.convert(aPattern.getExpression()); result = converter.convert(aPattern.getExpression(), generics);
} }
@Override @Override
public void visit(RecordPattern aRecordPattern) { public void visit(RecordPattern aRecordPattern) {
result = new TargetComplexPattern( result = new TargetComplexPattern(
converter.convert(aRecordPattern.getType()), converter.convert(aRecordPattern.getType(), generics),
aRecordPattern.getName(), aRecordPattern.getName(),
aRecordPattern.getSubPattern().stream().map(x -> (TargetPattern) converter.convert(x)).toList() aRecordPattern.getSubPattern().stream().map(x -> (TargetPattern) converter.convert(x, generics)).toList()
); );
} }
@Override @Override
public void visit(GuardedPattern aGuardedPattern) { 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 @Override
public void visit(Method method) { public void visit(Method method) {
this.method = method; this.method = method;
constraints = generatedGenerics.get(method); constraints = generatedGenerics.get(cl, method);
classConstraints = generatedGenerics.get(cl); classConstraints = generatedGenerics.get(cl);
if(method.getReturnType() instanceof TypePlaceholder) if(method.getReturnType() instanceof TypePlaceholder)
inserts.add(TypeInsertFactory.createInsertPoints( inserts.add(TypeInsertFactory.createInsertPoints(

View File

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

View File

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