Compare commits
109 Commits
fbde5afb1b
...
KPS2025
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9c519d0746 | ||
|
|
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 |
@@ -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!
|
||||
@@ -1,6 +0,0 @@
|
||||
sealed interface List<T> permits LinkedElem, Elem {}
|
||||
|
||||
record LinkedElem<T>(T a, List<T> l) implements List<T> {}
|
||||
record Elem<T>(T a) implements List<T> {}
|
||||
|
||||
public class SwitchAppend {}
|
||||
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.13.2</version>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<version>5.13.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/org.antlr/antlr4 -->
|
||||
<dependency>
|
||||
<groupId>org.antlr</groupId>
|
||||
<artifactId>antlr4</artifactId>
|
||||
<version>4.11.1</version>
|
||||
<version>4.13.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.16.1</version>
|
||||
<version>2.19.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.classgraph</groupId>
|
||||
<artifactId>classgraph</artifactId>
|
||||
<version>4.8.172</version>
|
||||
<version>4.8.180</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>33.2.0-jre</version>
|
||||
<version>33.4.8-jre</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/org.ow2.asm/asm -->
|
||||
<dependency>
|
||||
<groupId>org.ow2.asm</groupId>
|
||||
<artifactId>asm</artifactId>
|
||||
<version>9.5</version>
|
||||
<version>9.8</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<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>
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
public class Box<A> {
|
||||
public class Box {
|
||||
|
||||
A a;
|
||||
a;
|
||||
|
||||
public Box() { }
|
||||
public Box(A a) {
|
||||
public Box(a) {
|
||||
//this.a = a;
|
||||
}
|
||||
set(x) {
|
||||
a = x;
|
||||
}
|
||||
}
|
||||
7
resources/AllgemeinTest/Uncurrier.jav
Normal file
7
resources/AllgemeinTest/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);
|
||||
}
|
||||
}
|
||||
9
resources/AllgemeinTest/UncurrierMain.jav
Normal file
9
resources/AllgemeinTest/UncurrierMain.jav
Normal file
@@ -0,0 +1,9 @@
|
||||
import Uncurrier;
|
||||
import java.lang.Integer;
|
||||
|
||||
class UncurrierMain {
|
||||
meth(y) {
|
||||
var uc = new Uncurrier() ;
|
||||
uc.uncurry(x -> x+1);
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
25
resources/KPSPresentation/Faculty.jav
Normal file
25
resources/KPSPresentation/Faculty.jav
Normal file
@@ -0,0 +1,25 @@
|
||||
import java.lang.Integer;
|
||||
import java.lang.Double;
|
||||
import java.lang.System;
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class Faculty {
|
||||
public Fun1$$<Double, Double> fact = (x) -> {
|
||||
if (x == 1) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return x * (fact.apply(x-1.0));
|
||||
}
|
||||
};
|
||||
|
||||
public getFact(x) {
|
||||
return fact.apply(x);
|
||||
}
|
||||
|
||||
public static void main(x) {
|
||||
var f = new Faculty();
|
||||
var intRes = f.getFact(3.0);
|
||||
System.out.println(intRes);
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
106
resources/KPSPresentation/Main.jav
Normal file
106
resources/KPSPresentation/Main.jav
Normal file
@@ -0,0 +1,106 @@
|
||||
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;
|
||||
import MatrixOP;
|
||||
|
||||
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));
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
11
resources/KPSPresentation/MainFaculty.jav
Normal file
11
resources/KPSPresentation/MainFaculty.jav
Normal file
@@ -0,0 +1,11 @@
|
||||
import java.lang.System;
|
||||
import java.io.PrintStream;
|
||||
import Faculty;
|
||||
|
||||
public class MainFaculty {
|
||||
public static void main(x) {
|
||||
//var f = new Faculty();
|
||||
//var intRes = f.getFact(3);
|
||||
//System.out.println(intRes);
|
||||
}
|
||||
}
|
||||
20
resources/KPSPresentation/MainOL.jav
Normal file
20
resources/KPSPresentation/MainOL.jav
Normal file
@@ -0,0 +1,20 @@
|
||||
import java.lang.String ;
|
||||
import java.lang.System;
|
||||
import java.io.PrintStream;
|
||||
import java.lang.Float;
|
||||
import OL2;
|
||||
|
||||
class MainOL {
|
||||
public static main(x) {
|
||||
var ol = new OL2();
|
||||
|
||||
//the function main is applied to an integer
|
||||
//var res1 = ol.m2(2);
|
||||
//the main is applied to a double
|
||||
//System.out.println(ol.m2(2.0));
|
||||
//System.out.println(ol.m2("Hallo").toString());
|
||||
var res2 = ol.m2("Hallo").toString();
|
||||
System.out.println(res2);
|
||||
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
64
resources/KPSPresentation/MatrixOP.jav
Normal file
64
resources/KPSPresentation/MatrixOP.jav
Normal file
@@ -0,0 +1,64 @@
|
||||
import java.util.Vector;
|
||||
import java.lang.Integer;
|
||||
//import java.lang.Byte;
|
||||
import java.lang.Boolean;
|
||||
import java.lang.String;
|
||||
import java.lang.System;
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class MatrixOP extends Vector<Vector<Integer>> {
|
||||
|
||||
public MatrixOP () {
|
||||
}
|
||||
|
||||
public MatrixOP(vv) {
|
||||
Integer i;
|
||||
i = 0;
|
||||
while(i < vv.size()) {
|
||||
this.add(vv.elementAt(i));
|
||||
i=i+1;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
public static main(x) {
|
||||
var vv = new Vector<Vector<Integer>>();
|
||||
var v1 = new Vector<Integer> ();
|
||||
v1.addElement(2);
|
||||
v1.addElement(2);
|
||||
var v2 = new Vector<Integer> ();
|
||||
v2.addElement(3);
|
||||
v2.addElement(3);
|
||||
|
||||
//MatrixOP
|
||||
MatrixOP mOp1 = new MatrixOP();
|
||||
mOp1.addElement(v1);
|
||||
mOp1.addElement(v2);
|
||||
MatrixOP mOp2 = mOp1.mul.apply(mOp1, mOp1);
|
||||
System.out.print(mOp1); System.out.print(" * "); System.out.print(mOp1); System.out.print(" = "); System.out.println(mOp2);
|
||||
//System.out.print(mOp1 + " * " + mOp1 + " = " + mOp2);
|
||||
}
|
||||
}
|
||||
}
|
||||
33
resources/KPSPresentation/OL.jav
Normal file
33
resources/KPSPresentation/OL.jav
Normal file
@@ -0,0 +1,33 @@
|
||||
import java.lang.String;
|
||||
import java.lang.Integer;
|
||||
import java.lang.Double;
|
||||
import java.lang.Boolean;
|
||||
import java.lang.Object;
|
||||
import java.lang.System;
|
||||
import java.io.PrintStream;
|
||||
|
||||
|
||||
|
||||
|
||||
public class OL1 {
|
||||
|
||||
m1( x) { return x + x; }
|
||||
|
||||
|
||||
m1(x) { return x || x; }
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class OL2 {
|
||||
|
||||
m2(x) {
|
||||
var ol;
|
||||
ol = new OL1();
|
||||
return ol.m1(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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
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();
|
||||
};
|
||||
}
|
||||
}
|
||||
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;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -9,9 +9,13 @@ public class SwitchOverload {
|
||||
Number f(Double d) { return d * 2; }
|
||||
Number f(Integer i) { return i * 5; }
|
||||
|
||||
public m(r) {
|
||||
public m(r, x) {
|
||||
x = x + x;
|
||||
return switch(r) {
|
||||
case R(o) -> f(o);
|
||||
case R(o) -> {
|
||||
x = x + x;
|
||||
yield f(o);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -654,6 +654,7 @@ primaryPattern
|
||||
: typePattern #tPattern
|
||||
| recordPattern #rPattern
|
||||
| '(' pattern ')' #enclosedPattern
|
||||
| literal (',' literal)* #lPattern
|
||||
;
|
||||
|
||||
recordPattern
|
||||
@@ -677,7 +678,6 @@ recordComponentPatternElement
|
||||
|
||||
recordComponentPatternList
|
||||
: pattern (',' pattern)*
|
||||
| literal (',' literal)*
|
||||
;
|
||||
|
||||
// Java8
|
||||
|
||||
@@ -2,14 +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.Method;
|
||||
import de.dhbwstuttgart.syntaxtree.Pattern;
|
||||
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.*;
|
||||
@@ -18,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.*;
|
||||
@@ -90,14 +85,16 @@ public class Codegen {
|
||||
int localCounter;
|
||||
MethodVisitor mv;
|
||||
TargetType returnType;
|
||||
boolean isStatic = false;
|
||||
|
||||
Stack<BreakEnv> breakStack = new Stack<>();
|
||||
Stack<Integer> switchResultValue = new Stack<>();
|
||||
|
||||
State(TargetType returnType, MethodVisitor mv, int localCounter) {
|
||||
State(TargetType returnType, MethodVisitor mv, int localCounter, boolean isStatic) {
|
||||
this.returnType = returnType;
|
||||
this.mv = mv;
|
||||
this.localCounter = localCounter;
|
||||
this.isStatic = isStatic;
|
||||
}
|
||||
|
||||
void enterScope() {
|
||||
@@ -108,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);
|
||||
@@ -131,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);
|
||||
@@ -152,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);
|
||||
@@ -227,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);
|
||||
@@ -276,6 +282,8 @@ public class Codegen {
|
||||
mv.visitInsn(I2F);
|
||||
else if (dest.equals(TargetType.Double))
|
||||
mv.visitInsn(I2D);
|
||||
} else if (source.equals(TargetType.Boolean)) {
|
||||
unboxPrimitive(state, dest);
|
||||
} else if (isFunctionalInterface(source) && isFunctionalInterface(dest) &&
|
||||
!(source instanceof TargetFunNType && dest instanceof TargetFunNType)) {
|
||||
boxFunctionalInterface(state, source, dest);
|
||||
@@ -637,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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -759,6 +767,16 @@ public class Codegen {
|
||||
}
|
||||
}
|
||||
|
||||
private static TargetType removeGenerics(TargetType param) {
|
||||
return switch (param) {
|
||||
case null -> null;
|
||||
case TargetFunNType funNType -> new TargetFunNType(funNType.name(), funNType.funNParams(), List.of(), funNType.returnArguments());
|
||||
case TargetRefType refType -> new TargetRefType(refType.name());
|
||||
case TargetGenericType targetGenericType -> TargetType.Object;
|
||||
default -> param;
|
||||
};
|
||||
}
|
||||
|
||||
private void generateLambdaExpression(State state, TargetLambdaExpression lambda) {
|
||||
var mv = state.mv;
|
||||
|
||||
@@ -770,7 +788,8 @@ public class Codegen {
|
||||
|
||||
var parameters = new ArrayList<>(lambda.captures());
|
||||
parameters.addAll(signature.parameters());
|
||||
var implSignature = new TargetMethod.Signature(Set.of(), parameters, lambda.signature().returnType());
|
||||
parameters = parameters.stream().map(param -> param.withType(removeGenerics(param.pattern().type()))).collect(Collectors.toCollection(ArrayList::new));
|
||||
var implSignature = new TargetMethod.Signature(Set.of(), parameters, removeGenerics(lambda.signature().returnType()));
|
||||
|
||||
TargetMethod impl;
|
||||
if (lambdas.containsKey(lambda)) {
|
||||
@@ -778,21 +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());
|
||||
|
||||
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();
|
||||
@@ -927,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");
|
||||
}
|
||||
@@ -944,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;
|
||||
}
|
||||
@@ -1308,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();
|
||||
}
|
||||
@@ -1392,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();
|
||||
}
|
||||
|
||||
@@ -1405,7 +1428,7 @@ public class Codegen {
|
||||
throw new CodeGenException("Couldn't find suitable field accessor for '" + type.name() + "'");
|
||||
var field = clazz.getFieldDecl().get(i);
|
||||
var fieldType = converter.convert(field.getType());
|
||||
state.mv.visitMethodInsn(INVOKEVIRTUAL, type.getInternalName(), field.getName(), "()" + fieldType.toSignature(), false);
|
||||
state.mv.visitMethodInsn(INVOKEVIRTUAL, type.getInternalName(), field.getName(), "()" + fieldType.toDescriptor(), false);
|
||||
}
|
||||
|
||||
private void bindPattern(State state, TargetType type, TargetPattern pat, Label start, int index, int depth) {
|
||||
@@ -1430,7 +1453,24 @@ public class Codegen {
|
||||
state.mv.visitTypeInsn(CHECKCAST, pat.type().getInternalName());
|
||||
}
|
||||
|
||||
if (pat instanceof TargetTypePattern sp) {
|
||||
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);
|
||||
|
||||
var cont = new Label();
|
||||
state.mv.visitJumpInsn(IFNE, cont);
|
||||
for (var i = 0; i < depth - 1; 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);
|
||||
} 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) {
|
||||
@@ -1445,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);
|
||||
@@ -1476,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);
|
||||
@@ -1497,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)
|
||||
@@ -1521,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)
|
||||
@@ -1561,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);
|
||||
@@ -1578,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();
|
||||
}
|
||||
@@ -1671,7 +1759,7 @@ public class Codegen {
|
||||
|
||||
// Generate wrapper method
|
||||
var mv = cw2.visitMethod(ACC_PUBLIC, toMethod.name, toDescriptor, null, null);
|
||||
var state = new State(null, mv, 0);
|
||||
var state = new State(null, mv, 0, false);
|
||||
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitFieldInsn(GETFIELD, className, "wrapped", pair.from.toDescriptor());
|
||||
@@ -1695,7 +1783,7 @@ public class Codegen {
|
||||
|
||||
cw2.visitEnd();
|
||||
var bytes = cw2.toByteArray();
|
||||
converter.auxiliaries.put(className, bytes);
|
||||
compiler.auxiliaries.put(className, bytes);
|
||||
|
||||
// TODO These class loading shenanigans happen in a few places, the tests load the classes individually.
|
||||
// Instead we should just look at the folder.
|
||||
@@ -1703,7 +1791,7 @@ public class Codegen {
|
||||
converter.classLoader.findClass(className);
|
||||
} catch (ClassNotFoundException e) {
|
||||
try {
|
||||
converter.classLoader.loadClass(bytes);
|
||||
converter.classLoader.loadClass(className, bytes);
|
||||
} catch (LinkageError ignored) {}
|
||||
}
|
||||
}
|
||||
@@ -1738,7 +1826,7 @@ public class Codegen {
|
||||
bootstrapArgs[1] = String.join(";", clazz.fields().stream().map(TargetField::name).toArray(String[]::new));
|
||||
for (var i = 0; i < clazz.fields().size(); i++) {
|
||||
var field = clazz.fields().get(i);
|
||||
var fieldRef = new Handle(H_GETFIELD, clazz.getName(), field.name(), field.type().toSignature(), false);
|
||||
var fieldRef = new Handle(H_GETFIELD, clazz.getName(), field.name(), field.type().toDescriptor(), false);
|
||||
bootstrapArgs[i + 2] = fieldRef;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,10 @@ public class FunNGenerator {
|
||||
public final List<TargetType> inParams;
|
||||
public final List<TargetType> realParams;
|
||||
|
||||
public GenericParameters(TargetFunNType funNType) {
|
||||
this(funNType.funNParams(), funNType.returnArguments());
|
||||
}
|
||||
|
||||
public GenericParameters(List<TargetType> params, int numReturns) {
|
||||
this.realParams = params;
|
||||
this.inParams = flattenTypeParams(params);
|
||||
@@ -94,7 +98,7 @@ 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;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
package de.dhbwstuttgart.core;
|
||||
|
||||
import de.dhbwstuttgart.bytecode.Codegen;
|
||||
import de.dhbwstuttgart.bytecode.FunNGenerator;
|
||||
import de.dhbwstuttgart.environment.CompilationEnvironment;
|
||||
import de.dhbwstuttgart.environment.DirectoryClassLoader;
|
||||
import de.dhbwstuttgart.exceptions.DebugException;
|
||||
@@ -73,6 +74,11 @@ public class JavaTXCompiler {
|
||||
public final List<File> classPath;
|
||||
private final File outputPath;
|
||||
|
||||
public final Map<String, FunNGenerator.GenericParameters> usedFunN = new HashMap<>();
|
||||
public final Set<Integer> usedFunNSuperTypes = new HashSet<>();
|
||||
|
||||
public Map<String, byte[]> auxiliaries = new HashMap<>();
|
||||
|
||||
public DirectoryClassLoader getClassLoader() {
|
||||
return classLoader;
|
||||
}
|
||||
@@ -393,7 +399,12 @@ public class JavaTXCompiler {
|
||||
logFile.write(ASTTypePrinter.print(sf));
|
||||
System.out.println(ASTTypePrinter.print(sf));
|
||||
logFile.flush();
|
||||
System.out.println("Unify nach Oder-Constraints-Anpassung:" + unifyCons.toString());
|
||||
List<UnifyPair> andConstraintsSorted = unifyCons.getUndConstraints().stream()
|
||||
.sorted(Comparator.comparing(UnifyPair::getPairOp).thenComparing(UnifyPair::getLhsType, Comparator.comparing(UnifyType::getName)))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
System.out.println(andConstraintsSorted);
|
||||
|
||||
Set<PlaceholderType> varianceTPHold;
|
||||
Set<PlaceholderType> varianceTPH = new HashSet<>();
|
||||
varianceTPH = varianceInheritanceConstraintSet(unifyCons);
|
||||
@@ -416,7 +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();
|
||||
@@ -631,12 +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;
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -149,10 +150,10 @@ public class StatementGenerator {
|
||||
} else {
|
||||
type = methodparameters?
|
||||
TypePlaceholder.fresh(fp.getStart(), 1, false)
|
||||
: TypePlaceholder.fresh(fp.getStart());
|
||||
: 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());
|
||||
@@ -441,6 +442,7 @@ public class StatementGenerator {
|
||||
}
|
||||
|
||||
private Pattern convert(PatternContext pattern) {
|
||||
|
||||
return switch (pattern) {
|
||||
case PPatternContext pPattern -> {
|
||||
yield convert(pPattern.primaryPattern());
|
||||
@@ -455,6 +457,7 @@ public class StatementGenerator {
|
||||
}
|
||||
|
||||
private FormalParameter convert(PrimaryPatternContext pPattern) {
|
||||
|
||||
switch (pPattern) {
|
||||
case TPatternContext tPattern:
|
||||
TypePatternContext typePattern = tPattern.typePattern();
|
||||
@@ -465,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) {
|
||||
@@ -586,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) {
|
||||
@@ -700,8 +707,7 @@ public class StatementGenerator {
|
||||
if (!Objects.isNull(expr.methodCall())) {
|
||||
return convert(expr.methodCall(), expr.expression(), offset);
|
||||
} else if (!Objects.isNull(expr.identifier())) {
|
||||
// FIXME This is not the right way of handling any of this
|
||||
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
|
||||
@@ -777,64 +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) {
|
||||
// FIXME Why does this take a String argument???
|
||||
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) {
|
||||
@@ -870,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 "*=":
|
||||
@@ -890,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)
|
||||
@@ -1100,7 +1065,7 @@ 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) {
|
||||
@@ -1110,7 +1075,7 @@ public class StatementGenerator {
|
||||
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 {
|
||||
@@ -1134,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()),
|
||||
|
||||
@@ -269,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));
|
||||
|
||||
@@ -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);
|
||||
@@ -199,4 +202,22 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope {
|
||||
public int hashCode() {
|
||||
return Objects.hash(name);
|
||||
}
|
||||
|
||||
public Set<GenericTypeVar> getUserDefinedGenerics() {
|
||||
if (this.userDefinedGenerics != null) return this.userDefinedGenerics;
|
||||
|
||||
var genericsIter = getGenerics().iterator();
|
||||
if (genericsIter.hasNext()) {
|
||||
// Add empty set of generics to cache so that it doesn't try to calculate it later
|
||||
this.userDefinedGenerics = new HashSet<>();
|
||||
while (genericsIter.hasNext()) {
|
||||
var next = genericsIter.next();
|
||||
userDefinedGenerics.add(next);
|
||||
}
|
||||
} else {
|
||||
this.userDefinedGenerics = new HashSet<>();
|
||||
}
|
||||
|
||||
return this.userDefinedGenerics;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -34,7 +34,6 @@ public class ASTFactory {
|
||||
private static final HashMap<java.lang.Class, ClassOrInterface> cache = new HashMap<>();
|
||||
|
||||
public static ClassOrInterface createClass(java.lang.Class jreClass) {
|
||||
System.out.println(jreClass);
|
||||
if (cache.containsKey(jreClass))
|
||||
return cache.get(jreClass);
|
||||
|
||||
@@ -174,12 +173,12 @@ public class ASTFactory {
|
||||
superClass = (RefType) createType(java.lang.Object.class);
|
||||
}
|
||||
List<RefType> implementedInterfaces = new ArrayList<>();
|
||||
System.out.println(jreClass);
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,10 +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.DebugException;
|
||||
import de.dhbwstuttgart.parser.NullToken;
|
||||
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||
import de.dhbwstuttgart.syntaxtree.*;
|
||||
@@ -12,6 +11,8 @@ import de.dhbwstuttgart.syntaxtree.Record;
|
||||
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
|
||||
import de.dhbwstuttgart.syntaxtree.statement.*;
|
||||
import de.dhbwstuttgart.syntaxtree.type.*;
|
||||
import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter;
|
||||
import de.dhbwstuttgart.syntaxtree.visual.OutputGenerator;
|
||||
import de.dhbwstuttgart.target.tree.*;
|
||||
import de.dhbwstuttgart.target.tree.expression.*;
|
||||
import de.dhbwstuttgart.target.tree.type.*;
|
||||
@@ -33,7 +34,8 @@ public class ASTToTargetAST {
|
||||
|
||||
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;
|
||||
|
||||
@@ -58,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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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) {
|
||||
@@ -78,9 +82,9 @@ public class ASTToTargetAST {
|
||||
|
||||
all = new ArrayList<>();
|
||||
for (var set : resultSets) {
|
||||
all.add(new Generics(new JavaGenerics(this, set), new TxGenerics(this, set)));
|
||||
all.add(new Generics(compiler, set));
|
||||
}
|
||||
this.generics = all.get(0);
|
||||
this.generics = all.getFirst();
|
||||
}
|
||||
|
||||
public void addSignaturePair(TypePlaceholder signature, RefTypeOrTPHOrWildcardOrGeneric parameter) {
|
||||
@@ -90,9 +94,13 @@ public class ASTToTargetAST {
|
||||
}
|
||||
|
||||
Optional<Method> findMethod(ClassOrInterface owner, String name, List<TargetType> argumentList) {
|
||||
return findMethod(owner, name, argumentList, this.generics.javaGenerics, this.compiler);
|
||||
}
|
||||
|
||||
public static Optional<Method> findMethod(ClassOrInterface owner, String name, List<TargetType> argumentList, GenerateGenerics generics, JavaTXCompiler compiler) {
|
||||
Optional<Method> method = Optional.empty();
|
||||
while (method.isEmpty()) {
|
||||
method = owner.getMethods().stream().filter(m -> m.name.equals(name) && parameterEquals(m.getParameterList(), argumentList)).findFirst();
|
||||
method = owner.getMethods().stream().filter(m -> m.name.equals(name) && parameterEquals(m.getParameterList(), argumentList, generics)).findFirst();
|
||||
if (owner.getClassName().toString().equals("java.lang.Object")) break;
|
||||
owner = compiler.getClass(owner.getSuperClass().getName());
|
||||
}
|
||||
@@ -100,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;
|
||||
@@ -142,57 +150,219 @@ public class ASTToTargetAST {
|
||||
return ret;
|
||||
}
|
||||
|
||||
public List<List<TargetMethod>> groupOverloads(ClassOrInterface input, List<Method> methods) {
|
||||
var res = new ArrayList<List<TargetMethod>>();
|
||||
for (var method : methods) {
|
||||
// Convert all methods
|
||||
var methodsWithTphs = convert(input, method);
|
||||
// Then check for methods with the same signature
|
||||
var mapOfSignatures = new HashMap<TargetMethod.Signature, List<MethodWithTphs>>();
|
||||
for (var m : methodsWithTphs) {
|
||||
var methodsWithSameSignature = mapOfSignatures.getOrDefault(m.method.signature(), new ArrayList<>());
|
||||
methodsWithSameSignature.add(m);
|
||||
mapOfSignatures.put(m.method.signature(), methodsWithSameSignature);
|
||||
}
|
||||
// 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())));
|
||||
|
||||
var resMethods = new HashSet<TargetMethod>();
|
||||
for (var methodsWithSignature : mapOfSignatures.values()) {
|
||||
outer: for (var m1 : methodsWithSignature) {
|
||||
for (var m2 : methodsWithSignature) {
|
||||
for (var i = 0; i < m1.args.size(); i++) {
|
||||
var arg1 = m1.args.get(i);
|
||||
var arg2 = m2.args.get(i);
|
||||
if (arg1.parameter.equals(arg2.parameter)) {
|
||||
if (isSupertype(arg1.signature, arg2.signature) &&
|
||||
!arg1.signature.equals(arg2.signature)) continue outer;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
resMethods.add(m1.method);
|
||||
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);
|
||||
}
|
||||
}
|
||||
res.add(resMethods.stream().toList());
|
||||
}
|
||||
return res;
|
||||
|
||||
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);
|
||||
@@ -206,7 +376,8 @@ 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, input.getMethods()).stream().flatMap(List::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())
|
||||
@@ -220,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) {
|
||||
@@ -248,7 +424,7 @@ public class ASTToTargetAST {
|
||||
}
|
||||
|
||||
private List<TargetConstructor> convert(ClassOrInterface currentClass, Constructor input, TargetBlock fieldInitializer) {
|
||||
generics = all.get(0);
|
||||
generics = all.getFirst();
|
||||
List<TargetConstructor> result = new ArrayList<>();
|
||||
Set<List<MethodParameter>> parameterSet = new HashSet<>();
|
||||
this.currentMethod = input;
|
||||
@@ -271,69 +447,149 @@ public class ASTToTargetAST {
|
||||
return result;
|
||||
}
|
||||
|
||||
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 List<TargetMethod> convert(ClassOrInterface clazz, List<Method> overloadedMethods) {
|
||||
if (overloadedMethods.size() == 1) {
|
||||
return convert(clazz, overloadedMethods.getFirst()).stream().map(m -> m.method()).toList();
|
||||
}
|
||||
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 ArrayList<TargetMethod>();
|
||||
for (var method : methods) {
|
||||
var overloads = convert(clazz, method);
|
||||
for (var m : overloads) {
|
||||
var overload = m.method;
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -378,13 +634,30 @@ public class ASTToTargetAST {
|
||||
}).findFirst();
|
||||
}
|
||||
|
||||
record MethodWithTphs(TargetMethod method, List<SignaturePairTarget> args) {}
|
||||
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;
|
||||
var javaGenerics = this.generics.javaGenerics.generics(currentClass, method);
|
||||
@@ -408,11 +681,21 @@ public class ASTToTargetAST {
|
||||
|
||||
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);
|
||||
|
||||
signatures.add(new Signature(javaSignature, txSignature, generics));
|
||||
var listOfGenerics = collectedGenerics.getOrDefault(javaSignature, new ArrayList<>());
|
||||
listOfGenerics.add(generics);
|
||||
collectedGenerics.put(javaSignature, listOfGenerics);
|
||||
}
|
||||
|
||||
for (var signature : signatures) {
|
||||
generics = signature.generics;
|
||||
currentMethodOverloads = collectedGenerics.get(signature.java);
|
||||
|
||||
var newMethod = new TargetMethod(method.modifier, method.name, convert(method.block), signature.java, signature.tx);
|
||||
var concreteParams = tphsInMethods.getOrDefault(method, new HashSet<>()).stream().map(sig -> new SignaturePairTarget(convert(sig.signature), convert(sig.parameter))).toList();
|
||||
|
||||
result.add(new MethodWithTphs(newMethod, concreteParams));
|
||||
result.add(new MethodWithTphs(newMethod, generics, concreteParams));
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -422,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;
|
||||
}
|
||||
@@ -453,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);
|
||||
}
|
||||
@@ -490,7 +770,15 @@ public class ASTToTargetAST {
|
||||
return TargetFunNType.fromParams(params, filteredParams, gep.getReturnType() != null ? 1 : 0);
|
||||
}
|
||||
|
||||
private FunNGenerator.GenericParameters convertToParameters(TargetFunNType input) {
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isSubtype(TargetType test, TargetType other) {
|
||||
if (other.equals(TargetType.Object)) return true;
|
||||
if (test instanceof TargetFunNType tfun && other instanceof TargetFunNType ofun)
|
||||
return isSubtype(new FunNGenerator.GenericParameters(tfun), new FunNGenerator.GenericParameters(ofun));
|
||||
|
||||
var testClass = compiler.getClass(new JavaClassName(test.name()));
|
||||
var otherClass = compiler.getClass(new JavaClassName(other.name()));
|
||||
if (testClass == null) return false;
|
||||
@@ -518,28 +806,24 @@ public class ASTToTargetAST {
|
||||
}
|
||||
|
||||
public void generateFunNTypes() {
|
||||
for (var entry : usedFunN.entrySet()) {
|
||||
for (var entry : compiler.usedFunN.entrySet()) {
|
||||
var gep = entry.getValue();
|
||||
var superInterfaces = usedFunN.values().stream()
|
||||
var superInterfaces = compiler.usedFunN.values().stream()
|
||||
.filter(g -> !g.equals(gep))
|
||||
.filter(genericParameters -> isSubtype(gep, genericParameters))
|
||||
.map(FunNGenerator::getSpecializedClassName)
|
||||
.toList();
|
||||
|
||||
var code = FunNGenerator.generateSpecializedBytecode(gep, superInterfaces);
|
||||
|
||||
try {
|
||||
classLoader.findClass(entry.getKey());
|
||||
} catch (ClassNotFoundException e) {
|
||||
try {
|
||||
classLoader.loadClass(code);
|
||||
} catch (LinkageError ignored) {}
|
||||
}
|
||||
auxiliaries.put(entry.getKey(), code);
|
||||
compiler.auxiliaries.put(entry.getKey(), code);
|
||||
}
|
||||
}
|
||||
|
||||
protected TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input, GenerateGenerics generics) {
|
||||
public TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input, GenerateGenerics generics) {
|
||||
return convert(input, generics, compiler);
|
||||
}
|
||||
|
||||
public static TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input, GenerateGenerics generics, JavaTXCompiler compiler) {
|
||||
return input.acceptTV(new TypeVisitor<>() {
|
||||
@Override
|
||||
public TargetType visit(RefType refType) {
|
||||
@@ -551,31 +835,31 @@ public class ASTToTargetAST {
|
||||
}
|
||||
|
||||
var params = refType.getParaList().stream().map(type -> {
|
||||
return convert(type, generics);
|
||||
return convert(type, generics, compiler);
|
||||
}).toList();
|
||||
|
||||
if (name.matches("Fun\\d+\\$\\$")) { // TODO This seems like a bad idea
|
||||
var returnType = FunNGenerator.getReturnType(params);
|
||||
var className = FunNGenerator.getSpecializedClassName(FunNGenerator.getArguments(params), returnType);
|
||||
if (!usedFunNSuperTypes.contains(params.size())) {
|
||||
usedFunNSuperTypes.add(params.size());
|
||||
if (!compiler.usedFunNSuperTypes.contains(params.size())) {
|
||||
compiler.usedFunNSuperTypes.add(params.size());
|
||||
var code = FunNGenerator.generateSuperBytecode(params.size() - 1, returnType != null ? 1 : 0);
|
||||
var superClassName = FunNGenerator.getSuperClassName(params.size() - 1, returnType != null ? 1 : 0);
|
||||
try {
|
||||
classLoader.findClass(superClassName);
|
||||
compiler.classLoader.findClass(superClassName);
|
||||
} catch (ClassNotFoundException e) {
|
||||
try {
|
||||
classLoader.loadClass(code);
|
||||
compiler.classLoader.loadClass(superClassName, code);
|
||||
} catch (LinkageError ignored) {}
|
||||
}
|
||||
auxiliaries.put(superClassName, code);
|
||||
compiler.auxiliaries.put(superClassName, code);
|
||||
}
|
||||
FunNGenerator.GenericParameters gep = null;
|
||||
if (!usedFunN.containsKey(className)) {
|
||||
if (!compiler.usedFunN.containsKey(className)) {
|
||||
gep = new FunNGenerator.GenericParameters(params, returnType != null ? 1 : 0);
|
||||
usedFunN.put(className, gep);
|
||||
compiler.usedFunN.put(className, gep);
|
||||
} else {
|
||||
gep = usedFunN.get(className);
|
||||
gep = compiler.usedFunN.get(className);
|
||||
}
|
||||
return flattenFunNType(params, gep);
|
||||
}
|
||||
@@ -584,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
|
||||
@@ -594,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;
|
||||
@@ -137,8 +136,8 @@ public abstract class GenerateGenerics {
|
||||
Map<TPH, RefTypeOrTPHOrWildcardOrGeneric> concreteTypes = new HashMap<>();
|
||||
Map<TypePlaceholder, TypePlaceholder> equality = new HashMap<>();
|
||||
|
||||
GenerateGenerics(ASTToTargetAST astToTargetAST, ResultSet constraints) {
|
||||
this.astToTargetAST = astToTargetAST;
|
||||
GenerateGenerics(JavaTXCompiler compiler, ResultSet constraints) {
|
||||
this.compiler = compiler;
|
||||
for (var constraint : constraints.results) {
|
||||
if (constraint instanceof PairTPHsmallerTPH p) {
|
||||
System.out.println(p.left + " " + p.left.getVariance());
|
||||
@@ -170,6 +169,25 @@ public abstract class GenerateGenerics {
|
||||
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) {
|
||||
@@ -265,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)) {
|
||||
@@ -313,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());
|
||||
@@ -506,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() {
|
||||
@@ -572,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);
|
||||
@@ -672,11 +686,21 @@ public abstract class GenerateGenerics {
|
||||
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) {
|
||||
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) {}
|
||||
@@ -983,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,8 +69,4 @@ public class GenericsResult {
|
||||
return this.generics.getType(tph);
|
||||
return type;
|
||||
}
|
||||
|
||||
public TargetType resolveTarget(RefTypeOrTPHOrWildcardOrGeneric type) {
|
||||
return this.generics.getTargetType(type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package de.dhbwstuttgart.target.generate;
|
||||
|
||||
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
|
||||
import de.dhbwstuttgart.syntaxtree.Method;
|
||||
import de.dhbwstuttgart.typeinference.result.ResultSet;
|
||||
@@ -7,8 +8,8 @@ import de.dhbwstuttgart.typeinference.result.ResultSet;
|
||||
import java.util.Set;
|
||||
|
||||
final class JavaGenerics extends GenerateGenerics {
|
||||
JavaGenerics(ASTToTargetAST astToTargetAST, ResultSet constraints) {
|
||||
super(astToTargetAST, constraints);
|
||||
JavaGenerics(JavaTXCompiler compiler, ResultSet constraints) {
|
||||
super(compiler, constraints);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package de.dhbwstuttgart.target.generate;
|
||||
|
||||
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||
import de.dhbwstuttgart.exceptions.DebugException;
|
||||
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
||||
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal;
|
||||
@@ -13,6 +14,7 @@ import de.dhbwstuttgart.target.tree.expression.*;
|
||||
import de.dhbwstuttgart.target.tree.type.*;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.sql.Array;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.StreamSupport;
|
||||
@@ -31,54 +33,71 @@ public class StatementToTargetExpression implements ASTVisitor {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private class LambdaCaptureFinder extends TracingStatementVisitor {
|
||||
|
||||
// TODO The same mechanism is implemented in Codegen, maybe use it from there?
|
||||
final Stack<Set<String>> localVariables = new Stack<>();
|
||||
private final List<MethodParameter> parameters;
|
||||
private final List<MethodParameter> captures;
|
||||
|
||||
LambdaCaptureFinder(List<MethodParameter> parameters, List<MethodParameter> captures) {
|
||||
localVariables.push(new HashSet<>());
|
||||
this.parameters = parameters;
|
||||
this.captures = captures;
|
||||
}
|
||||
|
||||
boolean hasLocalVar(String name) {
|
||||
for (var localVariables : this.localVariables) {
|
||||
if (localVariables.contains(name))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Block block) {
|
||||
localVariables.push(new HashSet<>());
|
||||
super.visit(block);
|
||||
localVariables.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(LocalVar localVar) {
|
||||
super.visit(localVar);
|
||||
var capture = new MethodParameter(new TargetTypePattern(converter.convert(localVar.getType()), localVar.name));
|
||||
if (!hasLocalVar(localVar.name) && !parameters.contains(capture) && !captures.contains(capture))
|
||||
captures.add(capture);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(LocalVarDecl varDecl) {
|
||||
var localVariables = this.localVariables.peek();
|
||||
localVariables.add(varDecl.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(LambdaExpression lambda) {
|
||||
var newCaptures = new ArrayList<MethodParameter>();
|
||||
var captureFinder = new LambdaCaptureFinder(createParameters(lambda), newCaptures);
|
||||
lambda.methodBody.accept(captureFinder);
|
||||
newCaptures.removeAll(parameters);
|
||||
captures.addAll(newCaptures);
|
||||
}
|
||||
}
|
||||
|
||||
private List<MethodParameter> createParameters(LambdaExpression lambda) {
|
||||
return StreamSupport.stream(lambda.params.spliterator(), false)
|
||||
.map(p -> (FormalParameter) p)
|
||||
.map(p -> new MethodParameter(new TargetTypePattern(converter.convert(p.getType()), p.getName())))
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(LambdaExpression lambdaExpression) {
|
||||
var parameters = StreamSupport.stream(lambdaExpression.params.spliterator(), false)
|
||||
.map(p -> (FormalParameter) p)
|
||||
.map(p -> new MethodParameter(new TargetTypePattern(converter.convert(p.getType()), p.getName())))
|
||||
.toList();
|
||||
|
||||
var parameters = createParameters(lambdaExpression);
|
||||
List<MethodParameter> captures = new ArrayList<>();
|
||||
lambdaExpression.methodBody.accept(new TracingStatementVisitor() {
|
||||
// TODO The same mechanism is implemented in Codegen, maybe use it from there?
|
||||
final Stack<Set<String>> localVariables = new Stack<>();
|
||||
{
|
||||
localVariables.push(new HashSet<>());
|
||||
}
|
||||
|
||||
boolean hasLocalVar(String name) {
|
||||
for (var localVariables : this.localVariables) {
|
||||
if (localVariables.contains(name))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Block block) {
|
||||
localVariables.push(new HashSet<>());
|
||||
super.visit(block);
|
||||
localVariables.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(LocalVar localVar) {
|
||||
super.visit(localVar);
|
||||
var capture = new MethodParameter(new TargetTypePattern(converter.convert(localVar.getType()), localVar.name));
|
||||
if (!hasLocalVar(localVar.name) && !parameters.contains(capture) && !captures.contains(capture))
|
||||
captures.add(capture);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(LocalVarDecl varDecl) {
|
||||
var localVariables = this.localVariables.peek();
|
||||
localVariables.add(varDecl.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(LambdaExpression lambda) {
|
||||
} // Don't look at lambda expressions
|
||||
});
|
||||
var visitor = new LambdaCaptureFinder(parameters, captures);
|
||||
lambdaExpression.methodBody.accept(visitor);
|
||||
|
||||
TargetMethod.Signature signature = new TargetMethod.Signature(Set.of(), parameters, converter.convert(lambdaExpression.getReturnType()));;
|
||||
var tpe = converter.convert(lambdaExpression.getType());
|
||||
@@ -119,7 +138,10 @@ public class StatementToTargetExpression implements ASTVisitor {
|
||||
|
||||
@Override
|
||||
public void visit(BoolExpression bool) {
|
||||
System.out.println("BoolExpression");
|
||||
result = switch(bool.operation) {
|
||||
case OR -> new TargetBinaryOp.Or(converter.convert(bool.getType()), converter.convert(bool.lexpr), converter.convert(bool.rexpr));
|
||||
case AND -> new TargetBinaryOp.And(converter.convert(bool.getType()), converter.convert(bool.lexpr), converter.convert(bool.rexpr));
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -139,7 +161,11 @@ public class StatementToTargetExpression implements ASTVisitor {
|
||||
|
||||
@Override
|
||||
public void visit(FieldVar fieldVar) {
|
||||
result = new TargetFieldVar(converter.convert(fieldVar.getType()), converter.convert(fieldVar.receiver.getType()), fieldVar.isStatic, converter.convert(fieldVar.receiver), fieldVar.fieldVarName);
|
||||
var isStatic = false;
|
||||
var type = converter.convert(fieldVar.receiver.getType());
|
||||
var clazz = converter.compiler.getClass(new JavaClassName(type.name()));
|
||||
var field = clazz.getField(fieldVar.fieldVarName).orElseThrow();
|
||||
result = new TargetFieldVar(converter.convert(fieldVar.getType()), type, Modifier.isStatic(field.modifier), converter.convert(fieldVar.receiver), fieldVar.fieldVarName);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -446,7 +472,7 @@ public class StatementToTargetExpression implements ASTVisitor {
|
||||
var oldGenerics = converter.generics;
|
||||
|
||||
// Set the generics to matching result set
|
||||
for (var generics : converter.all) {
|
||||
for (var generics : converter.currentMethodOverloads) {
|
||||
var java = generics.javaGenerics();
|
||||
var equals = true;
|
||||
for (var pair : l) {
|
||||
@@ -563,6 +589,11 @@ public class StatementToTargetExpression implements ASTVisitor {
|
||||
result = new TargetTypePattern(converter.convert(aPattern.getType()), aPattern.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(LiteralPattern literalPattern) {
|
||||
result = new TargetExpressionPattern(converter.convert(literalPattern.value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ExpressionPattern aPattern) {
|
||||
result = converter.convert(aPattern.getExpression());
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package de.dhbwstuttgart.target.generate;
|
||||
|
||||
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
|
||||
import de.dhbwstuttgart.syntaxtree.Method;
|
||||
import de.dhbwstuttgart.typeinference.result.ResultSet;
|
||||
@@ -7,8 +8,8 @@ import de.dhbwstuttgart.typeinference.result.ResultSet;
|
||||
import java.util.Set;
|
||||
|
||||
final class TxGenerics extends GenerateGenerics {
|
||||
TxGenerics(ASTToTargetAST astToTargetAST, ResultSet constraints) {
|
||||
super(astToTargetAST, constraints);
|
||||
TxGenerics(JavaTXCompiler compiler, ResultSet constraints) {
|
||||
super(compiler, constraints);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -11,4 +11,8 @@ public record MethodParameter(TargetPattern pattern) {
|
||||
public MethodParameter withType(TargetType type) {
|
||||
return new MethodParameter(pattern.withType(type));
|
||||
}
|
||||
|
||||
public MethodParameter withName(String name) {
|
||||
return new MethodParameter(pattern.withName(name));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,30 +36,30 @@ public record TargetMethod(int access, String name, TargetBlock block, Signature
|
||||
public static String getDescriptor(TargetType returnType, TargetType... parameters) {
|
||||
String ret = "(";
|
||||
for (var parameterType : parameters) {
|
||||
ret += parameterType.toSignature();
|
||||
ret += parameterType.toDescriptor();
|
||||
}
|
||||
ret += ")";
|
||||
if (returnType == null) ret += "V";
|
||||
else ret += returnType.toSignature();
|
||||
else ret += returnType.toDescriptor();
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static String getSignature(Set<TargetGeneric> generics, List<MethodParameter> parameters, TargetType returnType) {
|
||||
String ret = "";
|
||||
if (generics.size() > 0) {
|
||||
if (!generics.isEmpty()) {
|
||||
ret += "<";
|
||||
for (var generic : generics) {
|
||||
ret += generic.name() + ":" + generic.bound().toDescriptor();
|
||||
ret += generic.name() + ":" + generic.bound().toSignature();
|
||||
}
|
||||
ret += ">";
|
||||
}
|
||||
ret += "(";
|
||||
for (var param : parameters) {
|
||||
ret += param.pattern().type().toDescriptor();
|
||||
ret += param.pattern().type().toSignature();
|
||||
}
|
||||
ret += ")";
|
||||
if (returnType == null) ret += "V";
|
||||
else ret += returnType.toDescriptor();
|
||||
else ret += returnType.toSignature();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -79,6 +79,10 @@ public record TargetMethod(int access, String name, TargetBlock block, Signature
|
||||
return (access & Opcodes.ACC_STATIC) != 0;
|
||||
}
|
||||
|
||||
public boolean isPrivate() {
|
||||
return (access & Opcodes.ACC_PRIVATE) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof TargetMethod otherMethod)) return false;
|
||||
|
||||
@@ -9,4 +9,9 @@ public record TargetComplexPattern(TargetType type, String name, List<TargetPatt
|
||||
public TargetComplexPattern withType(TargetType type) {
|
||||
return new TargetComplexPattern(type, name, subPatterns);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TargetComplexPattern withName(String name) {
|
||||
return new TargetComplexPattern(type, name, subPatterns);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package de.dhbwstuttgart.target.tree.expression;
|
||||
|
||||
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||
|
||||
public record TargetExpressionPattern(TargetExpression expression) implements TargetPattern {
|
||||
@Override
|
||||
public TargetPattern withType(TargetType type) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TargetType type() {
|
||||
return expression.type();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TargetPattern withName(String name) {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -12,4 +12,9 @@ public record TargetGuard(TargetPattern inner, TargetExpression expression) impl
|
||||
public TargetType type() {
|
||||
return inner.type();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TargetGuard withName(String name) {
|
||||
return new TargetGuard(inner.withName(name), expression);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package de.dhbwstuttgart.target.tree.expression;
|
||||
|
||||
import de.dhbwstuttgart.target.tree.type.TargetType;
|
||||
|
||||
public sealed interface TargetPattern extends TargetExpression permits TargetComplexPattern, TargetGuard, TargetTypePattern {
|
||||
public sealed interface TargetPattern extends TargetExpression permits TargetComplexPattern, TargetExpressionPattern, TargetGuard, TargetTypePattern {
|
||||
default String name() {
|
||||
return null;
|
||||
}
|
||||
@@ -10,4 +10,6 @@ public sealed interface TargetPattern extends TargetExpression permits TargetCom
|
||||
TargetPattern withType(TargetType type);
|
||||
|
||||
TargetType type();
|
||||
|
||||
TargetPattern withName(String name);
|
||||
}
|
||||
|
||||
@@ -7,4 +7,9 @@ public record TargetTypePattern(TargetType type, String name) implements TargetP
|
||||
public TargetTypePattern withType(TargetType type) {
|
||||
return new TargetTypePattern(type, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TargetTypePattern withName(String name) {
|
||||
return new TargetTypePattern(type, name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,12 +3,12 @@ package de.dhbwstuttgart.target.tree.type;
|
||||
public record TargetExtendsWildcard(TargetType innerType) implements TargetType {
|
||||
@Override
|
||||
public String toSignature() {
|
||||
return innerType.toSignature();
|
||||
return "+" + innerType.toSignature();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toDescriptor() {
|
||||
return "+" + innerType.toDescriptor();
|
||||
return innerType.toDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -33,9 +33,4 @@ public record TargetFunNType(String name, List<TargetType> funNParams, List<Targ
|
||||
public String getInternalName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toSignature() {
|
||||
return "L" + getInternalName() + ";";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,12 @@ package de.dhbwstuttgart.target.tree.type;
|
||||
|
||||
public record TargetGenericType(String name) implements TargetType {
|
||||
@Override
|
||||
public String toSignature() {
|
||||
public String toDescriptor() {
|
||||
return "Ljava/lang/Object;"; // TODO Use bounds for this?
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toDescriptor() {
|
||||
public String toSignature() {
|
||||
return "T" + getInternalName() + ";";
|
||||
}
|
||||
|
||||
|
||||
@@ -12,11 +12,6 @@ public record TargetRefType(String name, List<TargetType> params) implements Tar
|
||||
return this.name.replaceAll("\\.", "/");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toSignature() {
|
||||
return "L" + getInternalName() + ";";
|
||||
}
|
||||
|
||||
// Type erasure means we need to override hashCode and equals to only consider the name
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user