Compare commits
153 Commits
cc8f36d3ec
...
KPS2025
Author | SHA1 | Date | |
---|---|---|---|
|
db040d590e | ||
|
f496ff13b8 | ||
|
642ecc9a50 | ||
|
a0e59eebe8 | ||
acce38e8b1 | |||
dbd7f4fcfe | |||
9114642370 | |||
8ac0f96bd6 | |||
|
b29eb71238 | ||
|
e9ce071e2b | ||
3567bae0d7 | |||
9160c99cf2 | |||
c72a14cab3 | |||
10bb5d1d11 | |||
2842fc5069 | |||
5c5e0bd1e9 | |||
3d81318e01 | |||
53e2c20608 | |||
86e467fd82 | |||
25b14e9342 | |||
d0de0b31e4 | |||
dd180524b2 | |||
b3744bf5f7 | |||
fda16978c2 | |||
a485cd8fa6 | |||
f8c708f0f4 | |||
28d9946bbb | |||
7b4ca8f177 | |||
b879d7743d | |||
e26a43b400 | |||
5deed725ae | |||
8ae15f9d41 | |||
8c8e088612 | |||
2814c6538e | |||
dcbc29b49b | |||
05033bcb9d | |||
814f5dd5fa | |||
24ca985ccc | |||
d6ed0689bc | |||
d7676f36e3 | |||
|
9e323759d6 | ||
558083166d | |||
|
aec2f9a399 | ||
|
31df7a65f0 | ||
|
185989ba62 | ||
|
0eb48ba425 | ||
ceee9a49c4 | |||
ee64218a5f | |||
c50f14a4a3 | |||
1f4250ff84 | |||
ae41c7f19d | |||
2416c80c20 | |||
4cc55c0059 | |||
9434facfa0 | |||
09a6b9a788 | |||
8b342c5604 | |||
cdb93b5155 | |||
b07e848fa2 | |||
313cd20f36 | |||
567fcc3b9a | |||
d9936e7197 | |||
8f194b3102 | |||
1391206dfe | |||
659bf6b500 | |||
33ed22c06a | |||
70f7857661 | |||
45275b6888 | |||
2144dd9341 | |||
69c2bb3dc9 | |||
3a57d5e025 | |||
|
1e37538fde | ||
4cdd5d016c | |||
4318856fa8 | |||
1ace099d72 | |||
b76e1e46f0 | |||
09c483542d | |||
77411973be | |||
d0d9c46a67 | |||
|
24bf3d350f | ||
b9f9994de3 | |||
|
f0287c4611 | ||
|
edf609f916 | ||
|
14e2af7d2a | ||
|
158adf837a | ||
46b378e3a5 | |||
484a70c15c | |||
c461e89336 | |||
f846142ee1 | |||
443b8b0c09 | |||
ff715a22cf | |||
170955b333 | |||
88d81f4af7 | |||
bb11d24101 | |||
e2bf09548f | |||
|
c33e372446 | ||
|
7c546834c0 | ||
|
aa61f90fb1 | ||
|
b4da20e1d4 | ||
|
4d1950d0ba | ||
|
cc204f659a | ||
|
5893338783 | ||
e1e744152a | |||
|
fc22299af5 | ||
7811ecce63 | |||
44754e73ac | |||
|
6ee308a712 | ||
85d70378ca | |||
89bbbdacd8 | |||
|
fbde5afb1b | ||
6ccf2a3df6 | |||
b7979ac7e7 | |||
|
9ede47c2d6 | ||
|
406f98e55d | ||
|
a9d836ce25 | ||
|
fd8a66dd59 | ||
|
929392b7d4 | ||
|
f57c8aa5a9 | ||
|
daa38183fa | ||
eb454aa5b2 | |||
72035c48f2 | |||
54f258e333 | |||
|
114de0b236 | ||
|
8f094eb025 | ||
|
3ac3af2327 | ||
|
fbc9f1e755 | ||
|
94c359f7a1 | ||
|
3be557a32b | ||
9801f8a5ae | |||
f0b9bea23e | |||
|
96eb504174 | ||
ce4347dd96 | |||
|
4f0162ba64 | ||
|
6e1198ab3d | ||
7785c2d0aa | |||
a654f55deb | |||
|
7037bdf9ef | ||
|
d9860497df | ||
|
fdffc11580 | ||
|
c10de35ca2 | ||
|
56b73332c0 | ||
|
bdcd5ea3cf | ||
edafbbc5a0 | |||
ba8810e5df | |||
63493ed0f7 | |||
|
4dba867f9e | ||
|
06caf0ff66 | ||
ec92b5d5e1 | |||
091a6b8f1f | |||
60a1f3b220 | |||
7e6aeaf728 | |||
|
5d03995f10 | ||
|
1bc58573c7 | ||
|
3d2b935c60 |
@@ -1,5 +1,8 @@
|
||||
name: Build and Test with Maven
|
||||
on: [push]
|
||||
on:
|
||||
push:
|
||||
branches-ignore:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
Build-and-test-with-Maven:
|
||||
@@ -15,11 +18,11 @@ jobs:
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '21'
|
||||
java-version: '24'
|
||||
cache: 'maven'
|
||||
- name: Compile project
|
||||
run: |
|
||||
mvn compile
|
||||
- name: Run tests
|
||||
run: |
|
||||
mvn test
|
||||
mvn test
|
||||
|
45
.gitea/workflows/sonarqube.yml
Normal file
45
.gitea/workflows/sonarqube.yml
Normal file
@@ -0,0 +1,45 @@
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
name: SonarQube Scan
|
||||
jobs:
|
||||
sonarqube:
|
||||
name: SonarQube Trigger
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checking out
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
# Disabling shallow clone is recommended for improving relevancy of reporting
|
||||
fetch-depth: 0
|
||||
- name: Install maven
|
||||
run: |
|
||||
apt update
|
||||
apt install -y maven
|
||||
- name: Install java
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '24'
|
||||
cache: 'maven'
|
||||
- name: Compile project
|
||||
run: |
|
||||
mvn clean dependency:copy-dependencies verify
|
||||
- name: SonarQube Scan
|
||||
uses: SonarSource/sonarqube-scan-action@v5.3.0
|
||||
env:
|
||||
SONAR_HOST_URL: ${{ secrets.SONARQUBE_HOST }}
|
||||
SONAR_TOKEN: ${{ secrets.SONARQUBE_TOKEN }}
|
||||
with:
|
||||
args: >
|
||||
-Dsonar.projectKey=Java-TX
|
||||
-Dsonar.sources=src/main/java
|
||||
-Dsonar.tests=src/test/java
|
||||
-Dsonar.junit.reportPaths=target/test-reports
|
||||
-Dsonar.java.binaries=target/classes
|
||||
-Dsonar.java.libraries=target/dependency/*.jar
|
||||
-Dsonar.coverage.jacoco.xmlReportPaths=target/site/jacoco/jacoco.xml
|
7
README.md
Normal file
7
README.md
Normal file
@@ -0,0 +1,7 @@
|
||||
## Java-TX Compiler
|
||||
|
||||
[](https://gitea.hb.dhbw-stuttgart.de/sonarqube/dashboard?id=Java-TX)
|
||||
[](https://gitea.hb.dhbw-stuttgart.de/sonarqube/dashboard?id=Java-TX)
|
||||
[](https://gitea.hb.dhbw-stuttgart.de/sonarqube/dashboard?id=Java-TX)
|
||||
|
||||
Work in Progress Java-TX Compiler repository!
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@@ -2147,6 +2147,18 @@ public class Java17ParserBaseListener implements Java17ParserListener {
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitEnclosedPattern(Java17Parser.EnclosedPatternContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterLPattern(Java17Parser.LPatternContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitLPattern(Java17Parser.LPatternContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
|
@@ -1257,6 +1257,13 @@ public class Java17ParserBaseVisitor<T> extends AbstractParseTreeVisitor<T> impl
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitEnclosedPattern(Java17Parser.EnclosedPatternContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitLPattern(Java17Parser.LPatternContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
|
@@ -1960,6 +1960,18 @@ public interface Java17ParserListener extends ParseTreeListener {
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitEnclosedPattern(Java17Parser.EnclosedPatternContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code lPattern}
|
||||
* labeled alternative in {@link Java17Parser#primaryPattern}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterLPattern(Java17Parser.LPatternContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code lPattern}
|
||||
* labeled alternative in {@link Java17Parser#primaryPattern}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitLPattern(Java17Parser.LPatternContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link Java17Parser#recordPattern}.
|
||||
* @param ctx the parse tree
|
||||
|
@@ -1164,6 +1164,13 @@ public interface Java17ParserVisitor<T> extends ParseTreeVisitor<T> {
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitEnclosedPattern(Java17Parser.EnclosedPatternContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code lPattern}
|
||||
* labeled alternative in {@link Java17Parser#primaryPattern}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitLPattern(Java17Parser.LPatternContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by {@link Java17Parser#recordPattern}.
|
||||
* @param ctx the parse tree
|
||||
|
49
pom.xml
49
pom.xml
@@ -12,60 +12,79 @@ 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.11</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.6</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>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.jacoco</groupId>
|
||||
<artifactId>jacoco-maven-plugin</artifactId>
|
||||
<version>0.8.13</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>prepare-agent</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>report</id>
|
||||
<phase>prepare-package</phase>
|
||||
<goals>
|
||||
<goal>report</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.11.0</version>
|
||||
<version>3.14.0</version>
|
||||
<configuration>
|
||||
<compilerArgs>--enable-preview</compilerArgs>
|
||||
<source>21</source>
|
||||
<target>21</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>
|
||||
<argLine>--enable-preview</argLine>
|
||||
<argLine>${argLine} --enable-preview</argLine>
|
||||
<trimStackTrace>false</trimStackTrace>
|
||||
<excludes>
|
||||
<exclude>**/JavaTXCompilerTest.java</exclude>
|
||||
@@ -77,7 +96,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 +109,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>
|
||||
|
10
resources/AllgemeinTest/Bar.java
Normal file
10
resources/AllgemeinTest/Bar.java
Normal file
@@ -0,0 +1,10 @@
|
||||
public class Bar{
|
||||
|
||||
void visit(Object o){
|
||||
System.out.println("Object");
|
||||
}
|
||||
|
||||
void visit(Bla f){
|
||||
System.out.println("Foo");
|
||||
}
|
||||
}
|
@@ -1,8 +1,12 @@
|
||||
class Box<A> {
|
||||
public class Box {
|
||||
|
||||
A a;
|
||||
a;
|
||||
|
||||
public Box(A a) {
|
||||
this.a = a;
|
||||
public Box() { }
|
||||
public Box(a) {
|
||||
//this.a = a;
|
||||
}
|
||||
set(x) {
|
||||
a = x;
|
||||
}
|
||||
}
|
6
resources/AllgemeinTest/Foo.jav
Normal file
6
resources/AllgemeinTest/Foo.jav
Normal file
@@ -0,0 +1,6 @@
|
||||
public class Foo{
|
||||
|
||||
public accept(Bar b){
|
||||
b.visit(this);
|
||||
}
|
||||
}
|
9
resources/KPSPresentation/AddEle.jav
Normal file
9
resources/KPSPresentation/AddEle.jav
Normal file
@@ -0,0 +1,9 @@
|
||||
import java.util.Vector;
|
||||
import java.util.Collection;
|
||||
|
||||
class AddEle {
|
||||
addEle(x, y) {
|
||||
x.add(y);
|
||||
return x;
|
||||
}
|
||||
}
|
15
resources/KPSPresentation/Fac.jav
Normal file
15
resources/KPSPresentation/Fac.jav
Normal file
@@ -0,0 +1,15 @@
|
||||
import java.lang.Double;
|
||||
import java.lang.Integer;
|
||||
|
||||
public class Fac {
|
||||
|
||||
getFac(n){
|
||||
var res = 1;
|
||||
var i = 1;
|
||||
while(i<=n) {
|
||||
res = res * i;
|
||||
i++;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
18
resources/KPSPresentation/Faculty.jav
Normal file
18
resources/KPSPresentation/Faculty.jav
Normal file
@@ -0,0 +1,18 @@
|
||||
import java.lang.Integer;
|
||||
import java.lang.Float;
|
||||
|
||||
public class Faculty {
|
||||
public Fun1$$<Integer, Integer> fact = (x) -> {
|
||||
if (x == 1) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return x * (fact.apply(x-1));
|
||||
}
|
||||
};
|
||||
|
||||
public getFact(x) {
|
||||
return fact.apply(x);
|
||||
}
|
||||
|
||||
}
|
18
resources/KPSPresentation/FacultyBug.jav
Normal file
18
resources/KPSPresentation/FacultyBug.jav
Normal file
@@ -0,0 +1,18 @@
|
||||
import java.lang.Integer;
|
||||
import java.lang.Float;
|
||||
|
||||
public class FacultyBug {
|
||||
public Fun1$$<Float, Float> fact = (x) -> {
|
||||
if (x == 1) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return x * (fact.apply(x-1));
|
||||
}
|
||||
};
|
||||
|
||||
public getFact(x) {
|
||||
return fact.apply(x);
|
||||
}
|
||||
|
||||
}
|
11
resources/KPSPresentation/Id.jav
Normal file
11
resources/KPSPresentation/Id.jav
Normal file
@@ -0,0 +1,11 @@
|
||||
class Id {
|
||||
id2 = x -> x;
|
||||
|
||||
id(x) {
|
||||
return x;
|
||||
}
|
||||
|
||||
id3(x) {
|
||||
return id(x);
|
||||
}
|
||||
}
|
11
resources/KPSPresentation/Lambda.jav
Normal file
11
resources/KPSPresentation/Lambda.jav
Normal file
@@ -0,0 +1,11 @@
|
||||
import java.lang.Integer;
|
||||
|
||||
public class Lambda {
|
||||
|
||||
m () {
|
||||
var lam1 = (x) -> {
|
||||
return x * x;
|
||||
};
|
||||
return lam1;
|
||||
}
|
||||
}
|
105
resources/KPSPresentation/Main.jav
Normal file
105
resources/KPSPresentation/Main.jav
Normal file
@@ -0,0 +1,105 @@
|
||||
import java.lang.String ;
|
||||
import java.lang.System;
|
||||
import java.io.PrintStream;
|
||||
import java.lang.Character;
|
||||
import java.lang.Object;
|
||||
import java.lang.Integer;
|
||||
import fst;
|
||||
import Id;
|
||||
import OLMain;
|
||||
import Fac;
|
||||
import Faculty;
|
||||
import applyLambda;
|
||||
import java.util.Vector;
|
||||
import Matrix;
|
||||
|
||||
public class Main {
|
||||
public static main(x) {
|
||||
/*
|
||||
new fst().main(5);
|
||||
System.out.println(new fst().main(5));
|
||||
|
||||
//Id.jav: the identity-function
|
||||
//applied to an integer
|
||||
System.out.println(new Id().id(1));
|
||||
//applied to a string
|
||||
System.out.println(new Id().id("hallo"));
|
||||
//lamda-Expr
|
||||
//System.out.println(new Id().id2.apply(1));
|
||||
//Bug: https://gitea.hb.dhbw-stuttgart.de/JavaTX/JavaCompilerCore/issues/378
|
||||
|
||||
//OL.jav: Overloading
|
||||
OLMain ol = new OLMain();
|
||||
|
||||
//the function main is applied to an integer
|
||||
System.out.println(ol.main(2));
|
||||
//the main is applied to a double
|
||||
System.out.println(ol.main(2.0));
|
||||
System.out.println(ol.main("Hallo"));
|
||||
//Fac.jav
|
||||
System.out.println(new Fac().getFac(6));
|
||||
|
||||
|
||||
//Faculty.jav
|
||||
//System.out.println(new Faculty().fact.apply(6));
|
||||
//Bug: https://gitea.hb.dhbw-stuttgart.de/JavaTX/JavaCompilerCore/issues/378
|
||||
System.out.println(new Faculty().getFact(3));
|
||||
|
||||
//Lambda.jav: An lambda expression applied by the method apply
|
||||
//System.out.println(new Lambda().m().apply(77));
|
||||
//Bug: https://gitea.hb.dhbw-stuttgart.de/JavaTX/JavaCompilerCore/issues/378
|
||||
|
||||
//applyLambda.jav: A defined lambda expression is applied
|
||||
System.out.println(new applyLambda().m());
|
||||
*/
|
||||
Vector<Vector<Integer>> vv = new Vector<Vector<Integer>>();
|
||||
Vector<Integer> v1 = new Vector<Integer> ();
|
||||
v1.addElement(2);
|
||||
v1.addElement(2);
|
||||
Vector<Integer> v2 = new Vector<Integer> ();
|
||||
v2.addElement(3);
|
||||
v2.addElement(3);
|
||||
Matrix m1 = new Matrix();
|
||||
m1.addElement(v1);
|
||||
m1.addElement(v2);
|
||||
//vv.addElement(v1);
|
||||
//vv.addElement(v2);
|
||||
//Matrix m1 = new Matrix(vv);
|
||||
|
||||
Vector<Vector<Integer>> vv1 = new Vector<Vector<Integer>>();
|
||||
Vector<Integer> v3 = new Vector<Integer> ();
|
||||
v3.addElement(2);
|
||||
v3.addElement(2);
|
||||
Vector<Integer> v4 = new Vector<Integer> ();
|
||||
v4.addElement(3);
|
||||
v4.addElement(3);
|
||||
Matrix m2 = new Matrix();
|
||||
m2.addElement(v3);
|
||||
m2.addElement(v4);
|
||||
//vv1.addElement(v3);
|
||||
//vv1.addElement(v4);
|
||||
//Matrix m2 = new Matrix(vv1);
|
||||
|
||||
|
||||
//Matrix m3 = m1.mul(vv1);
|
||||
Matrix m3 = m1.mul(m2);
|
||||
System.out.println(m1.toString() + " * " + m2.toString() + " = " + m3.toString());
|
||||
/*
|
||||
//MatrixOP
|
||||
MatrixOP mOp1 = new MatrixOP();
|
||||
mOp1.addElement(v1);
|
||||
mOp1.addElement(v2);
|
||||
MatrixOP mOp2 = mOp1.mul.apply(mOp1, mOp1);
|
||||
System.out.println(m1.toString() + " * " + m2.toString() + " = " + mOp2.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public class MainBug {
|
||||
public static main(x) {
|
||||
System.out.println(new fst().main(5));
|
||||
//System.out.println(new FacultyBug().getFact(3));
|
||||
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
41
resources/KPSPresentation/Matrix.jav
Normal file
41
resources/KPSPresentation/Matrix.jav
Normal file
@@ -0,0 +1,41 @@
|
||||
import java.util.Vector;
|
||||
import java.lang.Integer;
|
||||
import java.lang.Boolean;
|
||||
|
||||
public class Matrix extends Vector<Vector<Integer>> {
|
||||
|
||||
|
||||
public Matrix () {
|
||||
}
|
||||
|
||||
public Matrix(vv) {
|
||||
var i = 0;
|
||||
while(i < vv.size()) {
|
||||
this.add(vv.elementAt(i));
|
||||
i=i+1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
mul(m) {
|
||||
var ret = new Matrix();
|
||||
var i = 0;
|
||||
while(i < size()) {
|
||||
var v1 = this.elementAt(i);
|
||||
var v2 = new Vector<Integer>();
|
||||
var j = 0;
|
||||
while(j < v1.size()) {
|
||||
var erg = 0;
|
||||
var k = 0;
|
||||
while(k < v1.size()) {
|
||||
erg = erg + v1.elementAt(k)
|
||||
* m.elementAt(k).elementAt(j);
|
||||
k++; }
|
||||
v2.addElement(erg);
|
||||
j++; }
|
||||
ret.addElement(v2);
|
||||
i++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
42
resources/KPSPresentation/MatrixOP.jav
Normal file
42
resources/KPSPresentation/MatrixOP.jav
Normal file
@@ -0,0 +1,42 @@
|
||||
import java.util.Vector;
|
||||
import java.lang.Integer;
|
||||
import java.lang.Byte;
|
||||
import java.lang.Boolean;
|
||||
|
||||
public class MatrixOP extends Vector<Vector<Integer>> {
|
||||
|
||||
MatrixOP () {
|
||||
}
|
||||
|
||||
MatrixOP(vv) {
|
||||
Integer i;
|
||||
i = 0;
|
||||
while(i < vv.size()) {
|
||||
this.add(vv.elementAt(i));
|
||||
i=i+1;
|
||||
}
|
||||
}
|
||||
|
||||
Fun2$$<Vector<? extends Vector<? extends Integer>>, Vector<? extends Vector<? extends Integer>>, MatrixOP> mul = (m1, m2) -> {
|
||||
var ret = new MatrixOP();
|
||||
var i = 0;
|
||||
while(i < m1.size()) {
|
||||
var v1 = m1.elementAt(i);
|
||||
var v2 = new Vector<Integer>();
|
||||
var j = 0;
|
||||
while(j < v1.size()) {
|
||||
var erg = 0;
|
||||
var k = 0;
|
||||
while(k < v1.size()) {
|
||||
erg = erg + v1.elementAt(k)
|
||||
* m2.elementAt(k).elementAt(j);
|
||||
k++; }
|
||||
// v2.addElement(new Integer(erg));
|
||||
v2.addElement(erg);
|
||||
j++; }
|
||||
ret.addElement(v2);
|
||||
i++;
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
}
|
30
resources/KPSPresentation/OL.jav
Normal file
30
resources/KPSPresentation/OL.jav
Normal file
@@ -0,0 +1,30 @@
|
||||
import java.lang.String;
|
||||
import java.lang.Integer;
|
||||
import java.lang.Double;
|
||||
import java.lang.Boolean;
|
||||
import java.lang.Object;
|
||||
|
||||
|
||||
|
||||
|
||||
class OL {
|
||||
|
||||
m(x) { return x + x; }
|
||||
|
||||
|
||||
m(x) { return x || x; }
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
class OLMain {
|
||||
|
||||
main(x) {
|
||||
var ol;
|
||||
ol = new OL();
|
||||
return ol.m(x);
|
||||
}
|
||||
}
|
||||
|
20
resources/KPSPresentation/OLFun.jav
Normal file
20
resources/KPSPresentation/OLFun.jav
Normal file
@@ -0,0 +1,20 @@
|
||||
import java.lang.String;
|
||||
import java.lang.Integer;
|
||||
import java.lang.Double;
|
||||
import java.util.Vector;
|
||||
import java.lang.Boolean;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public class OLFun {
|
||||
x;
|
||||
|
||||
|
||||
m(f, y) {
|
||||
y = f.apply(x+x);
|
||||
return x;
|
||||
}
|
||||
|
||||
}
|
12
resources/KPSPresentation/Pair.jav
Normal file
12
resources/KPSPresentation/Pair.jav
Normal file
@@ -0,0 +1,12 @@
|
||||
class Pair {
|
||||
fst;
|
||||
snd;
|
||||
|
||||
Pair(fst, snd) { this.fst=fst; this.snd=snd; }
|
||||
|
||||
getfst() { return this.fst; }
|
||||
|
||||
swap() {
|
||||
return new Pair<>(this.snd, this.fst);
|
||||
}
|
||||
}
|
9
resources/KPSPresentation/Plus.jav
Normal file
9
resources/KPSPresentation/Plus.jav
Normal file
@@ -0,0 +1,9 @@
|
||||
import java.lang.Integer;
|
||||
import java.lang.String;
|
||||
|
||||
public class Plus {
|
||||
|
||||
m(a, b) {
|
||||
return a+b;
|
||||
}
|
||||
}
|
25
resources/KPSPresentation/Sorting.jav
Normal file
25
resources/KPSPresentation/Sorting.jav
Normal file
@@ -0,0 +1,25 @@
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.lang.String;
|
||||
|
||||
public class Sorting{
|
||||
merge(a, b){
|
||||
a.addAll(b);
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
sort(in){
|
||||
var firstHalf = in;
|
||||
var secondHalf = in;
|
||||
return merge(sort(firstHalf), sort(secondHalf));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
void sort(a){
|
||||
a = merge(a,a);
|
||||
}
|
||||
*/
|
||||
}
|
20
resources/KPSPresentation/Swap.jav
Normal file
20
resources/KPSPresentation/Swap.jav
Normal file
@@ -0,0 +1,20 @@
|
||||
import java.lang.String;
|
||||
import java.lang.Object;
|
||||
import java.lang.System;
|
||||
import java.io.PrintStream;
|
||||
import java.lang.Character;
|
||||
|
||||
public class Swap{
|
||||
<ZDP, ZEA, ZDO, YZP, ZCY, ZDZ> Fun1$$<ZCY, Fun1$$<ZDZ, ZEA>> swap(f){
|
||||
return x->y->f.apply(y).apply(x);
|
||||
}
|
||||
|
||||
Fun1$$<String, Fun1$$<String, Fun1$$<String, String>>> swap(f){
|
||||
return x -> y -> z -> f.apply(z).apply(x).apply(y);
|
||||
}
|
||||
|
||||
public static main (y) {
|
||||
var func = x -> y -> z -> x + y + z;
|
||||
var res = new Swap().swap(func).apply("A").apply("B").apply("C");
|
||||
System.out.println(res);}
|
||||
}
|
6
resources/KPSPresentation/TPHMethod.jav
Normal file
6
resources/KPSPresentation/TPHMethod.jav
Normal file
@@ -0,0 +1,6 @@
|
||||
class TPHMethod {
|
||||
void m(a, b) {
|
||||
a = b;
|
||||
b=a;
|
||||
}
|
||||
}
|
16
resources/KPSPresentation/Test.jav
Normal file
16
resources/KPSPresentation/Test.jav
Normal file
@@ -0,0 +1,16 @@
|
||||
class Test{
|
||||
void m( op, a, b ){
|
||||
op.myapply(a, b);
|
||||
}
|
||||
}
|
||||
|
||||
class Atype{}
|
||||
class Btype{}
|
||||
|
||||
class Operator1{
|
||||
void myapply(Atype p1, Atype p2){...}
|
||||
}
|
||||
|
||||
class Operator2{
|
||||
void myapply(Btype p1, Btype p2){...}
|
||||
}
|
7
resources/KPSPresentation/Uncurrier.jav
Normal file
7
resources/KPSPresentation/Uncurrier.jav
Normal file
@@ -0,0 +1,7 @@
|
||||
public class Uncurrier{
|
||||
uncurry (f){
|
||||
return x -> f.apply(x);}
|
||||
uncurry (f){
|
||||
return (x, y) -> f.apply(x).apply(y);
|
||||
}
|
||||
}
|
7
resources/KPSPresentation/UncurrierMain.jav
Normal file
7
resources/KPSPresentation/UncurrierMain.jav
Normal file
@@ -0,0 +1,7 @@
|
||||
import Uncurrier;
|
||||
|
||||
class UncurrierMain {
|
||||
public static main(x) {
|
||||
var uc = new Uncurrier() ;
|
||||
}
|
||||
}
|
16
resources/KPSPresentation/VectorAdd.jav
Normal file
16
resources/KPSPresentation/VectorAdd.jav
Normal file
@@ -0,0 +1,16 @@
|
||||
import java.lang.Integer;
|
||||
import java.lang.String;
|
||||
import java.util.Vector;
|
||||
|
||||
class VectorAdd {
|
||||
vectorAdd(v1, v2) {
|
||||
var i = 0;
|
||||
var erg = new Vector<>();
|
||||
while (i < v1.size()) {
|
||||
erg.addElement(v1.elementAt(i) + v2.elementAt(i));
|
||||
i++;
|
||||
}
|
||||
return erg;
|
||||
}
|
||||
}
|
||||
|
16
resources/KPSPresentation/applyLambda.jav
Normal file
16
resources/KPSPresentation/applyLambda.jav
Normal file
@@ -0,0 +1,16 @@
|
||||
import java.util.Vector;
|
||||
class Apply { }
|
||||
|
||||
public class applyLambda {
|
||||
|
||||
public m () {
|
||||
var lam1 = (x) -> {
|
||||
return x;
|
||||
};
|
||||
|
||||
return lam1.apply(new Apply());
|
||||
//return lam1;
|
||||
//return new Vector();
|
||||
}
|
||||
}
|
||||
|
7
resources/KPSPresentation/fst.jav
Normal file
7
resources/KPSPresentation/fst.jav
Normal file
@@ -0,0 +1,7 @@
|
||||
//import java.lang.Integer;
|
||||
|
||||
class fst {
|
||||
main(x) {
|
||||
return x;
|
||||
}
|
||||
}
|
8
resources/KPSPresentation/genVector.jav
Normal file
8
resources/KPSPresentation/genVector.jav
Normal file
@@ -0,0 +1,8 @@
|
||||
import java.util.Vector;
|
||||
|
||||
class genVector {
|
||||
|
||||
m(v) {
|
||||
return v.elementAt(0);
|
||||
}
|
||||
}
|
8
resources/KPSPresentation/idTest.jav
Normal file
8
resources/KPSPresentation/idTest.jav
Normal file
@@ -0,0 +1,8 @@
|
||||
import java.lang.Integer;
|
||||
import Id;
|
||||
|
||||
class Test {
|
||||
m() {
|
||||
Integer o1 = new Id<Integer,Integer>().id2.apply(1);
|
||||
}
|
||||
}
|
9
resources/KPSPresentation/lambdaId.jav
Normal file
9
resources/KPSPresentation/lambdaId.jav
Normal file
@@ -0,0 +1,9 @@
|
||||
public class lambdaId {
|
||||
lambdaId = x -> x;
|
||||
|
||||
/*
|
||||
id3 (x) {
|
||||
return lambdaId.apply(x);
|
||||
}
|
||||
*/
|
||||
}
|
9
resources/KPSPresentation/mathStruc.jav
Normal file
9
resources/KPSPresentation/mathStruc.jav
Normal file
@@ -0,0 +1,9 @@
|
||||
class mathStruc {
|
||||
model;
|
||||
|
||||
innerOp = (o) -> (ms) -> new mathStruc<>(o.apply(model,ms.model));
|
||||
|
||||
mathStruc(m) {
|
||||
model =m;
|
||||
}
|
||||
}
|
18
resources/KPSPresentation/mathStrucInteger.jav
Normal file
18
resources/KPSPresentation/mathStrucInteger.jav
Normal file
@@ -0,0 +1,18 @@
|
||||
import java.lang.Integer;
|
||||
|
||||
class mathStruc {
|
||||
model;
|
||||
|
||||
innerOp = (o) -> (ms) -> new mathStruc<>(o.apply(model,ms.model));
|
||||
|
||||
mathStruc(m) {
|
||||
model =m;
|
||||
}
|
||||
}
|
||||
|
||||
class mathStrucIntegerUse {
|
||||
main() {
|
||||
var ms = new mathStruc<>(2);
|
||||
return ms.innerOp.apply((x,y) -> x+y).apply(ms);
|
||||
}
|
||||
}
|
90
resources/KPSPresentation/mathStrucMatrixOP.jav
Normal file
90
resources/KPSPresentation/mathStrucMatrixOP.jav
Normal file
@@ -0,0 +1,90 @@
|
||||
import java.util.Vector;
|
||||
import java.lang.Integer;
|
||||
import java.lang.Boolean;
|
||||
|
||||
public class mathStrucMatrixOP {
|
||||
model;
|
||||
|
||||
innerOp = (o) -> (ms) -> new mathStrucMatrixOP<>(o.apply(model,ms.model));
|
||||
|
||||
public mathStrucMatrixOP(m) {
|
||||
model =m;
|
||||
}
|
||||
}
|
||||
|
||||
public class MatrixOP extends Vector<Vector<Integer>> {
|
||||
|
||||
MatrixOP () {
|
||||
}
|
||||
|
||||
MatrixOP(vv) {
|
||||
Integer i;
|
||||
i = 0;
|
||||
while(i < vv.size()) {
|
||||
// Boolean a = this.add(vv.elementAt(i));
|
||||
this.add(vv.elementAt(i));
|
||||
i=i+1;
|
||||
}
|
||||
}
|
||||
|
||||
public mul = (m1, m2) -> {
|
||||
var ret = new MatrixOP();
|
||||
var i = 0;
|
||||
while(i < m1.size()) {
|
||||
var v1 = m1.elementAt(i);
|
||||
var v2 = new Vector<Integer>();
|
||||
var j = 0;
|
||||
while(j < v1.size()) {
|
||||
var erg = 0;
|
||||
var k = 0;
|
||||
while(k < v1.size()) {
|
||||
erg = erg + v1.elementAt(k)
|
||||
* m2.elementAt(k).elementAt(j);
|
||||
k++; }
|
||||
// v2.addElement(new Integer(erg));
|
||||
v2.addElement(erg);
|
||||
j++; }
|
||||
ret.addElement(v2);
|
||||
i++;
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
class mathStrucUseMatrixOP {
|
||||
|
||||
main() {
|
||||
Vector<Vector<Integer>> vv = new Vector<Vector<Integer>>();
|
||||
Vector<Integer> v1 = new Vector<Integer>();
|
||||
v1.addElement(2);
|
||||
v1.addElement(2);
|
||||
Vector<Integer> v2 = new Vector<Integer>();
|
||||
v2.addElement(3);
|
||||
v2.addElement(3);
|
||||
vv.addElement(v1);
|
||||
vv.addElement(v2);
|
||||
|
||||
MatrixOP m1 = new MatrixOP(vv);
|
||||
|
||||
Vector<Vector<Integer>> vv1 = new Vector<Vector<Integer>>();
|
||||
Vector<Integer> v3 = new Vector<Integer>();
|
||||
v3.addElement(2);
|
||||
v3.addElement(2);
|
||||
Vector<Integer> v4 = new Vector<Integer>();
|
||||
v4.addElement(3);
|
||||
v4.addElement(3);
|
||||
vv1.addElement(v3);
|
||||
vv1.addElement(v4);
|
||||
|
||||
MatrixOP m2 = new MatrixOP(vv1);
|
||||
|
||||
var mms;
|
||||
mms = new mathStrucMatrixOP<>(m1);
|
||||
var mms2;
|
||||
mms2 = new mathStrucMatrixOP<>(m2);
|
||||
var mms3;
|
||||
mms3 = mms.innerOp.apply(m1.mul).apply(mms2);
|
||||
return mms3;
|
||||
}
|
||||
}
|
14
resources/KPSPresentation/test1.jav
Normal file
14
resources/KPSPresentation/test1.jav
Normal file
@@ -0,0 +1,14 @@
|
||||
import java.lang.String;
|
||||
import java.lang.Boolean;
|
||||
import java.lang.Integer;
|
||||
import java.io.Serializable;
|
||||
|
||||
public class testclass{
|
||||
|
||||
public testMethod(ele){
|
||||
if(ele){
|
||||
return 1;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
15
resources/bytecode/javFiles/Assign.jav
Normal file
15
resources/bytecode/javFiles/Assign.jav
Normal file
@@ -0,0 +1,15 @@
|
||||
import java.lang.Integer;
|
||||
|
||||
public class Assign {
|
||||
public x = 10;
|
||||
public y = this;
|
||||
|
||||
public call() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public m() {
|
||||
this.call().call().y.x = 20;
|
||||
return x;
|
||||
}
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
class Box<A> {
|
||||
void m(A a) { }
|
||||
}
|
@@ -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();
|
||||
}
|
||||
|
15
resources/bytecode/javFiles/Bug332.jav
Normal file
15
resources/bytecode/javFiles/Bug332.jav
Normal file
@@ -0,0 +1,15 @@
|
||||
import java.lang.Object;
|
||||
|
||||
interface Visitor {
|
||||
public void visit(Object obj);
|
||||
public void visit(ClassA a);
|
||||
}
|
||||
|
||||
class ClassA {
|
||||
void accept(Visitor v) {
|
||||
v.visit(this);
|
||||
}
|
||||
}
|
||||
|
||||
public class Bug332 {
|
||||
}
|
10
resources/bytecode/javFiles/Bug337.jav
Normal file
10
resources/bytecode/javFiles/Bug337.jav
Normal file
@@ -0,0 +1,10 @@
|
||||
import java.lang.Integer;
|
||||
import java.lang.Number;
|
||||
import java.lang.Object;
|
||||
|
||||
public class Bug337 {
|
||||
public void main() {
|
||||
Fun1$$<Object, Integer> fun1 = x -> x.hashCode() + 1;
|
||||
Fun1$$<Number, Number> fun2 = fun1;
|
||||
}
|
||||
}
|
2
resources/bytecode/javFiles/Bug343.jav
Normal file
2
resources/bytecode/javFiles/Bug343.jav
Normal file
@@ -0,0 +1,2 @@
|
||||
public record Bug343() {
|
||||
}
|
22
resources/bytecode/javFiles/Bug363.jav
Normal file
22
resources/bytecode/javFiles/Bug363.jav
Normal 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
|
||||
}
|
||||
}
|
8
resources/bytecode/javFiles/Bug364.jav
Normal file
8
resources/bytecode/javFiles/Bug364.jav
Normal 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");
|
||||
}
|
||||
}
|
21
resources/bytecode/javFiles/Bug365.jav
Normal file
21
resources/bytecode/javFiles/Bug365.jav
Normal 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");
|
||||
}
|
||||
}
|
12
resources/bytecode/javFiles/Bug366.jav
Normal file
12
resources/bytecode/javFiles/Bug366.jav
Normal 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);
|
||||
}
|
||||
}
|
10
resources/bytecode/javFiles/Bug371.jav
Normal file
10
resources/bytecode/javFiles/Bug371.jav
Normal 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);
|
||||
}
|
||||
}
|
17
resources/bytecode/javFiles/Bug373.jav
Normal file
17
resources/bytecode/javFiles/Bug373.jav
Normal 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');
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
1
resources/bytecode/javFiles/GenericRecord.jav
Normal file
1
resources/bytecode/javFiles/GenericRecord.jav
Normal file
@@ -0,0 +1 @@
|
||||
public record GenericRecord<T>(T a) {}
|
24
resources/bytecode/javFiles/GenericRecordSwitchCase.jav
Normal file
24
resources/bytecode/javFiles/GenericRecordSwitchCase.jav
Normal file
@@ -0,0 +1,24 @@
|
||||
import java.lang.String;
|
||||
import java.lang.Integer;
|
||||
|
||||
sealed interface List permits LinkedElem, Elem {}
|
||||
|
||||
|
||||
public record LinkedElem<T>(T a,List l) implements List{}
|
||||
public record Elem<T>(T c) implements List{}
|
||||
|
||||
public class GenericRecordSwitchCase {
|
||||
public main(o) {
|
||||
return switch(o) {
|
||||
case LinkedElem(a, Elem(e)) -> a ;
|
||||
case LinkedElem(a, LinkedElem(e, Elem(f))) -> a;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -1,16 +0,0 @@
|
||||
import java.lang.Runnable;
|
||||
import java.lang.System;
|
||||
import java.lang.String;
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class LamRunnable {
|
||||
|
||||
public LamRunnable() {
|
||||
Runnable lam = () -> {
|
||||
System.out.println("lambda");
|
||||
};
|
||||
|
||||
lam.run();
|
||||
}
|
||||
}
|
||||
|
14
resources/bytecode/javFiles/Main.jav
Normal file
14
resources/bytecode/javFiles/Main.jav
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
@@ -2,9 +2,10 @@ import java.util.Vector;
|
||||
import java.lang.Integer;
|
||||
//import java.lang.Byte;
|
||||
import java.lang.Boolean;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public class MatrixOP extends Vector<Vector<Integer>> {
|
||||
|
||||
|
||||
MatrixOP () {
|
||||
}
|
||||
|
||||
@@ -36,8 +37,8 @@ public class MatrixOP extends Vector<Vector<Integer>> {
|
||||
v2.addElement(erg);
|
||||
j++; }
|
||||
ret.addElement(v2);
|
||||
i++;
|
||||
i++;
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
}
|
20
resources/bytecode/javFiles/OverloadNestedPattern.jav
Normal file
20
resources/bytecode/javFiles/OverloadNestedPattern.jav
Normal file
@@ -0,0 +1,20 @@
|
||||
import java.lang.Object;
|
||||
import java.lang.Integer;
|
||||
import java.lang.Float;
|
||||
|
||||
public record R(Object nested) {}
|
||||
|
||||
public class OverloadNestedPattern {
|
||||
|
||||
public Integer m(R(R(Integer a)), R(Integer b)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public Integer m(R(R(Float a)), R(Float b)) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
public Integer m(R(Integer a), R(Integer b)) {
|
||||
return 3;
|
||||
}
|
||||
}
|
@@ -2,15 +2,31 @@ import java.lang.Integer;
|
||||
import java.lang.Number;
|
||||
import java.lang.Float;
|
||||
|
||||
record Point(Number x, Number y) {}
|
||||
public record Point(Number x, Number y) {}
|
||||
|
||||
public class OverloadPattern {
|
||||
public m(Point(Integer x, Integer y)) {
|
||||
return x + y;
|
||||
public Number m(Point(Integer x, Integer y), Point(Float a, Float b)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public m(Point(Float x, Float y)) {
|
||||
return x * y;
|
||||
public Number m(Point(Integer x, Integer y), Point(Integer a, Integer b)) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
public Number m(Point(Float x, Float y), Point(Integer a, Integer b)) {
|
||||
return 3;
|
||||
}
|
||||
|
||||
public Number m(Point(Float x, Float y), Point(Float a, Float b)) {
|
||||
return 4;
|
||||
}
|
||||
|
||||
public Number m(Point(Integer x, Integer y)) {
|
||||
return 5;
|
||||
}
|
||||
|
||||
public Number m(Point(Float x, Float y)) {
|
||||
return 6;
|
||||
}
|
||||
|
||||
public m(Integer x) {
|
||||
|
21
resources/bytecode/javFiles/PatternMatchingHaskellStyle.jav
Normal file
21
resources/bytecode/javFiles/PatternMatchingHaskellStyle.jav
Normal file
@@ -0,0 +1,21 @@
|
||||
import java.lang.Boolean;
|
||||
|
||||
sealed interface List<T> permits LinkedElem, Elem {}
|
||||
|
||||
public record LinkedElem<T>(T a, List<T> l) implements List<T> {}
|
||||
public record Elem<T>(T a) implements List<T> {}
|
||||
|
||||
public class PatternMatchingHaskellStyle {
|
||||
|
||||
public append(LinkedElem(a, b), list2) {
|
||||
return handleAppend(a, b, list2);
|
||||
}
|
||||
|
||||
private handleAppend(a, Elem(e), list2) {
|
||||
return new LinkedElem<>(a, new LinkedElem<>(e, list2));
|
||||
}
|
||||
|
||||
private handleAppend(a, LinkedElem(e,r), list2) {
|
||||
return new LinkedElem<>(a, append(new LinkedElem(e, r), list2));
|
||||
}
|
||||
}
|
26
resources/bytecode/javFiles/PatternMatchingListAppend.jav
Normal file
26
resources/bytecode/javFiles/PatternMatchingListAppend.jav
Normal file
@@ -0,0 +1,26 @@
|
||||
import java.lang.Boolean;
|
||||
import java.lang.Object;
|
||||
|
||||
sealed interface List<T> permits Cons, Empty {}
|
||||
|
||||
public record Cons<T>(T a, List<T> l) implements List<T> {}
|
||||
public record Empty<T>() implements List<T> {}
|
||||
|
||||
public class PatternMatchingListAppend {
|
||||
|
||||
public append(Cons(a, b), list2) {
|
||||
return new Cons<>(a, append(b, list2));
|
||||
}
|
||||
|
||||
public append(Empty(), list2) {
|
||||
return list2;
|
||||
}
|
||||
|
||||
/*public append(a, list2) {
|
||||
switch(a) {
|
||||
case Cons(x, y) -> ...
|
||||
case Empty() ->
|
||||
}
|
||||
}*/
|
||||
|
||||
}
|
17
resources/bytecode/javFiles/PatternMatchingLiteralStyle.jav
Normal file
17
resources/bytecode/javFiles/PatternMatchingLiteralStyle.jav
Normal file
@@ -0,0 +1,17 @@
|
||||
import java.lang.Integer;
|
||||
import java.lang.Double;
|
||||
import java.lang.Number;
|
||||
import java.lang.String;
|
||||
|
||||
public record R(Number n) {}
|
||||
|
||||
public class SwitchOverload {
|
||||
|
||||
public f(){}
|
||||
|
||||
public m(r) {
|
||||
return switch(r) {
|
||||
case R("test") -> f();
|
||||
};
|
||||
}
|
||||
}
|
@@ -11,7 +11,7 @@ public class Switch {
|
||||
case Rec(Integer a, Float b) -> a + 10;
|
||||
case Rec(Integer a, Rec(Integer b, Integer c)) -> a + b + c;
|
||||
case Integer i -> i;
|
||||
default -> 0;
|
||||
//default -> 0;
|
||||
};
|
||||
}
|
||||
}
|
16
resources/bytecode/javFiles/SwitchAppend.jav
Normal file
16
resources/bytecode/javFiles/SwitchAppend.jav
Normal file
@@ -0,0 +1,16 @@
|
||||
sealed interface List<T> permits LinkedElem, Elem {}
|
||||
|
||||
public record LinkedElem<T>(T a, List<T> l) implements List<T> {}
|
||||
public record Elem<T>(T a) implements List<T> {}
|
||||
|
||||
public class SwitchAppend {
|
||||
public append(l1, l2) {
|
||||
return switch(l1) {
|
||||
case LinkedElem(a, Elem(e)) -> new LinkedElem<>(a, new LinkedElem<>(e, l2));
|
||||
case LinkedElem(a, r) -> new LinkedElem<>(a, append(r, l2));
|
||||
//Alternativ:
|
||||
//case LinkedElem(a, LinkedElem(e, r)) -> new LinkedElem<>(a, append(new LinkedElem(e, r), l2));
|
||||
//default -> null;
|
||||
};
|
||||
}
|
||||
}
|
22
resources/bytecode/javFiles/SwitchCaseHeritageDetection.jav
Normal file
22
resources/bytecode/javFiles/SwitchCaseHeritageDetection.jav
Normal file
@@ -0,0 +1,22 @@
|
||||
import java.lang.Integer;
|
||||
import java.lang.Object;
|
||||
import java.lang.Float;
|
||||
import java.lang.String;
|
||||
|
||||
public class NumberOrText{}
|
||||
public class Text extends NumberOrText{};
|
||||
public class Number extends NumberOrText{};
|
||||
|
||||
|
||||
public record Cons(Integer a, NumberOrText l){}
|
||||
|
||||
|
||||
public class SwitchCaseHeritageDetection {
|
||||
public main(o) {
|
||||
return switch(o) {
|
||||
case Cons(a, Text b) -> "Second Element is a Text";
|
||||
case Cons(a, Number b) -> "Second Element is a Number";
|
||||
default -> "None of the above cases";
|
||||
};
|
||||
}
|
||||
}
|
@@ -3,15 +3,15 @@ import java.lang.Object;
|
||||
import java.lang.Float;
|
||||
import java.lang.String;
|
||||
|
||||
public record Rec(Object a, Object b) {}
|
||||
public record Rec(Object a, Object b) {}
|
||||
|
||||
|
||||
|
||||
public class SwitchInfered {
|
||||
public main(o) {
|
||||
return switch (o) {
|
||||
case Rec(a, b) -> a;
|
||||
default -> 0;
|
||||
case Rec(a, b) -> "asd";
|
||||
default -> "cde";
|
||||
};
|
||||
}
|
||||
}
|
14
resources/bytecode/javFiles/SwitchNestedValue.jav
Normal file
14
resources/bytecode/javFiles/SwitchNestedValue.jav
Normal file
@@ -0,0 +1,14 @@
|
||||
import java.lang.Object;
|
||||
import java.lang.Integer;
|
||||
|
||||
public record R(Integer i) {}
|
||||
|
||||
public class SwitchNestedValue {
|
||||
public main(r) {
|
||||
return switch(r) {
|
||||
case R(10) -> 1;
|
||||
case R(20) -> 2;
|
||||
case R(i) -> 3;
|
||||
};
|
||||
}
|
||||
}
|
21
resources/bytecode/javFiles/SwitchOverload.jav
Normal file
21
resources/bytecode/javFiles/SwitchOverload.jav
Normal file
@@ -0,0 +1,21 @@
|
||||
import java.lang.Integer;
|
||||
import java.lang.Double;
|
||||
import java.lang.Number;
|
||||
|
||||
public record R(Number n) {}
|
||||
|
||||
public class SwitchOverload {
|
||||
|
||||
Number f(Double d) { return d * 2; }
|
||||
Number f(Integer i) { return i * 5; }
|
||||
|
||||
public m(r, x) {
|
||||
x = x + x;
|
||||
return switch(r) {
|
||||
case R(o) -> {
|
||||
x = x + x;
|
||||
yield f(o);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
27
resources/bytecode/javFiles/SwitchRecordList.jav
Normal file
27
resources/bytecode/javFiles/SwitchRecordList.jav
Normal file
@@ -0,0 +1,27 @@
|
||||
import java.lang.Integer;
|
||||
import java.lang.Object;
|
||||
import java.lang.Float;
|
||||
import java.lang.String;
|
||||
|
||||
sealed interface List permits LinkedElem, Elem {}
|
||||
|
||||
|
||||
public record LinkedElem(Integer a,List l) implements List{} //Implementiert List und wird auch permittet
|
||||
public record Elem(Integer c) implements List{} //Implementiert List, wird aber nicht permittet
|
||||
|
||||
public class SwitchCaseHeritageDetection {
|
||||
public main(o) {
|
||||
return switch(o) {
|
||||
case LinkedElem(a, Elem(e)) -> a + e;
|
||||
case LinkedElem(a, LinkedElem(e, Elem(f))) -> a + e + f;
|
||||
default -> 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -2,41 +2,21 @@ import java.lang.Integer;
|
||||
|
||||
public class Y {
|
||||
y;
|
||||
//factorial;
|
||||
|
||||
public Y() {
|
||||
y = f -> t -> f.apply(y.apply(f)).apply(t);
|
||||
//factorial = y.apply(f -> n -> { if (n == 0) return 1; else return n * f.apply(n - 1); });
|
||||
}
|
||||
/*
|
||||
getY() {
|
||||
return y;
|
||||
}
|
||||
*/
|
||||
}
|
||||
/*
|
||||
class fac1 {
|
||||
factorial;
|
||||
|
||||
fac1() {
|
||||
var y;
|
||||
y = new Y<Integer,Integer,Integer,Integer,Integer>().getY();
|
||||
factorial = y.apply(f -> n -> { if (n == 0) return 1; else return n * f.apply(n - 1); });
|
||||
y = f -> t -> f.apply(y.apply(f)).apply(t);
|
||||
}
|
||||
}
|
||||
|
||||
ergibt Parse-Error
|
||||
class fac1 {
|
||||
factorial;
|
||||
|
||||
fac1() {
|
||||
public class Fac1 {
|
||||
public factorial;
|
||||
public Fac1() {
|
||||
var y;
|
||||
y = new Y<>().y;
|
||||
var tmp = new Y<>(); // TODO Having new Y<>().y on one line doesn't work, see FIXME in StatementGenerator
|
||||
y = tmp.y;
|
||||
factorial = y.apply(f -> n -> { if (n == 0) return 1; else return n * f.apply(n - 1); });
|
||||
}
|
||||
public static void main(String args[]) {
|
||||
System.out.println(new fac1().factorial.apply(3));
|
||||
|
||||
public fac(v) {
|
||||
return factorial.apply(v);
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
||||
}
|
@@ -1,15 +0,0 @@
|
||||
sealed interface List<A> permits Cons, Nil {}
|
||||
|
||||
record Cons(A a, List<A> l) implements List<A> {}
|
||||
|
||||
record Nil()implements List<A> {
|
||||
|
||||
void m(x) {
|
||||
switch(x) {
|
||||
case Cons(a, Cons(b, List<A> l)) -> System.out.println(a);
|
||||
case Cons(a, Nil()) -> System.out.println(a);
|
||||
case Nil() -> System.out.println("Nil");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -654,6 +654,7 @@ primaryPattern
|
||||
: typePattern #tPattern
|
||||
| recordPattern #rPattern
|
||||
| '(' pattern ')' #enclosedPattern
|
||||
| literal (',' literal)* #lPattern
|
||||
;
|
||||
|
||||
recordPattern
|
||||
|
@@ -2,12 +2,9 @@ package de.dhbwstuttgart.bytecode;
|
||||
|
||||
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
||||
import de.dhbwstuttgart.parser.NullToken;
|
||||
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefType;
|
||||
import de.dhbwstuttgart.target.generate.ASTToTargetAST;
|
||||
import de.dhbwstuttgart.target.generate.StatementToTargetExpression;
|
||||
import de.dhbwstuttgart.target.tree.*;
|
||||
import de.dhbwstuttgart.target.tree.expression.*;
|
||||
import de.dhbwstuttgart.target.tree.type.*;
|
||||
@@ -16,7 +13,7 @@ import org.objectweb.asm.*;
|
||||
import java.lang.invoke.*;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.*;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.objectweb.asm.Opcodes.*;
|
||||
import static de.dhbwstuttgart.target.tree.expression.TargetBinaryOp.*;
|
||||
@@ -31,15 +28,21 @@ public class Codegen {
|
||||
private final JavaTXCompiler compiler;
|
||||
private final ASTToTargetAST converter;
|
||||
|
||||
private class CustomClassWriter extends ClassWriter {
|
||||
public CustomClassWriter() {
|
||||
super(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ClassLoader getClassLoader() {
|
||||
return compiler.getClassLoader();
|
||||
}
|
||||
}
|
||||
|
||||
public Codegen(TargetStructure clazz, JavaTXCompiler compiler, ASTToTargetAST converter) {
|
||||
this.clazz = clazz;
|
||||
this.className = clazz.qualifiedName().getClassName();
|
||||
this.cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS) {
|
||||
@Override
|
||||
protected ClassLoader getClassLoader() {
|
||||
return compiler.getClassLoader();
|
||||
}
|
||||
};
|
||||
this.cw = new CustomClassWriter();
|
||||
this.compiler = compiler;
|
||||
this.converter = converter;
|
||||
}
|
||||
@@ -82,16 +85,16 @@ public class Codegen {
|
||||
int localCounter;
|
||||
MethodVisitor mv;
|
||||
TargetType returnType;
|
||||
// This is used to remember the type from lambda expressions
|
||||
TargetType contextType;
|
||||
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() {
|
||||
@@ -102,6 +105,10 @@ public class Codegen {
|
||||
this.scope = this.scope.parent;
|
||||
}
|
||||
|
||||
LocalVar createVariable(TargetType type) {
|
||||
return createVariable("__var" + this.localCounter, type);
|
||||
}
|
||||
|
||||
LocalVar createVariable(String name, TargetType type) {
|
||||
var local = new LocalVar(localCounter, name, type);
|
||||
scope.add(local);
|
||||
@@ -125,6 +132,7 @@ public class Codegen {
|
||||
}
|
||||
|
||||
private void boxPrimitive(State state, TargetType type) {
|
||||
if (type instanceof TargetExtendsWildcard ew) type = ew.innerType();
|
||||
var mv = state.mv;
|
||||
if (type.equals(TargetType.Boolean) || type.equals(TargetType.boolean_)) {
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false);
|
||||
@@ -146,6 +154,7 @@ public class Codegen {
|
||||
}
|
||||
|
||||
private void unboxPrimitive(State state, TargetType type) {
|
||||
if (type instanceof TargetExtendsWildcard ew) type = ew.innerType();
|
||||
var mv = state.mv;
|
||||
if (type.equals(TargetType.Boolean)) {
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false);
|
||||
@@ -221,13 +230,16 @@ public class Codegen {
|
||||
}
|
||||
|
||||
private void convertTo(State state, TargetType source, TargetType dest) {
|
||||
if (source instanceof TargetExtendsWildcard ew) source = ew.innerType();
|
||||
if (dest instanceof TargetExtendsWildcard ew) dest = ew.innerType();
|
||||
|
||||
var mv = state.mv;
|
||||
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);
|
||||
@@ -270,13 +282,45 @@ 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);
|
||||
} else if (!(dest instanceof TargetGenericType)) {
|
||||
boxPrimitive(state, source);
|
||||
//boxPrimitive(state, source);
|
||||
mv.visitTypeInsn(CHECKCAST, dest.getInternalName());
|
||||
unboxPrimitive(state, dest);
|
||||
}
|
||||
}
|
||||
|
||||
record TypePair(TargetType from, TargetType to) {}
|
||||
private Map<TypePair, String> funWrapperClasses = new HashMap<>();
|
||||
|
||||
private void boxFunctionalInterface(State state, TargetType source, TargetType dest) {
|
||||
var mv = state.mv;
|
||||
var className = "FunWrapper$$" +
|
||||
source.name().replaceAll("\\.", "\\$") +
|
||||
"$_$" +
|
||||
dest.name().replaceAll("\\.", "\\$");
|
||||
|
||||
funWrapperClasses.put(new TypePair(source, dest), className);
|
||||
mv.visitTypeInsn(NEW, className);
|
||||
mv.visitInsn(DUP_X1);
|
||||
mv.visitInsn(SWAP);
|
||||
mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "(" + source.toDescriptor() + ")V", false);
|
||||
}
|
||||
|
||||
private boolean isFunctionalInterface(TargetType type) {
|
||||
if (type instanceof TargetFunNType) return true;
|
||||
if (type instanceof TargetRefType) {
|
||||
var clazz = compiler.getClass(new JavaClassName(type.name()));
|
||||
return (clazz.getModifiers() & Modifier.INTERFACE) != 0 && clazz.isFunctionalInterface();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private TargetType largerType(TargetType left, TargetType right) {
|
||||
if (left.equals(TargetType.String) || right.equals(TargetType.String)) {
|
||||
return TargetType.String;
|
||||
@@ -601,7 +645,7 @@ public class Codegen {
|
||||
} else if (op.expr() instanceof TargetFieldVar fieldVar) {
|
||||
generate(state, fieldVar.left());
|
||||
mv.visitInsn(SWAP);
|
||||
mv.visitFieldInsn(PUTFIELD, fieldVar.owner().getInternalName(), fieldVar.right(), fieldVar.type().toSignature());
|
||||
mv.visitFieldInsn(PUTFIELD, fieldVar.owner().getInternalName(), fieldVar.right(), fieldVar.type().toDescriptor());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -723,44 +767,29 @@ 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;
|
||||
|
||||
String methodName = "apply";
|
||||
TargetMethod.Signature signature = null;
|
||||
|
||||
if (!(state.contextType instanceof TargetFunNType ctx)) {
|
||||
var intf = compiler.getClass(new JavaClassName(state.contextType.name()));
|
||||
if (intf != null) {
|
||||
var method = intf.getMethods().stream().filter(m -> Modifier.isAbstract(m.modifier)).findFirst().orElseThrow();
|
||||
methodName = method.getName();
|
||||
var methodParams = new ArrayList<MethodParameter>();
|
||||
for (var i = 0; i < lambda.signature().parameters().size(); i++) {
|
||||
var param = lambda.signature().parameters().get(i);
|
||||
var tpe = converter.convert(method.getParameterList().getParameterAt(i).getType());
|
||||
methodParams.add(param.withType(tpe));
|
||||
}
|
||||
var retType = converter.convert(method.getReturnType());
|
||||
signature = new TargetMethod.Signature(Set.of(), methodParams, retType);
|
||||
}
|
||||
}
|
||||
if (signature == null) {
|
||||
signature = new TargetMethod.Signature(Set.of(), lambda.signature().parameters().stream().map(par -> par.withType(TargetType.Object)).toList(), TargetType.Object);
|
||||
}
|
||||
|
||||
signature = new TargetMethod.Signature(
|
||||
signature.generics(),
|
||||
signature.parameters().stream().map(par ->
|
||||
par.withType(par.pattern().type() instanceof TargetGenericType ? TargetType.Object : par.pattern().type())
|
||||
).toList(),
|
||||
signature.returnType() instanceof TargetGenericType ? TargetType.Object : signature.returnType()
|
||||
);
|
||||
TargetMethod.Signature signature = new TargetMethod.Signature(Set.of(),
|
||||
lambda.signature().parameters().stream().map(
|
||||
par -> par.withType(TargetType.Object)).toList(),
|
||||
lambda.signature().returnType() != null ? TargetType.Object : null);
|
||||
|
||||
var parameters = new ArrayList<>(lambda.captures());
|
||||
parameters.addAll(signature.parameters());
|
||||
var implSignature = new TargetMethod.Signature(Set.of(), parameters, lambda.signature().returnType());
|
||||
|
||||
// Normalize
|
||||
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)) {
|
||||
@@ -768,22 +797,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().toString()));
|
||||
params.addAll(lambda.captures().stream().map(mp -> mp.pattern().type()).toList());
|
||||
|
||||
var descriptor = TargetMethod.getDescriptor(state.contextType, params.toArray(TargetType[]::new));
|
||||
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();
|
||||
@@ -792,9 +821,42 @@ public class Codegen {
|
||||
mv.visitTypeInsn(CHECKCAST, capture.pattern().type().getInternalName());
|
||||
}
|
||||
|
||||
var descriptor = TargetMethod.getDescriptor(lambda.type(), params.toArray(TargetType[]::new));
|
||||
mv.visitInvokeDynamicInsn(methodName, descriptor, bootstrap, Type.getType(signature.getSignature()), handle, Type.getType(signature.getDescriptor()));
|
||||
}
|
||||
|
||||
private int findReturnCode(TargetType returnType) {
|
||||
if (returnType.equals(TargetType.boolean_)
|
||||
|| returnType.equals(TargetType.char_)
|
||||
|| returnType.equals(TargetType.int_)
|
||||
|| returnType.equals(TargetType.short_)
|
||||
|| returnType.equals(TargetType.byte_))
|
||||
return IRETURN;
|
||||
else if (returnType.equals(TargetType.long_))
|
||||
return LRETURN;
|
||||
else if (returnType.equals(TargetType.float_))
|
||||
return FRETURN;
|
||||
else if (returnType.equals(TargetType.double_))
|
||||
return DRETURN;
|
||||
return ARETURN;
|
||||
}
|
||||
|
||||
private int findLoadCode(TargetType loadType) {
|
||||
if (loadType.equals(TargetType.boolean_)
|
||||
|| loadType.equals(TargetType.char_)
|
||||
|| loadType.equals(TargetType.int_)
|
||||
|| loadType.equals(TargetType.short_)
|
||||
|| loadType.equals(TargetType.byte_))
|
||||
return ILOAD;
|
||||
else if (loadType.equals(TargetType.long_))
|
||||
return LLOAD;
|
||||
else if (loadType.equals(TargetType.float_))
|
||||
return FLOAD;
|
||||
else if (loadType.equals(TargetType.double_))
|
||||
return DLOAD;
|
||||
return ALOAD;
|
||||
}
|
||||
|
||||
private void generate(State state, TargetExpression expr) {
|
||||
var mv = state.mv;
|
||||
switch (expr) {
|
||||
@@ -819,10 +881,7 @@ public class Codegen {
|
||||
break;
|
||||
}
|
||||
case TargetCast cast:
|
||||
var ctx = state.contextType;
|
||||
state.contextType = cast.type();
|
||||
generate(state, cast.expr());
|
||||
state.contextType = ctx;
|
||||
convertTo(state, cast.expr().type(), cast.type());
|
||||
break;
|
||||
case TargetInstanceOf instanceOf:
|
||||
@@ -867,10 +926,7 @@ public class Codegen {
|
||||
case TargetAssign assign: {
|
||||
switch (assign.left()) {
|
||||
case TargetLocalVar localVar -> {
|
||||
var ctype = state.contextType;
|
||||
state.contextType = localVar.type();
|
||||
generate(state, assign.right());
|
||||
state.contextType = ctype;
|
||||
|
||||
convertTo(state, assign.right().type(), localVar.type());
|
||||
boxPrimitive(state, localVar.type());
|
||||
@@ -883,10 +939,7 @@ public class Codegen {
|
||||
if (!(dot.left() instanceof TargetThis && dot.isStatic()))
|
||||
generate(state, dot.left());
|
||||
|
||||
var ctype = state.contextType;
|
||||
state.contextType = fieldType;
|
||||
generate(state, assign.right());
|
||||
state.contextType = ctype;
|
||||
|
||||
convertTo(state, assign.right().type(), fieldType);
|
||||
boxPrimitive(state, fieldType);
|
||||
@@ -894,7 +947,7 @@ public class Codegen {
|
||||
mv.visitInsn(DUP);
|
||||
else
|
||||
mv.visitInsn(DUP_X1);
|
||||
mv.visitFieldInsn(dot.isStatic() ? PUTSTATIC : PUTFIELD, dot.owner().getInternalName(), dot.right(), fieldType.toSignature());
|
||||
mv.visitFieldInsn(dot.isStatic() ? PUTSTATIC : PUTFIELD, dot.owner().getInternalName(), dot.right(), fieldType.toDescriptor());
|
||||
}
|
||||
default -> throw new CodeGenException("Invalid assignment");
|
||||
}
|
||||
@@ -911,7 +964,7 @@ public class Codegen {
|
||||
case TargetFieldVar dot: {
|
||||
if (!dot.isStatic())
|
||||
generate(state, dot.left());
|
||||
mv.visitFieldInsn(dot.isStatic() ? GETSTATIC : GETFIELD, dot.left().type().getInternalName(), dot.right(), dot.type().toSignature());
|
||||
mv.visitFieldInsn(dot.isStatic() ? GETSTATIC : GETFIELD, dot.left().type().getInternalName(), dot.right(), dot.type().toDescriptor());
|
||||
unboxPrimitive(state, dot.type());
|
||||
break;
|
||||
}
|
||||
@@ -1016,29 +1069,12 @@ public class Codegen {
|
||||
case TargetReturn ret: {
|
||||
if (ret.expression() != null && state.returnType != null) {
|
||||
if (state.returnType instanceof TargetPrimitiveType) {
|
||||
var ctype = state.contextType;
|
||||
state.contextType = state.returnType;
|
||||
generate(state, ret.expression());
|
||||
state.contextType = ctype;
|
||||
|
||||
unboxPrimitive(state, state.returnType);
|
||||
if (state.returnType.equals(TargetType.boolean_)
|
||||
|| state.returnType.equals(TargetType.char_)
|
||||
|| state.returnType.equals(TargetType.int_)
|
||||
|| state.returnType.equals(TargetType.short_)
|
||||
|| state.returnType.equals(TargetType.byte_))
|
||||
mv.visitInsn(IRETURN);
|
||||
else if (state.returnType.equals(TargetType.long_))
|
||||
mv.visitInsn(LRETURN);
|
||||
else if (state.returnType.equals(TargetType.float_))
|
||||
mv.visitInsn(FRETURN);
|
||||
else if (state.returnType.equals(TargetType.double_))
|
||||
mv.visitInsn(DRETURN);
|
||||
mv.visitInsn(findReturnCode(state.returnType));
|
||||
} else {
|
||||
var ctype = state.contextType;
|
||||
state.contextType = state.returnType;
|
||||
generate(state, ret.expression());
|
||||
state.contextType = ctype;
|
||||
boxPrimitive(state, ret.expression().type());
|
||||
convertTo(state, ret.expression().type(), state.returnType);
|
||||
mv.visitInsn(ARETURN);
|
||||
@@ -1089,12 +1125,10 @@ public class Codegen {
|
||||
for (var i = 0; i < call.args().size(); i++) {
|
||||
var e = call.args().get(i);
|
||||
var arg = call.parameterTypes().get(i);
|
||||
var ctype = state.contextType;
|
||||
state.contextType = arg;
|
||||
generate(state, e);
|
||||
convertTo(state, e.type(), arg);
|
||||
if (!(arg instanceof TargetPrimitiveType))
|
||||
boxPrimitive(state, e.type());
|
||||
state.contextType = ctype;
|
||||
}
|
||||
var descriptor = call.getDescriptor();
|
||||
if (call.owner() instanceof TargetFunNType) // Decay FunN
|
||||
@@ -1280,8 +1314,7 @@ public class Codegen {
|
||||
state.enterScope();
|
||||
// This is the index to start the switch from
|
||||
mv.visitInsn(ICONST_0);
|
||||
if (aSwitch.isExpression())
|
||||
state.pushSwitch();
|
||||
state.pushSwitch();
|
||||
|
||||
// To be able to skip ahead to the next case
|
||||
var start = new Label();
|
||||
@@ -1295,16 +1328,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();
|
||||
}
|
||||
@@ -1325,11 +1359,7 @@ public class Codegen {
|
||||
}
|
||||
}
|
||||
|
||||
var defaultLabel = end;
|
||||
if (aSwitch.default_() != null) {
|
||||
defaultLabel = new Label();
|
||||
}
|
||||
|
||||
var defaultLabel = new Label();
|
||||
mv.visitTableSwitchInsn(0, labels.length - 1, defaultLabel, labels);
|
||||
|
||||
for (var i = 0; i < aSwitch.cases().size(); i++) {
|
||||
@@ -1364,11 +1394,18 @@ public class Codegen {
|
||||
if (aSwitch.isExpression()) mv.visitJumpInsn(GOTO, end);
|
||||
}
|
||||
|
||||
mv.visitLabel(defaultLabel);
|
||||
if (aSwitch.default_() != null) {
|
||||
mv.visitLabel(defaultLabel);
|
||||
generate(state, aSwitch.default_().body());
|
||||
if (aSwitch.default_().isSingleExpression() && aSwitch.isExpression())
|
||||
yieldValue(state, aSwitch.default_().body().statements().get(0).type());
|
||||
} else {
|
||||
// throw illegal argument exception on missing default case
|
||||
mv.visitTypeInsn(NEW, "java/lang/IllegalArgumentException");
|
||||
mv.visitInsn(DUP);
|
||||
mv.visitLdcInsn("Unhandled case value");
|
||||
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/IllegalArgumentException", "<init>", "(Ljava/lang/String;)V", false);
|
||||
mv.visitInsn(ATHROW);
|
||||
}
|
||||
|
||||
mv.visitLabel(end);
|
||||
@@ -1376,8 +1413,10 @@ public class Codegen {
|
||||
|
||||
state.breakStack.pop();
|
||||
if (aSwitch.isExpression()) {
|
||||
mv.visitVarInsn(ALOAD, state.switchResultValue.peek());
|
||||
unboxPrimitive(state, aSwitch.type());
|
||||
if (aSwitch.type() != null) {
|
||||
mv.visitVarInsn(ALOAD, state.switchResultValue.peek());
|
||||
unboxPrimitive(state, aSwitch.type());
|
||||
}
|
||||
state.popSwitch();
|
||||
}
|
||||
|
||||
@@ -1388,7 +1427,7 @@ public class Codegen {
|
||||
if (i >= clazz.getFieldDecl().size())
|
||||
throw new CodeGenException("Couldn't find suitable field accessor for '" + type.name() + "'");
|
||||
var field = clazz.getFieldDecl().get(i);
|
||||
var fieldType = new TargetRefType(((RefType) field.getType()).getName().toString());
|
||||
var fieldType = converter.convert(field.getType());
|
||||
state.mv.visitMethodInsn(INVOKEVIRTUAL, type.getInternalName(), field.getName(), "()" + fieldType.toDescriptor(), false);
|
||||
}
|
||||
|
||||
@@ -1396,25 +1435,42 @@ public class Codegen {
|
||||
if (pat.type() instanceof TargetPrimitiveType)
|
||||
boxPrimitive(state, pat.type());
|
||||
|
||||
state.mv.visitInsn(DUP);
|
||||
state.mv.visitTypeInsn(INSTANCEOF, pat.type().getInternalName());
|
||||
if (pat.type() instanceof TargetRefType) {
|
||||
state.mv.visitInsn(DUP);
|
||||
state.mv.visitTypeInsn(INSTANCEOF, pat.type().getInternalName());
|
||||
|
||||
var cont = new Label();
|
||||
state.mv.visitJumpInsn(IFNE, cont);
|
||||
for (var i = 0; i < depth; i++) {
|
||||
state.mv.visitInsn(POP);
|
||||
var cont = new Label();
|
||||
state.mv.visitJumpInsn(IFNE, cont);
|
||||
for (var i = 0; i < depth; i++) {
|
||||
state.mv.visitInsn(POP);
|
||||
}
|
||||
|
||||
state.mv.visitVarInsn(ALOAD, state.switchResultValue.peek());
|
||||
state.mv.visitLdcInsn(index + 1);
|
||||
state.mv.visitJumpInsn(GOTO, start);
|
||||
state.mv.visitLabel(cont);
|
||||
|
||||
state.mv.visitTypeInsn(CHECKCAST, pat.type().getInternalName());
|
||||
}
|
||||
|
||||
if (pat instanceof TargetExpressionPattern ep) {
|
||||
var cur = state.createVariable(pat.type());
|
||||
state.mv.visitVarInsn(ASTORE, cur.index);
|
||||
|
||||
var expr = new Equal(pat.type(), new TargetLocalVar(cur.type, cur.name), ep.expression());
|
||||
generate(state, expr);
|
||||
|
||||
state.mv.visitVarInsn(ALOAD, state.switchResultValue.peek());
|
||||
state.mv.visitLdcInsn(index + 1);
|
||||
state.mv.visitJumpInsn(GOTO, start);
|
||||
state.mv.visitLabel(cont);
|
||||
var cont = new Label();
|
||||
state.mv.visitJumpInsn(IFNE, cont);
|
||||
for (var i = 0; i < depth - 1; i++) {
|
||||
state.mv.visitInsn(POP);
|
||||
}
|
||||
|
||||
state.mv.visitTypeInsn(CHECKCAST, pat.type().getInternalName());
|
||||
|
||||
if (pat instanceof TargetTypePattern sp) {
|
||||
state.mv.visitVarInsn(ALOAD, state.switchResultValue.peek());
|
||||
state.mv.visitLdcInsn(index + 1);
|
||||
state.mv.visitJumpInsn(GOTO, start);
|
||||
state.mv.visitLabel(cont);
|
||||
} else if (pat instanceof TargetTypePattern sp) {
|
||||
var local = state.createVariable(sp.name(), sp.type());
|
||||
state.mv.visitVarInsn(ASTORE, local.index);
|
||||
} else if (pat instanceof TargetComplexPattern cp) {
|
||||
@@ -1429,10 +1485,27 @@ public class Codegen {
|
||||
// TODO Check if class is a Record
|
||||
|
||||
for (var i = 0; i < cp.subPatterns().size(); i++) {
|
||||
state.mv.visitInsn(DUP);
|
||||
|
||||
var subPattern = cp.subPatterns().get(i);
|
||||
|
||||
state.mv.visitInsn(DUP);
|
||||
extractField(state, cp.type(), i, clazz);
|
||||
|
||||
if (subPattern.type() instanceof TargetRefType || subPattern.type() instanceof TargetExtendsWildcard) {
|
||||
state.mv.visitInsn(DUP);
|
||||
state.mv.visitTypeInsn(INSTANCEOF, subPattern.type().getInternalName());
|
||||
|
||||
var cont = new Label();
|
||||
state.mv.visitJumpInsn(IFNE, cont);
|
||||
for (var j = 0; j < depth + 1; j++) {
|
||||
state.mv.visitInsn(POP);
|
||||
}
|
||||
|
||||
state.mv.visitVarInsn(ALOAD, state.switchResultValue.peek());
|
||||
state.mv.visitLdcInsn(index + 1);
|
||||
state.mv.visitJumpInsn(GOTO, start);
|
||||
state.mv.visitLabel(cont);
|
||||
}
|
||||
|
||||
bindPattern(state, subPattern.type(), subPattern, start, index, depth + 1);
|
||||
}
|
||||
state.mv.visitInsn(POP);
|
||||
@@ -1460,14 +1533,14 @@ public class Codegen {
|
||||
//if ((access & ACC_PRIVATE) == 0 && (access & ACC_PROTECTED) == 0) // TODO Implement access modifiers properly
|
||||
// access |= ACC_PUBLIC;
|
||||
|
||||
cw.visitField(access, field.name(), field.type().toSignature(), field.type().toDescriptor(), null);
|
||||
cw.visitField(access, field.name(), field.type().toDescriptor(), field.type().toSignature(), null);
|
||||
}
|
||||
|
||||
private void generateStaticConstructor(TargetMethod constructor) {
|
||||
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);
|
||||
@@ -1481,7 +1554,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)
|
||||
@@ -1505,33 +1578,53 @@ public class Codegen {
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
private int bindLocalVariables(State state, TargetPattern pattern, int offset, int field) {
|
||||
if (pattern instanceof TargetComplexPattern cp) {
|
||||
state.mv.visitVarInsn(ALOAD, offset);
|
||||
private void bindLocalVariables(State state, TargetComplexPattern cp, int offset) {
|
||||
state.mv.visitVarInsn(ALOAD, offset);
|
||||
|
||||
var clazz = findClass(new JavaClassName(cp.type().name()));
|
||||
if (clazz == null) throw new CodeGenException("Class definition for '" + cp.type().name() + "' not found");
|
||||
var clazz = findClass(new JavaClassName(cp.type().name()));
|
||||
if (clazz == null) throw new CodeGenException("Class definition for '" + cp.type().name() + "' not found");
|
||||
|
||||
for (var i = 0; i < cp.subPatterns().size(); i++) {
|
||||
var subPattern = cp.subPatterns().get(i);
|
||||
for (var i = 0; i < cp.subPatterns().size(); i++) {
|
||||
var subPattern = cp.subPatterns().get(i);
|
||||
|
||||
if (i < cp.subPatterns().size() - 1)
|
||||
state.mv.visitInsn(DUP);
|
||||
if (i < cp.subPatterns().size() - 1)
|
||||
state.mv.visitInsn(DUP);
|
||||
|
||||
extractField(state, cp.type(), i, clazz);
|
||||
extractField(state, cp.type(), i, clazz);
|
||||
if (subPattern.type() instanceof TargetRefType)
|
||||
state.mv.visitTypeInsn(CHECKCAST, subPattern.type().getInternalName());
|
||||
state.mv.visitVarInsn(ASTORE, offset);
|
||||
offset = bindLocalVariables(state, subPattern, offset, i);
|
||||
offset = state.createVariable(subPattern.name(), subPattern.type()).index;
|
||||
state.mv.visitVarInsn(ASTORE, offset);
|
||||
if (subPattern instanceof TargetComplexPattern cp2) {
|
||||
bindLocalVariables(state, cp2, offset);
|
||||
}
|
||||
} else if (pattern instanceof TargetTypePattern tp) {
|
||||
offset++;
|
||||
state.createVariable(tp.name(), tp.type());
|
||||
} else throw new NotImplementedException();
|
||||
return offset;
|
||||
}
|
||||
}
|
||||
private void generateMethod(TargetMethod method) {
|
||||
generateMethod(method, null);
|
||||
}
|
||||
|
||||
private void generateMethod(TargetMethod method) {
|
||||
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, new TargetRefType(clazz.qualifiedName().toString()).getInternalName(), "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)
|
||||
@@ -1545,10 +1638,21 @@ public class Codegen {
|
||||
|
||||
if (method.block() != null) {
|
||||
mv.visitCode();
|
||||
var state = new State(method.signature().returnType(), mv, method.isStatic() ? 0 : 1);
|
||||
for (var param : method.signature().parameters()) {
|
||||
bindLocalVariables(state, param.pattern(), 1, 0);
|
||||
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());
|
||||
}
|
||||
for (var param : method.signature().parameters()) {
|
||||
if (param.pattern() instanceof TargetComplexPattern cp)
|
||||
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);
|
||||
@@ -1562,12 +1666,12 @@ public class Codegen {
|
||||
if (!generics.isEmpty()) {
|
||||
ret += "<";
|
||||
for (var generic : generics) {
|
||||
ret += generic.name() + ":" + generic.bound().toDescriptor();
|
||||
ret += generic.name() + ":" + generic.bound().toSignature();
|
||||
}
|
||||
ret += ">";
|
||||
}
|
||||
if (clazz.superType() != null)
|
||||
ret += clazz.superType().toDescriptor();
|
||||
ret += clazz.superType().toSignature();
|
||||
for (var intf : clazz.implementingInterfaces()) {
|
||||
ret += intf.toSignature();
|
||||
}
|
||||
@@ -1582,13 +1686,26 @@ public class Codegen {
|
||||
if (!(clazz instanceof TargetInterface))
|
||||
access |= ACC_SUPER;
|
||||
|
||||
// Check sealed
|
||||
for (var intf : clazz.implementingInterfaces()) {
|
||||
var intfClass = compiler.getClass(new JavaClassName(intf.name()));
|
||||
if (intfClass.isSealed()) {
|
||||
if (intfClass.getPermittedSubtypes().stream().noneMatch(type -> type.getName().equals(new JavaClassName(className)))) {
|
||||
throw new CodeGenException("Sealed interface " + intfClass.getClassName() + " doesn't permit class " + className);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var signature = generateSignature(clazz, clazz.generics());
|
||||
var interfaces = clazz.implementingInterfaces().stream().map(TargetType::getInternalName).toArray(String[]::new);
|
||||
var superType = clazz.superType() != null ? clazz.superType().getInternalName() : "java/lang/Object";
|
||||
|
||||
cw.visit(V1_8, access, clazz.qualifiedName().toString().replaceAll("\\.", "/"), signature, superType, interfaces);
|
||||
if (clazz.txGenerics() != null && signature != null)
|
||||
cw.visitAttribute(new JavaTXSignatureAttribute(generateSignature(clazz, clazz.txGenerics())));
|
||||
if (clazz.txGenerics() != null && signature != null) {
|
||||
var txSignature = generateSignature(clazz, clazz.txGenerics());
|
||||
if (txSignature != null)
|
||||
cw.visitAttribute(new JavaTXSignatureAttribute(txSignature));
|
||||
}
|
||||
|
||||
clazz.fields().forEach(this::generateField);
|
||||
clazz.constructors().forEach(this::generateConstructor);
|
||||
@@ -1600,6 +1717,85 @@ public class Codegen {
|
||||
if (clazz instanceof TargetRecord)
|
||||
generateRecordMethods();
|
||||
|
||||
// Generate wrapper classes for function types
|
||||
for (var pair : funWrapperClasses.keySet()) {
|
||||
var className = funWrapperClasses.get(pair);
|
||||
ClassWriter cw2 = new CustomClassWriter();
|
||||
cw2.visit(V1_8, ACC_PUBLIC, className, null, "java/lang/Object", new String[] { pair.to.getInternalName() });
|
||||
cw2.visitField(ACC_PRIVATE, "wrapped", pair.from.toDescriptor(), null, null).visitEnd();
|
||||
|
||||
// Generate constructor
|
||||
var ctor = cw2.visitMethod(ACC_PUBLIC, "<init>", "(" + pair.from.toDescriptor() + ")V", null, null);
|
||||
ctor.visitVarInsn(ALOAD, 0);
|
||||
ctor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
|
||||
ctor.visitVarInsn(ALOAD, 0);
|
||||
ctor.visitVarInsn(ALOAD, 1);
|
||||
ctor.visitFieldInsn(PUTFIELD, className, "wrapped", pair.from.toDescriptor());
|
||||
ctor.visitInsn(RETURN);
|
||||
ctor.visitMaxs(0, 0);
|
||||
ctor.visitEnd();
|
||||
|
||||
String methodName = "apply";
|
||||
String fromDescriptor = null;
|
||||
TargetType fromReturn = null;
|
||||
if (!(pair.from instanceof TargetFunNType funNType)) {
|
||||
var fromClass = compiler.getClass(new JavaClassName(pair.from.name()));
|
||||
var fromMethod = fromClass.getMethods().stream().filter(m -> (m.modifier & ACC_ABSTRACT) != 0).findFirst().orElseThrow();
|
||||
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);
|
||||
fromDescriptor = TargetMethod.getDescriptor(fromReturn, fromParams);
|
||||
} else {
|
||||
fromReturn = funNType.returnArguments() > 0 ? TargetType.Object : null;
|
||||
fromDescriptor = funNType.toMethodDescriptor();
|
||||
}
|
||||
|
||||
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 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, false);
|
||||
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitFieldInsn(GETFIELD, className, "wrapped", pair.from.toDescriptor());
|
||||
for (var i = 0; i < toParams.length; i++) {
|
||||
var arg = toParams[i];
|
||||
mv.visitVarInsn(findLoadCode(arg), i + 1);
|
||||
}
|
||||
mv.visitMethodInsn(INVOKEINTERFACE, pair.from.getInternalName(), methodName, fromDescriptor, true);
|
||||
if (fromReturn != null) {
|
||||
if (toReturn instanceof TargetPrimitiveType) {
|
||||
convertTo(state, fromReturn, TargetType.toWrapper(toReturn));
|
||||
} else convertTo(state, fromReturn, toReturn);
|
||||
}
|
||||
|
||||
if (toReturn != null)
|
||||
mv.visitInsn(findReturnCode(toReturn));
|
||||
|
||||
else mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
|
||||
cw2.visitEnd();
|
||||
var bytes = cw2.toByteArray();
|
||||
compiler.auxiliaries.put(className, bytes);
|
||||
|
||||
// TODO These class loading shenanigans happen in a few places, the tests load the classes individually.
|
||||
// Instead we should just look at the folder.
|
||||
try {
|
||||
converter.classLoader.findClass(className);
|
||||
} catch (ClassNotFoundException e) {
|
||||
try {
|
||||
converter.classLoader.loadClass(className, bytes);
|
||||
} catch (LinkageError ignored) {}
|
||||
}
|
||||
}
|
||||
|
||||
cw.visitEnd();
|
||||
return cw.toByteArray();
|
||||
}
|
||||
|
@@ -1,11 +1,13 @@
|
||||
package de.dhbwstuttgart.bytecode;
|
||||
|
||||
import de.dhbwstuttgart.syntaxtree.statement.Break;
|
||||
import de.dhbwstuttgart.target.tree.TargetGeneric;
|
||||
import de.dhbwstuttgart.target.tree.type.*;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Type;
|
||||
|
||||
import java.sql.Array;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
@@ -33,6 +35,40 @@ public class FunNGenerator {
|
||||
public static class GenericParameters {
|
||||
int start;
|
||||
public List<TargetType> parameters = new ArrayList<>();
|
||||
final String descriptor;
|
||||
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);
|
||||
var type = new TargetRefType(FunNGenerator.getSuperClassName(params.size() - 1, numReturns), params);
|
||||
descriptor = applyDescriptor(type, this);
|
||||
}
|
||||
|
||||
private static List<TargetType> flattenTypeParams(List<TargetType> params) {
|
||||
var res = new ArrayList<TargetType>();
|
||||
for (var param : params) {
|
||||
if (param instanceof TargetSpecializedType tspec) {
|
||||
res.addAll(flattenTypeParams(tspec.params()));
|
||||
} else {
|
||||
res.add(param);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public TargetType getReturnType() {
|
||||
return FunNGenerator.getReturnType(realParams);
|
||||
}
|
||||
|
||||
public List<TargetType> getArguments() {
|
||||
return FunNGenerator.getArguments(realParams);
|
||||
}
|
||||
}
|
||||
|
||||
private static String applyDescriptor(TargetType type, GenericParameters gep) {
|
||||
@@ -62,14 +98,14 @@ public class FunNGenerator {
|
||||
}
|
||||
|
||||
private static String applySignature(TargetType a) { return a.toSignature(); }
|
||||
private static String applyNameDescriptor(TargetType a){ return a instanceof TargetGenericType ? "LTPH;" : String.format("%s", applySignature(a)); }
|
||||
private static String applyNameDescriptor(TargetType a){ return a instanceof TargetGenericType ? "LTPH;" : String.format("%s", a.toDescriptor()); }
|
||||
|
||||
public static String encodeType(TargetType type) {
|
||||
if (type == null) return VOID;
|
||||
return applyNameDescriptor(type).replace("/", "$").replace(";", "$_$");
|
||||
}
|
||||
|
||||
public static byte[] generateSuperBytecode(int numberArguments) {
|
||||
public static byte[] generateSuperBytecode(int numberArguments, int numReturnTypes) {
|
||||
StringBuilder superFunNClassSignature = new StringBuilder("<");
|
||||
StringBuilder superFunNMethodSignature = new StringBuilder("(");
|
||||
StringBuilder superFunNMethodDescriptor = new StringBuilder("(");
|
||||
@@ -80,30 +116,34 @@ public class FunNGenerator {
|
||||
superFunNMethodDescriptor.append(objectSignature);
|
||||
}
|
||||
superFunNClassSignature.append(String.format("%s:%s>%s", returnGeneric, objectSignature, objectSignature));
|
||||
superFunNMethodSignature.append(String.format(")T%s;", returnGeneric));
|
||||
superFunNMethodDescriptor.append(String.format(")%s", objectSignature));
|
||||
if (numReturnTypes > 0) {
|
||||
superFunNMethodSignature.append(String.format(")T%s;", returnGeneric));
|
||||
superFunNMethodDescriptor.append(String.format(")%s", objectSignature));
|
||||
} else {
|
||||
superFunNMethodSignature.append(")V");
|
||||
superFunNMethodDescriptor.append(")V");
|
||||
}
|
||||
|
||||
System.out.println(superFunNMethodSignature);
|
||||
|
||||
ClassWriter classWriter = new ClassWriter(0);
|
||||
MethodVisitor methodVisitor;
|
||||
classWriter.visit(bytecodeVersion, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, getSuperClassName(numberArguments), superFunNClassSignature.toString(), objectSuperType, null);
|
||||
classWriter.visit(bytecodeVersion, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, getSuperClassName(numberArguments, numReturnTypes), superFunNClassSignature.toString(), objectSuperType, null);
|
||||
methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, methodName, superFunNMethodDescriptor.toString(), superFunNMethodSignature.toString(), null);
|
||||
methodVisitor.visitEnd();
|
||||
classWriter.visitEnd();
|
||||
return classWriter.toByteArray();
|
||||
}
|
||||
|
||||
public static String getSuperClassName(int numberArguments) {
|
||||
return String.format("Fun%d$$", numberArguments);
|
||||
public static String getSuperClassName(int numberArguments, int returnArguments) {
|
||||
return returnArguments > 0 ? String.format("Fun%d$$", numberArguments) : String.format("FunVoid%d$$", numberArguments);
|
||||
}
|
||||
|
||||
public static byte[] generateSpecializedBytecode(List<TargetType> argumentTypes, TargetType returnType, GenericParameters gep) {
|
||||
List<TargetType> parameters = Stream
|
||||
.concat(argumentTypes.stream(), Stream.of(returnType))
|
||||
.toList();
|
||||
public static byte[] generateSpecializedBytecode(GenericParameters gep, List<String> superInterfaces) {
|
||||
var argumentTypes = gep.getArguments();
|
||||
var returnType = gep.getReturnType();
|
||||
|
||||
StringBuilder funNClassSignature = new StringBuilder(objectSignature + applyDescriptor(new TargetRefType(getSuperClassName(argumentTypes.size()), parameters), gep));
|
||||
StringBuilder funNClassSignature = new StringBuilder(objectSignature + gep.descriptor);
|
||||
boolean containsGeneric = false;
|
||||
|
||||
String genericSignature = "<";
|
||||
@@ -114,10 +154,18 @@ public class FunNGenerator {
|
||||
|
||||
genericSignature += ">";
|
||||
if (containsGeneric) funNClassSignature.insert(0, genericSignature);
|
||||
System.out.println(funNClassSignature.toString());
|
||||
|
||||
for (var superInterface : superInterfaces) {
|
||||
funNClassSignature.append('L');
|
||||
funNClassSignature.append(superInterface);
|
||||
funNClassSignature.append(';');
|
||||
}
|
||||
|
||||
var interfaces = new ArrayList<>(superInterfaces);
|
||||
interfaces.add(getSuperClassName(argumentTypes.size(), returnType != null ? 1 : 0));
|
||||
|
||||
ClassWriter classWriter = new ClassWriter(0);
|
||||
classWriter.visit(bytecodeVersion, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, getSpecializedClassName(argumentTypes, returnType), funNClassSignature.toString(), objectSuperType, new String[]{getSuperClassName(argumentTypes.size())});
|
||||
classWriter.visit(bytecodeVersion, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, getSpecializedClassName(argumentTypes, returnType), funNClassSignature.toString(), objectSuperType, interfaces.toArray(String[]::new));
|
||||
classWriter.visitEnd();
|
||||
return classWriter.toByteArray();
|
||||
}
|
||||
@@ -133,14 +181,24 @@ public class FunNGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
public static String getSpecializedClassName(GenericParameters gep) {
|
||||
return getSpecializedClassName(gep.getArguments(), gep.getReturnType());
|
||||
}
|
||||
|
||||
public static String getSpecializedClassName(List<TargetType> argumentTypes, TargetType returnType) {
|
||||
return String.format("Fun%d$$%s%s",
|
||||
var arguments = argumentTypes
|
||||
.stream()
|
||||
.map(FunNGenerator::encodeType)
|
||||
.collect(Collectors.joining());
|
||||
|
||||
if (returnType != null)
|
||||
return String.format("Fun%d$$%s%s",
|
||||
argumentTypes.size(),
|
||||
arguments,
|
||||
encodeType(returnType));
|
||||
else return String.format("FunVoidImpl%d$$%s",
|
||||
argumentTypes.size(),
|
||||
argumentTypes
|
||||
.stream()
|
||||
.map(FunNGenerator::encodeType)
|
||||
.collect(Collectors.joining()),
|
||||
encodeType(returnType));
|
||||
arguments);
|
||||
}
|
||||
|
||||
public static List<TargetType> getArguments(List<TargetType> list) {
|
||||
@@ -151,8 +209,8 @@ public class FunNGenerator {
|
||||
}
|
||||
|
||||
public static TargetType getReturnType(List<TargetType> list) {
|
||||
if(list.size() == 0)
|
||||
if(list.isEmpty())
|
||||
throw new IndexOutOfBoundsException();
|
||||
return list.get(list.size() - 1);
|
||||
return list.getLast();
|
||||
}
|
||||
}
|
||||
|
@@ -2,6 +2,7 @@
|
||||
package de.dhbwstuttgart.core;
|
||||
|
||||
import de.dhbwstuttgart.bytecode.Codegen;
|
||||
import de.dhbwstuttgart.bytecode.FunNGenerator;
|
||||
import de.dhbwstuttgart.environment.CompilationEnvironment;
|
||||
import de.dhbwstuttgart.environment.DirectoryClassLoader;
|
||||
import de.dhbwstuttgart.exceptions.DebugException;
|
||||
@@ -66,13 +67,18 @@ public class JavaTXCompiler {
|
||||
Boolean resultmodel = true;
|
||||
public final Map<File, SourceFile> sourceFiles = new HashMap<>();
|
||||
|
||||
Boolean log = true; //gibt an ob ein Log-File nach System.getProperty("user.dir")+""/logFiles/"" geschrieben werden soll?
|
||||
Boolean log = false; //gibt an ob ein Log-File nach System.getProperty("user.dir")+""/logFiles/"" geschrieben werden soll?
|
||||
public volatile UnifyTaskModel usedTasks = new UnifyTaskModel();
|
||||
public final DirectoryClassLoader classLoader;
|
||||
|
||||
public final List<File> classPath;
|
||||
private final File outputPath;
|
||||
|
||||
public final Map<String, FunNGenerator.GenericParameters> usedFunN = new HashMap<>();
|
||||
public final Set<Integer> usedFunNSuperTypes = new HashSet<>();
|
||||
|
||||
public Map<String, byte[]> auxiliaries = new HashMap<>();
|
||||
|
||||
public DirectoryClassLoader getClassLoader() {
|
||||
return classLoader;
|
||||
}
|
||||
@@ -327,74 +333,6 @@ public class JavaTXCompiler {
|
||||
logFile.write(ASTTypePrinter.print(f));
|
||||
}
|
||||
logFile.flush();
|
||||
|
||||
Set<String> methodParaTypeVarNames = allClasses.stream().map(x -> x.getMethods().stream().map(y -> y.getParameterList().getFormalparalist().stream().filter(z -> z.getType() instanceof TypePlaceholder).map(z -> ((TypePlaceholder) z.getType()).getName()).collect(Collectors.toCollection(HashSet::new))).reduce(new HashSet<String>(), (a, b) -> {
|
||||
a.addAll(b);
|
||||
return a;
|
||||
}, (a, b) -> {
|
||||
a.addAll(b);
|
||||
return a;
|
||||
})).reduce(new HashSet<String>(), (a, b) -> {
|
||||
a.addAll(b);
|
||||
return a;
|
||||
});
|
||||
|
||||
Set<String> constructorParaTypeVarNames = allClasses.stream().map(x -> x.getConstructors().stream().map(y -> y.getParameterList().getFormalparalist().stream().filter(z -> z.getType() instanceof TypePlaceholder).map(z -> ((TypePlaceholder) z.getType()).getName()).collect(Collectors.toCollection(HashSet::new))).reduce(new HashSet<String>(), (a, b) -> {
|
||||
a.addAll(b);
|
||||
return a;
|
||||
}, (a, b) -> {
|
||||
a.addAll(b);
|
||||
return a;
|
||||
})).reduce(new HashSet<String>(), (a, b) -> {
|
||||
a.addAll(b);
|
||||
return a;
|
||||
});
|
||||
|
||||
Set<String> paraTypeVarNames = methodParaTypeVarNames;
|
||||
paraTypeVarNames.addAll(constructorParaTypeVarNames);
|
||||
|
||||
Set<String> returnTypeVarNames = allClasses.stream().map(x -> x.getMethods().stream().filter(y -> y.getReturnType() instanceof TypePlaceholder).map(z -> ((TypePlaceholder) z.getReturnType()).getName()).collect(Collectors.toCollection(HashSet::new))).reduce((a, b) -> {
|
||||
a.addAll(b);
|
||||
return a;
|
||||
}).get();
|
||||
|
||||
Set<String> fieldTypeVarNames = allClasses.stream().map(x -> x.getFieldDecl().stream().filter(y -> y.getReturnType() instanceof TypePlaceholder).map(z -> ((TypePlaceholder) z.getReturnType()).getName()).collect(Collectors.toCollection(HashSet::new))).reduce((a, b) -> {
|
||||
a.addAll(b);
|
||||
return a;
|
||||
}).get();
|
||||
|
||||
returnTypeVarNames.addAll(fieldTypeVarNames);
|
||||
|
||||
unifyCons = unifyCons.map(x -> {
|
||||
// Hier muss ueberlegt werden, ob
|
||||
// 1. alle Argument- und Retuntyp-Variablen in allen UnifyPairs
|
||||
// mit disableWildcardtable() werden.
|
||||
// 2. alle Typvariablen mit Argument- oder Retuntyp-Variablen
|
||||
// in Beziehung auch auf disableWildcardtable() gesetzt werden muessen
|
||||
// PL 2018-04-23
|
||||
if ((x.getLhsType() instanceof PlaceholderType)) {
|
||||
if (paraTypeVarNames.contains(x.getLhsType().getName())) {
|
||||
((PlaceholderType) x.getLhsType()).setVariance((byte) 1);
|
||||
((PlaceholderType) x.getLhsType()).disableWildcardtable();
|
||||
}
|
||||
if (returnTypeVarNames.contains(x.getLhsType().getName())) {
|
||||
((PlaceholderType) x.getLhsType()).setVariance((byte) -1);
|
||||
((PlaceholderType) x.getLhsType()).disableWildcardtable();
|
||||
}
|
||||
}
|
||||
if ((x.getRhsType() instanceof PlaceholderType)) {
|
||||
if (paraTypeVarNames.contains(x.getRhsType().getName())) {
|
||||
((PlaceholderType) x.getRhsType()).setVariance((byte) 1);
|
||||
((PlaceholderType) x.getRhsType()).disableWildcardtable();
|
||||
}
|
||||
if (returnTypeVarNames.contains(x.getRhsType().getName())) {
|
||||
((PlaceholderType) x.getRhsType()).setVariance((byte) -1);
|
||||
((PlaceholderType) x.getRhsType()).disableWildcardtable();
|
||||
}
|
||||
}
|
||||
return x;// HIER DIE JEWEILS RECHT BZW. LINKE SEITE AUF GLEICHE VARIANZ SETZEN WIE DIE
|
||||
// JEWEILS ANDERE SEITE
|
||||
});
|
||||
Set<PlaceholderType> varianceTPHold;
|
||||
Set<PlaceholderType> varianceTPH = new HashSet<>();
|
||||
varianceTPH = varianceInheritanceConstraintSet(unifyCons);
|
||||
@@ -461,86 +399,12 @@ public class JavaTXCompiler {
|
||||
logFile.write(ASTTypePrinter.print(sf));
|
||||
System.out.println(ASTTypePrinter.print(sf));
|
||||
logFile.flush();
|
||||
List<UnifyPair> andConstraintsSorted = unifyCons.getUndConstraints().stream()
|
||||
.sorted(Comparator.comparing(UnifyPair::getPairOp).thenComparing(UnifyPair::getLhsType, Comparator.comparing(UnifyType::getName)))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
Set<String> methodParaTypeVarNames = allClasses.stream().map(x -> x.getMethods().stream().map(y -> y.getParameterList().getFormalparalist().stream().filter(z -> z.getType() instanceof TypePlaceholder).map(z -> ((TypePlaceholder) z.getType()).getName()).collect(Collectors.toCollection(HashSet::new))).reduce(new HashSet<String>(), (a, b) -> {
|
||||
a.addAll(b);
|
||||
return a;
|
||||
}, (a, b) -> {
|
||||
a.addAll(b);
|
||||
return a;
|
||||
})).reduce(new HashSet<String>(), (a, b) -> {
|
||||
a.addAll(b);
|
||||
return a;
|
||||
});
|
||||
System.out.println(andConstraintsSorted);
|
||||
|
||||
Set<String> constructorParaTypeVarNames = allClasses.stream().map(x -> x.getConstructors().stream().map(y -> y.getParameterList().getFormalparalist().stream().filter(z -> z.getType() instanceof TypePlaceholder).map(z -> ((TypePlaceholder) z.getType()).getName()).collect(Collectors.toCollection(HashSet::new))).reduce(new HashSet<String>(), (a, b) -> {
|
||||
a.addAll(b);
|
||||
return a;
|
||||
}, (a, b) -> {
|
||||
a.addAll(b);
|
||||
return a;
|
||||
})).reduce(new HashSet<String>(), (a, b) -> {
|
||||
a.addAll(b);
|
||||
return a;
|
||||
});
|
||||
|
||||
Set<String> paraTypeVarNames = methodParaTypeVarNames;
|
||||
paraTypeVarNames.addAll(constructorParaTypeVarNames);
|
||||
|
||||
Set<String> returnTypeVarNames = allClasses.stream().map(x -> x.getMethods().stream().filter(y -> y.getReturnType() instanceof TypePlaceholder).map(z -> ((TypePlaceholder) z.getReturnType()).getName()).collect(Collectors.toCollection(HashSet::new))).reduce((a, b) -> {
|
||||
a.addAll(b);
|
||||
return a;
|
||||
}).get();
|
||||
|
||||
Set<String> fieldTypeVarNames = allClasses.stream().map(x -> x.getFieldDecl().stream().filter(y -> y.getReturnType() instanceof TypePlaceholder).map(z -> ((TypePlaceholder) z.getReturnType()).getName()).collect(Collectors.toCollection(HashSet::new))).reduce((a, b) -> {
|
||||
a.addAll(b);
|
||||
return a;
|
||||
}).get();
|
||||
|
||||
returnTypeVarNames.addAll(fieldTypeVarNames);
|
||||
|
||||
unifyCons = unifyCons.map(x -> {
|
||||
// Hier muss ueberlegt werden, ob
|
||||
// 1. alle Argument- und Retuntyp-Variablen in allen UnifyPairs
|
||||
// mit disableWildcardtable() werden.
|
||||
// 2. alle Typvariablen mit Argument- oder Retuntyp-Variablen
|
||||
// in Beziehung auch auf disableWildcardtable() gesetzt werden muessen
|
||||
// PL 2018-04-23
|
||||
if ((x.getLhsType() instanceof PlaceholderType)) {
|
||||
if (paraTypeVarNames.contains(x.getLhsType().getName())) {
|
||||
((PlaceholderType) x.getLhsType()).setVariance((byte) 1);
|
||||
((PlaceholderType) x.getLhsType()).disableWildcardtable();
|
||||
}
|
||||
if (returnTypeVarNames.contains(x.getLhsType().getName())) {
|
||||
((PlaceholderType) x.getLhsType()).setVariance((byte) -1);
|
||||
((PlaceholderType) x.getLhsType()).disableWildcardtable();
|
||||
}
|
||||
}
|
||||
if ((x.getRhsType() instanceof PlaceholderType)) {
|
||||
if (paraTypeVarNames.contains(x.getRhsType().getName())) {
|
||||
((PlaceholderType) x.getRhsType()).setVariance((byte) 1);
|
||||
((PlaceholderType) x.getRhsType()).disableWildcardtable();
|
||||
}
|
||||
if (returnTypeVarNames.contains(x.getRhsType().getName())) {
|
||||
((PlaceholderType) x.getRhsType()).setVariance((byte) -1);
|
||||
((PlaceholderType) x.getRhsType()).disableWildcardtable();
|
||||
}
|
||||
}
|
||||
return x;// HIER DIE JEWEILS RECHT BZW. LINKE SEITE AUF GLEICHE VARIANZ SETZEN WIE DIE
|
||||
// JEWEILS ANDERE SEITE
|
||||
});
|
||||
|
||||
// PL 2020-02-05 alle Oder-Constraints Receiver und Parameter werden auf
|
||||
// variance 1 gesetzt
|
||||
// Es wird davon ausgegangen, dass in OderConstraints in Bedingungen für
|
||||
// Parameter die Typen der Argumente links stehen
|
||||
// und die Typen der Rückgabewerte immer rechts stehen
|
||||
|
||||
/*
|
||||
* unifyCons.getOderConstraints().forEach(z -> z.forEach(y -> y.forEach(x -> { if ((x.getLhsType() instanceof PlaceholderType) && x.getPairOp().compareTo(PairOperator.SMALLERDOT) == 0) { ((PlaceholderType) x.getLhsType()).setVariance((byte)1); } else if ((x.getRhsType() instanceof PlaceholderType) && x.getPairOp().compareTo(PairOperator.EQUALSDOT) == 0) { ((PlaceholderType) x.getRhsType()).setVariance((byte)-1); } })));
|
||||
*/
|
||||
|
||||
System.out.println("Unify nach Oder-Constraints-Anpassung:" + unifyCons.toString());
|
||||
Set<PlaceholderType> varianceTPHold;
|
||||
Set<PlaceholderType> varianceTPH = new HashSet<>();
|
||||
varianceTPH = varianceInheritanceConstraintSet(unifyCons);
|
||||
@@ -563,7 +427,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();
|
||||
@@ -778,11 +649,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();
|
||||
auxiliaries.forEach((name, source) -> {
|
||||
generatedClasses.put(new JavaClassName(name), source);
|
||||
});
|
||||
return generatedClasses;
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -30,7 +30,7 @@ public class CompilationEnvironment {
|
||||
public final PackageCrawler packageCrawler;
|
||||
|
||||
/**
|
||||
* Imitiert die Environment beim Aufruf des JavaCompilers auf einer Menge von java-Dateien Die Environment enth<EFBFBD>lt automatisch die Java Standard Library
|
||||
* Imitiert die Environment beim Aufruf des JavaCompilers auf einer Menge von java-Dateien Die Environment enthält automatisch die Java Standard Library
|
||||
*
|
||||
* @param sourceFiles die zu kompilierenden Dateien
|
||||
*/
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -158,7 +158,8 @@ public class FCGenerator {
|
||||
}
|
||||
|
||||
/**
|
||||
* Tauscht die GTVs in einem Typ gegen die entsprechenden Typen in der übergebenen Map aus.
|
||||
* Tauscht die GTVs in einem Typ gegen die entsprechenden Typen in der übergebenen Map aus auf der direkten Argumentebene.
|
||||
* Hier sind keine Wildcards zulässig
|
||||
*/
|
||||
private static class TypeExchanger implements TypeVisitor<RefTypeOrTPHOrWildcardOrGeneric>{
|
||||
|
||||
@@ -172,7 +173,7 @@ public class FCGenerator {
|
||||
public RefTypeOrTPHOrWildcardOrGeneric visit(RefType refType) {
|
||||
List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
|
||||
for(RefTypeOrTPHOrWildcardOrGeneric param : refType.getParaList()){
|
||||
params.add(param.acceptTV(this));
|
||||
params.add(param.acceptTV(new TypeExchangerInner(gtvs)));
|
||||
}
|
||||
RefTypeOrTPHOrWildcardOrGeneric ret = new RefType(refType.getName(), params, new NullToken());
|
||||
return ret;
|
||||
@@ -201,4 +202,51 @@ public class FCGenerator {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tauscht die GTVs in einem Typ gegen die entsprechenden Typen in der übergebenen Map aus auf den Argumenten der Argumente.
|
||||
* Hier sind Wildcards zulässig
|
||||
*/
|
||||
private static class TypeExchangerInner implements TypeVisitor<RefTypeOrTPHOrWildcardOrGeneric>{
|
||||
|
||||
private final HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> gtvs;
|
||||
|
||||
TypeExchangerInner(HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> gtvs){
|
||||
this.gtvs = gtvs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RefTypeOrTPHOrWildcardOrGeneric visit(RefType refType) {
|
||||
List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
|
||||
for(RefTypeOrTPHOrWildcardOrGeneric param : refType.getParaList()){
|
||||
params.add(param.acceptTV(this));
|
||||
}
|
||||
RefTypeOrTPHOrWildcardOrGeneric ret = new RefType(refType.getName(), params, new NullToken());
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RefTypeOrTPHOrWildcardOrGeneric visit(SuperWildcardType superWildcardType) {
|
||||
return superWildcardType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RefTypeOrTPHOrWildcardOrGeneric visit(TypePlaceholder typePlaceholder) {
|
||||
throw new DebugException("Dieser Fall darf nicht auftreten");
|
||||
}
|
||||
|
||||
@Override
|
||||
public RefTypeOrTPHOrWildcardOrGeneric visit(ExtendsWildcardType extendsWildcardType) {
|
||||
return extendsWildcardType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RefTypeOrTPHOrWildcardOrGeneric visit(GenericRefType genericRefType) {
|
||||
if(! gtvs.containsKey(genericRefType.getParsedName()))
|
||||
throw new DebugException("Dieser Fall darf nicht auftreten");
|
||||
return gtvs.get(genericRefType.getParsedName());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -14,6 +14,8 @@ import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||
import de.dhbwstuttgart.syntaxtree.*;
|
||||
import de.dhbwstuttgart.syntaxtree.statement.*;
|
||||
import de.dhbwstuttgart.syntaxtree.type.Void;
|
||||
import de.dhbwstuttgart.target.tree.expression.TargetUnaryOp;
|
||||
import de.dhbwstuttgart.target.generate.StatementToTargetExpression;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
|
||||
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
||||
@@ -101,7 +103,6 @@ import de.dhbwstuttgart.parser.scope.JavaClassRegistry;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefType;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
||||
import org.stringtemplate.v4.ST;
|
||||
|
||||
public class StatementGenerator {
|
||||
|
||||
@@ -125,7 +126,7 @@ public class StatementGenerator {
|
||||
this.superClass = superType;
|
||||
}
|
||||
|
||||
public ParameterList convert(Java17Parser.FormalParameterListContext formalParameterListContext) {
|
||||
public ParameterList convert(Java17Parser.FormalParameterListContext formalParameterListContext, boolean methodparameters) {
|
||||
List<Pattern> ret = new ArrayList<>();
|
||||
List<Java17Parser.FormalParameterContext> fps = new ArrayList<>();
|
||||
if (Objects.isNull(formalParameterListContext))
|
||||
@@ -147,10 +148,12 @@ public class StatementGenerator {
|
||||
if (fp.typeType() != null) {
|
||||
type = TypeGenerator.convert(fp.typeType(), reg, generics);
|
||||
} else {
|
||||
type = TypePlaceholder.fresh(fp.getStart());
|
||||
type = methodparameters?
|
||||
TypePlaceholder.fresh(fp.getStart(), 1, false)
|
||||
: TypePlaceholder.fresh(fp.getStart(), 1, false);
|
||||
}
|
||||
ret.add(new FormalParameter(paramName, type, fp.getStart()));
|
||||
localVars.put(paramName, type);
|
||||
localVars.put(paramName, type);
|
||||
}
|
||||
}
|
||||
return new ParameterList(ret, ret.get(0).getOffset());
|
||||
@@ -439,6 +442,7 @@ public class StatementGenerator {
|
||||
}
|
||||
|
||||
private Pattern convert(PatternContext pattern) {
|
||||
|
||||
return switch (pattern) {
|
||||
case PPatternContext pPattern -> {
|
||||
yield convert(pPattern.primaryPattern());
|
||||
@@ -453,6 +457,7 @@ public class StatementGenerator {
|
||||
}
|
||||
|
||||
private FormalParameter convert(PrimaryPatternContext pPattern) {
|
||||
|
||||
switch (pPattern) {
|
||||
case TPatternContext tPattern:
|
||||
TypePatternContext typePattern = tPattern.typePattern();
|
||||
@@ -463,21 +468,25 @@ public class StatementGenerator {
|
||||
case RPatternContext rPattern:
|
||||
RecordPatternContext recordPattern = rPattern.recordPattern();
|
||||
return convert(recordPattern);
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
case Java17Parser.LPatternContext patternContext: return new LiteralPattern(TypePlaceholder.fresh(patternContext.start), convert(patternContext.literal().get(0)), patternContext.start);
|
||||
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private RecordPattern convert(RecordPatternContext recordPatternCtx) {
|
||||
List<PatternContext> subPatternCtx = recordPatternCtx.recordStructurePattern().recordComponentPatternList().pattern();
|
||||
var cpl = recordPatternCtx.recordStructurePattern().recordComponentPatternList();
|
||||
List<PatternContext> subPatternCtx = cpl == null ? List.of() : cpl.pattern();
|
||||
List<Pattern> subPattern = subPatternCtx.stream().map(this::convert).collect(Collectors.toList());
|
||||
IdentifierContext identifierCtx = recordPatternCtx.identifier();
|
||||
var text = (identifierCtx != null) ? identifierCtx.getText() : null;
|
||||
//Hier evtl. Typ anpassen -> wenn kein Typ bekannt ist push neuen Typ auf Hashtable
|
||||
var type = recordPatternCtx.typeType() == null ? TypePlaceholder.fresh(recordPatternCtx.getStart()) : TypeGenerator.convert(recordPatternCtx.typeType(), reg, generics);
|
||||
if (text != null) localVars.put(text, type);
|
||||
return new RecordPattern(subPattern, text, type, recordPatternCtx.getStart());
|
||||
var ret = new RecordPattern(subPattern, text, type, recordPatternCtx.getStart());
|
||||
return ret;
|
||||
}
|
||||
|
||||
private Statement convert(Java17Parser.WhileloopContext stmt) {
|
||||
@@ -584,7 +593,7 @@ public class StatementGenerator {
|
||||
initValue = convert(varDecl.variableInitializer().expression());
|
||||
}
|
||||
var fieldEntry = fields.get(name.getText());
|
||||
return (new Assign(new AssignToField(new FieldVar(new This(varDecl.getStart()), (fieldEntry.modifiers() & Modifier.STATIC) != 0, name.getText(), type, varDecl.getStart())), initValue, name.getStart()));
|
||||
return (new Assign(new AssignToField(new FieldVar(new This(varDecl.getStart()), name.getText(), type, varDecl.getStart())), initValue, name.getStart()));
|
||||
}
|
||||
|
||||
private Statement convert(Java17Parser.BreakstmtContext stmt) {
|
||||
@@ -698,7 +707,7 @@ public class StatementGenerator {
|
||||
if (!Objects.isNull(expr.methodCall())) {
|
||||
return convert(expr.methodCall(), expr.expression(), offset);
|
||||
} else if (!Objects.isNull(expr.identifier())) {
|
||||
return generateLocalOrFieldVarOrClassName(expr.getText(), offset);
|
||||
return new FieldVar(convert(expr.expression()), expr.identifier().getText(), TypePlaceholder.fresh(expr.identifier().start), offset);
|
||||
} else {
|
||||
// Für alle anderen Optionen, wie Feldzugriff, Aufrufe von super oder explizite
|
||||
// generische Invokationen
|
||||
@@ -774,63 +783,25 @@ public class StatementGenerator {
|
||||
|
||||
/**
|
||||
* Der Parser kann nicht zwischen einer lokalen Variable, einem Feldzugriff und einer Klassenangabe unterscheiden.
|
||||
*
|
||||
*
|
||||
* @param expression
|
||||
* @param offset
|
||||
* @return
|
||||
*/
|
||||
private Expression generateLocalOrFieldVarOrClassName(String expression, Token offset) {
|
||||
String[] parts = expression.split("\\.");
|
||||
if (parts.length < 2) {
|
||||
// Check for localVar:
|
||||
if (localVars.get(expression) != null) {
|
||||
return new LocalVar(expression, localVars.get(expression), offset);
|
||||
} else if (fields.get(expression) != null) {// PL 2018-11-01 fields eingefuegt, damit die fields immer die
|
||||
// gleiche TPH bekommen
|
||||
var field = fields.get(expression);
|
||||
return new FieldVar(new This(offset), Modifier.isStatic(field.modifiers()), expression, fields.get(expression).type(), offset);
|
||||
} else if (reg.contains(expression)) {
|
||||
return generateStaticClassName(expression, offset);
|
||||
} else {
|
||||
// lokale Variable wurde ohne "var"-Keyword deklariert und direkt mit Wert versehen
|
||||
localVars.put(expression, TypePlaceholder.fresh(offset));
|
||||
return new LocalVar(expression, localVars.get(expression), offset);
|
||||
}
|
||||
}
|
||||
return generateFieldVarOrClassname(expression, offset);
|
||||
}
|
||||
|
||||
private Expression generateFieldVarOrClassname(String expression, Token offset) {
|
||||
String[] parts = expression.split("\\.");
|
||||
String whole = "";
|
||||
Expression receiver = null;
|
||||
for (String part : parts) {
|
||||
whole += part;
|
||||
// Check for Classname:
|
||||
if (reg.contains(whole)) {
|
||||
receiver = generateStaticClassName(whole, offset);
|
||||
break;
|
||||
}
|
||||
whole += ".";
|
||||
}
|
||||
var fieldName = parts[parts.length - 1];
|
||||
|
||||
var isStatic = false;
|
||||
if (parts.length < 2 || parts[0].contentEquals("this")) {
|
||||
receiver = new This(offset);
|
||||
isStatic = Modifier.isStatic(fields.get(fieldName).modifiers());
|
||||
} else if (parts[0].contentEquals("super")) {
|
||||
receiver = new Super(TypePlaceholder.fresh(offset), offset);
|
||||
isStatic = Modifier.isStatic(compiler.getClass(new JavaClassName(superClass.getName().toString())).getField(fieldName).orElseThrow().modifier);
|
||||
} else if (receiver == null) { // Handelt es sich um keinen Statischen Klassennamen:
|
||||
String part = expression.substring(0, expression.length() - (1 + parts[parts.length - 1].length()));
|
||||
receiver = generateLocalOrFieldVarOrClassName(part, offset);
|
||||
// Check for localVar:
|
||||
if (localVars.get(expression) != null) {
|
||||
return new LocalVar(expression, localVars.get(expression), offset);
|
||||
} else if (fields.get(expression) != null) {// PL 2018-11-01 fields eingefuegt, damit die fields immer die
|
||||
// gleiche TPH bekommen
|
||||
return new FieldVar(new This(offset), expression, fields.get(expression).type(), offset);
|
||||
} else if (reg.contains(expression)) {
|
||||
return generateStaticClassName(expression, offset);
|
||||
} else {
|
||||
StaticClassName cname = (StaticClassName) receiver;
|
||||
var javaClassName = reg.getName(cname.getType().toString());
|
||||
isStatic = Modifier.isStatic(compiler.getClass(javaClassName).getField(fieldName).orElseThrow().modifier);
|
||||
// lokale Variable wurde ohne "var"-Keyword deklariert und direkt mit Wert versehen
|
||||
localVars.put(expression, TypePlaceholder.fresh(offset));
|
||||
return new LocalVar(expression, localVars.get(expression), offset);
|
||||
}
|
||||
return new FieldVar(receiver, isStatic, fieldName, TypePlaceholder.fresh(offset), offset);
|
||||
}
|
||||
|
||||
private Expression convert(Java17Parser.ArrayaccessexpressionContext arrayaccess) {
|
||||
@@ -866,10 +837,8 @@ public class StatementGenerator {
|
||||
private Statement convert(AssignexpressionContext expr) {
|
||||
switch (expr.bop.getText()) {
|
||||
case "=":
|
||||
ExpressionContext leftside = expr.expression(0);
|
||||
AssignLeftSide leftHandSide = convert(leftside.getText(), leftside.getStart());
|
||||
Statement ret = new Assign(leftHandSide, convert(expr.expression(1)), expr.getStart());
|
||||
return ret;
|
||||
AssignLeftSide leftHandSide = convertAssignLHS(convert(expr.expression(0)));
|
||||
return new Assign(leftHandSide, convert(expr.expression(1)), expr.getStart());
|
||||
case "+=":
|
||||
case "-=":
|
||||
case "*=":
|
||||
@@ -886,8 +855,8 @@ public class StatementGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
private AssignLeftSide convert(String leftHandSide, Token start) {
|
||||
Expression leftSide = generateLocalOrFieldVarOrClassName(leftHandSide, start);
|
||||
private AssignLeftSide convertAssignLHS(Expression expr) {
|
||||
Expression leftSide = expr;
|
||||
if (leftSide instanceof FieldVar)
|
||||
return new AssignToField((FieldVar) leftSide);
|
||||
else if (leftSide instanceof LocalVar)
|
||||
@@ -1096,17 +1065,17 @@ public class StatementGenerator {
|
||||
List<Pattern> parameterList = new ArrayList<>();
|
||||
for (IdentifierContext identifier : lambdaParams.identifier()) {
|
||||
Token offset = identifier.getStart();
|
||||
parameterList.add(new FormalParameter(identifier.getText(), TypePlaceholder.fresh(offset), offset));
|
||||
parameterList.add(new FormalParameter(identifier.getText(), TypePlaceholder.fresh(offset, 1, false), offset));
|
||||
}
|
||||
params = new ParameterList(parameterList, lambdaParams.getStart());
|
||||
} else if (lambdaParams.formalParameterList() != null) {
|
||||
params = convert(lambdaParams.formalParameterList());
|
||||
params = convert(lambdaParams.formalParameterList(), false);
|
||||
// }else if( lambdaParams.inferredFormalParameterList != null){
|
||||
} else if (!Objects.isNull(lambdaParams.lambdaLVTIList())) {
|
||||
List<Pattern> parameterList = new ArrayList<>();
|
||||
for (LambdaLVTIParameterContext param : lambdaParams.lambdaLVTIList().lambdaLVTIParameter()) {
|
||||
Token offset = param.getStart();
|
||||
parameterList.add(new FormalParameter(param.identifier().getText(), TypePlaceholder.fresh(offset), offset));
|
||||
parameterList.add(new FormalParameter(param.identifier().getText(), TypePlaceholder.fresh(offset, 1, false), offset));
|
||||
}
|
||||
params = new ParameterList(parameterList, lambdaParams.getStart());
|
||||
} else {
|
||||
@@ -1130,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()),
|
||||
|
@@ -254,7 +254,10 @@ public class SyntaxTreeGenerator {
|
||||
List<RefType> implementedInterfaces = new ArrayList<>();
|
||||
List<Pattern> constructorParameters = new ArrayList<>();
|
||||
List<Statement> constructorStatements = new ArrayList<>();
|
||||
for (RecordComponentContext component : recordDeclaration.recordHeader().recordComponentList().recordComponent()) {
|
||||
|
||||
List<Java17Parser.RecordComponentContext> components = recordDeclaration.recordHeader().recordComponentList() != null ?
|
||||
recordDeclaration.recordHeader().recordComponentList().recordComponent(): List.of();
|
||||
for (RecordComponentContext component : components) {
|
||||
int fieldmodifiers = allmodifiers.get("private") + allmodifiers.get("final");
|
||||
String fieldname = component.identifier().getText();
|
||||
Token fieldoffset = component.getStart();
|
||||
@@ -266,7 +269,7 @@ public class SyntaxTreeGenerator {
|
||||
}
|
||||
fielddecl.add(new Field(fieldname, fieldtype, fieldmodifiers, fieldoffset));
|
||||
constructorParameters.add(new FormalParameter(fieldname, fieldtype, fieldoffset));
|
||||
FieldVar fieldvar = new FieldVar(new This(offset), false, fieldname, fieldtype, fieldoffset);
|
||||
FieldVar fieldvar = new FieldVar(new This(offset), fieldname, fieldtype, fieldoffset);
|
||||
constructorStatements.add(new Assign(new AssignToField(fieldvar), new LocalVar(fieldname, fieldtype, fieldoffset), offset));
|
||||
Statement returnStatement = new Return(fieldvar, offset);
|
||||
methods.add(new Method(allmodifiers.get("public"), fieldname, fieldtype, new ParameterList(new ArrayList<>(), offset), new Block(Arrays.asList(returnStatement), offset), new GenericDeclarationList(new ArrayList<>(), offset), offset));
|
||||
@@ -390,12 +393,12 @@ public class SyntaxTreeGenerator {
|
||||
if (!Objects.isNull(ctx.EXTENDS())) {
|
||||
extendedInterfaces.addAll(convert(ctx.typeList(0), generics));
|
||||
}
|
||||
List<RefType> permittedSubtypes = new ArrayList<>();
|
||||
List<RefType> permittedSubtypes = null;
|
||||
// Ist Bit für 'sealed'-Modifier gesetzt
|
||||
if ((modifiers & 4096) != 0) {
|
||||
if (!Objects.isNull(ctx.PERMITS())) {
|
||||
// permitted subtypes sind letzte typeList (siehe Grammatikregel 'classDeclaration')
|
||||
permittedSubtypes.addAll(convert(ctx.typeList(ctx.typeList().size() - 1), generics));
|
||||
permittedSubtypes = new ArrayList<>(convert(ctx.typeList(ctx.typeList().size() - 1), generics));
|
||||
} else {
|
||||
// falls sealed modifier ohne 'permits'-List oder umgekehrt
|
||||
throw new NotImplementedException("Invalid sealed class declaration");
|
||||
@@ -432,7 +435,7 @@ public class SyntaxTreeGenerator {
|
||||
}
|
||||
}
|
||||
StatementGenerator stmtgen = new StatementGenerator(superClass, compiler, reg, generics, fields, new HashMap<>());
|
||||
ParameterList paramlist = stmtgen.convert(bodydeclaration.formalParameters().formalParameterList());
|
||||
ParameterList paramlist = stmtgen.convert(bodydeclaration.formalParameters().formalParameterList(), true);
|
||||
MethodBodyContext body = bodydeclaration.methodBody();
|
||||
Block block = null;
|
||||
if (!(body instanceof EmptymethodContext)) {
|
||||
@@ -529,7 +532,7 @@ public class SyntaxTreeGenerator {
|
||||
|
||||
RefTypeOrTPHOrWildcardOrGeneric retType;
|
||||
if (Objects.isNull(header.refType())) {
|
||||
retType = TypePlaceholder.fresh(header.getStart());
|
||||
retType = TypePlaceholder.fresh(header.getStart(), -1, false);
|
||||
} else {
|
||||
if (header.refType() instanceof RefType2Context reftype) {
|
||||
retType = TypeGenerator.convert(reftype.typeType(), reg, generics);
|
||||
@@ -538,7 +541,7 @@ public class SyntaxTreeGenerator {
|
||||
}
|
||||
}
|
||||
StatementGenerator stmtgen = new StatementGenerator(superClass, compiler, reg, localgenerics, fields, new HashMap<>());
|
||||
ParameterList paramlist = stmtgen.convert(header.formalParameters().formalParameterList());
|
||||
ParameterList paramlist = stmtgen.convert(header.formalParameters().formalParameterList(), true);
|
||||
MethodBodyContext body = methoddeclaration.methodBody();
|
||||
Block block = null;
|
||||
if (body instanceof EmptymethodContext emptymethod) {
|
||||
@@ -578,7 +581,7 @@ public class SyntaxTreeGenerator {
|
||||
}
|
||||
RefTypeOrTPHOrWildcardOrGeneric retType = TypeGenerator.convertTypeName(name, constructordeclaration.getStart(), reg, localgenerics);
|
||||
StatementGenerator stmtgen = new StatementGenerator(superClass, compiler, reg, localgenerics, fields, new HashMap<>());
|
||||
ParameterList paramlist = stmtgen.convert(constructordeclaration.formalParameters().formalParameterList());
|
||||
ParameterList paramlist = stmtgen.convert(constructordeclaration.formalParameters().formalParameterList(), true);
|
||||
Block block = prepareBlock(stmtgen.convert(constructordeclaration.constructorBody, true), superClass);
|
||||
return new Constructor(modifiers, name, retType, paramlist, block, gtvDeclarations, constructordeclaration.getStart());
|
||||
}
|
||||
@@ -591,7 +594,7 @@ public class SyntaxTreeGenerator {
|
||||
} else {
|
||||
// PL 2019-12-06: variableDeclaratorList() eingefuegt, um als Token nicht die
|
||||
// Modifier zu bekommen
|
||||
fieldType = TypePlaceholder.fresh(fieldDeclContext.variableDeclarators().getStart());
|
||||
fieldType = TypePlaceholder.fresh(fieldDeclContext.variableDeclarators().getStart(), -1, false);
|
||||
}
|
||||
for (Java17Parser.VariableDeclaratorContext varDecl : fieldDeclContext.variableDeclarators().variableDeclarator()) {
|
||||
String fieldName = varDecl.variableDeclaratorId().getText();
|
||||
|
@@ -41,7 +41,7 @@ public class JavaClassName {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt von einem Klassennamen nur den Namen der Klasse zur<EFBFBD>ck
|
||||
* Gibt von einem Klassennamen nur den Namen der Klasse zurück
|
||||
* Beispiel:
|
||||
* java.lang.Object wird zu: Object
|
||||
*/
|
||||
|
@@ -5,9 +5,9 @@ import de.dhbwstuttgart.exceptions.NotImplementedException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Speichert die Klassen f<EFBFBD>r einen bestimmten Projektscope
|
||||
* Speichert die Klassen für einen bestimmten Projektscope
|
||||
*/
|
||||
public class JavaClassRegistry {
|
||||
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);
|
||||
}
|
||||
|
@@ -10,6 +10,8 @@ public interface ASTVisitor extends StatementVisitor{
|
||||
|
||||
void visit(FormalParameter formalParameter);
|
||||
|
||||
void visit(LiteralPattern literalPattern);
|
||||
|
||||
void visit(GenericDeclarationList genericTypeVars);
|
||||
|
||||
void visit(Field field);
|
||||
|
@@ -37,6 +37,11 @@ public abstract class AbstractASTWalker implements ASTVisitor {
|
||||
formalParameter.getType().accept((ASTVisitor) this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(LiteralPattern literalPattern) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(GenericDeclarationList genericTypeVars) {
|
||||
Iterator<GenericTypeVar> genericIterator = genericTypeVars.iterator();
|
||||
|
@@ -6,10 +6,12 @@ import de.dhbwstuttgart.syntaxtree.type.GenericRefType;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefType;
|
||||
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||
import de.dhbwstuttgart.target.tree.TargetGeneric;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Stellt jede Art von Klasse dar. Auch abstrakte Klassen und Interfaces
|
||||
@@ -31,6 +33,7 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope {
|
||||
private List<RefType> implementedInterfaces;
|
||||
private List<RefType> permittedSubtypes;
|
||||
private List<Constructor> constructors;
|
||||
private Set<GenericTypeVar> userDefinedGenerics;
|
||||
|
||||
public ClassOrInterface(int modifiers, JavaClassName name, List<Field> fielddecl, Optional<Constructor> fieldInitializations, Optional<Method> staticInitializer, List<Method> methods, List<Constructor> constructors, GenericDeclarationList genericClassParameters, RefType superClass, Boolean isInterface, Boolean isFunctionalInterface, List<RefType> implementedInterfaces, List<RefType> permittedSubtypes, Token offset, String fileName) {
|
||||
super(offset);
|
||||
@@ -86,6 +89,9 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope {
|
||||
return staticInitializer;
|
||||
}
|
||||
|
||||
public boolean isSealed() { return permittedSubtypes != null; }
|
||||
public List<RefType> getPermittedSubtypes() { return permittedSubtypes != null ? permittedSubtypes : List.of(); }
|
||||
|
||||
public boolean isInterface() {
|
||||
return (Modifier.INTERFACE & this.getModifiers()) != 0;
|
||||
}
|
||||
@@ -188,13 +194,30 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope {
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
ClassOrInterface that = (ClassOrInterface) o;
|
||||
return Objects.equals(name, that.name);
|
||||
if (!(o instanceof ClassOrInterface other)) return false;
|
||||
return Objects.equals(name, other.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(name);
|
||||
}
|
||||
|
||||
public Set<GenericTypeVar> getUserDefinedGenerics() {
|
||||
if (this.userDefinedGenerics != null) return this.userDefinedGenerics;
|
||||
|
||||
var genericsIter = getGenerics().iterator();
|
||||
if (genericsIter.hasNext()) {
|
||||
// Add empty set of generics to cache so that it doesn't try to calculate it later
|
||||
this.userDefinedGenerics = new HashSet<>();
|
||||
while (genericsIter.hasNext()) {
|
||||
var next = genericsIter.next();
|
||||
userDefinedGenerics.add(next);
|
||||
}
|
||||
} else {
|
||||
this.userDefinedGenerics = new HashSet<>();
|
||||
}
|
||||
|
||||
return this.userDefinedGenerics;
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,29 @@
|
||||
package de.dhbwstuttgart.syntaxtree;
|
||||
|
||||
|
||||
import de.dhbwstuttgart.syntaxtree.ASTVisitor;
|
||||
import de.dhbwstuttgart.syntaxtree.Pattern;
|
||||
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
|
||||
import de.dhbwstuttgart.syntaxtree.statement.Expression;
|
||||
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
|
||||
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation;
|
||||
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
|
||||
public class LiteralPattern extends FormalParameter
|
||||
{
|
||||
public final Expression value;
|
||||
public LiteralPattern(RefTypeOrTPHOrWildcardOrGeneric type, Expression value, Token offset) {
|
||||
super(null, type, offset);
|
||||
|
||||
this.value = value;
|
||||
}
|
||||
@Override
|
||||
public FormalParameter withType(RefTypeOrTPHOrWildcardOrGeneric type) {
|
||||
return new LiteralPattern(type, value, getOffset());
|
||||
}
|
||||
@Override
|
||||
public void accept(ASTVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
@@ -5,8 +5,10 @@ import java.util.*;
|
||||
|
||||
import de.dhbwstuttgart.parser.NullToken;
|
||||
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||
import de.dhbwstuttgart.target.generate.ASTToTargetAST;
|
||||
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
|
||||
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation;
|
||||
import de.dhbwstuttgart.typeinference.result.ResultSet;
|
||||
//import sun.security.x509.X509CertInfo;
|
||||
|
||||
public class SourceFile extends SyntaxTreeNode {
|
||||
@@ -18,6 +20,7 @@ public class SourceFile extends SyntaxTreeNode {
|
||||
private boolean isGenerated;
|
||||
|
||||
public List<ClassOrInterface> availableClasses = new ArrayList<>();
|
||||
public List<ASTToTargetAST.Generics> generics = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Die SourceFile repräsntiert eine zu einem Syntaxbaum eingelesene Java-Datei.
|
||||
@@ -40,6 +43,10 @@ public class SourceFile extends SyntaxTreeNode {
|
||||
this.imports = new HashSet<>(sf.imports);
|
||||
}
|
||||
|
||||
public void addResultSet(ResultSet rs) {
|
||||
|
||||
}
|
||||
|
||||
public void setPackageName(String packageName) {
|
||||
this.pkgName = packageName;
|
||||
}
|
||||
|
@@ -3,6 +3,7 @@ package de.dhbwstuttgart.syntaxtree;
|
||||
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal;
|
||||
import de.dhbwstuttgart.syntaxtree.statement.*;
|
||||
|
||||
|
||||
public interface StatementVisitor {
|
||||
|
||||
void visit(ArgumentList argumentList);
|
||||
|
@@ -176,8 +176,9 @@ public class ASTFactory {
|
||||
for (Type jreInterface : jreClass.getGenericInterfaces()) {
|
||||
implementedInterfaces.add((RefType) createType(jreInterface));
|
||||
}
|
||||
List<RefType> permittedSubtypes = new ArrayList<>();
|
||||
List<RefType> permittedSubtypes = null;
|
||||
if (jreClass.isSealed()) {
|
||||
permittedSubtypes = new ArrayList<>();
|
||||
for (Class subclass : jreClass.getPermittedSubclasses()) {
|
||||
permittedSubtypes.add((RefType) createType(subclass));
|
||||
}
|
||||
|
@@ -129,9 +129,10 @@ public class UnifyTypeFactory {
|
||||
if (tph.getName().equals("AFR")) {
|
||||
System.out.println("XXX"+innerType);
|
||||
}
|
||||
PlaceholderType ntph = new PlaceholderType(tph.getName());
|
||||
PlaceholderType ntph = new PlaceholderType(tph.getName(), tph.getVariance());
|
||||
ntph.setVariance(tph.getVariance());
|
||||
ntph.setOrCons(tph.getOrCons());
|
||||
ntph.setWildcardtable(tph.getWildcardtable());
|
||||
int in = PLACEHOLDERS.indexOf(ntph);
|
||||
if (in == -1) {
|
||||
PLACEHOLDERS.add(ntph);
|
||||
|
@@ -17,13 +17,11 @@ public class FieldVar extends Expression {
|
||||
|
||||
public final String fieldVarName;
|
||||
public final Expression receiver;
|
||||
public final boolean isStatic;
|
||||
|
||||
public FieldVar(Expression receiver, boolean isStatic, String fieldVarName, RefTypeOrTPHOrWildcardOrGeneric type, Token offset) {
|
||||
public FieldVar(Expression receiver, String fieldVarName, RefTypeOrTPHOrWildcardOrGeneric type, Token offset) {
|
||||
super(type, offset);
|
||||
this.fieldVarName = fieldVarName;
|
||||
this.receiver = receiver;
|
||||
this.isStatic = isStatic;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -8,6 +8,7 @@ import org.antlr.v4.runtime.Token;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
|
||||
public class RefType extends RefTypeOrTPHOrWildcardOrGeneric
|
||||
@@ -49,10 +50,7 @@ public class RefType extends RefTypeOrTPHOrWildcardOrGeneric
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 0;
|
||||
hash += super.hashCode();
|
||||
hash += this.name.hashCode();//Nur den Name hashen. Sorgt für langsame, aber funktionierende HashMaps
|
||||
return hash;
|
||||
return this.name.hashCode();//Nur den Name hashen. Sorgt für langsame, aber funktionierende HashMaps
|
||||
}
|
||||
|
||||
public RefType(JavaClassName fullyQualifiedName, List<RefTypeOrTPHOrWildcardOrGeneric> parameter, Token offset) {
|
||||
@@ -83,6 +81,7 @@ public class RefType extends RefTypeOrTPHOrWildcardOrGeneric
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if(obj instanceof RefType){
|
||||
if (!Objects.equals(this.name, ((RefType) obj).name)) return false;
|
||||
boolean ret = true;
|
||||
|
||||
//if(!(super.equals(obj))) PL 2020-03-12 muss vll. einkommentiert werden
|
||||
|
@@ -21,10 +21,18 @@ public class TypePlaceholder extends RefTypeOrTPHOrWildcardOrGeneric
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* wird im Generate Generics Teil nach der Rueckumwandlung nach dem Unify genutzt
|
||||
*/
|
||||
* variance shows the variance of the pair
|
||||
* 1: contravariant
|
||||
* -1 covariant
|
||||
* 0 invariant
|
||||
*/
|
||||
private int variance = 0;
|
||||
|
||||
/**
|
||||
* isWildcardable gibt an, ob ein Wildcardtyp dem PlaceholderType zugeordnet werden darf
|
||||
*/
|
||||
private boolean wildcardable = true;
|
||||
|
||||
/*
|
||||
* Fuer Oder-Constraints:
|
||||
* orCons = 1: Receiver
|
||||
@@ -39,10 +47,12 @@ public class TypePlaceholder extends RefTypeOrTPHOrWildcardOrGeneric
|
||||
* Factory-Methode <code>fresh()</code> erzeugt.
|
||||
* <br>Author: J�rg B�uerle
|
||||
*/
|
||||
private TypePlaceholder(String name, Token offset)
|
||||
private TypePlaceholder(String name, Token offset, int variance, boolean wildcardable)
|
||||
{
|
||||
super(offset);
|
||||
this.name = name;
|
||||
this.variance = variance;
|
||||
this.wildcardable = wildcardable;
|
||||
}
|
||||
|
||||
|
||||
@@ -53,11 +63,15 @@ public class TypePlaceholder extends RefTypeOrTPHOrWildcardOrGeneric
|
||||
* @return
|
||||
*/
|
||||
public static TypePlaceholder fresh(Token position){
|
||||
return new TypePlaceholder(NameGenerator.makeNewName(), position);
|
||||
return new TypePlaceholder(NameGenerator.makeNewName(), position, 0, true);
|
||||
}
|
||||
|
||||
public static TypePlaceholder fresh(Token position, int variance, boolean wildcardable){
|
||||
return new TypePlaceholder(NameGenerator.makeNewName(), position, variance, wildcardable);
|
||||
}
|
||||
|
||||
public static RefTypeOrTPHOrWildcardOrGeneric of(String name) {
|
||||
return new TypePlaceholder(name, new NullToken());
|
||||
return new TypePlaceholder(name, new NullToken(),0, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -120,4 +134,9 @@ public class TypePlaceholder extends RefTypeOrTPHOrWildcardOrGeneric
|
||||
public byte getOrCons() {
|
||||
return orCons;
|
||||
}
|
||||
|
||||
|
||||
public Boolean getWildcardtable() {
|
||||
return wildcardable;
|
||||
}
|
||||
}
|
||||
|
@@ -57,6 +57,11 @@ public class OutputGenerator implements ASTVisitor {
|
||||
out.append(formalParameter.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(LiteralPattern literalPattern) {
|
||||
literalPattern.value.accept(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(GenericDeclarationList genericTypeVars) {
|
||||
Iterator<GenericTypeVar> genericIterator = genericTypeVars.iterator();
|
||||
@@ -508,12 +513,11 @@ public class OutputGenerator implements ASTVisitor {
|
||||
aRecordPattern.getType().accept(this);
|
||||
out.append("(");
|
||||
List<Pattern> subPatterns = aRecordPattern.getSubPattern();
|
||||
int i;
|
||||
for (i = 0; i < subPatterns.size() - 1; i++) {
|
||||
for (var i = 0; i < subPatterns.size(); i++) {
|
||||
subPatterns.get(i).accept(this);
|
||||
out.append(", ");
|
||||
if (i < subPatterns.size() - 1)
|
||||
out.append(", ");
|
||||
}
|
||||
subPatterns.get(i).accept(this);
|
||||
String name;
|
||||
if ((name = aRecordPattern.getName()) != null)
|
||||
out.append(name);
|
||||
|
@@ -1,11 +1,9 @@
|
||||
package de.dhbwstuttgart.target.generate;
|
||||
|
||||
import de.dhbwstuttgart.bytecode.CodeGenException;
|
||||
import de.dhbwstuttgart.bytecode.FunNGenerator;
|
||||
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||
import de.dhbwstuttgart.environment.ByteArrayClassLoader;
|
||||
import de.dhbwstuttgart.environment.IByteArrayClassLoader;
|
||||
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
||||
import de.dhbwstuttgart.exceptions.DebugException;
|
||||
import de.dhbwstuttgart.parser.NullToken;
|
||||
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||
import de.dhbwstuttgart.syntaxtree.*;
|
||||
@@ -13,31 +11,40 @@ 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.*;
|
||||
import de.dhbwstuttgart.typeinference.result.*;
|
||||
|
||||
import javax.sql.rowset.RowSetWarning;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
/**
|
||||
* @author dholle
|
||||
*/
|
||||
public class ASTToTargetAST {
|
||||
|
||||
record SignaturePair(TypePlaceholder signature, RefTypeOrTPHOrWildcardOrGeneric parameter) {};
|
||||
record SignaturePairTarget(TargetType signature, TargetType parameter) {}
|
||||
|
||||
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;
|
||||
final Map<ClassOrInterface, Set<GenericTypeVar>> userDefinedGenerics = new HashMap<>();
|
||||
public List<Generics> currentMethodOverloads;
|
||||
|
||||
final Map<Method, Set<SignaturePair>> tphsInMethods = new HashMap<>();
|
||||
private Method currentMethod;
|
||||
|
||||
public final JavaTXCompiler compiler;
|
||||
|
||||
public List<RefTypeOrTPHOrWildcardOrGeneric> findAllVariants(RefTypeOrTPHOrWildcardOrGeneric type) {
|
||||
return javaGenerics().stream().map(generics -> generics.resolve(type)).distinct().toList();
|
||||
}
|
||||
|
||||
public List<GenericsResult> txGenerics() {
|
||||
return all.stream().map(generics -> new GenericsResult(generics.txGenerics)).toList();
|
||||
}
|
||||
@@ -53,17 +60,19 @@ public class ASTToTargetAST {
|
||||
}
|
||||
|
||||
public record Generics(JavaGenerics javaGenerics, TxGenerics txGenerics) {
|
||||
public Generics(JavaTXCompiler compiler, ResultSet set) {
|
||||
this(new JavaGenerics(compiler, set), new TxGenerics(compiler, set));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected IByteArrayClassLoader classLoader;
|
||||
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) {
|
||||
@@ -73,15 +82,25 @@ public class ASTToTargetAST {
|
||||
|
||||
all = new ArrayList<>();
|
||||
for (var set : resultSets) {
|
||||
all.add(new Generics(new JavaGenerics(this, set), new TxGenerics(this, set)));
|
||||
all.add(new Generics(compiler, set));
|
||||
}
|
||||
this.generics = all.get(0);
|
||||
this.generics = all.getFirst();
|
||||
}
|
||||
|
||||
public void addSignaturePair(TypePlaceholder signature, RefTypeOrTPHOrWildcardOrGeneric parameter) {
|
||||
var set = tphsInMethods.getOrDefault(currentMethod, new HashSet<>());
|
||||
set.add(new SignaturePair(signature, parameter));
|
||||
tphsInMethods.put(currentMethod, set);
|
||||
}
|
||||
|
||||
Optional<Method> findMethod(ClassOrInterface owner, String name, List<TargetType> argumentList) {
|
||||
return findMethod(owner, name, argumentList, this.generics.javaGenerics, this.compiler);
|
||||
}
|
||||
|
||||
public static Optional<Method> findMethod(ClassOrInterface owner, String name, List<TargetType> argumentList, GenerateGenerics generics, JavaTXCompiler compiler) {
|
||||
Optional<Method> method = Optional.empty();
|
||||
while (method.isEmpty()) {
|
||||
method = owner.getMethods().stream().filter(m -> m.name.equals(name) && parameterEquals(m.getParameterList(), argumentList)).findFirst();
|
||||
method = owner.getMethods().stream().filter(m -> m.name.equals(name) && parameterEquals(m.getParameterList(), argumentList, generics)).findFirst();
|
||||
if (owner.getClassName().toString().equals("java.lang.Object")) break;
|
||||
owner = compiler.getClass(owner.getSuperClass().getName());
|
||||
}
|
||||
@@ -89,16 +108,16 @@ public class ASTToTargetAST {
|
||||
}
|
||||
|
||||
Optional<Constructor> findConstructor(ClassOrInterface owner, List<TargetType> argumentList) {
|
||||
return owner.getConstructors().stream().filter(c -> parameterEquals(c.getParameterList(), argumentList)).findFirst();
|
||||
return owner.getConstructors().stream().filter(c -> parameterEquals(c.getParameterList(), argumentList, generics.javaGenerics)).findFirst();
|
||||
}
|
||||
|
||||
boolean parameterEquals(ParameterList parameterList, List<TargetType> arguments) {
|
||||
static boolean parameterEquals(ParameterList parameterList, List<TargetType> arguments, GenerateGenerics generics) {
|
||||
var pars = parameterList.getFormalparalist();
|
||||
if (pars.size() != arguments.size())
|
||||
return false;
|
||||
|
||||
for (var i = 0; i < pars.size(); i++) {
|
||||
var type1 = convert(pars.get(i).getType(), generics.javaGenerics);
|
||||
var type1 = generics.getTargetType(pars.get(i).getType());
|
||||
var type2 = arguments.get(i);
|
||||
if (type1 instanceof TargetGenericType)
|
||||
return true;
|
||||
@@ -131,23 +150,219 @@ public class ASTToTargetAST {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// This finds a common sealed interface type to group together methods that use different records
|
||||
private List<ClassOrInterface> commonSuperInterfaceTypes(TargetType a, TargetType b) {
|
||||
if (a instanceof TargetGenericType && b instanceof TargetGenericType) return List.of(ASTFactory.createObjectClass());
|
||||
if (a instanceof TargetRefType ta && b instanceof TargetGenericType)
|
||||
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()));
|
||||
|
||||
if (cla.equals(clb)) return List.of(cla);
|
||||
|
||||
while (!cla.equals(ASTFactory.createObjectClass())) {
|
||||
var clb2 = clb;
|
||||
while (!clb2.equals(ASTFactory.createObjectClass())) {
|
||||
for (var intfa : cla.getSuperInterfaces()) {
|
||||
for (var intfb : clb.getSuperInterfaces()) {
|
||||
if (intfa.equals(intfb)) {
|
||||
var clintf = compiler.getClass(intfa.getName());
|
||||
if (clintf.isSealed()) {
|
||||
res.add(clintf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
clb2 = compiler.getClass(clb2.getSuperClass().getName());
|
||||
}
|
||||
cla = compiler.getClass(cla.getSuperClass().getName());
|
||||
}
|
||||
return res.stream().toList();
|
||||
}
|
||||
return List.of();
|
||||
}
|
||||
|
||||
// TODO This is ugly and probably doesn't work right
|
||||
private boolean patternStrictlyEquals(TargetComplexPattern a, TargetComplexPattern b) {
|
||||
if (!a.name().equals(b.name())) return false;
|
||||
if (a.subPatterns().size() != b.subPatterns().size()) return false;
|
||||
for (var i = 0; i < a.subPatterns().size(); i++) {
|
||||
var p1 = a.subPatterns().get(i);
|
||||
var p2 = b.subPatterns().get(i);
|
||||
if (p1 instanceof TargetComplexPattern pc1 && p2 instanceof TargetComplexPattern pc2 &&
|
||||
patternStrictlyEquals(pc1, pc2)) return false;
|
||||
if (p1 instanceof TargetTypePattern pt1 && p2 instanceof TargetTypePattern pt2) {
|
||||
if (pt1.type() instanceof TargetGenericType && pt2.type() instanceof TargetGenericType) continue;
|
||||
}
|
||||
if (!p1.type().equals(p2.type()) && commonSuperInterfaceTypes(p1.type(), p2.type()).isEmpty()) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean canCombine(TargetMethod m1, TargetMethod m2) {
|
||||
if (!m1.name().equals(m2.name())) return false;
|
||||
var s1 = m1.signature();
|
||||
var s2 = m2.signature();
|
||||
if (s1.parameters().size() != s2.parameters().size()) return false;
|
||||
if (s1.parameters().isEmpty()) return false;
|
||||
for (var i = 0; i < s1.parameters().size(); i++) {
|
||||
var p1 = s1.parameters().get(i).pattern();
|
||||
var p2 = s2.parameters().get(i).pattern();
|
||||
if (p1.type() instanceof TargetGenericType || p2.type() instanceof TargetGenericType) continue;
|
||||
if (p1 instanceof TargetComplexPattern pc1 && p2 instanceof TargetComplexPattern pc2 &&
|
||||
patternStrictlyEquals(pc1, pc2)) return false;
|
||||
if (!p1.equals(p2) && commonSuperInterfaceTypes(p1.type(), p2.type()).isEmpty()) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private record Combination(TargetMethod a, TargetMethod b) {
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof Combination(TargetMethod a1, TargetMethod 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);
|
||||
}
|
||||
}
|
||||
|
||||
public List<List<TargetMethod>> groupOverloads(ClassOrInterface input, List<Method> methods) {
|
||||
var mapOfTargetMethods = new HashMap<Generics, TargetMethod[]>();
|
||||
for (var generics : all) {
|
||||
mapOfTargetMethods.put(generics, new TargetMethod[methods.size()]);
|
||||
}
|
||||
|
||||
for (var i = 0; i < methods.size(); i++) {
|
||||
var method = methods.get(i);
|
||||
// Convert all methods
|
||||
var methodsWithTphs = convert(input, method);
|
||||
for (var m : methodsWithTphs) {
|
||||
var resultMethods = mapOfTargetMethods.get(m.generics);
|
||||
resultMethods[i] = m.method;
|
||||
}
|
||||
}
|
||||
/*System.out.println("============== INPUT ==============");
|
||||
for (var m : mapOfTargetMethods.values()) {
|
||||
for (var v : m) System.out.println(v.name() + " " + v.getSignature());
|
||||
System.out.println();
|
||||
}*/
|
||||
|
||||
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, m2)) {
|
||||
//System.out.println(" Combining " + m1.getSignature() + " and " + m2.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.getSignature() + " and " + m3.getSignature());
|
||||
}
|
||||
} else {
|
||||
//System.out.println(" Not Combining " + m1.getSignature() + " and " + m2.getSignature());
|
||||
}
|
||||
if (!combinations.isEmpty()) allCombinations.add(combinations);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (allCombinations.isEmpty()) allCombinations.add(new HashSet<>());
|
||||
|
||||
// Combine back into output format
|
||||
var r0 = new HashSet<Set<TargetMethod>>();
|
||||
for (var combinations : allCombinations) {
|
||||
var r1 = new HashSet<Set<TargetMethod>>();
|
||||
// This is used to weed out duplicates
|
||||
var uniqued = new HashSet<TargetMethod>();
|
||||
// We go over all methods in the result
|
||||
for (var g : all) for (var i = 0; i < methods.size(); i++) {
|
||||
var r2 = new HashSet<TargetMethod>();
|
||||
var 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.name() + " " + m.getSignature());
|
||||
System.out.println();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public TargetStructure convert(ClassOrInterface input) {
|
||||
Set<TargetGeneric> javaGenerics = new HashSet<>();
|
||||
Set<TargetGeneric> txGenerics = new HashSet<>();
|
||||
|
||||
var genericsIter = input.getGenerics().iterator();
|
||||
if (genericsIter.hasNext()) {
|
||||
var userDefinedGenerics = input.getUserDefinedGenerics();
|
||||
if (!userDefinedGenerics.isEmpty()) {
|
||||
// Add empty set of generics to cache so that it doesn't try to calculate it later
|
||||
var userDefinedGenerics = new HashSet<GenericTypeVar>();
|
||||
this.userDefinedGenerics.put(input, userDefinedGenerics);
|
||||
while (genericsIter.hasNext()) {
|
||||
var next = genericsIter.next();
|
||||
userDefinedGenerics.add(next);
|
||||
// TODO Support multiple bounds
|
||||
javaGenerics.add(new TargetGeneric(next.getName(), convert(next.getBounds().get(0))));
|
||||
for (var generic : userDefinedGenerics) {
|
||||
// TODO Support multiple bouds
|
||||
javaGenerics.add(new TargetGeneric(generic.getName(), convert(generic.getBounds().getFirst())));
|
||||
}
|
||||
} else {
|
||||
this.userDefinedGenerics.put(input, new HashSet<>());
|
||||
// Generate generics only if there are no user defined ones
|
||||
javaGenerics = convert(generics.javaGenerics.generics(input), generics.javaGenerics);
|
||||
txGenerics = convert(generics.txGenerics.generics(input), generics.txGenerics);
|
||||
@@ -161,11 +376,12 @@ public class ASTToTargetAST {
|
||||
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.getMethods()).stream().map(m -> convert(input, m)).flatMap(Set::stream).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();
|
||||
staticConstructor = this.convert(input, input.getStaticInitializer().get()).stream().findFirst().orElseThrow().method;
|
||||
|
||||
if (input instanceof Record)
|
||||
return new TargetRecord(input.getModifiers(), input.getClassName(), javaGenerics, txGenerics, superInterfaces, constructors, staticConstructor, fields, methods);
|
||||
@@ -175,9 +391,14 @@ public class ASTToTargetAST {
|
||||
}
|
||||
|
||||
public List<MethodParameter> convert(ParameterList input, GenerateGenerics generics) {
|
||||
return input.getFormalparalist().stream().map(param ->
|
||||
new MethodParameter((TargetPattern) convert(param))
|
||||
).toList();
|
||||
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);
|
||||
if (pattern instanceof TargetComplexPattern) pattern = pattern.withName("__var" + i);
|
||||
res.add(new MethodParameter(pattern));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private boolean hasGeneric(Set<TargetGeneric> generics, GenericRefType type) {
|
||||
@@ -203,9 +424,10 @@ public class ASTToTargetAST {
|
||||
}
|
||||
|
||||
private List<TargetConstructor> convert(ClassOrInterface currentClass, Constructor input, TargetBlock fieldInitializer) {
|
||||
generics = all.get(0);
|
||||
generics = all.getFirst();
|
||||
List<TargetConstructor> result = new ArrayList<>();
|
||||
Set<List<MethodParameter>> parameterSet = new HashSet<>();
|
||||
this.currentMethod = input;
|
||||
|
||||
for (var s : all) {
|
||||
generics = s;
|
||||
@@ -225,118 +447,149 @@ public class ASTToTargetAST {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* This only considers type patterns, all other methods aren't grouped together
|
||||
* @param a
|
||||
* @param b
|
||||
* @return
|
||||
*/
|
||||
private boolean signatureEquals(Method a, Method b) {
|
||||
if (!a.name.equals(b.name)) return false;
|
||||
var para = a.getParameterList().getFormalparalist();
|
||||
var parb = b.getParameterList().getFormalparalist();
|
||||
if (para.size() != parb.size()) return false;
|
||||
|
||||
for (var i = 0; i < para.size(); i++) {
|
||||
var pa = para.get(i);
|
||||
var pb = parb.get(i);
|
||||
|
||||
if (pa instanceof RecordPattern rpa) {
|
||||
if (pb instanceof RecordPattern rpb) {
|
||||
if (rpa.getType().equals(rpb.getType())) continue;
|
||||
}
|
||||
return false;
|
||||
} else if (pa.getType().equals(pb.getType())) {
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO Nested patterns
|
||||
private List<List<Method>> groupOverloads(List<Method> input) {
|
||||
var done = new HashSet<Method>();
|
||||
var res = new ArrayList<List<Method>>();
|
||||
for (var method : input) {
|
||||
if (done.contains(method)) continue;
|
||||
var overloads = new ArrayList<Method>();
|
||||
overloads.add(method);
|
||||
done.add(method);
|
||||
for (var method2 : input) {
|
||||
if (!done.contains(method2) && signatureEquals(method, method2)) {
|
||||
done.add(method2);
|
||||
overloads.add(method2);
|
||||
}
|
||||
}
|
||||
res.add(overloads);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private String encodeName(String name, ParameterList params) {
|
||||
private String encodeName(String name, TargetMethod.Signature params) {
|
||||
var res = new StringBuilder();
|
||||
res.append(name);
|
||||
res.append('$');
|
||||
for (var param : params.getFormalparalist()) {
|
||||
if (param instanceof RecordPattern rp) {
|
||||
res.append(FunNGenerator.encodeType(convert(param.getType())));
|
||||
for (var pattern : rp.getSubPattern()) {
|
||||
res.append(FunNGenerator.encodeType(convert(pattern.getType())));
|
||||
}
|
||||
}
|
||||
for (var param : params.parameters()) {
|
||||
encodeName(param.pattern(), res);
|
||||
}
|
||||
return res.toString();
|
||||
}
|
||||
|
||||
private Set<TargetMethod> convert(ClassOrInterface clazz, List<Method> overloadedMethods) {
|
||||
if (overloadedMethods.size() == 1) {
|
||||
return convert(clazz, overloadedMethods.getFirst());
|
||||
}
|
||||
var methods = new ArrayList<Method>();
|
||||
for (var method : overloadedMethods) {
|
||||
var newMethod = new Method(
|
||||
method.modifier,
|
||||
method.name,
|
||||
//encodeName(method.name, method.getParameterList()),
|
||||
method.getReturnType(),
|
||||
method.getParameterList(),
|
||||
method.block,
|
||||
method.getGenerics(),
|
||||
method.getOffset()
|
||||
);
|
||||
methods.add(newMethod);
|
||||
}
|
||||
|
||||
// TODO Record overloading
|
||||
/*var template = overloadedMethods.get(0);
|
||||
|
||||
var pParams = new ArrayList<Pattern>();
|
||||
var i = 0;
|
||||
for (var par : template.getParameterList()) {
|
||||
pParams.add(switch (par) {
|
||||
case RecordPattern rp -> new RecordPattern(rp.getSubPattern(), "par" + i, rp.getType(), new NullToken());
|
||||
default -> par;
|
||||
});
|
||||
i++;
|
||||
}
|
||||
var params = new ParameterList(pParams, new NullToken());
|
||||
|
||||
var statements = new ArrayList<Statement>();
|
||||
statements.add(new Return(makeRecordSwitch(template.getReturnType(), params, res), new NullToken()));
|
||||
var block = new Block(statements, new NullToken());
|
||||
var entryPoint = new Method(template.modifier, template.name, template.getReturnType(), params, block, template.getGenerics(), new NullToken());
|
||||
|
||||
res.add(entryPoint); // TODO*/
|
||||
var res = new HashSet<TargetMethod>();
|
||||
for (var method : methods) {
|
||||
var overloads = convert(clazz, method);
|
||||
for (var overload : overloads) {
|
||||
if (res.contains(overload)) throw new CodeGenException("Duplicate method found: " + overload.name() + " with signature " + overload.signature().getSignature());
|
||||
res.add(overload);
|
||||
private void encodeName(TargetPattern pattern, StringBuilder res) {
|
||||
if (pattern instanceof TargetComplexPattern cp) {
|
||||
res.append(FunNGenerator.encodeType(cp.type()));
|
||||
for (var pat : cp.subPatterns()) {
|
||||
encodeName(pat, res);
|
||||
}
|
||||
} else {
|
||||
res.append(FunNGenerator.encodeType(pattern.type()));
|
||||
}
|
||||
}
|
||||
|
||||
private TargetExpression generatePatternOverloadsRec(int offset, TargetExpression switchExpr, List<TargetLocalVar> params, List<TargetPattern> patterns, List<TargetMethod> methods, TargetType classType) {
|
||||
if (methods.isEmpty()) throw new DebugException("Couldn't find a candidate for switch overloading");
|
||||
if (methods.size() == 1) {
|
||||
var method = methods.getFirst();
|
||||
var mParams = new ArrayList<TargetExpression>();
|
||||
for (var i = 0; i < params.size(); i++) {
|
||||
var tpe = method.signature().parameters().get(i).pattern().type();
|
||||
mParams.add(new TargetLocalVar(tpe, params.get(i).name()));
|
||||
}
|
||||
TargetExpression caseBody = new TargetMethodCall(
|
||||
method.signature().returnType(),
|
||||
new TargetThis(classType),
|
||||
mParams,
|
||||
classType,
|
||||
method.name(),
|
||||
false, false, method.isPrivate()
|
||||
);
|
||||
if (method.signature().returnType() != null) {
|
||||
caseBody = new TargetReturn(caseBody);
|
||||
}
|
||||
return caseBody;
|
||||
}
|
||||
|
||||
var cases = new ArrayList<TargetSwitch.Case>();
|
||||
var usedPatterns = new HashSet<TargetPattern>();
|
||||
|
||||
for (var method : methods) {
|
||||
var patternsRec = new ArrayList<>(patterns);
|
||||
|
||||
TargetExpression expr = null;
|
||||
var i = 0;
|
||||
for (var param : method.signature().parameters()) {
|
||||
if (i == offset) {
|
||||
patternsRec.add(param.pattern());
|
||||
}
|
||||
if (i > offset) {
|
||||
// Find next pattern
|
||||
expr = params.get(i);
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
var lastPattern = patternsRec.getLast();
|
||||
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;
|
||||
j++;
|
||||
}
|
||||
return true;
|
||||
}).toList();
|
||||
|
||||
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);
|
||||
|
||||
cases.add(case_);
|
||||
}
|
||||
|
||||
return new TargetSwitch(switchExpr, cases, null, true);
|
||||
}
|
||||
|
||||
private List<TargetMethod> generatePatternOverloads(ClassOrInterface clazz, List<TargetMethod> overloadedMethods) {
|
||||
if (overloadedMethods.size() <= 1) return overloadedMethods;
|
||||
// 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 signatureParams = new ArrayList<MethodParameter>();
|
||||
for (var i = 0; i < firstMethod.signature().parameters().size(); i++) {
|
||||
var p1 = firstMethod.signature().parameters().get(i).pattern();
|
||||
var t1 = p1.type();
|
||||
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();
|
||||
commonSubTypes.retainAll(commonSuperInterfaceTypes(t1, t3));
|
||||
}
|
||||
if (commonSubTypes.size() > 1) throw new DebugException("Invalid overload");
|
||||
// TODO accept multiple types
|
||||
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));
|
||||
}
|
||||
|
||||
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()));
|
||||
}
|
||||
var returnType = commonSubTypes.isEmpty() ? TargetType.Object : new TargetRefType(commonSubTypes.iterator().next().getClassName().toString());
|
||||
|
||||
var parameters = signatureParams.stream().map( p -> new TargetLocalVar(p.pattern().type(), p.pattern().name())).toList();
|
||||
//var patterns = List.of((TargetComplexPattern) firstMethod.signature().parameters().stream()
|
||||
// .filter(p -> p.pattern() instanceof TargetComplexPattern).findFirst().orElseThrow().pattern());
|
||||
|
||||
// Generate dispatch method
|
||||
var classType = new TargetRefType(clazz.getClassName().getClassName());
|
||||
var stmt = generatePatternOverloadsRec(0, new TargetLocalVar(signatureParams.getFirst().pattern().type(), signatureParams.getFirst().pattern().name()), parameters, List.of(), res, classType);
|
||||
var block = new TargetBlock(List.of(stmt));
|
||||
|
||||
var signature = new TargetMethod.Signature(Set.of(), signatureParams, returnType);
|
||||
var bridgeMethod = new TargetMethod(firstMethod.access(), firstMethod.name(), block, signature, firstMethod.txSignature());
|
||||
|
||||
res.add(bridgeMethod);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -381,10 +634,29 @@ public class ASTToTargetAST {
|
||||
}).findFirst();
|
||||
}
|
||||
|
||||
private Set<TargetMethod> convert(ClassOrInterface currentClass, Method method) {
|
||||
generics = all.get(0);
|
||||
Set<TargetMethod> result = new HashSet<>();
|
||||
Set<List<MethodParameter>> parameterSet = new HashSet<>();
|
||||
record MethodWithTphs(TargetMethod method, Generics generics, List<SignaturePairTarget> args) {
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof MethodWithTphs that)) return false;
|
||||
return Objects.equals(method, that.method) && Objects.equals(args, that.args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(method, args);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -402,19 +674,28 @@ public class ASTToTargetAST {
|
||||
}
|
||||
}
|
||||
|
||||
List<MethodParameter> finalParams = params;
|
||||
if (parameterSet.stream().noneMatch(p -> p.equals(finalParams))) {
|
||||
List<MethodParameter> txParams = convert(method.getParameterList(), this.generics.txGenerics);
|
||||
List<MethodParameter> txParams = convert(method.getParameterList(), this.generics.txGenerics);
|
||||
|
||||
var javaMethodGenerics = collectMethodGenerics(currentClass, generics.javaGenerics(), javaGenerics, method);
|
||||
var txMethodGenerics = collectMethodGenerics(currentClass, generics.txGenerics(), txGenerics, method);
|
||||
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 newMethod = new TargetMethod(method.modifier, method.name, convert(method.block), javaSignature, txSignature);
|
||||
result.add(newMethod);
|
||||
parameterSet.add(params);
|
||||
}
|
||||
var javaSignature = new TargetMethod.Signature(javaMethodGenerics, params, returnType);
|
||||
var txSignature = new TargetMethod.Signature(txMethodGenerics, txParams, convert(method.getReturnType(), this.generics.txGenerics));
|
||||
|
||||
signatures.add(new Signature(javaSignature, txSignature, generics));
|
||||
var listOfGenerics = collectedGenerics.getOrDefault(javaSignature, new ArrayList<>());
|
||||
listOfGenerics.add(generics);
|
||||
collectedGenerics.put(javaSignature, listOfGenerics);
|
||||
}
|
||||
|
||||
for (var signature : signatures) {
|
||||
generics = signature.generics;
|
||||
currentMethodOverloads = collectedGenerics.get(signature.java);
|
||||
|
||||
var newMethod = new TargetMethod(method.modifier, method.name, convert(method.block), signature.java, signature.tx);
|
||||
var concreteParams = tphsInMethods.getOrDefault(method, new HashSet<>()).stream().map(sig -> new SignaturePairTarget(convert(sig.signature), convert(sig.parameter))).toList();
|
||||
|
||||
result.add(new MethodWithTphs(newMethod, generics, concreteParams));
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -424,7 +705,9 @@ public class ASTToTargetAST {
|
||||
var list = new ArrayList<MethodParameter>();
|
||||
for (var i = 0; i < paraList.getFormalparalist().size(); i++) {
|
||||
var param = paraList.getParameterAt(i);
|
||||
list.add(new MethodParameter((TargetPattern) convert(param)).withType(convert(superList.getParameterAt(i).getType(), generics)));
|
||||
var pattern = (TargetPattern) convert(param);
|
||||
if (pattern instanceof TargetComplexPattern) pattern = pattern.withName("__var" + i);
|
||||
list.add(new MethodParameter(pattern).withType(convert(superList.getParameterAt(i).getType(), generics)));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
@@ -455,11 +738,6 @@ public class ASTToTargetAST {
|
||||
return new TargetField(input.modifier, convert(input.getType(), generics.javaGenerics), input.getName());
|
||||
}
|
||||
|
||||
private final Map<String, FunNGenerator.GenericParameters> usedFunN = new HashMap<>();
|
||||
private final Set<Integer> usedFunNSuperTypes = new HashSet<>();
|
||||
|
||||
public Map<String, byte[]> auxiliaries = new HashMap<>();
|
||||
|
||||
public TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input) {
|
||||
return convert(input, generics.javaGenerics);
|
||||
}
|
||||
@@ -486,13 +764,66 @@ public class ASTToTargetAST {
|
||||
}
|
||||
var filteredParams = new ArrayList<TargetType>();
|
||||
for (var i = 0; i < newParams.size(); i++) {
|
||||
if (gep.parameters.get(i) != null)
|
||||
if (i < gep.inParams.size() && gep.inParams.get(i) != null)
|
||||
filteredParams.add(newParams.get(i));
|
||||
}
|
||||
return TargetFunNType.fromParams(params, filteredParams);
|
||||
return TargetFunNType.fromParams(params, filteredParams, gep.getReturnType() != null ? 1 : 0);
|
||||
}
|
||||
|
||||
protected TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input, GenerateGenerics generics) {
|
||||
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;
|
||||
while (testClass != null) {
|
||||
if (testClass.equals(otherClass)) return true;
|
||||
if (testClass.getClassName().equals(new JavaClassName("java.lang.Object"))) break;
|
||||
testClass = compiler.getClass(testClass.getSuperClass().getName());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isSupertype(TargetType test, TargetType other) {
|
||||
return isSubtype(other, test);
|
||||
}
|
||||
|
||||
private boolean isSubtype(FunNGenerator.GenericParameters test, FunNGenerator.GenericParameters other) {
|
||||
if (test.getArguments().size() != other.getArguments().size()) return false;
|
||||
if (!isSubtype(test.getReturnType(), other.getReturnType())) return false;
|
||||
for (int i = 0; i < test.getArguments().size(); i++) {
|
||||
var arg1 = test.getArguments().get(i);
|
||||
var arg2 = other.getArguments().get(i);
|
||||
if (!isSupertype(arg1, arg2)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void generateFunNTypes() {
|
||||
for (var entry : compiler.usedFunN.entrySet()) {
|
||||
var gep = entry.getValue();
|
||||
var superInterfaces = compiler.usedFunN.values().stream()
|
||||
.filter(g -> !g.equals(gep))
|
||||
.filter(genericParameters -> isSubtype(gep, genericParameters))
|
||||
.map(FunNGenerator::getSpecializedClassName)
|
||||
.toList();
|
||||
|
||||
var code = FunNGenerator.generateSpecializedBytecode(gep, superInterfaces);
|
||||
compiler.auxiliaries.put(entry.getKey(), code);
|
||||
}
|
||||
}
|
||||
|
||||
public TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input, GenerateGenerics generics) {
|
||||
return convert(input, generics, compiler);
|
||||
}
|
||||
|
||||
public static TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input, GenerateGenerics generics, JavaTXCompiler compiler) {
|
||||
return input.acceptTV(new TypeVisitor<>() {
|
||||
@Override
|
||||
public TargetType visit(RefType refType) {
|
||||
@@ -504,41 +835,31 @@ public class ASTToTargetAST {
|
||||
}
|
||||
|
||||
var params = refType.getParaList().stream().map(type -> {
|
||||
var res = convert(type, generics);
|
||||
if (res == null) res = new TargetRefType("java.lang.Void");
|
||||
return res;
|
||||
return convert(type, generics, compiler);
|
||||
}).toList();
|
||||
|
||||
if (name.matches("Fun\\d+\\$\\$")) { // TODO This seems like a bad idea
|
||||
var className = FunNGenerator.getSpecializedClassName(FunNGenerator.getArguments(params), FunNGenerator.getReturnType(params));
|
||||
if (!usedFunNSuperTypes.contains(params.size())) {
|
||||
usedFunNSuperTypes.add(params.size());
|
||||
var code = FunNGenerator.generateSuperBytecode(params.size() - 1);
|
||||
var superClassName = FunNGenerator.getSuperClassName(params.size() - 1);
|
||||
var returnType = FunNGenerator.getReturnType(params);
|
||||
var className = FunNGenerator.getSpecializedClassName(FunNGenerator.getArguments(params), returnType);
|
||||
if (!compiler.usedFunNSuperTypes.contains(params.size())) {
|
||||
compiler.usedFunNSuperTypes.add(params.size());
|
||||
var code = FunNGenerator.generateSuperBytecode(params.size() - 1, returnType != null ? 1 : 0);
|
||||
var superClassName = FunNGenerator.getSuperClassName(params.size() - 1, returnType != null ? 1 : 0);
|
||||
try {
|
||||
classLoader.findClass(superClassName);
|
||||
compiler.classLoader.findClass(superClassName);
|
||||
} catch (ClassNotFoundException e) {
|
||||
try {
|
||||
classLoader.loadClass(code);
|
||||
compiler.classLoader.loadClass(superClassName, code);
|
||||
} catch (LinkageError ignored) {}
|
||||
}
|
||||
auxiliaries.put(superClassName, code);
|
||||
compiler.auxiliaries.put(superClassName, code);
|
||||
}
|
||||
FunNGenerator.GenericParameters gep = null;
|
||||
if (!usedFunN.containsKey(className)) {
|
||||
gep = new FunNGenerator.GenericParameters();
|
||||
var code = FunNGenerator.generateSpecializedBytecode(FunNGenerator.getArguments(params), FunNGenerator.getReturnType(params), gep);
|
||||
try {
|
||||
classLoader.findClass(className);
|
||||
} catch (ClassNotFoundException e) {
|
||||
try {
|
||||
classLoader.loadClass(code);
|
||||
} catch (LinkageError ignored) {}
|
||||
}
|
||||
usedFunN.put(className, gep);
|
||||
auxiliaries.put(className, code);
|
||||
if (!compiler.usedFunN.containsKey(className)) {
|
||||
gep = new FunNGenerator.GenericParameters(params, returnType != null ? 1 : 0);
|
||||
compiler.usedFunN.put(className, gep);
|
||||
} else {
|
||||
gep = usedFunN.get(className);
|
||||
gep = compiler.usedFunN.get(className);
|
||||
}
|
||||
return flattenFunNType(params, gep);
|
||||
}
|
||||
@@ -547,7 +868,7 @@ public class ASTToTargetAST {
|
||||
|
||||
@Override
|
||||
public TargetType visit(SuperWildcardType superWildcardType) {
|
||||
return new TargetSuperWildcard(convert(superWildcardType.getInnerType(), generics));
|
||||
return new TargetSuperWildcard(convert(superWildcardType.getInnerType(), generics, compiler));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -557,7 +878,7 @@ public class ASTToTargetAST {
|
||||
|
||||
@Override
|
||||
public TargetType visit(ExtendsWildcardType extendsWildcardType) {
|
||||
return new TargetExtendsWildcard(convert(extendsWildcardType.getInnerType(), generics));
|
||||
return new TargetExtendsWildcard(convert(extendsWildcardType.getInnerType(), generics, compiler));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -1,10 +1,9 @@
|
||||
package de.dhbwstuttgart.target.generate;
|
||||
|
||||
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||
import de.dhbwstuttgart.parser.JavaTXParser;
|
||||
import de.dhbwstuttgart.parser.NullToken;
|
||||
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
|
||||
import de.dhbwstuttgart.syntaxtree.Constructor;
|
||||
import de.dhbwstuttgart.syntaxtree.GenericTypeVar;
|
||||
import de.dhbwstuttgart.syntaxtree.Method;
|
||||
import de.dhbwstuttgart.syntaxtree.*;
|
||||
import de.dhbwstuttgart.syntaxtree.statement.*;
|
||||
import de.dhbwstuttgart.syntaxtree.type.*;
|
||||
import de.dhbwstuttgart.syntaxtree.type.Void;
|
||||
@@ -21,7 +20,7 @@ import java.util.stream.Stream;
|
||||
|
||||
public abstract class GenerateGenerics {
|
||||
|
||||
private final ASTToTargetAST astToTargetAST;
|
||||
private final JavaTXCompiler compiler;
|
||||
|
||||
public class TPH {
|
||||
private final TypePlaceholder wrap;
|
||||
@@ -134,11 +133,11 @@ public abstract class GenerateGenerics {
|
||||
final Map<Method, Set<Pair>> familyOfMethods = new HashMap<>();
|
||||
|
||||
final Set<PairLT> simplifiedConstraints = new HashSet<>();
|
||||
final Map<TPH, RefTypeOrTPHOrWildcardOrGeneric> concreteTypes = new HashMap<>();
|
||||
final Map<TypePlaceholder, TypePlaceholder> equality = new HashMap<>();
|
||||
Map<TPH, RefTypeOrTPHOrWildcardOrGeneric> concreteTypes = new HashMap<>();
|
||||
Map<TypePlaceholder, TypePlaceholder> equality = new HashMap<>();
|
||||
|
||||
GenerateGenerics(ASTToTargetAST astToTargetAST, ResultSet constraints) {
|
||||
this.astToTargetAST = astToTargetAST;
|
||||
GenerateGenerics(JavaTXCompiler compiler, ResultSet constraints) {
|
||||
this.compiler = compiler;
|
||||
for (var constraint : constraints.results) {
|
||||
if (constraint instanceof PairTPHsmallerTPH p) {
|
||||
System.out.println(p.left + " " + p.left.getVariance());
|
||||
@@ -154,6 +153,41 @@ 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()) {
|
||||
res.addAll(findTypeVariables(param));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
Set<TPH> findTypeVariables(Pattern pattern) {
|
||||
var res = new HashSet<TPH>();
|
||||
if (pattern instanceof RecordPattern rp) {
|
||||
for (var subPattern : rp.getSubPattern()) {
|
||||
res.addAll(findTypeVariables(subPattern));
|
||||
}
|
||||
}
|
||||
res.addAll(findTypeVariables(pattern.getType()));
|
||||
return res;
|
||||
}
|
||||
|
||||
Set<TPH> findTypeVariables(RefTypeOrTPHOrWildcardOrGeneric type) {
|
||||
var result = new HashSet<TPH>();
|
||||
if (type instanceof TypePlaceholder tph) {
|
||||
@@ -249,7 +283,7 @@ public abstract class GenerateGenerics {
|
||||
Set<TPH> typeVariablesOfClass,
|
||||
Set<Pair> result
|
||||
) {
|
||||
var userDefinedGenericsOfClass = astToTargetAST.userDefinedGenerics.get(owner);
|
||||
var userDefinedGenericsOfClass = owner.getUserDefinedGenerics();
|
||||
|
||||
// Type variables with bounds that are also type variables of the method
|
||||
for (var typeVariable : new HashSet<>(typeVariables)) {
|
||||
@@ -297,7 +331,7 @@ public abstract class GenerateGenerics {
|
||||
|
||||
if (methodCall.receiver instanceof ExpressionReceiver expressionReceiver) {
|
||||
if (expressionReceiver.expr instanceof This) {
|
||||
var optMethod = astToTargetAST.findMethod(owner, methodCall.name, methodCall.signatureArguments().stream().map(astToTargetAST::convert).toList());
|
||||
var optMethod = ASTToTargetAST.findMethod(owner, methodCall.name, methodCall.signatureArguments().stream().map(x -> getTargetType(x)).toList(), GenerateGenerics.this, compiler);
|
||||
if (optMethod.isEmpty()) return;
|
||||
var method2 = optMethod.get();
|
||||
System.out.println("In: " + method.getName() + " Method: " + method2.getName());
|
||||
@@ -490,9 +524,7 @@ public abstract class GenerateGenerics {
|
||||
|
||||
if (!(method instanceof Constructor))
|
||||
typeVariables.addAll(findTypeVariables(method.getReturnType()));
|
||||
for (var arg : method.getParameterList().getFormalparalist()) {
|
||||
typeVariables.addAll(findTypeVariables(arg.getType()));
|
||||
}
|
||||
typeVariables.addAll(findTypeVariables(method.getParameterList()));
|
||||
|
||||
if (method.block != null)
|
||||
method.block.accept(new TracingStatementVisitor() {
|
||||
@@ -556,9 +588,7 @@ public abstract class GenerateGenerics {
|
||||
|
||||
var usedTphs = new HashSet<TPH>();
|
||||
// For eliminating inner type variables we need to figure out which ones are actually used
|
||||
for (var param : method.getParameterList().getFormalparalist()) {
|
||||
usedTphs.addAll(findTypeVariables(param.getType()));
|
||||
}
|
||||
usedTphs.addAll(findTypeVariables(method.getParameterList()));
|
||||
usedTphs.addAll(findTypeVariables(method.getReturnType()));
|
||||
referenced.addAll(usedTphs);
|
||||
referenced.addAll(typeVariablesOfClass);
|
||||
@@ -652,17 +682,25 @@ public abstract class GenerateGenerics {
|
||||
}
|
||||
|
||||
void normalize(Set<Pair> result, Set<Pair> classGenerics, Set<TPH> usedTphs) {
|
||||
outer:
|
||||
for (var p1 : new HashSet<>(result)) {
|
||||
if (p1 instanceof PairLT ptph && ptph.left.resolve().equals(ptph.right.resolve()))
|
||||
result.remove(p1); // TODO This is a bit strange
|
||||
}
|
||||
for (var tph : usedTphs) {
|
||||
for (var p1 : new HashSet<>(result)) {
|
||||
if (p1 instanceof PairLT ptph && ptph.left.equals(ptph.right))
|
||||
result.remove(p1); // TODO This is a bit strange
|
||||
if (p1.left.equals(tph)) continue outer;
|
||||
}
|
||||
|
||||
if (classGenerics == null || classGenerics.stream().noneMatch((pair) -> pair.left.equals(tph)))
|
||||
addToPairs(result, new PairEQ(tph, ASTToTargetAST.OBJECT));
|
||||
}
|
||||
var all = new HashSet<>(result);
|
||||
for (var p : all) {
|
||||
if (p instanceof PairEQ peq && peq.right.equals(ASTToTargetAST.OBJECT)) {
|
||||
for (var p2 : all) {
|
||||
if (p2 instanceof PairLT && p2.left.equals(p.left)) {
|
||||
result.remove(p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private record ToAdd(TypePlaceholder left, TypePlaceholder right) {}
|
||||
@@ -969,8 +1007,8 @@ public abstract class GenerateGenerics {
|
||||
}
|
||||
var type = concreteTypes.get(new TPH(tph));
|
||||
if (type == null) return new TargetGenericType(tph.getName());
|
||||
return astToTargetAST.convert(type, this);
|
||||
return ASTToTargetAST.convert(type, this, compiler);
|
||||
}
|
||||
return astToTargetAST.convert(in, this);
|
||||
return ASTToTargetAST.convert(in, this, compiler);
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user