Compare commits

...

42 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
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
d6ed0689bc Fix test
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 1m33s
2025-07-23 11:56:34 +02:00
d7676f36e3 Fix #371
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 1m55s
2025-07-23 11:44:10 +02:00
julian
9e323759d6 sort resultsets before printing them to the console to enhance comparability between results
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 1m28s
2025-07-16 11:17:53 +02:00
558083166d Fix subtyping of function types
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 1m45s
2025-07-15 15:02:15 +02:00
julian
aec2f9a399 adjust FiniteClosure to only use imported types + some necessary ones
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 1m37s
2025-07-15 14:06:51 +02:00
pl@gohorb.ba-horb.de
31df7a65f0 deleted: ../resources/bytecode/javFiles/Bug365a.jav
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 10m24s
modified:   ../src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java
	modified:   ../src/test/java/TestComplete.java
2025-07-08 17:44:55 +02:00
pl@gohorb.ba-horb.de
185989ba62 --- a/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java
+++ b/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java
@@ -73,7 +73,7 @@ public class TYPEStmt implements StatementVisitor {

     @Override
     public void visit(LambdaExpression lambdaExpression) {
-        TypePlaceholder tphRetType = TypePlaceholder.fresh(new NullToken());
+        TypePlaceholder tphRetType = TypePlaceholder.fresh(new NullToken(), -1, false);
         List<RefTypeOrTPHOrWildcardOrGeneric> lambdaParams = lambdaExpression.params.getFormalparalist().stream().map((formalParameter -> formalParameter.getType())).collect(Collectors.toList());
         lambdaParams.add(tphRetType);
         // lambdaParams.add(0,tphRetType);
@@ -635,6 +635,7 @@ public class TYPEStmt implements StatementVisitor {
             params.add(resolver.resolve(new GenericRefType(gtv.getName(), new NullToken())));
         }
         RefTypeOrTPHOrWildcardOrGeneric receiverType;

	modified:   ../src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java
2025-07-08 14:32:05 +02:00
pl@gohorb.ba-horb.de
0eb48ba425 new file: resources/bytecode/javFiles/Bug365a.jav
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 4m44s
modified:   src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java
	modified:   src/test/java/TestComplete.java
2025-07-07 13:11:27 +02:00
ceee9a49c4 Merge branch 'issue363' of ssh://gitea.hb.dhbw-stuttgart.de:2222/JavaTX/JavaCompilerCore into issue363
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 34m14s
2025-07-02 11:09:44 +02:00
ee64218a5f Fix class files not generating FunN types when using jar file 2025-07-02 11:09:38 +02:00
c50f14a4a3 .gitea/workflows/build_and_test.yml aktualisiert
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 6m52s
2025-07-01 14:35:08 +00:00
1f4250ff84 Update project to java 24, update dependencies and change api to Junit 5
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 45s
2025-07-01 15:55:58 +02:00
ae41c7f19d Fix #366 2025-07-01 15:54:08 +02:00
2416c80c20 Merge branch 'issue363' of ssh://gitea.hb.dhbw-stuttgart.de:2222/JavaTX/JavaCompilerCore into issue363
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Has been cancelled
2025-07-01 13:46:19 +02:00
4cc55c0059 Add test for #366 2025-07-01 13:45:56 +02:00
9434facfa0 Purge generics from lambdas
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 50m14s
2025-06-20 15:43:15 +02:00
09a6b9a788 Fix lambda expression captures
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 13m35s
2025-06-18 18:31:22 +02:00
8b342c5604 the last commit message was a lie, nothing was fixed. The lambdas does not even respect the arguments it is given?
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Has been cancelled
2025-06-18 16:46:27 +02:00
cdb93b5155 Remove ByteArrayClassLoader and fix #363
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 4m35s
2025-06-18 15:26:14 +02:00
b07e848fa2 Remove print statement
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 5m56s
2025-06-18 13:24:59 +02:00
313cd20f36 Fix #364
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Has been cancelled
2025-06-18 13:24:06 +02:00
567fcc3b9a rename issues to bug
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 5m52s
2025-06-18 12:59:00 +02:00
d9936e7197 add issue 364
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Has been cancelled
2025-06-18 12:55:50 +02:00
8f194b3102 add issue 363
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Has been cancelled
2025-06-18 12:48:55 +02:00
1391206dfe Merge branch 'master' of ssh://gitea.hb.dhbw-stuttgart.de:2222/JavaTX/JavaCompilerCore
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 6m10s
2025-05-15 15:31:17 +02:00
659bf6b500 Fix warnings in test by using correct order of arguments 2025-05-15 15:31:05 +02:00
33ed22c06a Update java version
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 5m33s
2025-05-06 12:00:57 +00:00
70f7857661 Ignore tests that aren't working
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 41s
2025-05-06 13:51:08 +02:00
45275b6888 Merge pull request 'Fix #356' (#357) from sealedInterfacesFix into patternMatching
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 44s
Reviewed-on: #357
2025-02-12 14:19:58 +00:00
2144dd9341 Working on patterns, grouping is functional now
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 44s
2025-02-05 17:09:31 +01:00
69c2bb3dc9 Work on the right grouping, looking pretty good so far
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 5m46s
2025-02-04 17:19:08 +01:00
3a57d5e025 Left uncommitted
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 5m31s
2025-01-31 16:04:22 +01:00
58 changed files with 1939 additions and 1407 deletions

View File

@@ -15,7 +15,7 @@ jobs:
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '22'
java-version: '24'
cache: 'maven'
- name: Compile project
run: |

28
pom.xml
View File

@@ -12,37 +12,37 @@ http://maven.apache.org/maven-v4_0_0.xsd">
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.13.2</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.antlr/antlr4 -->
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4</artifactId>
<version>4.11.1</version>
<version>4.13.2</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.16.1</version>
<version>2.19.0</version>
</dependency>
<dependency>
<groupId>io.github.classgraph</groupId>
<artifactId>classgraph</artifactId>
<version>4.8.172</version>
<version>4.8.180</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>33.2.0-jre</version>
<version>33.4.8-jre</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.ow2.asm/asm -->
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>9.5</version>
<version>9.8</version>
</dependency>
</dependencies>
@@ -51,17 +51,17 @@ http://maven.apache.org/maven-v4_0_0.xsd">
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<version>3.14.0</version>
<configuration>
<compilerArgs>--enable-preview</compilerArgs>
<source>22</source>
<target>22</target>
<source>24</source>
<target>24</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.1.0</version>
<version>3.5.3</version>
<configuration>
<redirectTestOutputToFile>true</redirectTestOutputToFile>
<reportsDirectory>${project.build.directory}/test-reports</reportsDirectory>
@@ -77,7 +77,7 @@ http://maven.apache.org/maven-v4_0_0.xsd">
<plugin>
<groupId>org.antlr</groupId>
<artifactId>antlr4-maven-plugin</artifactId>
<version>4.11.1</version>
<version>4.13.2</version>
<executions>
<execution>
<id>antlr</id>
@@ -90,7 +90,7 @@ http://maven.apache.org/maven-v4_0_0.xsd">
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version>
<version>3.4.2</version>
<configuration>
<archive>
<manifest>

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,22 @@
import java.lang.String;
public class Bug363 {
uncurry (f){
return x -> f.apply(x);
}
uncurry (f){
return (x, y) -> f.apply(x).apply(y);
}
uncurry (f){
return (x, y, z) -> f.apply(x).apply(y).apply(z);
}
public test(){
var f = x -> y -> z -> x + y + z;
var g = uncurry(f);
return g.apply("A", "B", "C"); // Outputs: 6
}
}

View File

@@ -0,0 +1,8 @@
import java.lang.String;
public class Bug364{
public main(){
var f = x -> y -> z -> x + y + z;
return f.apply("A").apply("B").apply("C");
}
}

View File

@@ -0,0 +1,21 @@
import java.lang.String;
import java.lang.Object;
public class Bug365{
swap(f){
return x -> y -> f.apply(y).apply(x);
}
swap(Fun1$$<String, Fun1$$<String, Fun1$$<String, Object>>> f){
return x -> y -> z -> f.apply(z).apply(y).apply(x);
}
public ex1() {
var func = x -> y -> z -> x + y + z;
return func.apply("A").apply("B").apply("C");
}
public ex2() {
var func = x -> y -> z -> x + y + z;
return swap(func).apply("A").apply("B").apply("C");
}
}

View File

@@ -0,0 +1,12 @@
import java.lang.Integer;
public class Bug366 {
public static lambda() {
return (a, b) -> a + b;
}
public static test() {
var l = lambda();
return l.apply(10, 20);
}
}

View File

@@ -0,0 +1,10 @@
import java.lang.Boolean;
public class Bug371 {
static m1(x, y) { return x || y; }
static m2(x, y) { return x && y; }
public static test() {
return m2(m1(true, false), true);
}
}

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

@@ -1,16 +0,0 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.lang.String;
import java.util.stream.Stream;
import java.util.function.Function;
import java.util.function.Predicate;
import java.lang.Integer;
class BugXXX {
public main() {
List<Integer> i = new ArrayList<>(List.of(1,2,3,4,5,6,7,8,9,10));
Optional<Integer> tmp = i.stream().filter(x -> x == 5).map(x -> x*2).findFirst();
return tmp;
}
}

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

@@ -13,6 +13,7 @@ import org.objectweb.asm.*;
import java.lang.invoke.*;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.stream.Collectors;
import static org.objectweb.asm.Opcodes.*;
import static de.dhbwstuttgart.target.tree.expression.TargetBinaryOp.*;
@@ -84,14 +85,16 @@ public class Codegen {
int localCounter;
MethodVisitor mv;
TargetType returnType;
boolean isStatic = false;
Stack<BreakEnv> breakStack = new Stack<>();
Stack<Integer> switchResultValue = new Stack<>();
State(TargetType returnType, MethodVisitor mv, int localCounter) {
State(TargetType returnType, MethodVisitor mv, int localCounter, boolean isStatic) {
this.returnType = returnType;
this.mv = mv;
this.localCounter = localCounter;
this.isStatic = isStatic;
}
void enterScope() {
@@ -229,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);
@@ -274,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);
@@ -757,6 +762,16 @@ public class Codegen {
}
}
private static TargetType removeGenerics(TargetType param) {
return switch (param) {
case null -> null;
case TargetFunNType funNType -> new TargetFunNType(funNType.name(), funNType.funNParams(), List.of(), funNType.returnArguments());
case TargetRefType refType -> new TargetRefType(refType.name());
case TargetGenericType targetGenericType -> TargetType.Object;
default -> param;
};
}
private void generateLambdaExpression(State state, TargetLambdaExpression lambda) {
var mv = state.mv;
@@ -768,7 +783,8 @@ public class Codegen {
var parameters = new ArrayList<>(lambda.captures());
parameters.addAll(signature.parameters());
var implSignature = new TargetMethod.Signature(Set.of(), parameters, lambda.signature().returnType());
parameters = parameters.stream().map(param -> param.withType(removeGenerics(param.pattern().type()))).collect(Collectors.toCollection(ArrayList::new));
var implSignature = new TargetMethod.Signature(Set.of(), parameters, removeGenerics(lambda.signature().returnType()));
TargetMethod impl;
if (lambdas.containsKey(lambda)) {
@@ -776,21 +792,22 @@ public class Codegen {
} else {
var name = "lambda$" + lambdaCounter++;
impl = new TargetMethod(0, name, lambda.block(), implSignature, null);
generateMethod(impl);
impl = new TargetMethod(state.isStatic ? ACC_STATIC : 0, name, lambda.block(), implSignature, null);
generateMethod(impl, state);
lambdas.put(lambda, impl);
}
var mt = MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class, MethodType.class, MethodHandle.class, MethodType.class);
var bootstrap = new Handle(H_INVOKESTATIC, "java/lang/invoke/LambdaMetafactory", "metafactory", mt.toMethodDescriptorString(), false);
var handle = new Handle(H_INVOKEVIRTUAL, clazz.getName(), impl.name(), implSignature.getDescriptor(), false);
var handle = new Handle(state.isStatic ? H_INVOKESTATIC : H_INVOKEVIRTUAL, clazz.getName(), impl.name(), implSignature.getDescriptor(), false);
var params = new ArrayList<TargetType>();
params.add(new TargetRefType(clazz.qualifiedName().getClassName()));
if(!state.isStatic) params.add(new TargetRefType(clazz.qualifiedName().getClassName()));
params.addAll(lambda.captures().stream().map(mp -> mp.pattern().type()).toList());
mv.visitVarInsn(ALOAD, 0);
if (!state.isStatic)
mv.visitVarInsn(ALOAD, 0);
for (var index = 0; index < lambda.captures().size(); index++) {
var capture = lambda.captures().get(index);
var pattern = (TargetTypePattern) capture.pattern();
@@ -1306,16 +1323,17 @@ public class Codegen {
var mt = MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class, Object[].class);
var bootstrap = new Handle(H_INVOKESTATIC, "java/lang/runtime/SwitchBootstraps", "typeSwitch", mt.toMethodDescriptorString(), false);
var types = new ArrayList<Object>(aSwitch.cases().size());
var types = new ArrayList<>(aSwitch.cases().size());
for (var cse : aSwitch.cases()) for (var label : cse.labels()) {
if (label instanceof TargetTypePattern || label instanceof TargetComplexPattern)
types.add(Type.getObjectType(label.type().getInternalName()));
else if (label instanceof TargetLiteral lit)
if (label instanceof TargetTypePattern || label instanceof TargetComplexPattern) {
if (label.type() instanceof TargetGenericType) types.add(Type.getType(Object.class));
else types.add(Type.getObjectType(label.type().getInternalName()));
} else if (label instanceof TargetLiteral lit) {
types.add(lit.value());
else if (label instanceof TargetGuard guard)
} else if (label instanceof TargetGuard guard) {
types.add(Type.getObjectType(guard.inner().type().getInternalName()));
// TODO Same here we need to evaluate constant;
else {
// TODO Same here we need to evaluate constant;
} else {
System.out.println(label);
throw new NotImplementedException();
}
@@ -1517,7 +1535,7 @@ public class Codegen {
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "<clinit>", "()V", null, null);
mv.visitCode();
var state = new State(null, mv, 0);
var state = new State(null, mv, 0, true);
generate(state, constructor.block());
mv.visitInsn(RETURN);
@@ -1531,7 +1549,7 @@ public class Codegen {
mv.visitAttribute(new JavaTXSignatureAttribute(constructor.getTXSignature()));
mv.visitCode();
var state = new State(null, mv, 1);
var state = new State(null, mv, 1, false);
for (var param : constructor.parameters()) {
var pattern = param.pattern();
if (pattern instanceof TargetTypePattern tp)
@@ -1577,9 +1595,31 @@ public class Codegen {
}
}
}
private void generateMethod(TargetMethod method) {
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)
@@ -1593,7 +1633,10 @@ public class Codegen {
if (method.block() != null) {
mv.visitCode();
var state = new State(method.signature().returnType(), mv, method.isStatic() ? 0 : 1);
var state = new State(method.signature().returnType(), mv, method.isStatic() ? 0 : 1, method.isStatic());
if (parent != null) {
state.scope.parent = parent.scope;
}
var offset = 1;
for (var param : method.signature().parameters()) {
state.createVariable(param.pattern().name(), param.pattern().type());
@@ -1603,6 +1646,8 @@ public class Codegen {
bindLocalVariables(state, cp, offset);
offset++;
}
//if (parent != null) System.out.println("parent: " + parent.scope.locals.keySet());
//System.out.println(state.scope.locals.keySet());
generate(state, method.block());
if (method.signature().returnType() == null)
mv.visitInsn(RETURN);
@@ -1694,7 +1739,7 @@ public class Codegen {
methodName = fromMethod.name;
fromReturn = converter.convert(fromMethod.getReturnType());
var fromParams = converter.convert(fromMethod.getParameterList(), converter.generics.javaGenerics()).stream().map(m -> m.pattern().type()).toArray(TargetType[]::new);
var fromParams = converter.convert(fromMethod.getParameterList()).stream().map(m -> m.pattern().type()).toArray(TargetType[]::new);
fromDescriptor = TargetMethod.getDescriptor(fromReturn, fromParams);
} else {
fromReturn = funNType.returnArguments() > 0 ? TargetType.Object : null;
@@ -1704,12 +1749,12 @@ public class Codegen {
var toClass = compiler.getClass(new JavaClassName(pair.to.name()));
var toMethod = toClass.getMethods().stream().filter(m -> (m.modifier & ACC_ABSTRACT) != 0).findFirst().orElseThrow();
var toReturn = converter.convert(toMethod.getReturnType());
var toParams = converter.convert(toMethod.getParameterList(), converter.generics.javaGenerics()).stream().map(m -> m.pattern().type()).toArray(TargetType[]::new);
var toParams = converter.convert(toMethod.getParameterList()).stream().map(m -> m.pattern().type()).toArray(TargetType[]::new);
var toDescriptor = TargetMethod.getDescriptor(toReturn, toParams);
// Generate wrapper method
var mv = cw2.visitMethod(ACC_PUBLIC, toMethod.name, toDescriptor, null, null);
var state = new State(null, mv, 0);
var state = new State(null, mv, 0, false);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, className, "wrapped", pair.from.toDescriptor());
@@ -1741,7 +1786,7 @@ public class Codegen {
converter.classLoader.findClass(className);
} catch (ClassNotFoundException e) {
try {
converter.classLoader.loadClass(bytes);
converter.classLoader.loadClass(className, bytes);
} catch (LinkageError ignored) {}
}
}

View File

@@ -39,6 +39,10 @@ public class FunNGenerator {
public final List<TargetType> inParams;
public final List<TargetType> realParams;
public GenericParameters(TargetFunNType funNType) {
this(funNType.funNParams(), funNType.returnArguments());
}
public GenericParameters(List<TargetType> params, int numReturns) {
this.realParams = params;
this.inParams = flattenTypeParams(params);

View File

@@ -393,7 +393,12 @@ public class JavaTXCompiler {
logFile.write(ASTTypePrinter.print(sf));
System.out.println(ASTTypePrinter.print(sf));
logFile.flush();
System.out.println("Unify nach Oder-Constraints-Anpassung:" + unifyCons.toString());
List<UnifyPair> andConstraintsSorted = unifyCons.getUndConstraints().stream()
.sorted(Comparator.comparing(UnifyPair::getPairOp).thenComparing(UnifyPair::getLhsType, Comparator.comparing(UnifyType::getName)))
.collect(Collectors.toList());
System.out.println(andConstraintsSorted);
Set<PlaceholderType> varianceTPHold;
Set<PlaceholderType> varianceTPH = new HashSet<>();
varianceTPH = varianceInheritanceConstraintSet(unifyCons);
@@ -416,7 +421,14 @@ public class JavaTXCompiler {
UnifyResultListenerImpl li = new UnifyResultListenerImpl();
urm.addUnifyResultListener(li);
unify.unifyParallel(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, logFile, log, urm, usedTasks);
System.out.println("RESULT Final: " + li.getResults());
//System.out.println("RESULT Final: " + li.getResults());
var finalResults = li.getResults().stream().sorted().toList();
int i = 0;
System.out.println("RESULT Final: ");
for (var result : finalResults){
System.out.println("Result: " + i++);
System.out.println(result.getSortedResults());
}
System.out.println("Constraints for Generated Generics: " + " ???");
logFile.write("RES_FINAL: " + li.getResults().toString() + "\n");
logFile.flush();
@@ -631,12 +643,12 @@ public class JavaTXCompiler {
var codegen = new Codegen(converter.convert(clazz), this, converter);
var code = codegen.generate();
generatedClasses.put(clazz.getClassName(), code);
converter.auxiliaries.forEach((name, source) -> {
generatedClasses.put(new JavaClassName(name), source);
});
}
generatedGenerics.put(sf, converter.javaGenerics());
converter.generateFunNTypes();
converter.auxiliaries.forEach((name, source) -> {
generatedClasses.put(new JavaClassName(name), source);
});
return generatedClasses;
}

View File

@@ -1,13 +0,0 @@
package de.dhbwstuttgart.environment;
public class ByteArrayClassLoader extends ClassLoader implements IByteArrayClassLoader {
@Override
public Class _defineClass(String name, byte[] code, int i, int length) throws ClassFormatError {
return defineClass(name, code, i, length);
}
@Override
public Class<?> findClass(String name) throws ClassNotFoundException {
return super.findClass(name);
}
}

View File

@@ -6,18 +6,22 @@ import java.nio.file.Path;
public interface IByteArrayClassLoader {
Class loadClass(String path) throws ClassNotFoundException;
Class<?> loadClass(String path) throws ClassNotFoundException;
default Class loadClass(byte[] code) {
return this._defineClass(null, code, 0, code.length);
default Class<?> loadClass(byte[] code) {
return this.loadClass(null, code);
}
default Class loadClass(Path path) throws IOException {
default Class<?> loadClass(String name, byte[] code) {
return this._defineClass(name, code, 0, code.length);
}
default Class<?> loadClass(Path path) throws IOException {
var code = Files.readAllBytes(path);
return this._defineClass(null, code, 0, code.length);
}
public Class<?> findClass(String name) throws ClassNotFoundException;
Class _defineClass(String name, byte[] code, int i, int length) throws ClassFormatError;
Class<?> _defineClass(String name, byte[] code, int i, int length) throws ClassFormatError;
}

View File

@@ -1099,9 +1099,9 @@ public class StatementGenerator {
block = lambdaGenerator.convert(expression.lambdaBody().block(), true);
}
List<RefTypeOrTPHOrWildcardOrGeneric> funNParams = new ArrayList<>();
funNParams.add(TypePlaceholder.fresh(expression.getStart()));// ret-Type
funNParams.add(TypePlaceholder.fresh(expression.getStart(), -1, false));// ret-Type
params.getFormalparalist().forEach(formalParameter -> // Für jeden Parameter einen TPH anfügen:
funNParams.add(TypePlaceholder.fresh(expression.getStart())));
funNParams.add(TypePlaceholder.fresh(expression.getStart(), 1, false)));
RefTypeOrTPHOrWildcardOrGeneric lambdaType = TypePlaceholder.fresh(expression.getStart());
// RefType lambdaType = new
// RefType(reg.getName("Fun"+params.getFormalparalist().size()),

View File

@@ -7,7 +7,7 @@ import java.util.*;
/**
* Speichert die Klassen f<>r einen bestimmten Projektscope
*/
public class JavaClassRegistry {
public class JavaClassRegistry{
final Map<JavaClassName, Integer> existingClasses = new HashMap<>();
public JavaClassRegistry(Map<String, Integer> initialNames) {
@@ -22,6 +22,10 @@ public class JavaClassRegistry {
}
}
public Set<JavaClassName> getAllClassNames(){
return existingClasses.keySet();
}
public void addName(String className, int numberOfGenerics) {
existingClasses.put(new JavaClassName(className), numberOfGenerics);
}

View File

@@ -2,7 +2,6 @@ package de.dhbwstuttgart.target.generate;
import de.dhbwstuttgart.bytecode.FunNGenerator;
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.environment.ByteArrayClassLoader;
import de.dhbwstuttgart.environment.IByteArrayClassLoader;
import de.dhbwstuttgart.exceptions.DebugException;
import de.dhbwstuttgart.parser.NullToken;
@@ -12,6 +11,8 @@ import de.dhbwstuttgart.syntaxtree.Record;
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
import de.dhbwstuttgart.syntaxtree.statement.*;
import de.dhbwstuttgart.syntaxtree.type.*;
import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter;
import de.dhbwstuttgart.syntaxtree.visual.OutputGenerator;
import de.dhbwstuttgart.target.tree.*;
import de.dhbwstuttgart.target.tree.expression.*;
import de.dhbwstuttgart.target.tree.type.*;
@@ -32,9 +33,9 @@ public class ASTToTargetAST {
public static RefType OBJECT = ASTFactory.createObjectType(); // TODO It would be better if I could call this directly but the hashcode seems to change
protected List<Generics> all;
public Generics generics;
public List<Generics> currentMethodOverloads;
public List<Generics> all;
//public Generics generics;
//public List<Generics> currentMethodOverloads;
final Map<ClassOrInterface, Set<GenericTypeVar>> userDefinedGenerics = new HashMap<>();
final Map<Method, Set<SignaturePair>> tphsInMethods = new HashMap<>();
@@ -54,24 +55,24 @@ public class ASTToTargetAST {
return all.stream().map(generics -> new GenericsResult(generics.javaGenerics)).toList();
}
public TargetExpression convert(Pattern pattern) {
var converter = new StatementToTargetExpression(this);
public TargetExpression convert(Pattern pattern, IGenerics generics) {
var converter = new StatementToTargetExpression(this, generics);
pattern.accept(converter);
return converter.result;
}
public record Generics(JavaGenerics javaGenerics, TxGenerics txGenerics) {
public record Generics(IGenerics javaGenerics, IGenerics txGenerics) {
}
public IByteArrayClassLoader classLoader;
protected SourceFile sourceFile;
public ASTToTargetAST(List<ResultSet> resultSets) {
this(null, resultSets);
public ASTToTargetAST(List<ResultSet> resultSets, IByteArrayClassLoader classLoader) {
this(null, resultSets, classLoader);
}
public ASTToTargetAST(JavaTXCompiler compiler, List<ResultSet> resultSets) {
this(compiler, resultSets, null, new ByteArrayClassLoader());
public ASTToTargetAST(JavaTXCompiler compiler, List<ResultSet> resultSets, IByteArrayClassLoader classLoader) {
this(compiler, resultSets, null, classLoader);
}
public ASTToTargetAST(JavaTXCompiler compiler, List<ResultSet> resultSets, SourceFile sourceFile, IByteArrayClassLoader classLoader) {
@@ -83,7 +84,6 @@ public class ASTToTargetAST {
for (var set : resultSets) {
all.add(new Generics(new JavaGenerics(this, set), new TxGenerics(this, set)));
}
this.generics = all.get(0);
}
public void addSignaturePair(TypePlaceholder signature, RefTypeOrTPHOrWildcardOrGeneric parameter) {
@@ -112,20 +112,23 @@ public class ASTToTargetAST {
return false;
for (var i = 0; i < pars.size(); i++) {
var type1 = convert(pars.get(i).getType(), generics.javaGenerics);
var type1 = pars.get(i).getType();
var type2 = arguments.get(i);
if (type1 instanceof TargetGenericType)
return true;
if (TargetType.toPrimitive(type2).equals(type1))
return true;
if (!type1.equals(type2))
return false;
//if (type1 instanceof GenericRefType)
// return true;
//if (TargetType.toPrimitive(type2).equals(type1))
// return true;
if (type1 instanceof RefType rt) {
if (type2 instanceof TargetRefType rt2 && !rt2.name().equals(rt.getName().toString())) {
return false;
}
}
}
return true;
}
Set<TargetGeneric> convert(Set<GenerateGenerics.Pair> result, GenerateGenerics generics) {
Set<TargetGeneric> convert(Set<GenerateGenerics.Pair> result, IGenerics generics) {
return result.stream().map(p -> {
if (p instanceof GenerateGenerics.PairLT pair) {
return new TargetGeneric(pair.left.resolve().getName(), convert(pair.right.resolve(), generics));
@@ -137,7 +140,7 @@ public class ASTToTargetAST {
}).collect(Collectors.toSet());
}
public List<TargetGeneric> convert(GenericTypeVar typeVar, GenerateGenerics generics) {
public List<TargetGeneric> convert(GenericTypeVar typeVar, IGenerics generics) {
var ret = new ArrayList<TargetGeneric>();
for (var bound : typeVar.getBounds()) {
ret.add(new TargetGeneric(typeVar.getName(), generics.getTargetType(bound)));
@@ -145,49 +148,26 @@ public class ASTToTargetAST {
return ret;
}
// This is used to serve as a custom equality to signature that performs a weak check without going into record patterns.
// The two signatures are considered equal if all the argument types match.
// This also turns equal if both types implement a sealed super interface
class PatternSignature {
final TargetMethod.Signature signature;
final String name;
PatternSignature(String name, TargetMethod.Signature signature) {
this.signature = signature;
this.name = name;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof PatternSignature other)) return false;
if (!this.name.equals(other.name)) return false;
if (other.signature.parameters().size() != signature.parameters().size()) return false;
for (var i = 0; i < signature.parameters().size(); i++) {
var p1 = signature.parameters().get(i).pattern().type();
var p2 = other.signature.parameters().get(i).pattern().type();
if (p1 instanceof TargetGenericType && p2 instanceof TargetGenericType) continue;
if (!p1.equals(p2) && commonSuperInterfaceTypes(p1, p2).isEmpty()) return false;
}
return true;
}
@Override
public int hashCode() {
return signature.parameters().size();
}
}
// This finds a common sealed interface type to group together methods that use different records
// This function should do matching or unification
private List<ClassOrInterface> commonSuperInterfaceTypes(TargetType a, TargetType b) {
if (a instanceof TargetGenericType && b instanceof TargetGenericType) return List.of(ASTFactory.createClass(Object.class));
if (a instanceof TargetGenericType && b instanceof TargetGenericType) return List.of(ASTFactory.createObjectClass());
if (a instanceof TargetRefType ta && b instanceof TargetGenericType)
return List.of(compiler.getClass(new JavaClassName(ta.name())));
if (b instanceof TargetRefType tb && a instanceof TargetGenericType)
return List.of(compiler.getClass(new JavaClassName(tb.name())));
if (a instanceof TargetRefType ta && b instanceof TargetRefType tb) {
var res = new HashSet<ClassOrInterface>();
var cla = compiler.getClass(new JavaClassName(ta.name()));
var clb = compiler.getClass(new JavaClassName(tb.name()));
while (!cla.equals(ASTFactory.createClass(Object.class))) {
if (cla.equals(clb)) return List.of(cla);
while (!cla.equals(ASTFactory.createObjectClass())) {
var clb2 = clb;
while (!clb2.equals(ASTFactory.createClass(Object.class))) {
while (!clb2.equals(ASTFactory.createObjectClass())) {
for (var intfa : cla.getSuperInterfaces()) {
for (var intfb : clb.getSuperInterfaces()) {
if (intfa.equals(intfb)) {
@@ -207,51 +187,155 @@ public class ASTToTargetAST {
return List.of();
}
public List<List<TargetMethod>> groupOverloads(ClassOrInterface input, List<Method> methods) {
var mapOfSignatures = new HashMap<PatternSignature, List<TargetMethod>>();
for (var method : methods) {
private boolean canCombine(Signature m1, Signature m2) {
var pl1 = m1.java.parameters();
var pl2 = m2.java.parameters();
if (pl1.size() != pl2.size()) return false;
if (pl1.isEmpty()) return false;
for (var i = 0; i < pl1.size(); i++) {
var p1 = pl1.get(i).pattern();
var p2 = pl2.get(i).pattern();
// TPH <> RefType sind nicht unterscheidbar
if (p1.type() instanceof TargetGenericType || p2.type() instanceof TargetGenericType) continue;
// Pattern(X) <> Pattern(Y) ist nicht unterscheidbar
if (p1 instanceof TargetComplexPattern pc1 && p2 instanceof TargetComplexPattern pc2 &&
pc1.type().equals(pc2.type())) continue;
if (!p1.equals(p2)) return false;
}
return true;
}
private record Combination(MethodWithTphs a, MethodWithTphs b) {
@Override
public boolean equals(Object o) {
if (!(o instanceof Combination(MethodWithTphs a1, MethodWithTphs b1))) return false;
return this.a.equals(a1) && this.b.equals(b1) ||
this.a.equals(b1) && this.b.equals(a1);
}
@Override
public int hashCode() {
return Objects.hashCode(a) + Objects.hashCode(b);
}
}
private List<List<MethodWithTphs>> groupOverloads(ClassOrInterface input, List<Method> methods) {
var mapOfTargetMethods = new HashMap<Generics, MethodWithTphs[]>();
for (var gen : all) {
mapOfTargetMethods.put(gen, new MethodWithTphs[methods.size()]);
}
for (var i = 0; i < methods.size(); i++) {
var method = methods.get(i);
// Convert all methods
var methodsWithTphs = convert(input, method);
// Then check for methods with the same signature
var resMethods = new HashSet<MethodWithTphs>();
for (var m1 : methodsWithTphs) {
System.out.println(m1.method.name() + " -> " + m1.method.signature().parameters().stream().map(m -> m.pattern().type()).toList());
for (var m : methodsWithTphs) {
var resultMethods = mapOfTargetMethods.get(m.generics);
resultMethods[i] = new MethodWithTphs(m.method, m.generics, m.signature);
}
}
System.out.println("============== INPUT ==============");
for (var m : mapOfTargetMethods.values()) {
for (var v : m) if (v != null) System.out.println(v.method.name + " " + v.signature.java.getSignature());
System.out.println();
}
outer:
for (var m1 : methodsWithTphs) {
for (var m2 : methodsWithTphs) {
for (var i = 0; i < m1.args.size(); i++) {
var arg1 = m1.args.get(i);
var arg2 = m2.args.get(i);
if (arg1.parameter.equals(arg2.parameter)) {
if (isSupertype(arg1.signature, arg2.signature) &&
!arg1.signature.equals(arg2.signature)) continue outer;
var allCombinations = new HashSet<Set<Combination>>();
// Combine methods based on their signature and position in the result set
for (var g1 : all) {
var resMeth1 = mapOfTargetMethods.get(g1);
for (var i = 0; i < methods.size(); i++) {
var m1 = resMeth1[i];
if (m1 == null) continue;
for (var g2 : all) {
if (g1 == g2) continue; // No need to combine the same method
var resMeth2 = mapOfTargetMethods.get(g2);
var m2 = resMeth2[i];
if (m2 == null) continue;
var combinations = new HashSet<Combination>();
if (canCombine(m1.signature, m2.signature)) {
System.out.println(" Combining " + m1.signature.java.getSignature() + " and " + m2.signature.java.getSignature());
combinations.add(new Combination(m1, m2));
for (var j = 0; j < methods.size(); j++) {
if (j == i) continue;
var m3 = resMeth2[j];
if (m3 == null) continue;
var m4 = resMeth1[j];
if (m4 == null) continue;
combinations.add(new Combination(m4, m3));
System.out.println("Also Combining " + m4.signature.java.getSignature() + " and " + m3.signature.java.getSignature());
}
} else {
System.out.println(" Not Combining " + m1.signature.java.getSignature() + " and " + m2.signature.java.getSignature());
}
if (!combinations.isEmpty()) allCombinations.add(combinations);
}
resMethods.add(m1);
}
for (var m : resMethods) {
var signature = new PatternSignature(m.method.name(), m.method.signature());
var methodsWithSameSignature = mapOfSignatures.getOrDefault(signature, new ArrayList<>());
methodsWithSameSignature.add(m.method);
mapOfSignatures.put(signature, methodsWithSameSignature);
}
}
mapOfSignatures.values().forEach(e -> {
e.forEach(e2 -> {
System.out.println(e2.name() + " -> " + e2.signature().parameters().stream().map(m -> m.pattern().type()).toList());
});
if (allCombinations.isEmpty()) allCombinations.add(new HashSet<>());
// Combine back into output format
var r0 = new HashSet<Set<MethodWithTphs>>();
for (var combinations : allCombinations) {
var r1 = new HashSet<Set<MethodWithTphs>>();
// This is used to weed out duplicates
var uniqued = new HashSet<MethodWithTphs>();
// We go over all methods in the result
for (var g : all) for (var i = 0; i < methods.size(); i++) {
var r2 = new HashSet<MethodWithTphs>();
var m = mapOfTargetMethods.get(g)[i];
if (m == null) continue;
if (!uniqued.contains(m)) {
// Add the method to r2
r2.add(m);
uniqued.add(m);
} else continue;
// Find all combinations that contain the method and add them to the result
// if not filtered out by uniqued
for (var c : combinations) {
if (c.a.equals(m) || c.b.equals(m)) {
if (!uniqued.contains(c.a)) {
r2.add(c.a);
uniqued.add(c.a);
}
if (!uniqued.contains(c.b)) {
r2.add(c.b);
uniqued.add(c.b);
}
}
}
r1.add(r2);
}
outer: for (var s1 : r1) {
for (var s2 : new HashSet<>(r0)) {
if (s2.containsAll(s1)) {
continue outer;
} else if (s1.containsAll(s2)) {
r0.remove(s2);
r0.add(s1);
continue outer;
}
}
r0.add(s1);
}
}
var result = r0.stream().map(l -> l.stream().toList()).toList();
System.out.println("============== OUTPUT ==============");
for (var l : result) {
for (var m : l) System.out.println(m.method.name + " " + m.signature.java.getSignature());
System.out.println();
});
return mapOfSignatures.values().stream().toList();
}
return result;
}
public TargetStructure convert(ClassOrInterface input) {
var generics = all.getFirst();
Set<TargetGeneric> javaGenerics = new HashSet<>();
Set<TargetGeneric> txGenerics = new HashSet<>();
@@ -264,7 +348,7 @@ public class ASTToTargetAST {
var next = genericsIter.next();
userDefinedGenerics.add(next);
// TODO Support multiple bounds
javaGenerics.add(new TargetGeneric(next.getName(), convert(next.getBounds().get(0))));
javaGenerics.add(new TargetGeneric(next.getName(), convert(next.getBounds().getFirst(), generics.javaGenerics)));
}
} else {
this.userDefinedGenerics.put(input, new HashSet<>());
@@ -275,17 +359,20 @@ public class ASTToTargetAST {
TargetBlock fieldInitializer = null;
if (input.getfieldInitializations().isPresent())
fieldInitializer = convert(input.getfieldInitializations().get().block);
fieldInitializer = convert(input.getfieldInitializations().get().block, generics.javaGenerics);
TargetBlock finalFieldInitializer = fieldInitializer;
var superInterfaces = input.getSuperInterfaces().stream().map(clazz -> convert(clazz, generics.javaGenerics)).toList();
var constructors = input.getConstructors().stream().map(constructor -> this.convert(input, constructor, finalFieldInitializer)).flatMap(List::stream).toList();
var fields = input.getFieldDecl().stream().map(this::convert).toList();
var methods = groupOverloads(input, input.getMethods()).stream().map(m -> generatePatternOverloads(input, m)).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(f -> convert(f, generics.javaGenerics)).toList();
var methods = groupOverloads(input, input.getMethods()).stream().map(m -> generatePatternOverloads(input, m)).flatMap(List::stream)
.collect(Collectors.toSet()).stream().toList(); // Unique generated methods
TargetMethod staticConstructor = null;
if (input.getStaticInitializer().isPresent())
staticConstructor = this.convert(input, input.getStaticInitializer().get()).stream().findFirst().orElseThrow().method;
if (input.getStaticInitializer().isPresent()) {
var init = this.convert(input, input.getStaticInitializer().get()).stream().findFirst().orElseThrow();
staticConstructor = this.convert(init, init.generics.javaGenerics);
}
if (input instanceof Record)
return new TargetRecord(input.getModifiers(), input.getClassName(), javaGenerics, txGenerics, superInterfaces, constructors, staticConstructor, fields, methods);
@@ -294,11 +381,16 @@ public class ASTToTargetAST {
else return new TargetClass(input.getModifiers(), input.getClassName(), convert(input.getSuperClass(), generics.javaGenerics), javaGenerics, txGenerics, superInterfaces, constructors, staticConstructor, fields, methods);
}
public List<MethodParameter> convert(ParameterList input, GenerateGenerics generics) {
@Deprecated
public List<MethodParameter> convert(ParameterList input) {
return convert(input, all.getFirst().javaGenerics);
}
public List<MethodParameter> convert(ParameterList input, IGenerics generics) {
var res = new ArrayList<MethodParameter>();
for (var i = 0; i < input.getFormalparalist().size(); i++) {
var param = input.getFormalparalist().get(i);
var pattern = (TargetPattern) convert(param);
var pattern = (TargetPattern) convert(param, generics);
if (pattern instanceof TargetComplexPattern) pattern = pattern.withName("__var" + i);
res.add(new MethodParameter(pattern));
}
@@ -309,7 +401,7 @@ public class ASTToTargetAST {
return generics.stream().anyMatch(g -> g.name().equals(type.getParsedName()));
}
private Set<TargetGeneric> collectMethodGenerics(ClassOrInterface clazz, GenerateGenerics generateGenerics, Set<GenerateGenerics.Pair> generics, Method input) {
private Set<TargetGeneric> collectMethodGenerics(ClassOrInterface clazz, IGenerics generateGenerics, Set<GenerateGenerics.Pair> generics, Method input) {
var convertedGenerics = new HashSet<>(convert(generics, generateGenerics));
outer: for (GenericTypeVar typeVar : input.getGenerics()) {
for (var classGeneric : clazz.getGenerics()) {
@@ -327,7 +419,7 @@ public class ASTToTargetAST {
return convertedGenerics;
}
private List<TargetConstructor> convert(ClassOrInterface currentClass, Constructor input, TargetBlock fieldInitializer) {
private List<TargetConstructor> convert(ClassOrInterface currentClass, Constructor input, TargetBlock fieldInitializer, Generics generics) {
generics = all.get(0);
List<TargetConstructor> result = new ArrayList<>();
Set<List<MethodParameter>> parameterSet = new HashSet<>();
@@ -335,15 +427,15 @@ public class ASTToTargetAST {
for (var s : all) {
generics = s;
var javaGenerics = this.generics.javaGenerics.generics(currentClass, input);
var txGenerics = this.generics.txGenerics.generics(currentClass, input);
List<MethodParameter> params = convert(input.getParameterList(), this.generics.javaGenerics);
var javaGenerics = generics.javaGenerics.generics(currentClass, input);
var txGenerics = generics.txGenerics.generics(currentClass, input);
List<MethodParameter> params = convert(input.getParameterList(), generics.javaGenerics);
if (parameterSet.stream().noneMatch(p -> p.equals(params))) {
List<MethodParameter> txParams = convert(input.getParameterList(), this.generics.txGenerics);
List<MethodParameter> txParams = convert(input.getParameterList(), generics.txGenerics);
var javaMethodGenerics = collectMethodGenerics(currentClass, generics.javaGenerics(), javaGenerics, input);
var txMethodGenerics = collectMethodGenerics(currentClass, generics.txGenerics(), txGenerics, input);
result.add(new TargetConstructor(input.modifier, javaMethodGenerics, txMethodGenerics, params, txParams, convert(input.block), fieldInitializer));
result.add(new TargetConstructor(input.modifier, javaMethodGenerics, txMethodGenerics, params, txParams, convert(input.block, generics.javaGenerics), fieldInitializer));
parameterSet.add(params);
}
}
@@ -351,10 +443,13 @@ public class ASTToTargetAST {
return result;
}
private static int counter = 0;
private String encodeName(String name, TargetMethod.Signature params) {
var res = new StringBuilder();
res.append(name);
res.append('$');
res.append(counter++);
res.append('$');
for (var param : params.parameters()) {
encodeName(param.pattern(), res);
}
@@ -403,7 +498,7 @@ public class ASTToTargetAST {
}
var cases = new ArrayList<TargetSwitch.Case>();
var usedPatterns = new HashSet<TargetType>();
var usedPatterns = new HashSet<TargetPattern>();
for (var method : methods) {
var patternsRec = new ArrayList<>(patterns);
@@ -423,20 +518,21 @@ public class ASTToTargetAST {
}
var lastPattern = patternsRec.getLast();
var type = unwrap(lastPattern.type());
if (usedPatterns.contains(type)) continue;
usedPatterns.add(type);
if (usedPatterns.contains(lastPattern)) continue;
usedPatterns.add(lastPattern);
var candidates = methods.stream().filter(m -> {
var j = 0;
for (var param : m.signature().parameters()) {
if (j >= patternsRec.size()) return true;
if (!patternsRec.get(j).type().equals(param.pattern().type())) return false;
if (!patternsRec.get(j).equals(param.pattern())) return false;
j++;
}
return true;
}).toList();
//System.out.println(offset + " -> " + lastPattern);
//candidates.forEach(m -> System.out.println(m.getSignature()));
var caseBody = generatePatternOverloadsRec(offset + 1, expr, params, patternsRec, candidates, classType);
var body = new TargetBlock(List.of(caseBody));
var case_ = new TargetSwitch.Case(List.of(lastPattern), body);
@@ -447,19 +543,14 @@ public class ASTToTargetAST {
return new TargetSwitch(switchExpr, cases, null, true);
}
private List<TargetMethod> generatePatternOverloads(ClassOrInterface clazz, List<TargetMethod> overloadedMethods) {
if (overloadedMethods.size() <= 1) return overloadedMethods;
private List<TargetMethod> generatePatternOverloads(ClassOrInterface clazz, List<MethodWithTphs> overloadedMethods) {
if (overloadedMethods.isEmpty()) return List.of();
// Check if we have a pattern as a parameter
var firstMethod = overloadedMethods.getFirst();
var secondMethod = overloadedMethods.get(1);
if (firstMethod.signature().parameters().stream().noneMatch(mp -> mp.pattern() instanceof TargetComplexPattern)) return overloadedMethods;
// Rename existing methods
var res = new ArrayList<TargetMethod>();
for (var method : overloadedMethods) {
var name = encodeName(method.name(), method.signature());
res.add(new TargetMethod(method.access(), name, method.block(), method.signature(), method.txSignature()));
}
var firstMethod = convert(overloadedMethods.getFirst(), overloadedMethods.getFirst().generics.javaGenerics);
if (overloadedMethods.size() == 1) return List.of(firstMethod);
var secondMethod = convert(overloadedMethods.get(1), overloadedMethods.get(1).generics.javaGenerics);
if (firstMethod.signature().parameters().stream().noneMatch(mp -> mp.pattern() instanceof TargetComplexPattern))
return overloadedMethods.stream().map(m -> convert(m, m.generics.javaGenerics)).toList();
var signatureParams = new ArrayList<MethodParameter>();
for (var i = 0; i < firstMethod.signature().parameters().size(); i++) {
@@ -468,21 +559,43 @@ public class ASTToTargetAST {
var t2 = secondMethod.signature().parameters().get(i).pattern().type();
var commonSubTypes = new HashSet<>(commonSuperInterfaceTypes(t1, t2));
for (var m : overloadedMethods.subList(2, overloadedMethods.size())) {
var t3 = m.signature().parameters().get(i).pattern().type();
var t3 = m.signature().java.parameters().get(i).pattern().type();
commonSubTypes.retainAll(commonSuperInterfaceTypes(t1, t3));
}
if (commonSubTypes.size() != 1) throw new DebugException("Invalid overload");
if (commonSubTypes.size() > 1) throw new DebugException("Invalid overload");
// TODO accept multiple types
var superType = commonSubTypes.iterator().next();
var superType = ASTFactory.createObjectClass();
if (!commonSubTypes.isEmpty())
superType = commonSubTypes.iterator().next();
String name;
if (p1 instanceof TargetComplexPattern) name = "__var" + i;
else name = p1.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()));
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());
@@ -503,7 +616,7 @@ public class ASTToTargetAST {
}
private Expression makeRecordSwitch(RefTypeOrTPHOrWildcardOrGeneric returnType, ParameterList params, List<Method> overloadedMethods) {
var param = params.getFormalparalist().get(0);
var param = params.getFormalparalist().getFirst();
assert param instanceof RecordPattern; // TODO
var cases = new ArrayList<SwitchBlock>();
@@ -523,7 +636,7 @@ public class ASTToTargetAST {
return swtch;
}
private Optional<Method> findSuperMethodToOverride(ClassOrInterface currentClass, String name, List<MethodParameter> params) {
private Optional<Method> findSuperMethodToOverride(ClassOrInterface currentClass, String name, List<MethodParameter> params, IGenerics generics) {
var superClass = compiler.getClass(currentClass.getSuperClass().getName());
var methodStream = superClass.getMethods().stream();
for (var superInterface : currentClass.getSuperInterfaces()) {
@@ -536,103 +649,106 @@ public class ASTToTargetAST {
if (sParams.getFormalparalist().size() != params.size()) return false;
for (var i = 0; i < params.size(); i++) {
var a = TargetType.toPrimitive(params.get(i).pattern().type());
var b = convert(sParams.getFormalparalist().get(i).getType());
var b = convert(sParams.getFormalparalist().get(i).getType(), generics);
if (!Objects.equals(a, b)) return false;
}
return true;
}).findFirst();
}
record MethodWithTphs(TargetMethod method, List<SignaturePairTarget> args) {}
record MethodWithTphs(Method method, Generics generics, Signature signature) {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof MethodWithTphs that)) return false;
return Objects.equals(method, that.method) && Objects.equals(signature, that.signature);
}
@Override
public int hashCode() {
return Objects.hash(method, signature);
}
}
private TargetMethod convert(MethodWithTphs mtph, IGenerics generics) {
return new TargetMethod(mtph.method.modifier, mtph.method.name, convert(mtph.method.block, generics), mtph.signature.java(), mtph.signature.tx());
}
record Signature(TargetMethod.Signature java, TargetMethod.Signature tx, Generics generics) {}
private List<MethodWithTphs> convert(ClassOrInterface currentClass, Method method) {
generics = all.getFirst();
List<MethodWithTphs> result = new ArrayList<>();
this.currentMethod = method;
List<Signature> signatures = new ArrayList<>();
HashMap<TargetMethod.Signature, List<Generics>> collectedGenerics = new HashMap<>();
for (var s : all) {
generics = s;
var javaGenerics = this.generics.javaGenerics.generics(currentClass, method);
var txGenerics = this.generics.txGenerics.generics(currentClass, method);
List<MethodParameter> params = convert(method.getParameterList(), this.generics.javaGenerics);
var returnType = convert(method.getReturnType(), this.generics.javaGenerics);
var superMethod = findSuperMethodToOverride(currentClass, method.getName(), params);
for (var generics : all) {
var javaGenerics = generics.javaGenerics.generics(currentClass, method);
var txGenerics = generics.txGenerics.generics(currentClass, method);
List<MethodParameter> params = convert(method.getParameterList(), generics.javaGenerics);
var returnType = convert(method.getReturnType(), generics.javaGenerics);
var superMethod = findSuperMethodToOverride(currentClass, method.getName(), params, generics.javaGenerics);
if (superMethod.isPresent()) {
// If we find a super method to override, use its parameters and return types
var newReturnType = convert(superMethod.get().getReturnType(), this.generics.javaGenerics);
var newReturnType = convert(superMethod.get().getReturnType(), generics.javaGenerics);
if (newReturnType instanceof TargetPrimitiveType && TargetType.toPrimitive(returnType).equals(newReturnType)) {
returnType = newReturnType;
params = convert(superMethod.get().getParameterList(), method.getParameterList(), this.generics.javaGenerics);
params = convert(superMethod.get().getParameterList(), method.getParameterList(), generics.javaGenerics);
}
}
List<MethodParameter> txParams = convert(method.getParameterList(), this.generics.txGenerics);
List<MethodParameter> txParams = convert(method.getParameterList(), generics.txGenerics);
var javaMethodGenerics = collectMethodGenerics(currentClass, generics.javaGenerics(), javaGenerics, method);
var txMethodGenerics = collectMethodGenerics(currentClass, generics.txGenerics(), txGenerics, method);
var javaSignature = new TargetMethod.Signature(javaMethodGenerics, params, returnType);
var txSignature = new TargetMethod.Signature(txMethodGenerics, txParams, convert(method.getReturnType(), this.generics.txGenerics));
var txSignature = new TargetMethod.Signature(txMethodGenerics, txParams, convert(method.getReturnType(), generics.txGenerics));
signatures.add(new Signature(javaSignature, txSignature, generics));
var listOfGenerics = collectedGenerics.getOrDefault(javaSignature, new ArrayList<>());
listOfGenerics.add(generics);
collectedGenerics.put(javaSignature, listOfGenerics);
}
for (var signature : signatures) {
generics = signature.generics;
currentMethodOverloads = collectedGenerics.get(signature.java);
var newMethod = new TargetMethod(method.modifier, method.name, convert(method.block), signature.java, signature.tx);
var concreteParams = tphsInMethods.getOrDefault(method, new HashSet<>()).stream().map(sig -> new SignaturePairTarget(convert(sig.signature), convert(sig.parameter))).toList();
result.add(new MethodWithTphs(newMethod, concreteParams));
result.add(new MethodWithTphs(method, signature.generics, signature));
}
return result;
}
private List<MethodParameter> convert(ParameterList superList, ParameterList paraList, JavaGenerics generics) {
private List<MethodParameter> convert(ParameterList superList, ParameterList paraList, IGenerics generics) {
var list = new ArrayList<MethodParameter>();
for (var i = 0; i < paraList.getFormalparalist().size(); i++) {
var param = paraList.getParameterAt(i);
var pattern = (TargetPattern) convert(param);
var pattern = (TargetPattern) convert(param, generics);
if (pattern instanceof TargetComplexPattern) pattern = pattern.withName("__var" + i);
list.add(new MethodParameter(pattern).withType(convert(superList.getParameterAt(i).getType(), generics)));
}
return list;
}
protected TargetSwitch.Case convert(SwitchBlock block) {
return new TargetSwitch.Case(block.getLabels().stream().map(this::convert).toList(), convert((Block) block), block.isExpression);
protected TargetSwitch.Case convert(SwitchBlock block, IGenerics generics) {
return new TargetSwitch.Case(block.getLabels().stream().map(s -> convert(s, generics)).toList(), convert((Block) block, generics), block.isExpression);
}
protected TargetBlock convert(Block block) {
protected TargetBlock convert(Block block, IGenerics generics) {
if (block == null) return null;
return new TargetBlock(block.statements.stream().map(this::convert).toList());
return new TargetBlock(block.statements.stream().map(s -> convert(s, generics)).toList());
}
protected TargetBlock convertWrapInBlock(Expression expression) {
var res = convert(expression);
protected TargetBlock convertWrapInBlock(Expression expression, IGenerics generics) {
var res = convert(expression, generics);
if (!(res instanceof TargetBlock))
return new TargetBlock(List.of(res));
return (TargetBlock) res;
}
protected TargetExpression convert(Expression expr) {
var converter = new StatementToTargetExpression(this);
protected TargetExpression convert(Expression expr, IGenerics generics) {
var converter = new StatementToTargetExpression(this, generics);
expr.accept(converter);
return converter.result;
}
private TargetField convert(Field input) {
return new TargetField(input.modifier, convert(input.getType(), generics.javaGenerics), input.getName());
private TargetField convert(Field input, IGenerics generics) {
return new TargetField(input.modifier, convert(input.getType(), generics), input.getName());
}
private final Map<String, FunNGenerator.GenericParameters> usedFunN = new HashMap<>();
@@ -640,9 +756,6 @@ public class ASTToTargetAST {
public Map<String, byte[]> auxiliaries = new HashMap<>();
public TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input) {
return convert(input, generics.javaGenerics);
}
private static void collectArguments(TargetSpecializedType tspec, List<TargetType> newParams) {
for (var i = 0; i < tspec.params().size(); i++) {
@@ -672,7 +785,15 @@ public class ASTToTargetAST {
return TargetFunNType.fromParams(params, filteredParams, gep.getReturnType() != null ? 1 : 0);
}
private FunNGenerator.GenericParameters convertToParameters(TargetFunNType input) {
return null;
}
private boolean isSubtype(TargetType test, TargetType other) {
if (other.equals(TargetType.Object)) return true;
if (test instanceof TargetFunNType tfun && other instanceof TargetFunNType ofun)
return isSubtype(new FunNGenerator.GenericParameters(tfun), new FunNGenerator.GenericParameters(ofun));
var testClass = compiler.getClass(new JavaClassName(test.name()));
var otherClass = compiler.getClass(new JavaClassName(other.name()));
if (testClass == null) return false;
@@ -709,19 +830,17 @@ public class ASTToTargetAST {
.toList();
var code = FunNGenerator.generateSpecializedBytecode(gep, superInterfaces);
try {
classLoader.findClass(entry.getKey());
} catch (ClassNotFoundException e) {
try {
classLoader.loadClass(code);
} catch (LinkageError ignored) {}
}
auxiliaries.put(entry.getKey(), code);
}
}
protected TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input, GenerateGenerics generics) {
// FIXME This method shouldn't be used
@Deprecated
public TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input) {
return convert(input, all.getFirst().javaGenerics);
}
public TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input, IGenerics generics) {
return input.acceptTV(new TypeVisitor<>() {
@Override
public TargetType visit(RefType refType) {
@@ -747,7 +866,7 @@ public class ASTToTargetAST {
classLoader.findClass(superClassName);
} catch (ClassNotFoundException e) {
try {
classLoader.loadClass(code);
classLoader.loadClass(superClassName, code);
} catch (LinkageError ignored) {}
}
auxiliaries.put(superClassName, code);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -6,7 +6,7 @@ import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
public class Constraint<A> extends HashSet<A> {
public class Constraint<A> extends HashSet<A> implements Comparable<Constraint<A>> {
private static final long serialVersionUID = 1L;
private Boolean isInherited = false;//wird beides nur für die Method-Constraints benoetigt
private Boolean isImplemented = false;
@@ -73,5 +73,9 @@ public class Constraint<A> extends HashSet<A> {
public String toStringBase() {
return super.toString();
}
@Override
public int compareTo(Constraint<A> o) {
return this.toString().compareTo(o.toString());
}
}

View File

@@ -5,7 +5,7 @@ import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
/**
* Paare, welche das Unifikationsergebnis darstellen
*/
public abstract class ResultPair<A extends RefTypeOrTPHOrWildcardOrGeneric,B extends RefTypeOrTPHOrWildcardOrGeneric> {
public abstract class ResultPair<A extends RefTypeOrTPHOrWildcardOrGeneric, B extends RefTypeOrTPHOrWildcardOrGeneric> implements Comparable<ResultPair<A,B>> {
private final A left;
private final B right;
@@ -58,5 +58,14 @@ public abstract class ResultPair<A extends RefTypeOrTPHOrWildcardOrGeneric,B ext
return false;
return true;
}
@Override
public int compareTo(ResultPair<A, B> o) {
if (o == null) {
return 1; // this is greater than null
}
return o.left.toString().compareTo(this.left.toString());
}
}

View File

@@ -1,6 +1,8 @@
package de.dhbwstuttgart.typeinference.result;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import de.dhbwstuttgart.exceptions.NotImplementedException;
@@ -12,7 +14,7 @@ import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
@SuppressWarnings("rawtypes")
public class ResultSet {
public class ResultSet implements Comparable<ResultSet>{
public final Set<ResultPair> results;
public Set<ResultPair<TypePlaceholder, TypePlaceholder>> genIns;
@@ -22,6 +24,10 @@ public class ResultSet {
this.genIns = new HashSet<>();
results.forEach(x -> { if (x instanceof PairTPHsmallerTPH) { this.genIns.add(x);}} );
}
public List<ResultPair> getSortedResults() {
return results.stream().sorted().toList();
}
public boolean contains(ResultPair toCheck) {
return this.results.contains(toCheck);
@@ -63,6 +69,21 @@ public class ResultSet {
public int hashCode() {
return results.hashCode();
}
@Override
public int compareTo(ResultSet o) {
List<ResultPair> thisSorted = this.getSortedResults();
List<ResultPair> otherSorted = o.getSortedResults();
int sizeCompare = Integer.compare(thisSorted.size(), otherSorted.size());
if (sizeCompare != 0) return sizeCompare;
for (int i = 0; i < thisSorted.size(); i++) {
int cmp = thisSorted.get(i).compareTo(otherSorted.get(i));
if (cmp != 0) return cmp;
}
return 0;
}
}
class Resolver implements ResultSetVisitor {

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

@@ -73,7 +73,7 @@ public class TYPEStmt implements StatementVisitor {
@Override
public void visit(LambdaExpression lambdaExpression) {
TypePlaceholder tphRetType = TypePlaceholder.fresh(new NullToken());
TypePlaceholder tphRetType = TypePlaceholder.fresh(new NullToken(), -1, false);
List<RefTypeOrTPHOrWildcardOrGeneric> lambdaParams = lambdaExpression.params.getFormalparalist().stream().map((formalParameter -> formalParameter.getType())).collect(Collectors.toList());
lambdaParams.add(tphRetType);
// lambdaParams.add(0,tphRetType);
@@ -635,6 +635,7 @@ public class TYPEStmt implements StatementVisitor {
params.add(resolver.resolve(new GenericRefType(gtv.getName(), new NullToken())));
}
RefTypeOrTPHOrWildcardOrGeneric receiverType;
if (receiver instanceof FunNClass) {
receiverType = new RefType(new JavaClassName(receiver.getClassName().toString() + "$$"), params, new NullToken()); // new FunN(params);
} else {

View File

@@ -53,7 +53,7 @@ class Node<T> {
addDescendant(descendant);
}
}
/**
* Adds a directed edge from the predecessor to this node (predecessor -> this)
*/
@@ -73,7 +73,7 @@ class Node<T> {
addPredecessor(predecessor);
}
}
/**
* The content of this node.
*/

View File

@@ -1,6 +1,6 @@
import static org.junit.Assert.*;
import static org.junit.jupiter.api.Assertions.*;
import static targetast.TestCodegen.generateClassFiles;
import java.io.File;
@@ -9,13 +9,12 @@ import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import com.google.common.collect.Lists;
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.environment.ByteArrayClassLoader;
public class AllgemeinTest {

View File

@@ -6,12 +6,12 @@ import de.dhbwstuttgart.syntaxtree.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
import de.dhbwstuttgart.syntaxtree.type.*;
import de.dhbwstuttgart.target.generate.ASTToTargetAST;
import org.junit.Test;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.*;
import static org.junit.jupiter.api.Assertions.*;
public class GenericsParserTest {

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
import de.dhbwstuttgart.core.JavaTXCompiler;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import java.io.File;
import java.util.List;
@@ -24,7 +24,7 @@ public class TestPackages {
}
@Test
@Ignore("This doesn't work")
@Disabled("This doesn't work")
public void testPackagesCircular() throws Exception {
var cmp = new JavaTXCompiler(
List.of(

View File

@@ -4,7 +4,7 @@ import de.dhbwstuttgart.syntaxtree.SourceFile;
import de.dhbwstuttgart.typedeployment.TypeInsert;
import de.dhbwstuttgart.typedeployment.TypeInsertFactory;
import de.dhbwstuttgart.typeinference.result.ResultSet;
import org.junit.Test;
import org.junit.jupiter.api.Test;
import java.io.File;
import java.nio.file.Path;

View File

@@ -4,7 +4,7 @@ package astfactory;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
import de.dhbwstuttgart.syntaxtree.type.GenericRefType;
import org.junit.Test;
import org.junit.jupiter.api.Test;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
@@ -12,7 +12,8 @@ import java.lang.reflect.TypeVariable;
import java.util.Arrays;
import java.util.HashMap;
import static org.junit.Assert.*;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class ASTFactoryTest<A> extends HashMap<String, A>{
@Test

View File

@@ -3,7 +3,7 @@ package finiteClosure;
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.FCGenerator;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
import org.junit.Test;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.Collection;

View File

@@ -1,9 +1,5 @@
package syntaxtreegenerator;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
@@ -12,21 +8,23 @@ import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.exceptions.NotImplementedException;
import de.dhbwstuttgart.syntaxtree.SourceFile;
import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter;
import static org.junit.jupiter.api.Assertions.*;
/**
* Unit-Tests für den 'SyntaxTreeGenerator' aus dem Package 'parser' nach Vorbild der Klasse 'TestComplete' aus dem Test-Package 'targetast'
*/
public class TestComplete {
private static HashMap<String, File[]> javFiles = new HashMap<>();
@BeforeClass
@BeforeAll
public static void setUp() {
final String testFileDirectory = "resources/bytecode/javFiles/";
final String expectedASTDirectory = "resources/syntaxtreegenerator/";
@@ -353,7 +351,7 @@ public class TestComplete {
assertEquals("Comparing expected and resulting AST for mathStrucInteger.jav", expectedAST, resultingAST);
} catch (Exception exc) {
exc.printStackTrace();
assertTrue("An error occured while generating the AST for mathStrucInteger.jav", exc instanceof NotImplementedException);
assertInstanceOf(NotImplementedException.class, exc);
}
}

View File

@@ -1,15 +1,15 @@
package syntaxtreegenerator;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.util.HashMap;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter;
@@ -17,7 +17,7 @@ import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter;
public class TestNewFeatures {
private static HashMap<String, File[]> javFiles = new HashMap<>();
@BeforeClass
@BeforeAll
public static void setUp() {
final String testFileDirectory = "resources/syntaxtreegenerator/javFiles/";
final String expectedASTDirectory = "resources/syntaxtreegenerator/";

View File

@@ -2,7 +2,6 @@ package targetast;
import com.google.common.reflect.TypeToken;
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.environment.ByteArrayClassLoader;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.syntaxtree.*;
@@ -10,13 +9,13 @@ import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.target.generate.ASTToTargetAST;
import de.dhbwstuttgart.target.tree.TargetStructure;
import de.dhbwstuttgart.typeinference.result.ResultSet;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import java.nio.file.Path;
import java.util.*;
import static org.junit.Assert.*;
import static org.junit.jupiter.api.Assertions.*;
public class ASTToTypedTargetAST {
@@ -24,7 +23,7 @@ public class ASTToTypedTargetAST {
public void emptyClass() {
ClassOrInterface emptyClass = new ClassOrInterface(0, new JavaClassName("EmptyClass"), new ArrayList<>(), Optional.empty(), Optional.empty(), new ArrayList<>(), new ArrayList<>(), new GenericDeclarationList(new ArrayList<>(), new NullToken()), new RefType(new JavaClassName("Object"), new NullToken()), false, false, new ArrayList<>(), new ArrayList<>(), new NullToken(), null);
ResultSet emptyResultSet = new ResultSet(new HashSet<>());
TargetStructure emptyTargetClass = new ASTToTargetAST(List.of(emptyResultSet)).convert(emptyClass);
TargetStructure emptyTargetClass = new ASTToTargetAST(List.of(emptyResultSet), TestCodegen.createClassLoader()).convert(emptyClass);
assert emptyTargetClass.getName().equals("EmptyClass");
assert emptyTargetClass.methods().size() == 0;
assert emptyTargetClass.fields().size() == 0;
@@ -32,13 +31,14 @@ public class ASTToTypedTargetAST {
@Test
public void overloading() throws Exception {
var classLoader = TestCodegen.createClassLoader();
var file = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/Overloading.jav").toFile();
var compiler = new JavaTXCompiler(file);
var resultSet = compiler.typeInference(file);
var converter = new ASTToTargetAST(compiler, resultSet);
var converter = new ASTToTargetAST(compiler, resultSet, classLoader);
var classes = compiler.sourceFiles.get(file).getClasses();
var classLoader = new ByteArrayClassLoader();
var overloading = TestCodegen.generateClass(converter.convert(classes.get(0)), classLoader);
var overloading2 = TestCodegen.generateClass(converter.convert(classes.get(1)), classLoader);
@@ -54,46 +54,54 @@ public class ASTToTypedTargetAST {
@Test
public void tphsAndGenerics() throws Exception {
var classLoader = TestCodegen.createClassLoader();
var file = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/Tph2.jav").toFile();
var compiler = new JavaTXCompiler(file);
var resultSet = compiler.typeInference(file);
var converter = new ASTToTargetAST(compiler, resultSet);
var converter = new ASTToTargetAST(compiler, resultSet, classLoader);
var classes = compiler.sourceFiles.get(file).getClasses();
var tphAndGenerics = TestCodegen.generateClass(converter.convert(classes.get(0)), new ByteArrayClassLoader());
var tphAndGenerics = TestCodegen.generateClass(converter.convert(classes.get(0)), classLoader);
}
@Test
public void cycles() throws Exception {
var classLoader = TestCodegen.createClassLoader();
var file = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/Cycle.jav").toFile();
var compiler = new JavaTXCompiler(file);
var resultSet = compiler.typeInference(file);
var converter = new ASTToTargetAST(compiler, resultSet);
var converter = new ASTToTargetAST(compiler, resultSet, classLoader);
var classes = compiler.sourceFiles.get(file).getClasses();
var cycle = TestCodegen.generateClass(converter.convert(classes.get(0)), new ByteArrayClassLoader());
var cycle = TestCodegen.generateClass(converter.convert(classes.get(0)), classLoader);
}
@Test
public void infimum() throws Exception {
var classLoader = TestCodegen.createClassLoader();
var file = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/Infimum.jav").toFile();
var compiler = new JavaTXCompiler(file);
var resultSet = compiler.typeInference(file);
var converter = new ASTToTargetAST(compiler, resultSet);
var converter = new ASTToTargetAST(compiler, resultSet, classLoader);
var classes = compiler.sourceFiles.get(file).getClasses();
var infimum = TestCodegen.generateClass(converter.convert(classes.get(0)), new ByteArrayClassLoader());
var infimum = TestCodegen.generateClass(converter.convert(classes.get(0)), classLoader);
}
@Test
public void gen() throws Exception {
var classLoader = TestCodegen.createClassLoader();
var file = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/Gen.jav").toFile();
var compiler = new JavaTXCompiler(file);
var resultSet = compiler.typeInference(file);
var converter = new ASTToTargetAST(compiler, resultSet);
var converter = new ASTToTargetAST(compiler, resultSet, classLoader);
var classes = compiler.sourceFiles.get(file).getClasses();
var generics = TestCodegen.generateClass(converter.convert(classes.get(0)), new ByteArrayClassLoader());
var generics = TestCodegen.generateClass(converter.convert(classes.get(0)), TestCodegen.createClassLoader());
var m = generics.getDeclaredMethod("m", Vector.class);
var mReturnType = m.getGenericReturnType();
assertEquals(mReturnType, m.getParameters()[0].getParameterizedType());
@@ -103,13 +111,15 @@ public class ASTToTypedTargetAST {
@Test
public void definedGenerics() throws Exception {
var classLoader = TestCodegen.createClassLoader();
var file = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/Generics.jav").toFile();
var compiler = new JavaTXCompiler(file);
var resultSet = compiler.typeInference(file);
var converter = new ASTToTargetAST(compiler, resultSet);
var converter = new ASTToTargetAST(compiler, resultSet, classLoader);
var classes = compiler.sourceFiles.get(file).getClasses();
var generics = TestCodegen.generateClass(converter.convert(classes.get(0)), new ByteArrayClassLoader());
var generics = TestCodegen.generateClass(converter.convert(classes.get(0)), classLoader);
var B = generics.getTypeParameters()[0];
var mt1 = generics.getDeclaredMethod("mt1", Object.class);
var constructor = generics.getDeclaredConstructor(Object.class);
@@ -121,13 +131,15 @@ public class ASTToTypedTargetAST {
@Test
public void definedGenerics2() throws Exception {
var classLoader = TestCodegen.createClassLoader();
var file = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/Generics2.jav").toFile();
var compiler = new JavaTXCompiler(file);
var resultSet = compiler.typeInference(file);
var converter = new ASTToTargetAST(compiler, resultSet);
var converter = new ASTToTargetAST(compiler, resultSet, classLoader);
var classes = compiler.sourceFiles.get(file).getClasses();
var generics2 = TestCodegen.generateClass(converter.convert(classes.get(0)), new ByteArrayClassLoader());
var generics2 = TestCodegen.generateClass(converter.convert(classes.get(0)), classLoader);
assertEquals(generics2.getTypeParameters()[0].getBounds()[0], String.class);
var m = generics2.getDeclaredMethod("m1", Object.class);
assertEquals(m.getTypeParameters()[0].getBounds()[0], Integer.class);
@@ -135,26 +147,30 @@ public class ASTToTypedTargetAST {
}
@Test
@Ignore("Not implemented")
@Disabled("Not implemented")
public void definedGenerics3() throws Exception {
var classLoader = TestCodegen.createClassLoader();
var file = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/Generics3.jav").toFile();
var compiler = new JavaTXCompiler(file);
var resultSet = compiler.typeInference(file);
var converter = new ASTToTargetAST(compiler, resultSet);
var converter = new ASTToTargetAST(compiler, resultSet, classLoader);
var classes = compiler.sourceFiles.get(file).getClasses();
var generics3 = TestCodegen.generateClass(converter.convert(classes.get(0)), new ByteArrayClassLoader());
var generics3 = TestCodegen.generateClass(converter.convert(classes.get(0)), classLoader);
}
@Test
public void definedGenerics4() throws Exception {
var classLoader = TestCodegen.createClassLoader();
var file = Path.of(System.getProperty("user.dir"), "/resources/bytecode/javFiles/Generics4.jav").toFile();
var compiler = new JavaTXCompiler(file);
var resultSet = compiler.typeInference(file);
var converter = new ASTToTargetAST(compiler, resultSet);
var converter = new ASTToTargetAST(compiler, resultSet, classLoader);
var classes = compiler.sourceFiles.get(file).getClasses();
var generics4 = TestCodegen.generateClass(converter.convert(classes.get(0)), new ByteArrayClassLoader());
var generics4 = TestCodegen.generateClass(converter.convert(classes.get(0)), classLoader);
// var instance = generics4.getDeclaredConstructor().newInstance();
// var method = generics4.getDeclaredMethod("m2", Object.class);

View File

@@ -1,22 +1,21 @@
package targetast;
import de.dhbwstuttgart.environment.ByteArrayClassLoader;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class GreaterEqualTest {
static Class<?> classToTest;
static Object instance;
@BeforeClass
@BeforeAll
public static void beforeClass() throws Exception {
var classFiles = TestCodegen.generateClassFiles(new ByteArrayClassLoader(), "GreaterEqual.jav");
var classFiles = TestCodegen.generateClassFiles(TestCodegen.createClassLoader(), "GreaterEqual.jav");
classToTest = classFiles.get("GreaterEqual");
instance = classToTest.getDeclaredConstructor().newInstance();
}

View File

@@ -1,21 +1,20 @@
package targetast;
import de.dhbwstuttgart.environment.ByteArrayClassLoader;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Method;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class GreaterThanTest {
static Class<?> classToTest;
static Object instance;
@BeforeClass
@BeforeAll
public static void beforeClass() throws Exception {
var classFiles = TestCodegen.generateClassFiles(new ByteArrayClassLoader(), "GreaterThan.jav");
var classFiles = TestCodegen.generateClassFiles(TestCodegen.createClassLoader(), "GreaterThan.jav");
classToTest = classFiles.get("GreaterThan");
instance = classToTest.getDeclaredConstructor().newInstance();
}

View File

@@ -1,22 +1,20 @@
package targetast;
import de.dhbwstuttgart.environment.ByteArrayClassLoader;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Method;
import java.nio.file.Path;
import java.util.Vector;
import static org.junit.Assert.assertEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class InheritTest {
private static Class<?> classToTest, classToTestAA, classToTestBB, classToTestCC, classToTestDD;
private static Object instanceOfClass, instanceOfClassAA, instanceOfClassBB, instanceOfClassCC, instanceOfClassDD;
@BeforeClass
@BeforeAll
public static void setUpBeforeClass() throws Exception {
var classLoader = new ByteArrayClassLoader();
var classLoader = TestCodegen.createClassLoader();
var classes = TestCodegen.generateClassFiles(classLoader, "Inherit.jav");
classToTest = classes.get("Inherit");
@@ -35,72 +33,72 @@ public class InheritTest {
@Test
public void testmainAA() throws Exception {
Method m = classToTestAA.getDeclaredMethod("m", Integer.class);
assertEquals(m.invoke(instanceOfClassAA, 5), "AA");
assertEquals("AA", m.invoke(instanceOfClassAA, 5));
Method main = classToTest.getDeclaredMethod("main", classToTestAA, Integer.class);
assertEquals(main.invoke(instanceOfClass, instanceOfClassAA, 5), "AA");
assertEquals("AA", main.invoke(instanceOfClass, instanceOfClassAA, 5));
}
@Test
public void testmainBB() throws Exception {
Method m = classToTestAA.getDeclaredMethod("m", Integer.class);
assertEquals(m.invoke(instanceOfClassBB, 5), "AA");
assertEquals("AA", m.invoke(instanceOfClassBB, 5));
Method main = classToTest.getDeclaredMethod("main", classToTestAA, Integer.class);
assertEquals(main.invoke(instanceOfClass, instanceOfClassBB, 5), "AA");
assertEquals("AA", main.invoke(instanceOfClass, instanceOfClassBB, 5));
}
@Test
public void testmainCC() throws Exception {
Method m = classToTestCC.getDeclaredMethod("m", Integer.class);
assertEquals(m.invoke(instanceOfClassCC, 5), "CC");
assertEquals("CC", m.invoke(instanceOfClassCC, 5));
Method main = classToTest.getDeclaredMethod("main", classToTestCC, Integer.class);
assertEquals(main.invoke(instanceOfClass, instanceOfClassCC, 5), "CC");
assertEquals("CC", main.invoke(instanceOfClass, instanceOfClassCC, 5));
}
@Test
public void testmainDD() throws Exception {
Method m = classToTestCC.getDeclaredMethod("m", Integer.class);
assertEquals(m.invoke(instanceOfClassDD, 5), "CC");
assertEquals("CC", m.invoke(instanceOfClassDD, 5));
Method main = classToTest.getDeclaredMethod("main", classToTestCC, Integer.class);
assertEquals(main.invoke(instanceOfClass, instanceOfClassDD, 5), "CC");
assertEquals("CC", main.invoke(instanceOfClass, instanceOfClassDD, 5));
}
@Test
public void testmainVectorAA() throws Exception {
Method m = classToTestAA.getDeclaredMethod("m", Integer.class);
assertEquals(m.invoke(instanceOfClassAA, 5), "AA");
assertEquals("AA", m.invoke(instanceOfClassAA, 5));
Vector v = new Vector<>();
v.add(instanceOfClassAA);
Method main = classToTest.getDeclaredMethod("main", Vector.class, Integer.class);
assertEquals(main.invoke(instanceOfClass, v, 5), "AA");
assertEquals("AA", main.invoke(instanceOfClass, v, 5));
}
@Test
public void testmainVectorBB() throws Exception {
Method m = classToTestAA.getDeclaredMethod("m", Integer.class);
assertEquals(m.invoke(instanceOfClassBB, 5), "AA");
assertEquals("AA", m.invoke(instanceOfClassBB, 5));
Vector v = new Vector<>();
v.add(instanceOfClassBB);
Method main = classToTest.getDeclaredMethod("main", Vector.class, Integer.class);
assertEquals(main.invoke(instanceOfClass, v, 5), "AA");
assertEquals("AA", main.invoke(instanceOfClass, v, 5));
}
@Test
public void testmainVectorCC() throws Exception {
Method m = classToTestCC.getDeclaredMethod("m", Integer.class);
assertEquals(m.invoke(instanceOfClassCC, 5), "CC");
assertEquals("CC", m.invoke(instanceOfClassCC, 5));
Vector v = new Vector<>();
v.add(instanceOfClassCC);
Method main = classToTest.getDeclaredMethod("main", Vector.class, Integer.class);
assertEquals(main.invoke(instanceOfClass, v, 5), "CC");
assertEquals("CC", main.invoke(instanceOfClass, v, 5));
}
@Test
public void testmainVectorDD() throws Exception {
Method m = classToTestCC.getDeclaredMethod("m", Integer.class);
assertEquals(m.invoke(instanceOfClassDD, 5), "CC");
assertEquals("CC", m.invoke(instanceOfClassDD, 5));
Vector v = new Vector<>();
v.add(instanceOfClassDD);
Method main = classToTest.getDeclaredMethod("main", Vector.class, Integer.class);
assertEquals(main.invoke(instanceOfClass, v, 5), "CC");
assertEquals("CC", main.invoke(instanceOfClass, v, 5));
}
}

View File

@@ -1,23 +1,22 @@
package targetast;
import de.dhbwstuttgart.environment.ByteArrayClassLoader;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Method;
import java.util.Vector;
import static org.junit.Assert.assertEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
@Ignore("FIXME")
@Disabled("FIXME")
public class InheritTest2 {
private static Class<?> classToTest, classToTestAA, classToTestBB, classToTestCC, classToTestDD;
private static Object instanceOfClass, instanceOfClassAA, instanceOfClassBB, instanceOfClassCC, instanceOfClassDD;
@BeforeClass
@BeforeAll
public static void setUpBeforeClass() throws Exception {
var classLoader = new ByteArrayClassLoader();
var classLoader = TestCodegen.createClassLoader();
classToTest = TestCodegen.generateClassFiles(classLoader, "Inherit2.jav").get("Inherit2");
classToTestAA = TestCodegen.generateClassFiles(classLoader, "AA.jav").get("AA");
classToTestBB = TestCodegen.generateClassFiles(classLoader, "BB.jav").get("BB");

View File

@@ -1,21 +1,20 @@
package targetast;
import de.dhbwstuttgart.environment.ByteArrayClassLoader;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Method;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class LessEqualTest {
static Class<?> classToTest;
static Object instance;
@BeforeClass
@BeforeAll
public static void beforeClass() throws Exception {
var classFiles = TestCodegen.generateClassFiles(new ByteArrayClassLoader(), "LessEqual.jav");
var classFiles = TestCodegen.generateClassFiles(TestCodegen.createClassLoader(), "LessEqual.jav");
classToTest = classFiles.get("LessEqual");
instance = classToTest.getDeclaredConstructor().newInstance();
}

View File

@@ -1,21 +1,20 @@
package targetast;
import de.dhbwstuttgart.environment.ByteArrayClassLoader;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Method;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class LessThanTest {
static Class<?> classToTest;
static Object instance;
@BeforeClass
@BeforeAll
public static void beforeClass() throws Exception {
var classFiles = TestCodegen.generateClassFiles(new ByteArrayClassLoader(), "LessThan.jav");
var classFiles = TestCodegen.generateClassFiles(TestCodegen.createClassLoader(), "LessThan.jav");
classToTest = classFiles.get("LessThan");
instance = classToTest.getDeclaredConstructor().newInstance();
}

View File

@@ -1,12 +1,12 @@
package targetast;
import de.dhbwstuttgart.environment.ByteArrayClassLoader;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Method;
import static org.junit.Assert.assertEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class OLTest {
private static Class<?> classToTest;
@@ -14,9 +14,9 @@ public class OLTest {
private static Object instanceOfClass;
private static Object instanceOfClass1;
@BeforeClass
@BeforeAll
public static void setUpBeforeClass() throws Exception {
var classFiles = TestCodegen.generateClassFiles(new ByteArrayClassLoader(), "OL.jav");
var classFiles = TestCodegen.generateClassFiles(TestCodegen.createClassLoader(), "OL.jav");
classToTest = classFiles.get("OL");
instanceOfClass = classToTest.getDeclaredConstructor().newInstance();
classToTest1 = classFiles.get("OLMain");

View File

@@ -1,20 +1,19 @@
package targetast;
import de.dhbwstuttgart.environment.ByteArrayClassLoader;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Method;
import static org.junit.Assert.assertEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class PostIncTest {
private static Class<?> classToTest;
private static Object instanceOfClass;
@BeforeClass
@BeforeAll
public static void setUpBeforeClass() throws Exception {
var classFiles = TestCodegen.generateClassFiles(new ByteArrayClassLoader(), "PostIncDec.jav");
var classFiles = TestCodegen.generateClassFiles(TestCodegen.createClassLoader(), "PostIncDec.jav");
classToTest = classFiles.get("PostIncDec");
instanceOfClass = classToTest.getDeclaredConstructor().newInstance();
}

View File

@@ -1,20 +1,19 @@
package targetast;
import de.dhbwstuttgart.environment.ByteArrayClassLoader;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Method;
import static org.junit.Assert.assertEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class PreIncTest {
private static Class<?> classToTest;
private static Object instanceOfClass;
@BeforeClass
@BeforeAll
public static void setUpBeforeClass() throws Exception {
var classFiles = TestCodegen.generateClassFiles(new ByteArrayClassLoader(), "PreInc.jav");
var classFiles = TestCodegen.generateClassFiles(TestCodegen.createClassLoader(), "PreInc.jav");
classToTest = classFiles.get("PreInc");
instanceOfClass = classToTest.getDeclaredConstructor().newInstance();
}

View File

@@ -1,22 +1,21 @@
package targetast;
import de.dhbwstuttgart.environment.ByteArrayClassLoader;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Method;
import java.util.Stack;
import java.util.Vector;
import static org.junit.Assert.assertEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class PutTest {
private static Class<?> classToTest;
private static Object instanceOfClass;
@BeforeClass
@BeforeAll
public static void setUpBeforeClass() throws Exception {
var classFiles = TestCodegen.generateClassFiles(new ByteArrayClassLoader(), "Put.jav");
var classFiles = TestCodegen.generateClassFiles(TestCodegen.createClassLoader(), "Put.jav");
classToTest = classFiles.get("Put");
instanceOfClass = classToTest.getDeclaredConstructor().newInstance();
}

View File

@@ -2,7 +2,7 @@ package targetast;
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.bytecode.Codegen;
import de.dhbwstuttgart.environment.ByteArrayClassLoader;
import de.dhbwstuttgart.environment.DirectoryClassLoader;
import de.dhbwstuttgart.environment.IByteArrayClassLoader;
import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.target.generate.ASTToTargetAST;
@@ -14,10 +14,10 @@ import de.dhbwstuttgart.target.tree.expression.*;
import de.dhbwstuttgart.target.tree.type.TargetFunNType;
import de.dhbwstuttgart.target.tree.type.TargetRefType;
import de.dhbwstuttgart.target.tree.type.TargetType;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import static org.junit.Assert.*;
import static org.junit.jupiter.api.Assertions.*;
import org.objectweb.asm.Opcodes;
@@ -37,6 +37,10 @@ public class TestCodegen {
Files.write(outputPath.resolve(name + ".class"), code);
}
public static IByteArrayClassLoader createClassLoader() {
return new DirectoryClassLoader(List.of(outputPath.toFile()), ClassLoader.getSystemClassLoader());
}
public static Path path = Path.of(System.getProperty("user.dir"), "resources/bytecode/javFiles/");
public static Map<String, ? extends Class<?>> generateClassFiles(IByteArrayClassLoader classLoader, String... files) throws IOException, ClassNotFoundException {
@@ -119,7 +123,7 @@ public class TestCodegen {
public void testEmptyClass() throws Exception {
var clazz = new TargetClass(Opcodes.ACC_PUBLIC, new JavaClassName("Empty"));
clazz.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "main", List.of(), null, new TargetBlock(List.of()));
generateClass(clazz, new ByteArrayClassLoader()).getDeclaredMethod("main").invoke(null);
generateClass(clazz, createClassLoader()).getDeclaredMethod("main").invoke(null);
}
@Test
@@ -132,7 +136,7 @@ public class TestCodegen {
targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "mul", List.of(new MethodParameter(TargetType.Integer, "a"), new MethodParameter(TargetType.Integer, "b")), TargetType.Integer, new TargetBlock(List.of(new TargetReturn(new TargetBinaryOp.Mul(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "a"), new TargetLocalVar(TargetType.Integer, "b"))))));
targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "rem", List.of(new MethodParameter(TargetType.Integer, "a"), new MethodParameter(TargetType.Integer, "b")), TargetType.Integer, new TargetBlock(List.of(new TargetReturn(new TargetBinaryOp.Rem(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "a"), new TargetLocalVar(TargetType.Integer, "b"))))));
var clazz = generateClass(targetClass, new ByteArrayClassLoader());
var clazz = generateClass(targetClass, createClassLoader());
assertEquals(clazz.getDeclaredMethod("add", Integer.class, Integer.class).invoke(null, 10, 10), 20);
assertEquals(clazz.getDeclaredMethod("sub", Integer.class, Integer.class).invoke(null, 20, 10), 10);
assertEquals(clazz.getDeclaredMethod("div", Integer.class, Integer.class).invoke(null, 20, 10), 2);
@@ -148,7 +152,7 @@ public class TestCodegen {
targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "neg", List.of(new MethodParameter(TargetType.Integer, "a")), TargetType.Integer, new TargetBlock(List.of(new TargetReturn(new TargetUnaryOp.Negate(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "a"))))));
targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "add", List.of(new MethodParameter(TargetType.Integer, "a")), TargetType.Integer, new TargetBlock(List.of(new TargetReturn(new TargetUnaryOp.Add(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "a"))))));
var clazz = generateClass(targetClass, new ByteArrayClassLoader());
var clazz = generateClass(targetClass, createClassLoader());
assertEquals(clazz.getDeclaredMethod("not", Integer.class).invoke(null, 10), -11);
assertEquals(clazz.getDeclaredMethod("neg", Integer.class).invoke(null, 10), -10);
assertEquals(clazz.getDeclaredMethod("add", Integer.class).invoke(null, 10), 10);
@@ -162,7 +166,7 @@ public class TestCodegen {
targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "and", List.of(new MethodParameter(TargetType.Boolean, "a"), new MethodParameter(TargetType.Boolean, "b")), TargetType.Boolean, new TargetBlock(List.of(new TargetReturn(new TargetBinaryOp.And(TargetType.Boolean, new TargetLocalVar(TargetType.Boolean, "a"), new TargetLocalVar(TargetType.Boolean, "b"))))));
targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "or", List.of(new MethodParameter(TargetType.Boolean, "a"), new MethodParameter(TargetType.Boolean, "b")), TargetType.Boolean, new TargetBlock(List.of(new TargetReturn(new TargetBinaryOp.Or(TargetType.Boolean, new TargetLocalVar(TargetType.Boolean, "a"), new TargetLocalVar(TargetType.Boolean, "b"))))));
var clazz = generateClass(targetClass, new ByteArrayClassLoader());
var clazz = generateClass(targetClass, createClassLoader());
var and = clazz.getDeclaredMethod("and", Boolean.class, Boolean.class);
var or = clazz.getDeclaredMethod("or", Boolean.class, Boolean.class);
assertEquals(and.invoke(null, true, false), false);
@@ -176,7 +180,7 @@ public class TestCodegen {
public void testArithmeticConvert() throws Exception {
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, new JavaClassName("ArithmeticConvert"));
targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "add", List.of(), TargetType.Long, new TargetBlock(List.of(new TargetReturn(new TargetBinaryOp.Add(TargetType.Long, new TargetLiteral.CharLiteral((char) 10), new TargetLiteral.LongLiteral((long) 20))))));
var clazz = generateClass(targetClass, new ByteArrayClassLoader());
var clazz = generateClass(targetClass, createClassLoader());
assertEquals(clazz.getDeclaredMethod("add").invoke(null), (long) 30);
}
@@ -185,7 +189,7 @@ public class TestCodegen {
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, new JavaClassName("HelloWorld"));
targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "helloWorld", List.of(), null, new TargetBlock(List.of(new TargetMethodCall(null, new TargetFieldVar(new TargetRefType("java.io.PrintStream"), new TargetRefType("java.lang.System"), true, new TargetClassName(new TargetRefType("java.lang.System")), "out"), List.of(new TargetLiteral.StringLiteral("Hello World!")), new TargetRefType("java.io.PrintStream"), "println", false, false, false))));
var clazz = generateClass(targetClass, new ByteArrayClassLoader());
var clazz = generateClass(targetClass, createClassLoader());
clazz.getDeclaredMethod("helloWorld").invoke(null);
}
@@ -193,7 +197,7 @@ public class TestCodegen {
public void testIfStatement() throws Exception {
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, new JavaClassName("IfStmt"));
targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "ifStmt", List.of(new MethodParameter(TargetType.Integer, "val")), TargetType.Integer, new TargetBlock(List.of(new TargetIf(new TargetBinaryOp.Equal(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "val"), new TargetLiteral.IntLiteral(10)), new TargetReturn(new TargetLiteral.IntLiteral(1)), new TargetIf(new TargetBinaryOp.Less(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "val"), new TargetLiteral.IntLiteral(5)), new TargetReturn(new TargetLiteral.IntLiteral(2)), new TargetReturn(new TargetLiteral.IntLiteral(3)))))));
var clazz = generateClass(targetClass, new ByteArrayClassLoader());
var clazz = generateClass(targetClass, createClassLoader());
var ifStmt = clazz.getDeclaredMethod("ifStmt", Integer.class);
assertEquals(ifStmt.invoke(null, 10), 1);
assertEquals(ifStmt.invoke(null, 3), 2);
@@ -204,7 +208,7 @@ public class TestCodegen {
public void testFor() throws Exception {
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, new JavaClassName("For"));
targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "forLoop", List.of(), TargetType.Integer, new TargetBlock(List.of(new TargetVarDecl(TargetType.Integer, "sum", new TargetLiteral.IntLiteral(0)), new TargetFor(List.of(new TargetVarDecl(TargetType.Integer, "i", new TargetLiteral.IntLiteral(0))), new TargetBinaryOp.Less(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "i"), new TargetLiteral.IntLiteral(10)), List.of(new TargetAssign(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "i"), new TargetBinaryOp.Add(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "i"), new TargetLiteral.IntLiteral(1)))), new TargetBlock(List.of(new TargetAssign(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "sum"), new TargetBinaryOp.Add(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "sum"), new TargetLocalVar(TargetType.Integer, "i")))))), new TargetReturn(new TargetLocalVar(TargetType.Integer, "sum")))));
var clazz = generateClass(targetClass, new ByteArrayClassLoader());
var clazz = generateClass(targetClass, createClassLoader());
assertEquals(clazz.getDeclaredMethod("forLoop").invoke(null), 45);
}
@@ -212,7 +216,7 @@ public class TestCodegen {
public void testWhile() throws Exception {
var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, new JavaClassName("While"));
targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "whileLoop", List.of(), TargetType.Integer, new TargetBlock(List.of(new TargetVarDecl(TargetType.Integer, "i", new TargetLiteral.IntLiteral(0)), new TargetWhile(new TargetBinaryOp.Less(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "i"), new TargetLiteral.IntLiteral(10)), new TargetBlock(List.of(new TargetAssign(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "i"), new TargetBinaryOp.Add(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "i"), new TargetLiteral.IntLiteral(1)))))), new TargetReturn(new TargetLocalVar(TargetType.Integer, "i")))));
var clazz = generateClass(targetClass, new ByteArrayClassLoader());
var clazz = generateClass(targetClass, createClassLoader());
assertEquals(clazz.getDeclaredMethod("whileLoop").invoke(null), 10);
}
@@ -235,7 +239,7 @@ public class TestCodegen {
new TargetReturn(new TargetLocalVar(TargetType.Integer, "res"))
)));
var clazz = generateClass(targetClass, new ByteArrayClassLoader());
var clazz = generateClass(targetClass, createClassLoader());
var m = clazz.getDeclaredMethod("switchClassic", Integer.class);
assertEquals(m.invoke(null, 10), 0);
assertEquals(m.invoke(null, 15), 1);
@@ -264,7 +268,7 @@ public class TestCodegen {
List.of(new TargetLiteral.IntLiteral(2))
), true), TargetType.Integer)
))));
var clazz = generateClass(targetClass, new ByteArrayClassLoader());
var clazz = generateClass(targetClass, createClassLoader());
var m = clazz.getDeclaredMethod("switchType", Object.class);
assertEquals(m.invoke(null, "String"), 0);
assertEquals(m.invoke(null, 10), 1);
@@ -273,9 +277,9 @@ public class TestCodegen {
}
@Test
@Ignore("The lambda class is not generated because we don't call ASTToTargetAST")
@Disabled("The lambda class is not generated because we don't call ASTToTargetAST")
public void testLambda() throws Exception {
var classLoader = new ByteArrayClassLoader();
var classLoader = createClassLoader();
// var fun = classLoader.loadClass(Path.of(System.getProperty("user.dir"), "src/test/java/targetast/Fun1$$.class"));
var interfaceType = TargetFunNType.fromParams(List.of(TargetType.Integer), 1);

View File

@@ -12,9 +12,9 @@ import de.dhbwstuttgart.target.generate.Bound;
import static de.dhbwstuttgart.target.generate.Bound.*;
import de.dhbwstuttgart.target.generate.BoundsList;
import de.dhbwstuttgart.target.generate.GenericsResult;
import org.junit.Ignore;
import org.junit.Test;
import static org.junit.Assert.*;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
import java.io.File;
import java.io.IOException;
@@ -22,7 +22,7 @@ import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
@Ignore("TODO: Rewrite with the new algorithm")
@Disabled("TODO: Rewrite with the new algorithm")
public class TestGenerics {
private static final String rootDirectory = System.getProperty("user.dir") + "/resources/insertGenerics/javFiles/";
private static final String bytecodeDirectory = System.getProperty("user.dir") + "targetTest";
@@ -65,7 +65,7 @@ public class TestGenerics {
var b = result.findField("b");
var generics = result.genericsResults.get(0);
assertEquals(1, generics.get(anyMethod).size());
assertEquals(1, generics.get(result.clazz, anyMethod).size());
assertEquals(2, generics.get(result.clazz).size());
var ECK1 = generics.getBounds(otherMethod.getParameterList().getParameterAt(0).getType(), result.clazz, anyMethod);
@@ -86,7 +86,7 @@ public class TestGenerics {
var generics = result.genericsResults.get(0);
assertEquals(1, generics.get(result.clazz).size());
assertEquals(0, generics.get(fReturn).size());
assertEquals(0, generics.get(result.clazz, fReturn).size());
var N = generics.getBounds(fReturn.getReturnType(), result.clazz);
var NChain = new BoundsList(onClass(OBJECT));
@@ -101,8 +101,8 @@ public class TestGenerics {
var generics = result.genericsResults.get(0);
assertEquals(0, generics.get(result.clazz).size());
assertEquals(3, generics.get(m).size());
assertEquals(3, generics.get(main).size());
assertEquals(3, generics.get(result.clazz, m).size());
assertEquals(3, generics.get(result.clazz, main).size());
{
var AJ = generics.getBounds(m.getParameterList().getParameterAt(0).getType(), result.clazz, m);
@@ -143,9 +143,9 @@ public class TestGenerics {
var generics = result.genericsResults.get(0);
assertEquals(1, generics.get(result.clazz).size());
assertEquals(2, generics.get(id).size());
assertEquals(1, generics.get(setA).size());
assertEquals(2, generics.get(m).size());
assertEquals(2, generics.get(result.clazz, id).size());
assertEquals(1, generics.get(result.clazz, setA).size());
assertEquals(2, generics.get(result.clazz, m).size());
var R = generics.getBounds(a.getType(), result.clazz);
var RChain = new BoundsList(onClass(OBJECT));
@@ -183,9 +183,9 @@ public class TestGenerics {
var generics = result.genericsResults.get(0);
assertEquals(1, generics.get(result.clazz).size());
assertEquals(2, generics.get(id).size());
assertEquals(2, generics.get(m).size());
assertEquals(3, generics.get(main).size());
assertEquals(2, generics.get(result.clazz, id).size());
assertEquals(2, generics.get(result.clazz, m).size());
assertEquals(3, generics.get(result.clazz, main).size());
var N = generics.getBounds(a.getType(), result.clazz);
assertEquals(N, new BoundsList(onClass(OBJECT)));
@@ -215,7 +215,7 @@ public class TestGenerics {
var anyMethod = result.findMethod("anyMethod");
var generics = result.genericsResults.get(0);
assertEquals(1, generics.get(anyMethod).size());
assertEquals(1, generics.get(result.clazz, anyMethod).size());
var M = generics.getBounds(anyMethod.getReturnType(), result.clazz, anyMethod);
assertEquals(M, new BoundsList(onMethod(OBJECT)));

View File

@@ -1,21 +1,21 @@
package targetast;
import de.dhbwstuttgart.environment.ByteArrayClassLoader;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Method;
import static org.junit.Assert.assertEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class TphTest {
private static Class<?> classToTest;
private static Object instanceOfClass;
@BeforeClass
@BeforeAll
public static void setUpBeforeClass() throws Exception {
var classFiles = TestCodegen.generateClassFiles(new ByteArrayClassLoader(), "Tph.jav");
var classFiles = TestCodegen.generateClassFiles(TestCodegen.createClassLoader(), "Tph.jav");
classToTest = classFiles.get("Tph");
instanceOfClass = classToTest.getDeclaredConstructor().newInstance();
}

View File

@@ -1,20 +1,19 @@
package targetast;
import de.dhbwstuttgart.environment.ByteArrayClassLoader;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Method;
import static org.junit.Assert.assertEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class WhileTest {
private static Class<?> classToTest;
private static Object instanceOfClass;
@BeforeClass
@BeforeAll
public static void setUpBeforeClass() throws Exception {
var classFiles = TestCodegen.generateClassFiles(new ByteArrayClassLoader(), "While.jav");
var classFiles = TestCodegen.generateClassFiles(TestCodegen.createClassLoader(), "While.jav");
classToTest = classFiles.get("While");
instanceOfClass = classToTest.getDeclaredConstructor().newInstance();
}

View File

@@ -8,8 +8,8 @@ import de.dhbwstuttgart.typedeployment.TypeInsert;
import de.dhbwstuttgart.typedeployment.TypeInsertFactory;
import de.dhbwstuttgart.typeinference.result.ResultSet;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Disabled;
import java.io.File;
import java.io.IOException;
@@ -22,7 +22,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Ignore("To be renewed")
@Disabled("To be renewed")
public class JavaTXCompilerTest {
public static final String rootDirectory = System.getProperty("user.dir") + "/src/test/resources/javFiles/";