Compare commits

...

28 Commits

Author SHA1 Message Date
3567bae0d7 Decouple Generics from ASTToTargetAST
All checks were successful
SonarQube Scan / SonarQube Trigger (push) Successful in 3m16s
2025-09-17 17:19:23 +02:00
9160c99cf2 README.md hinzugefügt
All checks were successful
SonarQube Scan / SonarQube Trigger (push) Successful in 2m42s
2025-08-01 13:58:56 +00:00
c72a14cab3 Add libraries to sonar
All checks were successful
SonarQube Scan / SonarQube Trigger (push) Successful in 2m45s
2025-07-31 18:03:50 +02:00
10bb5d1d11 Typo
All checks were successful
SonarQube Scan / SonarQube Trigger (push) Successful in 3m30s
2025-07-31 17:25:31 +02:00
2842fc5069 Readd workflow for tests on other branches
Some checks failed
SonarQube Scan / SonarQube Trigger (push) Has been cancelled
2025-07-31 17:24:21 +02:00
5c5e0bd1e9 split up
All checks were successful
SonarQube Scan / SonarQube Trigger (push) Successful in 2m42s
2025-07-31 15:17:18 +02:00
3d81318e01 Different property
Some checks failed
SonarQube Scan / SonarQube Trigger (push) Failing after 2m4s
2025-07-31 15:11:43 +02:00
53e2c20608 Debug log
Some checks failed
SonarQube Scan / SonarQube Trigger (push) Failing after 2m12s
2025-07-31 15:03:53 +02:00
86e467fd82 Add test directory?
Some checks failed
SonarQube Scan / SonarQube Trigger (push) Failing after 2m2s
2025-07-31 15:00:21 +02:00
25b14e9342 Fix encoding issues
Some checks failed
SonarQube Scan / SonarQube Trigger (push) Failing after 2m39s
2025-07-31 14:53:17 +02:00
d0de0b31e4 Add test metadata
Some checks failed
SonarQube Scan / SonarQube Trigger (push) Failing after 2m49s
2025-07-31 14:42:41 +02:00
dd180524b2 Remove duplicate workflow
All checks were successful
SonarQube Scan / SonarQube Trigger (push) Successful in 2m40s
2025-07-31 14:35:04 +02:00
b3744bf5f7 Fix argLine not being passed to test
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Has been cancelled
SonarQube Scan / SonarQube Trigger (push) Successful in 3m4s
2025-07-31 14:22:06 +02:00
fda16978c2 Correct workflow
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Has been cancelled
SonarQube Scan / SonarQube Trigger (push) Successful in 3m22s
2025-07-31 14:07:03 +02:00
a485cd8fa6 Add jacoco
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Has been cancelled
SonarQube Scan / SonarQube Trigger (push) Has been cancelled
2025-07-31 14:05:42 +02:00
f8c708f0f4 Add classes directory
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Has been cancelled
SonarQube Scan / SonarQube Trigger (push) Successful in 1m50s
2025-07-31 13:54:59 +02:00
28d9946bbb Add debug logging
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Has been cancelled
SonarQube Scan / SonarQube Trigger (push) Failing after 1m7s
2025-07-31 13:51:46 +02:00
7b4ca8f177 Add src
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Has been cancelled
SonarQube Scan / SonarQube Trigger (push) Failing after 1m7s
2025-07-31 13:40:42 +02:00
b879d7743d Compile with maven
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Has been cancelled
SonarQube Scan / SonarQube Trigger (push) Failing after 1m8s
2025-07-31 13:31:56 +02:00
e26a43b400 Add project key
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Has been cancelled
SonarQube Scan / SonarQube Trigger (push) Failing after 31s
2025-07-31 13:28:23 +02:00
5deed725ae Fix again
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Has been cancelled
SonarQube Scan / SonarQube Trigger (push) Failing after 26s
2025-07-31 12:16:17 +02:00
8ae15f9d41 Update again
Some checks failed
SonarQube Scan / SonarQube Trigger (push) Has been cancelled
Build and Test with Maven / Build-and-test-with-Maven (push) Has been cancelled
2025-07-31 12:15:11 +02:00
8c8e088612 Use newer scanner
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Has been cancelled
SonarQube Scan / SonarQube Trigger (push) Failing after 20s
2025-07-31 12:06:21 +02:00
2814c6538e Add jdk 17
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 1m48s
SonarQube Scan / SonarQube Trigger (push) Failing after 24s
2025-07-31 11:56:58 +02:00
dcbc29b49b Nano
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Has been cancelled
SonarQube Scan / SonarQube Trigger (push) Failing after 13s
2025-07-31 11:49:01 +02:00
05033bcb9d Sonar
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Has been cancelled
2025-07-31 11:48:03 +02:00
814f5dd5fa Add main method #372
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 1m40s
2025-07-23 16:00:37 +02:00
24ca985ccc Fix #373
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 1m17s
2025-07-23 14:41:57 +02:00
22 changed files with 265 additions and 79 deletions

View File

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

View File

@@ -0,0 +1,45 @@
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

7
README.md Normal file
View File

@@ -0,0 +1,7 @@
## 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,6 +48,25 @@ http://maven.apache.org/maven-v4_0_0.xsd">
<build>
<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>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
@@ -65,7 +84,7 @@ http://maven.apache.org/maven-v4_0_0.xsd">
<configuration>
<redirectTestOutputToFile>true</redirectTestOutputToFile>
<reportsDirectory>${project.build.directory}/test-reports</reportsDirectory>
<argLine>--enable-preview</argLine>
<argLine>${argLine} --enable-preview</argLine>
<trimStackTrace>false</trimStackTrace>
<excludes>
<exclude>**/JavaTXCompilerTest.java</exclude>

View File

@@ -6,7 +6,7 @@ import java.util.stream.Stream;
public class Bug325 {
public main() {
List<Integer> list = new ArrayList<>(List.of(1,2,3,4,5));
var list = new ArrayList<>(List.of(1,2,3,4,5));
var func = x -> x*2;
return list.stream().map(func).toList();
}

View File

@@ -0,0 +1,17 @@
import java.lang.Boolean;
import java.lang.Integer;
import java.lang.System;
import java.io.PrintStream;
import java.lang.Character;
public class Bug373 {
public static main() {
System.out.println(true);
System.out.println(false);
System.out.println(1);
System.out.println(1l);
System.out.println(1.0);
System.out.println(1.0f);
System.out.println('a');
}
}

View File

@@ -0,0 +1,14 @@
import java.lang.Object;
import java.lang.System;
import java.lang.Iterable;
import java.io.PrintStream;
import java.util.List;
import java.lang.String;
class Main {
static main(args) {
for (var arg : args) {
System.out.println(arg);
}
}
}

View File

@@ -232,9 +232,9 @@ public class Codegen {
if (source.equals(dest))
return;
if (source.equals(TargetType.Long)) {
if (dest.equals(TargetType.Integer)) {
if (dest.equals(TargetType.Integer))
mv.visitInsn(L2I);
} else if (dest.equals(TargetType.Float))
else if (dest.equals(TargetType.Float))
mv.visitInsn(L2F);
else if (dest.equals(TargetType.Double))
mv.visitInsn(L2D);
@@ -277,6 +277,8 @@ public class Codegen {
mv.visitInsn(I2F);
else if (dest.equals(TargetType.Double))
mv.visitInsn(I2D);
} else if (source.equals(TargetType.Boolean)) {
unboxPrimitive(state, dest);
} else if (isFunctionalInterface(source) && isFunctionalInterface(dest) &&
!(source instanceof TargetFunNType && dest instanceof TargetFunNType)) {
boxFunctionalInterface(state, source, dest);
@@ -1597,8 +1599,27 @@ public class Codegen {
generateMethod(method, null);
}
private void generateMainMethod() {
var mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESTATIC, "java/util/List", "of", "([Ljava/lang/Object;)Ljava/util/List;", true);
mv.visitMethodInsn(INVOKESTATIC, className, "main", "(Ljava/util/List;)V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
private void generateMethod(TargetMethod method, State parent) {
var access = method.access();
var params = method.signature().parameters();
if (method.name().equals("main") && method.isStatic() && params.size() == 1 &&
params.getFirst().pattern().type().equals(new TargetRefType("java.util.List", List.of(new TargetRefType("java.lang.String"))))) {
generateMainMethod();
}
if (method.block() == null)
access |= ACC_ABSTRACT;
if (clazz instanceof TargetInterface)
@@ -1757,7 +1778,7 @@ public class Codegen {
cw2.visitEnd();
var bytes = cw2.toByteArray();
converter.auxiliaries.put(className, bytes);
compiler.auxiliaries.put(className, bytes);
// TODO These class loading shenanigans happen in a few places, the tests load the classes individually.
// Instead we should just look at the folder.

View File

@@ -2,6 +2,7 @@
package de.dhbwstuttgart.core;
import de.dhbwstuttgart.bytecode.Codegen;
import de.dhbwstuttgart.bytecode.FunNGenerator;
import de.dhbwstuttgart.environment.CompilationEnvironment;
import de.dhbwstuttgart.environment.DirectoryClassLoader;
import de.dhbwstuttgart.exceptions.DebugException;
@@ -73,6 +74,11 @@ public class JavaTXCompiler {
public final List<File> classPath;
private final File outputPath;
public final Map<String, FunNGenerator.GenericParameters> usedFunN = new HashMap<>();
public final Set<Integer> usedFunNSuperTypes = new HashSet<>();
public Map<String, byte[]> auxiliaries = new HashMap<>();
public DirectoryClassLoader getClassLoader() {
return classLoader;
}
@@ -646,7 +652,7 @@ public class JavaTXCompiler {
}
generatedGenerics.put(sf, converter.javaGenerics());
converter.generateFunNTypes();
converter.auxiliaries.forEach((name, source) -> {
auxiliaries.forEach((name, source) -> {
generatedClasses.put(new JavaClassName(name), source);
});
return generatedClasses;

View File

@@ -30,7 +30,7 @@ public class CompilationEnvironment {
public final PackageCrawler packageCrawler;
/**
* Imitiert die Environment beim Aufruf des JavaCompilers auf einer Menge von java-Dateien Die Environment enth<EFBFBD>lt automatisch die Java Standard Library
* Imitiert die Environment beim Aufruf des JavaCompilers auf einer Menge von java-Dateien Die Environment enthält automatisch die Java Standard Library
*
* @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<EFBFBD>ck
* Gibt von einem Klassennamen nur den Namen der Klasse zurück
* Beispiel:
* java.lang.Object wird zu: Object
*/

View File

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

View File

@@ -6,10 +6,12 @@ import de.dhbwstuttgart.syntaxtree.type.GenericRefType;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.target.tree.TargetGeneric;
import org.antlr.v4.runtime.Token;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.stream.Collectors;
/**
* Stellt jede Art von Klasse dar. Auch abstrakte Klassen und Interfaces
@@ -31,6 +33,7 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope {
private List<RefType> implementedInterfaces;
private List<RefType> permittedSubtypes;
private List<Constructor> constructors;
private Set<GenericTypeVar> userDefinedGenerics;
public ClassOrInterface(int modifiers, JavaClassName name, List<Field> fielddecl, Optional<Constructor> fieldInitializations, Optional<Method> staticInitializer, List<Method> methods, List<Constructor> constructors, GenericDeclarationList genericClassParameters, RefType superClass, Boolean isInterface, Boolean isFunctionalInterface, List<RefType> implementedInterfaces, List<RefType> permittedSubtypes, Token offset, String fileName) {
super(offset);
@@ -199,4 +202,22 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope {
public int hashCode() {
return Objects.hash(name);
}
public Set<GenericTypeVar> getUserDefinedGenerics() {
if (this.userDefinedGenerics != null) return this.userDefinedGenerics;
var genericsIter = getGenerics().iterator();
if (genericsIter.hasNext()) {
// Add empty set of generics to cache so that it doesn't try to calculate it later
this.userDefinedGenerics = new HashSet<>();
while (genericsIter.hasNext()) {
var next = genericsIter.next();
userDefinedGenerics.add(next);
}
} else {
this.userDefinedGenerics = new HashSet<>();
}
return this.userDefinedGenerics;
}
}

View File

@@ -5,8 +5,10 @@ import java.util.*;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.target.generate.ASTToTargetAST;
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation;
import de.dhbwstuttgart.typeinference.result.ResultSet;
//import sun.security.x509.X509CertInfo;
public class SourceFile extends SyntaxTreeNode {
@@ -18,6 +20,7 @@ public class SourceFile extends SyntaxTreeNode {
private boolean isGenerated;
public List<ClassOrInterface> availableClasses = new ArrayList<>();
public List<ASTToTargetAST.Generics> generics = new ArrayList<>();
/**
* Die SourceFile repräsntiert eine zu einem Syntaxbaum eingelesene Java-Datei.
@@ -40,6 +43,10 @@ public class SourceFile extends SyntaxTreeNode {
this.imports = new HashSet<>(sf.imports);
}
public void addResultSet(ResultSet rs) {
}
public void setPackageName(String packageName) {
this.pkgName = packageName;
}

View File

@@ -36,7 +36,6 @@ public class ASTToTargetAST {
public Generics generics;
public List<Generics> currentMethodOverloads;
final Map<ClassOrInterface, Set<GenericTypeVar>> userDefinedGenerics = new HashMap<>();
final Map<Method, Set<SignaturePair>> tphsInMethods = new HashMap<>();
private Method currentMethod;
@@ -61,9 +60,11 @@ public class ASTToTargetAST {
}
public record Generics(JavaGenerics javaGenerics, TxGenerics txGenerics) {
public Generics(JavaTXCompiler compiler, ResultSet set) {
this(new JavaGenerics(compiler, set), new TxGenerics(compiler, set));
}
}
public IByteArrayClassLoader classLoader;
protected SourceFile sourceFile;
@@ -81,9 +82,9 @@ public class ASTToTargetAST {
all = new ArrayList<>();
for (var set : resultSets) {
all.add(new Generics(new JavaGenerics(this, set), new TxGenerics(this, set)));
all.add(new Generics(compiler, set));
}
this.generics = all.get(0);
this.generics = all.getFirst();
}
public void addSignaturePair(TypePlaceholder signature, RefTypeOrTPHOrWildcardOrGeneric parameter) {
@@ -93,9 +94,13 @@ public class ASTToTargetAST {
}
Optional<Method> findMethod(ClassOrInterface owner, String name, List<TargetType> argumentList) {
return findMethod(owner, name, argumentList, this.generics.javaGenerics, this.compiler);
}
public static Optional<Method> findMethod(ClassOrInterface owner, String name, List<TargetType> argumentList, GenerateGenerics generics, JavaTXCompiler compiler) {
Optional<Method> method = Optional.empty();
while (method.isEmpty()) {
method = owner.getMethods().stream().filter(m -> m.name.equals(name) && parameterEquals(m.getParameterList(), argumentList)).findFirst();
method = owner.getMethods().stream().filter(m -> m.name.equals(name) && parameterEquals(m.getParameterList(), argumentList, generics)).findFirst();
if (owner.getClassName().toString().equals("java.lang.Object")) break;
owner = compiler.getClass(owner.getSuperClass().getName());
}
@@ -103,16 +108,16 @@ public class ASTToTargetAST {
}
Optional<Constructor> findConstructor(ClassOrInterface owner, List<TargetType> argumentList) {
return owner.getConstructors().stream().filter(c -> parameterEquals(c.getParameterList(), argumentList)).findFirst();
return owner.getConstructors().stream().filter(c -> parameterEquals(c.getParameterList(), argumentList, generics.javaGenerics)).findFirst();
}
boolean parameterEquals(ParameterList parameterList, List<TargetType> arguments) {
static boolean parameterEquals(ParameterList parameterList, List<TargetType> arguments, GenerateGenerics generics) {
var pars = parameterList.getFormalparalist();
if (pars.size() != arguments.size())
return false;
for (var i = 0; i < pars.size(); i++) {
var type1 = convert(pars.get(i).getType(), generics.javaGenerics);
var type1 = generics.getTargetType(pars.get(i).getType());
var type2 = arguments.get(i);
if (type1 instanceof TargetGenericType)
return true;
@@ -350,19 +355,14 @@ public class ASTToTargetAST {
Set<TargetGeneric> javaGenerics = new HashSet<>();
Set<TargetGeneric> txGenerics = new HashSet<>();
var genericsIter = input.getGenerics().iterator();
if (genericsIter.hasNext()) {
var userDefinedGenerics = input.getUserDefinedGenerics();
if (!userDefinedGenerics.isEmpty()) {
// Add empty set of generics to cache so that it doesn't try to calculate it later
var userDefinedGenerics = new HashSet<GenericTypeVar>();
this.userDefinedGenerics.put(input, userDefinedGenerics);
while (genericsIter.hasNext()) {
var next = genericsIter.next();
userDefinedGenerics.add(next);
// TODO Support multiple bounds
javaGenerics.add(new TargetGeneric(next.getName(), convert(next.getBounds().get(0))));
for (var generic : userDefinedGenerics) {
// TODO Support multiple bouds
javaGenerics.add(new TargetGeneric(generic.getName(), convert(generic.getBounds().getFirst())));
}
} else {
this.userDefinedGenerics.put(input, new HashSet<>());
// Generate generics only if there are no user defined ones
javaGenerics = convert(generics.javaGenerics.generics(input), generics.javaGenerics);
txGenerics = convert(generics.txGenerics.generics(input), generics.txGenerics);
@@ -424,7 +424,7 @@ public class ASTToTargetAST {
}
private List<TargetConstructor> convert(ClassOrInterface currentClass, Constructor input, TargetBlock fieldInitializer) {
generics = all.get(0);
generics = all.getFirst();
List<TargetConstructor> result = new ArrayList<>();
Set<List<MethodParameter>> parameterSet = new HashSet<>();
this.currentMethod = input;
@@ -468,13 +468,6 @@ public class ASTToTargetAST {
}
}
private TargetType unwrap(TargetType type) {
if (type instanceof TargetRefType ref) {
if (!ref.params().isEmpty()) return new TargetRefType(ref.name());
}
return type;
}
private TargetExpression generatePatternOverloadsRec(int offset, TargetExpression switchExpr, List<TargetLocalVar> params, List<TargetPattern> patterns, List<TargetMethod> methods, TargetType classType) {
if (methods.isEmpty()) throw new DebugException("Couldn't find a candidate for switch overloading");
if (methods.size() == 1) {
@@ -745,11 +738,6 @@ public class ASTToTargetAST {
return new TargetField(input.modifier, convert(input.getType(), generics.javaGenerics), input.getName());
}
private final Map<String, FunNGenerator.GenericParameters> usedFunN = new HashMap<>();
private final Set<Integer> usedFunNSuperTypes = new HashSet<>();
public Map<String, byte[]> auxiliaries = new HashMap<>();
public TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input) {
return convert(input, generics.javaGenerics);
}
@@ -818,20 +806,24 @@ public class ASTToTargetAST {
}
public void generateFunNTypes() {
for (var entry : usedFunN.entrySet()) {
for (var entry : compiler.usedFunN.entrySet()) {
var gep = entry.getValue();
var superInterfaces = usedFunN.values().stream()
var superInterfaces = compiler.usedFunN.values().stream()
.filter(g -> !g.equals(gep))
.filter(genericParameters -> isSubtype(gep, genericParameters))
.map(FunNGenerator::getSpecializedClassName)
.toList();
var code = FunNGenerator.generateSpecializedBytecode(gep, superInterfaces);
auxiliaries.put(entry.getKey(), code);
compiler.auxiliaries.put(entry.getKey(), code);
}
}
protected TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input, GenerateGenerics generics) {
public TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input, GenerateGenerics generics) {
return convert(input, generics, compiler);
}
public static TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input, GenerateGenerics generics, JavaTXCompiler compiler) {
return input.acceptTV(new TypeVisitor<>() {
@Override
public TargetType visit(RefType refType) {
@@ -843,31 +835,31 @@ public class ASTToTargetAST {
}
var params = refType.getParaList().stream().map(type -> {
return convert(type, generics);
return convert(type, generics, compiler);
}).toList();
if (name.matches("Fun\\d+\\$\\$")) { // TODO This seems like a bad idea
var returnType = FunNGenerator.getReturnType(params);
var className = FunNGenerator.getSpecializedClassName(FunNGenerator.getArguments(params), returnType);
if (!usedFunNSuperTypes.contains(params.size())) {
usedFunNSuperTypes.add(params.size());
if (!compiler.usedFunNSuperTypes.contains(params.size())) {
compiler.usedFunNSuperTypes.add(params.size());
var code = FunNGenerator.generateSuperBytecode(params.size() - 1, returnType != null ? 1 : 0);
var superClassName = FunNGenerator.getSuperClassName(params.size() - 1, returnType != null ? 1 : 0);
try {
classLoader.findClass(superClassName);
compiler.classLoader.findClass(superClassName);
} catch (ClassNotFoundException e) {
try {
classLoader.loadClass(superClassName, code);
compiler.classLoader.loadClass(superClassName, code);
} catch (LinkageError ignored) {}
}
auxiliaries.put(superClassName, code);
compiler.auxiliaries.put(superClassName, code);
}
FunNGenerator.GenericParameters gep = null;
if (!usedFunN.containsKey(className)) {
if (!compiler.usedFunN.containsKey(className)) {
gep = new FunNGenerator.GenericParameters(params, returnType != null ? 1 : 0);
usedFunN.put(className, gep);
compiler.usedFunN.put(className, gep);
} else {
gep = usedFunN.get(className);
gep = compiler.usedFunN.get(className);
}
return flattenFunNType(params, gep);
}
@@ -876,7 +868,7 @@ public class ASTToTargetAST {
@Override
public TargetType visit(SuperWildcardType superWildcardType) {
return new TargetSuperWildcard(convert(superWildcardType.getInnerType(), generics));
return new TargetSuperWildcard(convert(superWildcardType.getInnerType(), generics, compiler));
}
@Override
@@ -886,7 +878,7 @@ public class ASTToTargetAST {
@Override
public TargetType visit(ExtendsWildcardType extendsWildcardType) {
return new TargetExtendsWildcard(convert(extendsWildcardType.getInnerType(), generics));
return new TargetExtendsWildcard(convert(extendsWildcardType.getInnerType(), generics, compiler));
}
@Override

View File

@@ -1,5 +1,7 @@
package de.dhbwstuttgart.target.generate;
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.parser.JavaTXParser;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.syntaxtree.*;
import de.dhbwstuttgart.syntaxtree.statement.*;
@@ -18,7 +20,7 @@ import java.util.stream.Stream;
public abstract class GenerateGenerics {
private final ASTToTargetAST astToTargetAST;
private final JavaTXCompiler compiler;
public class TPH {
private final TypePlaceholder wrap;
@@ -134,8 +136,8 @@ public abstract class GenerateGenerics {
Map<TPH, RefTypeOrTPHOrWildcardOrGeneric> concreteTypes = new HashMap<>();
Map<TypePlaceholder, TypePlaceholder> equality = new HashMap<>();
GenerateGenerics(ASTToTargetAST astToTargetAST, ResultSet constraints) {
this.astToTargetAST = astToTargetAST;
GenerateGenerics(JavaTXCompiler compiler, ResultSet constraints) {
this.compiler = compiler;
for (var constraint : constraints.results) {
if (constraint instanceof PairTPHsmallerTPH p) {
System.out.println(p.left + " " + p.left.getVariance());
@@ -281,7 +283,7 @@ public abstract class GenerateGenerics {
Set<TPH> typeVariablesOfClass,
Set<Pair> result
) {
var userDefinedGenericsOfClass = astToTargetAST.userDefinedGenerics.get(owner);
var userDefinedGenericsOfClass = owner.getUserDefinedGenerics();
// Type variables with bounds that are also type variables of the method
for (var typeVariable : new HashSet<>(typeVariables)) {
@@ -329,7 +331,7 @@ public abstract class GenerateGenerics {
if (methodCall.receiver instanceof ExpressionReceiver expressionReceiver) {
if (expressionReceiver.expr instanceof This) {
var optMethod = astToTargetAST.findMethod(owner, methodCall.name, methodCall.signatureArguments().stream().map(astToTargetAST::convert).toList());
var optMethod = ASTToTargetAST.findMethod(owner, methodCall.name, methodCall.signatureArguments().stream().map(x -> getTargetType(x)).toList(), GenerateGenerics.this, compiler);
if (optMethod.isEmpty()) return;
var method2 = optMethod.get();
System.out.println("In: " + method.getName() + " Method: " + method2.getName());
@@ -1005,8 +1007,8 @@ public abstract class GenerateGenerics {
}
var type = concreteTypes.get(new TPH(tph));
if (type == null) return new TargetGenericType(tph.getName());
return astToTargetAST.convert(type, this);
return ASTToTargetAST.convert(type, this, compiler);
}
return astToTargetAST.convert(in, this);
return ASTToTargetAST.convert(in, this, compiler);
}
}

View File

@@ -69,8 +69,4 @@ public class GenericsResult {
return this.generics.getType(tph);
return type;
}
public TargetType resolveTarget(RefTypeOrTPHOrWildcardOrGeneric type) {
return this.generics.getTargetType(type);
}
}

View File

@@ -1,5 +1,6 @@
package de.dhbwstuttgart.target.generate;
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.typeinference.result.ResultSet;
@@ -7,8 +8,8 @@ import de.dhbwstuttgart.typeinference.result.ResultSet;
import java.util.Set;
final class JavaGenerics extends GenerateGenerics {
JavaGenerics(ASTToTargetAST astToTargetAST, ResultSet constraints) {
super(astToTargetAST, constraints);
JavaGenerics(JavaTXCompiler compiler, ResultSet constraints) {
super(compiler, constraints);
}
@Override

View File

@@ -1,5 +1,6 @@
package de.dhbwstuttgart.target.generate;
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.typeinference.result.ResultSet;
@@ -7,8 +8,8 @@ import de.dhbwstuttgart.typeinference.result.ResultSet;
import java.util.Set;
final class TxGenerics extends GenerateGenerics {
TxGenerics(ASTToTargetAST astToTargetAST, ResultSet constraints) {
super(astToTargetAST, constraints);
TxGenerics(JavaTXCompiler compiler, ResultSet constraints) {
super(compiler, constraints);
}
@Override

View File

@@ -1,6 +1,7 @@
package de.dhbwstuttgart.typeinference.typeAlgo;
import de.dhbwstuttgart.exceptions.DebugException;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.parser.SourceLoc;
import de.dhbwstuttgart.parser.antlr.Java17Parser;
import de.dhbwstuttgart.parser.scope.JavaClassName;
@@ -9,15 +10,18 @@ import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
import de.dhbwstuttgart.syntaxtree.statement.Statement;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.target.tree.type.TargetRefType;
import de.dhbwstuttgart.typeinference.assumptions.FieldAssumption;
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation;
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation;
import de.dhbwstuttgart.typeinference.constraints.Constraint;
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
import de.dhbwstuttgart.typeinference.constraints.Pair;
import de.dhbwstuttgart.typeinference.unify.model.PairOperator;
import de.dhbwstuttgart.util.BiRelation;
import org.antlr.v4.runtime.Token;
import java.lang.reflect.Modifier;
import java.util.*;
public class TYPE {
@@ -87,12 +91,25 @@ public class TYPE {
TypeInferenceBlockInformation blockInfo = new TypeInferenceBlockInformation(info.getAvailableClasses(), currentClass, m);
TYPEStmt methodScope = new TYPEStmt(blockInfo);
ConstraintSet constraintSet = new ConstraintSet();
m.getParameterList().getFormalparalist().forEach(el -> {
if(el instanceof RecordPattern){
constraintSet.addAll(addRecursiveParameterConstraints((RecordPattern) el, blockInfo));
}
});
if (m.name.equals("main") && Modifier.isStatic(m.modifier) && m.getParameterList().getFormalparalist().size() == 1) {
// Add constraint for main method
var firstParam = m.getParameterList().getParameterAt(0);
constraintSet.addUndConstraint(new Pair(firstParam.getType(),
new RefType(new JavaClassName("java.util.List"),
List.of(new RefType(new JavaClassName("java.lang.String"), new NullToken())),
new NullToken()),
PairOperator.EQUALSDOT));
} else {
m.getParameterList().getFormalparalist().forEach(el -> {
if (el instanceof RecordPattern rp){
constraintSet.addAll(addRecursiveParameterConstraints(rp, blockInfo));
}
});
}
m.block.accept(methodScope);
constraintSet.addAll(methodScope.getConstraints());
return constraintSet;

View File

@@ -1196,6 +1196,15 @@ public class TestComplete {
assertEquals(20, m.invoke(instance));
}
@Test
public void testMain() throws Exception {
var classFiles = generateClassFiles(createClassLoader(), "Main.jav");
var clazz = classFiles.get("Main");
var m = clazz.getDeclaredMethod("main", List.class);
m.setAccessible(true);
m.invoke(null, List.of("foo", "bar", "baz"));
}
@Test
public void testBug122() throws Exception {
var classFiles = generateClassFiles(createClassLoader(), "Bug122.jav");
@@ -1459,4 +1468,12 @@ public class TestComplete {
var m = clazz.getDeclaredMethod("test");
assertEquals(true, m.invoke(null));
}
@Test
public void testBug373() throws Exception {
var classFiles = generateClassFiles(createClassLoader(), "Bug373.jav");
var clazz = classFiles.get("Bug373");
var m = clazz.getDeclaredMethod("main");
m.invoke(null);
}
}

View File

@@ -66,7 +66,7 @@ public class TestCodegen {
converter.generateFunNTypes();
for (var entry : converter.auxiliaries.entrySet()) {
for (var entry : compiler.auxiliaries.entrySet()) {
writeClassFile(entry.getKey(), entry.getValue());
}
}
@@ -112,7 +112,7 @@ public class TestCodegen {
converter.generateFunNTypes();
for (var entry : converter.auxiliaries.entrySet()) {
for (var entry : compiler.auxiliaries.entrySet()) {
writeClassFile(entry.getKey(), entry.getValue());
}