Compare commits

..

72 Commits

Author SHA1 Message Date
Fabian Holzwarth
1af31e4513 feat: update parallelization for 0variance 2025-08-04 13:41:17 +02:00
Fabian Holzwarth
5b06f0a249 Merge branch 'feat/unify-server' into feat/unify-server-0variance 2025-07-21 16:27:55 +02:00
Fabian Holzwarth
3d99f282f5 feat: cleanup code 2025-07-21 16:12:56 +02:00
Fabian Holzwarth
512b10542e feat: adjusted parallelization 2025-07-21 15:41:04 +02:00
Fabian Holzwarth
3b1185d9d0 feat: paralellize 0-variance cases 2025-07-20 15:06:50 +02:00
Fabian Holzwarth
303c91dc87 chore: making classnames more expressive and cleanup some structures 2025-07-19 12:50:30 +02:00
Fabian Holzwarth
603a8b176a feat: implement partically cancellable tasks 2025-07-16 11:16:30 +02:00
Fabian Holzwarth
f396189a4b feat: add timestamp to server output 2025-07-12 13:44:18 +02:00
Fabian Holzwarth
e7f4a94908 feat: fixed old condition on server timeout 2025-07-12 13:22:54 +02:00
Fabian Holzwarth
ce49a4b9a5 feat: reduce temporary objects and repeated loops 2025-07-12 13:14:55 +02:00
Fabian Holzwarth
03b3692724 feat: update indepenedentest 2025-07-11 12:50:27 +02:00
Fabian Holzwarth
f0022d2b6f feat: use presized hashMaps to reduce resizing 2025-07-11 11:22:06 +02:00
Fabian Holzwarth
b1015cfa82 feat: update logging and add success-level 2025-07-07 16:19:04 +02:00
Fabian Holzwarth
b63a27a0a0 feat: improve server by assinging configured thread pools 2025-07-07 15:59:46 +02:00
Fabian Holzwarth
3b0a53d3c4 feat: add cross dependency, fix: socket closing and error messages 2025-07-07 15:19:56 +02:00
Fabian Holzwarth
50dbbf5f86 feat: implement generalized socket client, server logger and cleanup code 2025-07-07 14:01:27 +02:00
Fabian Holzwarth
130c491ac0 feat: more Boxing replacements 2025-07-06 15:49:59 +02:00
Fabian Holzwarth
9f9b264ac4 feat: replace unnecessary boxing with primitives 2025-07-06 15:18:51 +02:00
Fabian Holzwarth
1393db05c2 feat: implement lazy evaluation for logger outputs 2025-07-06 13:37:47 +02:00
Fabian Holzwarth
93e1a8787c feat: do not create a new context, if nothing changes 2025-07-05 11:43:10 +02:00
Fabian Holzwarth
0129d7540f feat use perMessagDeflate compression in websocket and use logger for message outpute 2025-07-05 11:16:06 +02:00
Fabian Holzwarth
7ea8337aee feat: remove unused logging library 2025-07-05 11:15:33 +02:00
Fabian Holzwarth
28458d405f feat: ignore server test 2025-07-02 15:47:55 +02:00
Fabian Holzwarth
1b905cb3e2 feat: implement loggers for the rest of the compiler 2025-07-01 23:06:09 +02:00
Fabian Holzwarth
d02c3583e9 feat: implement new logger into type inference code 2025-07-01 22:16:29 +02:00
Fabian Holzwarth
ca98e83fd2 feat: added logger 2025-07-01 21:21:39 +02:00
Fabian Holzwarth
c80a0c8596 feat: fix error by reintroducing name generator and add server tests 2025-06-30 16:42:20 +02:00
Fabian Holzwarth
2278fb1b91 feat: undo removing NameGenerator to fix errors in ast generation 2025-06-30 12:46:41 +02:00
Fabian Holzwarth
32b16cd5fd feat: replace concurrent modification with correct function call 2025-06-30 11:49:53 +02:00
Fabian Holzwarth
fd30c5f63f feat: prevent reusing the placeholder registry in tests 2025-06-29 16:04:54 +02:00
Fabian Holzwarth
8bfd6ae255 feat: remove redundant lambda functions and Set-resizings 2025-06-28 14:48:43 +02:00
Fabian Holzwarth
ad2dfb13bd feat: speedup toString methods by using a StringBuilder instead of String concatenation 2025-06-28 14:30:12 +02:00
Fabian Holzwarth
501633a90c feat: fix test with null methodSignatureConstraint 2025-06-28 14:06:34 +02:00
Fabian Holzwarth
4defa50ca2 feat: added version check on connecting 2025-06-25 19:48:29 +02:00
Fabian Holzwarth
d65e90536a feat: replace NameGenerator with instance of PlaceholderRegistry to prevent duplicates 2025-06-25 19:15:28 +02:00
Fabian Holzwarth
3de7f1aa61 fix: try generating new placeholders only in current placeholderRegistry context to prevent duplicates 2025-06-25 17:38:56 +02:00
Fabian Holzwarth
029e40b775 feat: make packets directional and self handling 2025-06-25 17:35:49 +02:00
Fabian Holzwarth
459bfcdd5f feat: added tests for client-server communication 2025-06-23 16:13:43 +02:00
Fabian Holzwarth
02886c38ea feat: fixed error in object serialization 2025-06-23 16:13:21 +02:00
Fabian Holzwarth
57ffae0481 fix: fixed some serialization and deserialization issues 2025-06-22 15:11:49 +02:00
Fabian Holzwarth
d084d74a25 feat: fixed mismatch in PairOperator serialization 2025-06-22 10:10:32 +02:00
Fabian Holzwarth
cd15016f61 feat: allow subclasses when asserting values 2025-06-21 13:44:29 +02:00
Fabian Holzwarth
b0e5eee25c feat: rename Object... to Serial... and move into separate classes 2025-06-21 13:40:24 +02:00
Fabian Holzwarth
d1bd285be7 fix: replace reflection class check with simple string check 2025-06-21 13:23:01 +02:00
Fabian Holzwarth
a902fd5bee feat: replaced HashMaps with better type safety structure 2025-06-21 12:58:45 +02:00
Fabian Holzwarth
ced9fdc9f7 fix: non serialized constraitnContext 2025-06-20 19:09:33 +02:00
Fabian Holzwarth
53417bf298 feat: implement serialization and adjust packets to correct data types 2025-06-20 18:53:25 +02:00
Fabian Holzwarth
2d4da03f00 feat: implementing client-server model 2025-06-18 19:58:23 +02:00
Fabian Holzwarth
f7a13f5faa feat: turn UnifyContext into a record 2025-06-18 18:26:44 +02:00
Fabian Holzwarth
8fe80b4396 feat: move static placeholder generation into object 2025-06-18 17:47:29 +02:00
Fabian Holzwarth
eb1201ae5e feat: apply future-based approach to inner cartesian loop 2025-06-09 16:49:45 +02:00
Fabian Holzwarth
963ad76593 feat: make cartesian loop computation Future-based 2025-06-09 15:30:04 +02:00
Fabian Holzwarth
1eba09e3b0 feat: change cartesian while loop into recursive 2025-06-09 15:16:09 +02:00
Fabian Holzwarth
fc82125d14 feat: change TypeUnifyTask to use future-based logic 2025-06-09 14:53:37 +02:00
Fabian Holzwarth
dad468368b feat: make functions unify and unify2 future-based 2025-06-09 13:14:44 +02:00
Fabian Holzwarth
fdd4f3aa59 feat: implement variance-dependent calculation as Future based 2025-06-09 12:59:23 +02:00
Fabian Holzwarth
a0c11b60e8 Remove unnecessary parameter and fix some parallelization 2025-06-07 16:11:34 +02:00
Fabian Holzwarth
4cddf73e6d feat: small fixes for correct parameters 2025-06-07 14:38:18 +02:00
Fabian Holzwarth
5024a02447 feat: implement unify context and prepare variance code capsulation 2025-06-07 11:53:32 +02:00
Fabian Holzwarth
6c2d97b770 chore: code cleanup 2025-05-26 15:49:01 +02:00
Fabian Holzwarth
426c2916d3 feat: remove unnecessary synchronized blocks 2025-05-26 14:40:17 +02:00
Fabian Holzwarth
f722a00fbb feat: use the current thread for computation as well 2025-05-25 15:55:07 +02:00
Fabian Holzwarth
32797c9b9f feat: cleanup more cartesian product code 2025-05-24 12:43:42 +02:00
Fabian Holzwarth
87f655c85a feat: isolate constraint-filtering for one tv from computeCartesianRecursive 2025-05-23 16:10:37 +02:00
Fabian Holzwarth
613dceae1d feat: added Logger class, remove empty println start cleanup of computeCartesianRecursive 2025-05-23 14:12:25 +02:00
Fabian Holzwarth
81cac06e16 feat: add tool for merging many hash sets in parallel 2025-05-23 14:11:52 +02:00
Fabian Holzwarth
a47d5bc024 feat: slightly improved placeholder name generation 2025-05-23 14:04:48 +02:00
Fabian Holzwarth
e5916d455a feat: format and merge results in parallel 2025-05-19 17:05:18 +02:00
Fabian Holzwarth
ebb639e72e feat: remove log flushes 2025-05-18 16:29:19 +02:00
Fabian Holzwarth
f0a4a51ce6 feat: replace thread counter with thread pool 2025-05-18 15:40:31 +02:00
Fabian Holzwarth
7442880452 feat: limit placeholder generation to uppercase chars 2025-05-18 13:24:29 +02:00
Fabian Holzwarth
c4dc3b4245 feat: replace random based placeholder generation with deterministic approach 2025-05-18 12:41:56 +02:00
152 changed files with 9430 additions and 5703 deletions

View File

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

40
independentTest.sh Executable file
View File

@@ -0,0 +1,40 @@
#!/usr/bin/env bash
REPO="https://gitea.hb.dhbw-stuttgart.de/f.holzwarth/JavaCompilerCore.git"
TDIR="./testBuild"
rm -rf "$TDIR" 2>/dev/null
mkdir $TDIR
cd $TDIR
git clone $REPO .
git checkout feat/unify-server
# git checkout 93e1a8787cd94c73f4538f6a348f58613893a584
# git checkout dad468368b86bdd5a3d3b2754b17617cee0a9107 # 1:55
# git checkout a0c11b60e8c9d7addcbe0d3a09c9ce2924e9d5c0 # 2:25
# git checkout 4cddf73e6d6c9116d3e1705c4b27a8e7f18d80c3 # 2:27
# git checkout 6c2d97b7703d954e4a42eef3ec374bcf313af75c # 2:13
# git checkout f722a00fbb6e69423d48a890e4a6283471763e64 # 1:35
# git checkout f0a4a51ce65639ce9a9470ff0fdb538fdf9c02cc # 2:19
# git checkout 1391206dfe59263cdb22f93371cfd1dd5465d97f # 1:29
date "+%Y.%m.%d %H:%M:%S"
# sed -i -e 's/source>21/source>23/g' pom.xml
# sed -i -e 's/target>21/target>23/g' pom.xml
mvn clean compile -DskipTests package
time java -jar target/JavaTXcompiler-0.1-jar-with-dependencies.jar resources/bytecode/javFiles/Matrix.jav;
# mvn clean compile test
echo -e "\nCleanup... "
cd -
rm -rf "$TDIR" 2>/dev/null
echo -e "\nFinished "
date "+%Y.%m.%d %H:%M:%S"
echo -e "\n "

48
pom.xml
View File

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

View File

@@ -0,0 +1,51 @@
class C1 {
C1 self() {
return this;
}
}
class C2 {
C2 self() {
return this;
}
}
class Example {
untypedMethod(var) {
return var.self().self().self().self()
.self().self().self().self()
.self().self().self().self()
.self().self().self().self()
.self().self().self().self()
.self().self().self().self()
.self().self().self().self()
.self().self().self().self()
.self().self().self().self()
.self().self().self().self()
.self().self().self().self()
.self().self().self().self()
.self().self().self().self()
.self().self().self().self()
.self().self().self().self()
.self().self().self().self()
.self().self().self().self()
.self().self().self().self()
.self().self().self().self()
.self().self().self().self()
.self().self().self().self()
.self().self().self().self()
.self().self().self().self()
.self().self().self().self()
.self().self().self().self()
.self().self().self().self()
.self().self().self().self()
.self().self().self().self()
.self().self().self().self()
.self().self().self().self()
.self().self().self().self()
.self().self().self().self()
.self().self().self().self()
.self().self().self().self()
.self().self().self().self();
}
}

View File

@@ -0,0 +1,43 @@
import java.lang.Integer;
import java.lang.Boolean;
import java.util.Queue;
import java.util.Vector;
import java.util.List;
import java.util.ArrayDeque;
class Pos {
public Integer x;
public Integer y;
public Pos(Integer x, Integer y) {
this.x = x;
this.y = y;
}
}
class GridSearch {
Pos search(Vector<Vector<Boolean>> grid) {
var w = grid.size();
var h = grid.getFirst().size();
// keep a queue on which cells to check
var cellQueue = new ArrayDeque<Pos>();
cellQueue.add(new Pos(0,0));
while (!cellQueue.isEmpty()) {
var pos = cellQueue.poll();
// if the target was found: return the position
var value = grid.get(pos.x).get(pos.y);
if (value) {
return pos;
}
// keep searching on neighboring tiles
if (pos.x < w-1) cellQueue.add(new Pos(pos.x + 1, pos.y));
if (pos.y < h-1) cellQueue.add(new Pos(pos.x, pos.y + 1));
}
return (Pos)null;
}
}

View File

@@ -0,0 +1,42 @@
import java.util.List;
import java.util.AbstractList;
import java.util.Vector;
import java.lang.Integer;
class Pixel {
public color;
}
class Mask {
mask;
Mask(mask) {
this.mask = mask;
}
apply(pixels) {
var w = mask.size();
var h = mask.get(0).size();
var imgW = pixels.size();
var imgH = pixels.get(0).size();
for (var x = 0; x < imgW - w; x++) {
for (var y = 0; y < imgH - h; y++) {
var total = 0;
for (var xd = 0; xd < w; xd++) {
for (var yd = 0; yd < h; yd++) {
var p = pixels.get(x + xd).get(y + yd);
var m = mask.get(xd).get(yd);
total = total + (p.color * m);
}
}
pixels.get(x).get(y).color = total;
}
}
return pixels;
}
}

View File

@@ -0,0 +1,39 @@
import java.lang.Integer;
import java.lang.Boolean;
import java.util.ArrayList;
import java.util.HashMap;
public class PascalsTriangle {
create(n) {
var rows = new ArrayList<ArrayList<Integer>>();
var evens = new ArrayList<ArrayList<Boolean>>();
if (n <= 0) return rows;
// first row
rows.add(new ArrayList<Integer>(1));
evens.add(new ArrayList<Boolean>(false));
for (int y = 1; y < n; y++) {
var row = new ArrayList<Integer>();
var evensRow = new ArrayList<Boolean>();
row.add(1);
evensRow.add(false);
for (int x = 1; x < y-1; x++) {
int tl = rows.getLast().get(x-1);
int tr = rows.getLast().get(x);
row.add(tl + tr);
evensRow.add(((tl + tr) % 2) == 1);
}
row.add(1);
rows.add(row);
evensRow.add(false);
evens.add(evensRow);
}
return rows;
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,17 @@
import java.util.List;
import java.lang.Integer;
//import java.util.Collection;
public class Merge2 {
public merge(a, b) {
a.addAll(b);
return a;
}
public sort(in){
var firstHalf = in.subList(1,2);
return merge(sort(firstHalf), sort(in));
}
}

View File

@@ -8,18 +8,20 @@ import de.dhbwstuttgart.target.generate.ASTToTargetAST;
import de.dhbwstuttgart.target.tree.*; import de.dhbwstuttgart.target.tree.*;
import de.dhbwstuttgart.target.tree.expression.*; import de.dhbwstuttgart.target.tree.expression.*;
import de.dhbwstuttgart.target.tree.type.*; import de.dhbwstuttgart.target.tree.type.*;
import de.dhbwstuttgart.util.Logger;
import org.objectweb.asm.*; import org.objectweb.asm.*;
import java.lang.invoke.*; import java.lang.invoke.*;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;
import static org.objectweb.asm.Opcodes.*; import static org.objectweb.asm.Opcodes.*;
import static de.dhbwstuttgart.target.tree.expression.TargetBinaryOp.*; import static de.dhbwstuttgart.target.tree.expression.TargetBinaryOp.*;
import static de.dhbwstuttgart.target.tree.expression.TargetLiteral.*; import static de.dhbwstuttgart.target.tree.expression.TargetLiteral.*;
public class Codegen { public class Codegen {
public static Logger logger = new Logger("codegen");
private final TargetStructure clazz; private final TargetStructure clazz;
private final ClassWriter cw; private final ClassWriter cw;
public final String className; public final String className;
@@ -85,16 +87,14 @@ public class Codegen {
int localCounter; int localCounter;
MethodVisitor mv; MethodVisitor mv;
TargetType returnType; TargetType returnType;
boolean isStatic = false;
Stack<BreakEnv> breakStack = new Stack<>(); Stack<BreakEnv> breakStack = new Stack<>();
Stack<Integer> switchResultValue = new Stack<>(); Stack<Integer> switchResultValue = new Stack<>();
State(TargetType returnType, MethodVisitor mv, int localCounter, boolean isStatic) { State(TargetType returnType, MethodVisitor mv, int localCounter) {
this.returnType = returnType; this.returnType = returnType;
this.mv = mv; this.mv = mv;
this.localCounter = localCounter; this.localCounter = localCounter;
this.isStatic = isStatic;
} }
void enterScope() { void enterScope() {
@@ -232,9 +232,9 @@ public class Codegen {
if (source.equals(dest)) if (source.equals(dest))
return; return;
if (source.equals(TargetType.Long)) { if (source.equals(TargetType.Long)) {
if (dest.equals(TargetType.Integer)) if (dest.equals(TargetType.Integer)) {
mv.visitInsn(L2I); mv.visitInsn(L2I);
else if (dest.equals(TargetType.Float)) } else if (dest.equals(TargetType.Float))
mv.visitInsn(L2F); mv.visitInsn(L2F);
else if (dest.equals(TargetType.Double)) else if (dest.equals(TargetType.Double))
mv.visitInsn(L2D); mv.visitInsn(L2D);
@@ -277,8 +277,6 @@ public class Codegen {
mv.visitInsn(I2F); mv.visitInsn(I2F);
else if (dest.equals(TargetType.Double)) else if (dest.equals(TargetType.Double))
mv.visitInsn(I2D); mv.visitInsn(I2D);
} else if (source.equals(TargetType.Boolean)) {
unboxPrimitive(state, dest);
} else if (isFunctionalInterface(source) && isFunctionalInterface(dest) && } else if (isFunctionalInterface(source) && isFunctionalInterface(dest) &&
!(source instanceof TargetFunNType && dest instanceof TargetFunNType)) { !(source instanceof TargetFunNType && dest instanceof TargetFunNType)) {
boxFunctionalInterface(state, source, dest); boxFunctionalInterface(state, source, dest);
@@ -762,16 +760,6 @@ 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) { private void generateLambdaExpression(State state, TargetLambdaExpression lambda) {
var mv = state.mv; var mv = state.mv;
@@ -783,8 +771,7 @@ public class Codegen {
var parameters = new ArrayList<>(lambda.captures()); var parameters = new ArrayList<>(lambda.captures());
parameters.addAll(signature.parameters()); parameters.addAll(signature.parameters());
parameters = parameters.stream().map(param -> param.withType(removeGenerics(param.pattern().type()))).collect(Collectors.toCollection(ArrayList::new)); var implSignature = new TargetMethod.Signature(Set.of(), parameters, lambda.signature().returnType());
var implSignature = new TargetMethod.Signature(Set.of(), parameters, removeGenerics(lambda.signature().returnType()));
TargetMethod impl; TargetMethod impl;
if (lambdas.containsKey(lambda)) { if (lambdas.containsKey(lambda)) {
@@ -792,21 +779,20 @@ public class Codegen {
} else { } else {
var name = "lambda$" + lambdaCounter++; var name = "lambda$" + lambdaCounter++;
impl = new TargetMethod(state.isStatic ? ACC_STATIC : 0, name, lambda.block(), implSignature, null); impl = new TargetMethod(0, name, lambda.block(), implSignature, null);
generateMethod(impl, state); generateMethod(impl);
lambdas.put(lambda, impl); lambdas.put(lambda, impl);
} }
var mt = MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class, MethodType.class, MethodHandle.class, MethodType.class); 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 bootstrap = new Handle(H_INVOKESTATIC, "java/lang/invoke/LambdaMetafactory", "metafactory", mt.toMethodDescriptorString(), false);
var handle = new Handle(state.isStatic ? H_INVOKESTATIC : H_INVOKEVIRTUAL, clazz.getName(), impl.name(), implSignature.getDescriptor(), false); var handle = new Handle(H_INVOKEVIRTUAL, clazz.getName(), impl.name(), implSignature.getDescriptor(), false);
var params = new ArrayList<TargetType>(); var params = new ArrayList<TargetType>();
if(!state.isStatic) params.add(new TargetRefType(clazz.qualifiedName().getClassName())); params.add(new TargetRefType(clazz.qualifiedName().getClassName()));
params.addAll(lambda.captures().stream().map(mp -> mp.pattern().type()).toList()); params.addAll(lambda.captures().stream().map(mp -> mp.pattern().type()).toList());
if (!state.isStatic)
mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 0);
for (var index = 0; index < lambda.captures().size(); index++) { for (var index = 0; index < lambda.captures().size(); index++) {
var capture = lambda.captures().get(index); var capture = lambda.captures().get(index);
@@ -1334,7 +1320,7 @@ public class Codegen {
types.add(Type.getObjectType(guard.inner().type().getInternalName())); types.add(Type.getObjectType(guard.inner().type().getInternalName()));
// TODO Same here we need to evaluate constant; // TODO Same here we need to evaluate constant;
} else { } else {
System.out.println(label); logger.info(label);
throw new NotImplementedException(); throw new NotImplementedException();
} }
} }
@@ -1535,7 +1521,7 @@ public class Codegen {
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "<clinit>", "()V", null, null); MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "<clinit>", "()V", null, null);
mv.visitCode(); mv.visitCode();
var state = new State(null, mv, 0, true); var state = new State(null, mv, 0);
generate(state, constructor.block()); generate(state, constructor.block());
mv.visitInsn(RETURN); mv.visitInsn(RETURN);
@@ -1549,7 +1535,7 @@ public class Codegen {
mv.visitAttribute(new JavaTXSignatureAttribute(constructor.getTXSignature())); mv.visitAttribute(new JavaTXSignatureAttribute(constructor.getTXSignature()));
mv.visitCode(); mv.visitCode();
var state = new State(null, mv, 1, false); var state = new State(null, mv, 1);
for (var param : constructor.parameters()) { for (var param : constructor.parameters()) {
var pattern = param.pattern(); var pattern = param.pattern();
if (pattern instanceof TargetTypePattern tp) if (pattern instanceof TargetTypePattern tp)
@@ -1595,31 +1581,9 @@ public class Codegen {
} }
} }
} }
private void generateMethod(TargetMethod method) { private void generateMethod(TargetMethod method) {
generateMethod(method, null);
}
private void generateMainMethod() {
var mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESTATIC, "java/util/List", "of", "([Ljava/lang/Object;)Ljava/util/List;", true);
mv.visitMethodInsn(INVOKESTATIC, className, "main", "(Ljava/util/List;)V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
private void generateMethod(TargetMethod method, State parent) {
var access = method.access(); var 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) if (method.block() == null)
access |= ACC_ABSTRACT; access |= ACC_ABSTRACT;
if (clazz instanceof TargetInterface) if (clazz instanceof TargetInterface)
@@ -1633,10 +1597,7 @@ public class Codegen {
if (method.block() != null) { if (method.block() != null) {
mv.visitCode(); mv.visitCode();
var state = new State(method.signature().returnType(), mv, method.isStatic() ? 0 : 1, method.isStatic()); var state = new State(method.signature().returnType(), mv, method.isStatic() ? 0 : 1);
if (parent != null) {
state.scope.parent = parent.scope;
}
var offset = 1; var offset = 1;
for (var param : method.signature().parameters()) { for (var param : method.signature().parameters()) {
state.createVariable(param.pattern().name(), param.pattern().type()); state.createVariable(param.pattern().name(), param.pattern().type());
@@ -1646,8 +1607,6 @@ public class Codegen {
bindLocalVariables(state, cp, offset); bindLocalVariables(state, cp, offset);
offset++; offset++;
} }
//if (parent != null) System.out.println("parent: " + parent.scope.locals.keySet());
//System.out.println(state.scope.locals.keySet());
generate(state, method.block()); generate(state, method.block());
if (method.signature().returnType() == null) if (method.signature().returnType() == null)
mv.visitInsn(RETURN); mv.visitInsn(RETURN);
@@ -1739,7 +1698,7 @@ public class Codegen {
methodName = fromMethod.name; methodName = fromMethod.name;
fromReturn = converter.convert(fromMethod.getReturnType()); fromReturn = converter.convert(fromMethod.getReturnType());
var fromParams = converter.convert(fromMethod.getParameterList()).stream().map(m -> m.pattern().type()).toArray(TargetType[]::new); var fromParams = converter.convert(fromMethod.getParameterList(), converter.generics.javaGenerics()).stream().map(m -> m.pattern().type()).toArray(TargetType[]::new);
fromDescriptor = TargetMethod.getDescriptor(fromReturn, fromParams); fromDescriptor = TargetMethod.getDescriptor(fromReturn, fromParams);
} else { } else {
fromReturn = funNType.returnArguments() > 0 ? TargetType.Object : null; fromReturn = funNType.returnArguments() > 0 ? TargetType.Object : null;
@@ -1749,12 +1708,12 @@ public class Codegen {
var toClass = compiler.getClass(new JavaClassName(pair.to.name())); var toClass = compiler.getClass(new JavaClassName(pair.to.name()));
var toMethod = toClass.getMethods().stream().filter(m -> (m.modifier & ACC_ABSTRACT) != 0).findFirst().orElseThrow(); var toMethod = toClass.getMethods().stream().filter(m -> (m.modifier & ACC_ABSTRACT) != 0).findFirst().orElseThrow();
var toReturn = converter.convert(toMethod.getReturnType()); var toReturn = converter.convert(toMethod.getReturnType());
var toParams = converter.convert(toMethod.getParameterList()).stream().map(m -> m.pattern().type()).toArray(TargetType[]::new); var toParams = converter.convert(toMethod.getParameterList(), converter.generics.javaGenerics()).stream().map(m -> m.pattern().type()).toArray(TargetType[]::new);
var toDescriptor = TargetMethod.getDescriptor(toReturn, toParams); var toDescriptor = TargetMethod.getDescriptor(toReturn, toParams);
// Generate wrapper method // Generate wrapper method
var mv = cw2.visitMethod(ACC_PUBLIC, toMethod.name, toDescriptor, null, null); var mv = cw2.visitMethod(ACC_PUBLIC, toMethod.name, toDescriptor, null, null);
var state = new State(null, mv, 0, false); var state = new State(null, mv, 0);
mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, className, "wrapped", pair.from.toDescriptor()); mv.visitFieldInsn(GETFIELD, className, "wrapped", pair.from.toDescriptor());
@@ -1786,7 +1745,7 @@ public class Codegen {
converter.classLoader.findClass(className); converter.classLoader.findClass(className);
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
try { try {
converter.classLoader.loadClass(className, bytes); converter.classLoader.loadClass(bytes);
} catch (LinkageError ignored) {} } catch (LinkageError ignored) {}
} }
} }

View File

@@ -39,10 +39,6 @@ public class FunNGenerator {
public final List<TargetType> inParams; public final List<TargetType> inParams;
public final List<TargetType> realParams; public final List<TargetType> realParams;
public GenericParameters(TargetFunNType funNType) {
this(funNType.funNParams(), funNType.returnArguments());
}
public GenericParameters(List<TargetType> params, int numReturns) { public GenericParameters(List<TargetType> params, int numReturns) {
this.realParams = params; this.realParams = params;
this.inParams = flattenTypeParams(params); this.inParams = flattenTypeParams(params);
@@ -124,7 +120,7 @@ public class FunNGenerator {
superFunNMethodDescriptor.append(")V"); superFunNMethodDescriptor.append(")V");
} }
System.out.println(superFunNMethodSignature); Codegen.logger.info(superFunNMethodSignature);
ClassWriter classWriter = new ClassWriter(0); ClassWriter classWriter = new ClassWriter(0);
MethodVisitor methodVisitor; MethodVisitor methodVisitor;

View File

@@ -1,45 +1,80 @@
package de.dhbwstuttgart.core; package de.dhbwstuttgart.core;
import de.dhbwstuttgart.server.SocketClient;
import de.dhbwstuttgart.util.Logger;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.*; import java.util.*;
public class ConsoleInterface { public class ConsoleInterface {
private static final String directory = System.getProperty("user.dir");
/**
* Leave the argument configurations here for the rest of the code to read
*/
public static Logger.LogLevel logLevel = Logger.LogLevel.ERROR;
public static boolean writeLogFiles = false;
public static Optional<String> unifyServerUrl = Optional.empty();
public static void main(String[] args) throws IOException, ClassNotFoundException { public static void main(String[] args) throws IOException, ClassNotFoundException {
List<File> input = new ArrayList<>(); List<File> input = new ArrayList<>();
List<File> classpath = new ArrayList<>(); List<File> classpath = new ArrayList<>();
String outputPath = null; String outputPath = null;
Iterator<String> it = Arrays.asList(args).iterator(); Iterator<String> it = Arrays.asList(args).iterator();
if(args.length == 0){ Optional<Integer> serverPort = Optional.empty();
if (args.length == 0) {
System.out.println("No input files given. Get help with --help"); System.out.println("No input files given. Get help with --help");
System.exit(1); System.exit(1);
}else if(args.length == 1 && args[0].equals("--help")){ } else if (args.length == 1 && args[0].equals("--help")) {
System.out.println("Usage: javatx [OPTION]... [FILE]...\n" + System.out.println("Usage: javatx [OPTION]... [FILE]...\n" +
"\t-cp\tSet Classpath\n" + "\t-cp\tSet Classpath\n" +
"\t-d\tSet destination directory"); "\t-d\tSet destination directory\n" +
"\t[--server-mode <port>]\n" +
"\t[--unify-server <url>]\n" +
"\t[--write-logs]\n" +
"\t[-v|-vv-|-vvv]");
System.exit(1); System.exit(1);
} }
while(it.hasNext()){ while (it.hasNext()) {
String arg = it.next(); String arg = it.next();
if(arg.equals("-d")){ if (arg.equals("-d")) {
outputPath = it.next(); outputPath = it.next();
}else if(arg.startsWith("-d")) { } else if (arg.startsWith("-d")) {
outputPath = arg.substring(2); outputPath = arg.substring(2);
}else if(arg.equals("-cp") || arg.equals("-classpath")){ } else if (arg.equals("-cp") || arg.equals("-classpath")) {
String[] cps = it.next().split(":"); String[] cps = it.next().split(":");
for(String cp : cps){ for (String cp : cps) {
classpath.add(new File(cp)); classpath.add(new File(cp));
} }
}else{ } else if (arg.equals("--server-mode")) {
serverPort = Optional.of(Integer.parseInt(it.next()));
} else if (arg.equals("--unify-server")) {
unifyServerUrl = Optional.of(it.next());
} else if (arg.equals("--write-logs")) {
ConsoleInterface.writeLogFiles = true;
} else if (arg.startsWith("-v")) {
logLevel = switch (arg) {
case "-v" -> Logger.LogLevel.WARNING;
case "-vv" -> Logger.LogLevel.INFO;
case "-vvv" -> Logger.LogLevel.DEBUG;
default -> throw new IllegalArgumentException("Argument " + arg + " is not a valid verbosity level");
};
} else {
input.add(new File(arg)); input.add(new File(arg));
} }
} }
if (serverPort.isPresent()) {
if (unifyServerUrl.isPresent()) throw new RuntimeException("Cannot use unifyServer when in server mode!");
JavaTXServer server = new JavaTXServer(serverPort.get());
server.listen();
}
else {
JavaTXCompiler compiler = new JavaTXCompiler(input, classpath, outputPath != null ? new File(outputPath) : null); JavaTXCompiler compiler = new JavaTXCompiler(input, classpath, outputPath != null ? new File(outputPath) : null);
//compiler.typeInference(); //compiler.typeInference();
compiler.generateBytecode(); compiler.generateBytecode();
SocketClient.closeIfOpen();
}
} }

View File

@@ -12,6 +12,11 @@ import de.dhbwstuttgart.parser.SyntaxTreeGenerator.SyntaxTreeGenerator;
import de.dhbwstuttgart.parser.antlr.Java17Parser.SourceFileContext; import de.dhbwstuttgart.parser.antlr.Java17Parser.SourceFileContext;
import de.dhbwstuttgart.parser.scope.JavaClassName; import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.parser.scope.JavaClassRegistry; import de.dhbwstuttgart.parser.scope.JavaClassRegistry;
import de.dhbwstuttgart.server.SocketClient;
import de.dhbwstuttgart.server.SocketFuture;
import de.dhbwstuttgart.server.packet.SetAutoclosePacket;
import de.dhbwstuttgart.server.packet.UnifyRequestPacket;
import de.dhbwstuttgart.server.packet.UnifyResultPacket;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface; import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.syntaxtree.GenericTypeVar; import de.dhbwstuttgart.syntaxtree.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.Method; import de.dhbwstuttgart.syntaxtree.Method;
@@ -19,6 +24,7 @@ import de.dhbwstuttgart.syntaxtree.ParameterList;
import de.dhbwstuttgart.syntaxtree.SourceFile; import de.dhbwstuttgart.syntaxtree.SourceFile;
import de.dhbwstuttgart.syntaxtree.GenericDeclarationList; import de.dhbwstuttgart.syntaxtree.GenericDeclarationList;
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
import de.dhbwstuttgart.syntaxtree.factory.NameGenerator;
import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory; import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory;
import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType; import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType;
import de.dhbwstuttgart.syntaxtree.type.GenericRefType; import de.dhbwstuttgart.syntaxtree.type.GenericRefType;
@@ -35,10 +41,13 @@ import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
import de.dhbwstuttgart.typeinference.constraints.Pair; import de.dhbwstuttgart.typeinference.constraints.Pair;
import de.dhbwstuttgart.typeinference.result.ResultSet; import de.dhbwstuttgart.typeinference.result.ResultSet;
import de.dhbwstuttgart.typeinference.typeAlgo.TYPE; import de.dhbwstuttgart.typeinference.typeAlgo.TYPE;
import de.dhbwstuttgart.typeinference.unify.PlaceholderRegistry;
import de.dhbwstuttgart.typeinference.unify.RuleSet; import de.dhbwstuttgart.typeinference.unify.RuleSet;
import de.dhbwstuttgart.typeinference.unify.TypeUnify; import de.dhbwstuttgart.typeinference.unify.TypeUnify;
import de.dhbwstuttgart.typeinference.unify.UnifyContext;
import de.dhbwstuttgart.typeinference.unify.distributeVariance; import de.dhbwstuttgart.typeinference.unify.distributeVariance;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unify.model.FiniteClosure;
import de.dhbwstuttgart.typeinference.unify.model.PairOperator; import de.dhbwstuttgart.typeinference.unify.model.PairOperator;
import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType; import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
@@ -49,6 +58,7 @@ import de.dhbwstuttgart.typeinference.unify.UnifyResultListenerImpl;
import de.dhbwstuttgart.typeinference.unify.UnifyResultModel; import de.dhbwstuttgart.typeinference.unify.UnifyResultModel;
import de.dhbwstuttgart.typeinference.unify.UnifyTaskModel; import de.dhbwstuttgart.typeinference.unify.UnifyTaskModel;
import de.dhbwstuttgart.util.Logger;
import java.io.*; import java.io.*;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.nio.file.Path; import java.nio.file.Path;
@@ -61,12 +71,15 @@ import org.apache.commons.io.output.NullOutputStream;
public class JavaTXCompiler { public class JavaTXCompiler {
// do not use this in any code, that can be executed serverside!
public static PlaceholderRegistry defaultClientPlaceholderRegistry = new PlaceholderRegistry();
public static Logger defaultLogger = new Logger();
// public static JavaTXCompiler INSTANCE; // public static JavaTXCompiler INSTANCE;
final CompilationEnvironment environment; final CompilationEnvironment environment;
Boolean resultmodel = true; Boolean resultmodel = true;
public final Map<File, SourceFile> sourceFiles = new HashMap<>(); public final Map<File, SourceFile> sourceFiles = new HashMap<>();
Boolean log = false; //gibt an ob ein Log-File nach System.getProperty("user.dir")+""/logFiles/"" geschrieben werden soll?
public volatile UnifyTaskModel usedTasks = new UnifyTaskModel(); public volatile UnifyTaskModel usedTasks = new UnifyTaskModel();
public final DirectoryClassLoader classLoader; public final DirectoryClassLoader classLoader;
@@ -78,12 +91,7 @@ public class JavaTXCompiler {
} }
public JavaTXCompiler(File sourceFile) throws IOException, ClassNotFoundException { public JavaTXCompiler(File sourceFile) throws IOException, ClassNotFoundException {
this(Arrays.asList(sourceFile), List.of(), new File(".")); this(Collections.singletonList(sourceFile), List.of(), new File("."));
}
public JavaTXCompiler(File sourceFile, Boolean log) throws IOException, ClassNotFoundException {
this(sourceFile);
this.log = log;
} }
public JavaTXCompiler(List<File> sourceFiles) throws IOException, ClassNotFoundException { public JavaTXCompiler(List<File> sourceFiles) throws IOException, ClassNotFoundException {
@@ -91,6 +99,11 @@ public class JavaTXCompiler {
} }
public JavaTXCompiler(List<File> sources, List<File> contextPath, File outputPath) throws IOException, ClassNotFoundException { public JavaTXCompiler(List<File> sources, List<File> contextPath, File outputPath) throws IOException, ClassNotFoundException {
// ensure new default placeholder registry for tests
defaultClientPlaceholderRegistry = new PlaceholderRegistry();
NameGenerator.reset();
ASTToTargetAST.OBJECT = ASTFactory.createObjectType();
var path = new ArrayList<>(contextPath); var path = new ArrayList<>(contextPath);
if (contextPath.isEmpty()) { if (contextPath.isEmpty()) {
// When no contextPaths are given, the working directory is the sources root // When no contextPaths are given, the working directory is the sources root
@@ -300,13 +313,15 @@ public class JavaTXCompiler {
Set<Set<UnifyPair>> results = new HashSet<>(); Set<Set<UnifyPair>> results = new HashSet<>();
UnifyResultModel urm = null; UnifyResultModel urm = null;
// urm.addUnifyResultListener(resultListener); // urm.addUnifyResultListener(resultListener);
try { logFile = logFile == null ? new FileWriter("log_" + sourceFiles.keySet().iterator().next().getName()) : logFile;
logFile = logFile == null ? new FileWriter(new File("log_" + sourceFiles.keySet().iterator().next().getName())) : logFile; Logger logger = new Logger(logFile, "TypeInferenceAsync");
IFiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses, logFile, getClassLoader(), this); UnifyContext context = new UnifyContext(logger, true, urm, usedTasks, defaultClientPlaceholderRegistry);
System.out.println(finiteClosure);
IFiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses, logger, getClassLoader(), this, context.placeholderRegistry());
logger.info(finiteClosure.toString());
urm = new UnifyResultModel(cons, finiteClosure); urm = new UnifyResultModel(cons, finiteClosure);
urm.addUnifyResultListener(resultListener); urm.addUnifyResultListener(resultListener);
ConstraintSet<UnifyPair> unifyCons = UnifyTypeFactory.convert(this, cons); ConstraintSet<UnifyPair> unifyCons = UnifyTypeFactory.convert(this, cons, context.placeholderRegistry());
Function<UnifyPair, UnifyPair> distributeInnerVars = x -> { Function<UnifyPair, UnifyPair> distributeInnerVars = x -> {
UnifyType lhs, rhs; UnifyType lhs, rhs;
@@ -317,16 +332,15 @@ public class JavaTXCompiler {
return x; return x;
}; };
logFile.write(unifyCons.toString()); logger.debug(unifyCons.toString());
unifyCons = unifyCons.map(distributeInnerVars); unifyCons = unifyCons.map(distributeInnerVars);
logFile.write(unifyCons.toString()); logger.debug(unifyCons.toString());
TypeUnify unify = new TypeUnify();
// Set<Set<UnifyPair>> results = new HashSet<>(); Nach vorne gezogen // Set<Set<UnifyPair>> results = new HashSet<>(); Nach vorne gezogen
logFile.write("FC:\\" + finiteClosure.toString() + "\n"); logger.debug("FC:\\" + finiteClosure.toString() + "\n");
for (SourceFile f : this.sourceFiles.values()) { for (SourceFile f : this.sourceFiles.values()) {
logFile.write(ASTTypePrinter.print(f)); logger.debug(ASTTypePrinter.print(f));
} }
logFile.flush(); // logFile.flush();
Set<PlaceholderType> varianceTPHold; Set<PlaceholderType> varianceTPHold;
Set<PlaceholderType> varianceTPH = new HashSet<>(); Set<PlaceholderType> varianceTPH = new HashSet<>();
varianceTPH = varianceInheritanceConstraintSet(unifyCons); varianceTPH = varianceInheritanceConstraintSet(unifyCons);
@@ -342,10 +356,8 @@ public class JavaTXCompiler {
List<Set<Constraint<UnifyPair>>> oderConstraints = unifyCons.getOderConstraints()/* List<Set<Constraint<UnifyPair>>> oderConstraints = unifyCons.getOderConstraints()/*
* .stream().map(x -> { Set<Set<UnifyPair>> ret = new HashSet<>(); for (Constraint<UnifyPair> y : x) { ret.add(new HashSet<>(y)); } return ret; }).collect(Collectors. toCollection(ArrayList::new)) * .stream().map(x -> { Set<Set<UnifyPair>> ret = new HashSet<>(); for (Constraint<UnifyPair> y : x) { ret.add(new HashSet<>(y)); } return ret; }).collect(Collectors. toCollection(ArrayList::new))
*/; */;
unify.unifyAsync(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, logFile, log, urm, usedTasks); TypeUnify.unifyAsync(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, context);
} catch (IOException e) {
System.err.println("kein LogFile");
}
return urm; return urm;
} }
@@ -365,14 +377,17 @@ public class JavaTXCompiler {
final ConstraintSet<Pair> cons = getConstraints(file); final ConstraintSet<Pair> cons = getConstraints(file);
Set<Set<UnifyPair>> results = new HashSet<>(); Set<Set<UnifyPair>> results = new HashSet<>();
try { PlaceholderRegistry placeholderRegistry = new PlaceholderRegistry();
var logFolder = new File(System.getProperty("user.dir") + "/logFiles/"); var logFolder = new File(System.getProperty("user.dir") + "/logFiles/");
if (log) logFolder.mkdirs(); if (ConsoleInterface.writeLogFiles && !logFolder.mkdirs()) throw new RuntimeException("Could not creat directoy for log files: " + logFolder);
Writer logFile = log ? new FileWriter(new File(logFolder, "log_" + sourceFiles.keySet().iterator().next().getName())) : new OutputStreamWriter(new NullOutputStream()); Writer logFile = ConsoleInterface.writeLogFiles ? new FileWriter(new File(logFolder, "log_" + sourceFiles.keySet().iterator().next().getName())) : new OutputStreamWriter(new NullOutputStream());
IFiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses.stream().toList(), logFile, classLoader, this); Logger logger = new Logger(logFile, "TypeInference");
System.out.println(finiteClosure);
ConstraintSet<UnifyPair> unifyCons = UnifyTypeFactory.convert(this, cons); FiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses.stream().toList(), logger, classLoader, this, placeholderRegistry);
System.out.println("xxx1"); logger.info(finiteClosure.toString());
ConstraintSet<UnifyPair> unifyCons = UnifyTypeFactory.convert(this, cons, placeholderRegistry);
logger.info("xxx1");
Function<UnifyPair, UnifyPair> distributeInnerVars = x -> { Function<UnifyPair, UnifyPair> distributeInnerVars = x -> {
UnifyType lhs, rhs; UnifyType lhs, rhs;
if (((lhs = x.getLhsType()) instanceof PlaceholderType) && ((rhs = x.getRhsType()) instanceof PlaceholderType) && (((PlaceholderType) lhs).isInnerType() || ((PlaceholderType) rhs).isInnerType())) { if (((lhs = x.getLhsType()) instanceof PlaceholderType) && ((rhs = x.getRhsType()) instanceof PlaceholderType) && (((PlaceholderType) lhs).isInnerType() || ((PlaceholderType) rhs).isInnerType())) {
@@ -383,22 +398,16 @@ public class JavaTXCompiler {
}; };
logFile.write("Unify:" + unifyCons.toString()); logger.debug("Unify:" + unifyCons.toString());
System.out.println("Unify:" + unifyCons.toString()); logger.info("Unify:" + unifyCons.toString());
unifyCons = unifyCons.map(distributeInnerVars); unifyCons = unifyCons.map(distributeInnerVars);
logFile.write("\nUnify_distributeInnerVars: " + unifyCons.toString()); logger.debug("\nUnify_distributeInnerVars: " + unifyCons.toString());
TypeUnify unify = new TypeUnify();
// Set<Set<UnifyPair>> results = new HashSet<>(); Nach vorne gezogen // Set<Set<UnifyPair>> results = new HashSet<>(); Nach vorne gezogen
logFile.write("FC:\\" + finiteClosure.toString() + "\n"); logger.debug("FC:\\" + finiteClosure.toString() + "\n");
logFile.write(ASTTypePrinter.print(sf)); logger.debug(ASTTypePrinter.print(sf));
System.out.println(ASTTypePrinter.print(sf)); logger.info(ASTTypePrinter.print(sf));
logFile.flush(); // logFile.flush();
List<UnifyPair> andConstraintsSorted = unifyCons.getUndConstraints().stream() logger.info("Unify nach Oder-Constraints-Anpassung:" + unifyCons.toString());
.sorted(Comparator.comparing(UnifyPair::getPairOp).thenComparing(UnifyPair::getLhsType, Comparator.comparing(UnifyType::getName)))
.collect(Collectors.toList());
System.out.println(andConstraintsSorted);
Set<PlaceholderType> varianceTPHold; Set<PlaceholderType> varianceTPHold;
Set<PlaceholderType> varianceTPH = new HashSet<>(); Set<PlaceholderType> varianceTPH = new HashSet<>();
varianceTPH = varianceInheritanceConstraintSet(unifyCons); varianceTPH = varianceInheritanceConstraintSet(unifyCons);
@@ -415,23 +424,27 @@ public class JavaTXCompiler {
/* /*
* Set<Set<UnifyPair>> ret = new HashSet<>(); for (Constraint<UnifyPair> y : x) { ret.add(new HashSet<>(y)); } return ret; }).collect(Collectors.toCollection(ArrayList::new)) * Set<Set<UnifyPair>> ret = new HashSet<>(); for (Constraint<UnifyPair> y : x) { ret.add(new HashSet<>(y)); } return ret; }).collect(Collectors.toCollection(ArrayList::new))
*/; */;
if (resultmodel) {
if (ConsoleInterface.unifyServerUrl.isPresent()) {
UnifyResultModel urm = new UnifyResultModel(cons, finiteClosure);
UnifyContext context = new UnifyContext(logger, true, urm, usedTasks, placeholderRegistry);
SocketFuture<UnifyResultPacket> future = SocketClient.execute(
UnifyRequestPacket.create(finiteClosure, cons, unifyCons, context.placeholderRegistry())
);
SocketClient.execute(SetAutoclosePacket.create());
return future.get().getResultSet(context);
}
else if (resultmodel) {
/* UnifyResultModel Anfang */ /* UnifyResultModel Anfang */
UnifyResultModel urm = new UnifyResultModel(cons, finiteClosure); UnifyResultModel urm = new UnifyResultModel(cons, finiteClosure);
UnifyResultListenerImpl li = new UnifyResultListenerImpl(); UnifyResultListenerImpl li = new UnifyResultListenerImpl();
urm.addUnifyResultListener(li); urm.addUnifyResultListener(li);
unify.unifyParallel(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, logFile, log, urm, usedTasks); UnifyContext context = new UnifyContext(logger, true, urm, usedTasks, placeholderRegistry);
//System.out.println("RESULT Final: " + li.getResults()); TypeUnify.unifyParallel(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, context);
var finalResults = li.getResults().stream().sorted().toList(); logger.info("RESULT Final: " + li.getResults());
int i = 0; logger.info("Constraints for Generated Generics: " + " ???");
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.write("RES_FINAL: " + li.getResults().toString() + "\n");
logFile.flush(); // logFile.flush();
return li.getResults(); return li.getResults();
} }
/* UnifyResultModel End */ /* UnifyResultModel End */
@@ -439,34 +452,33 @@ public class JavaTXCompiler {
// Set<Set<UnifyPair>> result = unify.unify(unifyCons.getUndConstraints(), // Set<Set<UnifyPair>> result = unify.unify(unifyCons.getUndConstraints(),
// oderConstraints, finiteClosure, logFile, log, new UnifyResultModel(cons, // oderConstraints, finiteClosure, logFile, log, new UnifyResultModel(cons,
// finiteClosure)); // finiteClosure));
Set<Set<UnifyPair>> result = unify.unifyOderConstraints(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, logFile, log, new UnifyResultModel(cons, finiteClosure), usedTasks); UnifyContext context = new UnifyContext(logger, false, new UnifyResultModel(cons, finiteClosure), usedTasks, placeholderRegistry);
System.out.println("RESULT: " + result); Set<Set<UnifyPair>> result = TypeUnify.unifyOderConstraints(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, context);
logger.info("RESULT: " + result);
logFile.write("RES: " + result.toString() + "\n"); logFile.write("RES: " + result.toString() + "\n");
logFile.flush(); // logFile.flush();
results.addAll(result); results.addAll(result);
results = results.stream().map(x -> { results = results.stream().map(x -> {
Optional<Set<UnifyPair>> res = new RuleSet().subst(x.stream().map(y -> { Optional<Set<UnifyPair>> res = new RuleSet(placeholderRegistry).subst(x.stream().map(y -> {
if (y.getPairOp() == PairOperator.SMALLERDOTWC) if (y.getPairOp() == PairOperator.SMALLERDOTWC)
y.setPairOp(PairOperator.EQUALSDOT); y.setPairOp(PairOperator.EQUALSDOT);
return y; // alle Paare a <.? b erden durch a =. b ersetzt return y; // alle Paare a <.? b erden durch a =. b ersetzt
}).collect(Collectors.toCollection(HashSet::new))); }).collect(Collectors.toCollection(HashSet::new)));
if (res.isPresent()) {// wenn subst ein Erg liefert wurde was veraendert if (res.isPresent()) {// wenn subst ein Erg liefert wurde was veraendert
return new TypeUnifyTask().applyTypeUnificationRules(res.get(), finiteClosure); return new TypeUnifyTask(context).applyTypeUnificationRules(res.get(), finiteClosure);
} else } else
return x; // wenn nichts veraendert wurde wird x zurueckgegeben return x; // wenn nichts veraendert wurde wird x zurueckgegeben
}).collect(Collectors.toCollection(HashSet::new)); }).collect(Collectors.toCollection(HashSet::new));
System.out.println("RESULT Final: " + results); logger.info("RESULT Final: " + results);
System.out.println("Constraints for Generated Generics: " + " ???"); logger.info("Constraints for Generated Generics: " + " ???");
logFile.write("RES_FINAL: " + results.toString() + "\n"); logger.debug("RES_FINAL: " + results.toString() + "\n");
logFile.flush(); // logFile.flush();
logFile.write("PLACEHOLDERS: " + PlaceholderType.EXISTING_PLACEHOLDERS); logger.debug("PLACEHOLDERS: " + placeholderRegistry);
logFile.flush(); // logFile.flush();
} }
} catch (IOException e) {
System.err.println("kein LogFile"); return results.stream().map((unifyPairs -> new ResultSet(UnifyTypeFactory.convert(unifyPairs, Pair.generateTPHMap(cons), placeholderRegistry)))).collect(Collectors.toList());
}
return results.stream().map((unifyPairs -> new ResultSet(UnifyTypeFactory.convert(unifyPairs, Pair.generateTPHMap(cons))))).collect(Collectors.toList());
} }
/** /**
@@ -598,10 +610,6 @@ public class JavaTXCompiler {
} }
} }
/**
* @param path - output-Directory can be null, then class file output is in the same directory as the parsed source files
* @return
*/
public Map<JavaClassName, byte[]> generateBytecode(File sourceFile) throws ClassNotFoundException, IOException { public Map<JavaClassName, byte[]> generateBytecode(File sourceFile) throws ClassNotFoundException, IOException {
var sf = sourceFiles.get(sourceFile); var sf = sourceFiles.get(sourceFile);
if (sf.isGenerated()) return null; if (sf.isGenerated()) return null;
@@ -643,12 +651,12 @@ public class JavaTXCompiler {
var codegen = new Codegen(converter.convert(clazz), this, converter); var codegen = new Codegen(converter.convert(clazz), this, converter);
var code = codegen.generate(); var code = codegen.generate();
generatedClasses.put(clazz.getClassName(), code); generatedClasses.put(clazz.getClassName(), code);
}
generatedGenerics.put(sf, converter.javaGenerics());
converter.generateFunNTypes();
converter.auxiliaries.forEach((name, source) -> { converter.auxiliaries.forEach((name, source) -> {
generatedClasses.put(new JavaClassName(name), source); generatedClasses.put(new JavaClassName(name), source);
}); });
}
generatedGenerics.put(sf, converter.javaGenerics());
converter.generateFunNTypes();
return generatedClasses; return generatedClasses;
} }
@@ -656,15 +664,15 @@ public class JavaTXCompiler {
FileOutputStream output; FileOutputStream output;
for (JavaClassName name : classFiles.keySet()) { for (JavaClassName name : classFiles.keySet()) {
byte[] bytecode = classFiles.get(name); byte[] bytecode = classFiles.get(name);
System.out.println("generating " + name + ".class file ..."); defaultLogger.info("generating " + name + ".class file ...");
var subPath = preserveHierarchy ? path : Path.of(path.toString(), name.getPackageName().split("\\.")).toFile(); var subPath = preserveHierarchy ? path : Path.of(path.toString(), name.getPackageName().split("\\.")).toFile();
File outputFile = new File(subPath, name.getClassName() + ".class"); File outputFile = new File(subPath, name.getClassName() + ".class");
outputFile.getAbsoluteFile().getParentFile().mkdirs(); outputFile.getAbsoluteFile().getParentFile().mkdirs();
System.out.println(outputFile); defaultLogger.info(outputFile.toString());
output = new FileOutputStream(outputFile); output = new FileOutputStream(outputFile);
output.write(bytecode); output.write(bytecode);
output.close(); output.close();
System.out.println(name + ".class file generated"); defaultLogger.success(name + ".class file generated");
} }
} }

View File

@@ -0,0 +1,31 @@
package de.dhbwstuttgart.core;
import de.dhbwstuttgart.server.SocketServer;
public class JavaTXServer {
public static boolean isRunning = false;
final SocketServer socketServer;
public JavaTXServer(int port) {
this.socketServer = new SocketServer(port);
}
public void listen() {
isRunning = true;
socketServer.start();
}
public void forceStop() {
try {
socketServer.stop();
}
catch (InterruptedException exception) {
System.err.println("Interrupted socketServer: " + exception);
}
isRunning = false;
}
}

View File

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

View File

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

View File

@@ -0,0 +1,11 @@
package de.dhbwstuttgart.exceptions;
/**
* Eine Runtime Exception, die für den Fall genutzt wird, dass eine Unifikation abgebrochen wird.
* Durch das Werfen einer Exception können Abbrüche auch aus Methodenaufrufen heraus
* geprüft werden, da zuvor nur ein return X; stattfinden würde.
*/
public class UnifyCancelException extends RuntimeException {
}

View File

@@ -7,6 +7,7 @@ import de.dhbwstuttgart.parser.antlr.Java17Parser;
import de.dhbwstuttgart.parser.scope.JavaClassRegistry; import de.dhbwstuttgart.parser.scope.JavaClassRegistry;
import de.dhbwstuttgart.syntaxtree.SourceFile; import de.dhbwstuttgart.syntaxtree.SourceFile;
import de.dhbwstuttgart.util.Logger;
import org.antlr.v4.runtime.CharStream; import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream; import org.antlr.v4.runtime.CommonTokenStream;
@@ -17,6 +18,9 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
public class JavaTXParser { public class JavaTXParser {
public static Logger logger = new Logger("Parser");
public static Java17Parser.SourceFileContext parse(File source) throws IOException, java.lang.ClassNotFoundException { public static Java17Parser.SourceFileContext parse(File source) throws IOException, java.lang.ClassNotFoundException {
InputStream stream = new FileInputStream(source); InputStream stream = new FileInputStream(source);
// DEPRECATED: ANTLRInputStream input = new ANTLRInputStream(stream); // DEPRECATED: ANTLRInputStream input = new ANTLRInputStream(stream);

View File

@@ -1,4 +1,25 @@
package de.dhbwstuttgart.parser; package de.dhbwstuttgart.parser;
public record SourceLoc(String file, int line) { import de.dhbwstuttgart.server.packet.dataContainers.ISerializableData;
import de.dhbwstuttgart.server.packet.dataContainers.KeyStorage;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialMap;
public record SourceLoc(String file, int line) implements ISerializableData {
@Override
public SerialMap toSerial(KeyStorage keyStorage) {
var serialized = new SerialMap();
serialized.put("file", file);
serialized.put("line", line);
return serialized;
}
public static SourceLoc fromSerial(SerialMap data) {
return new SourceLoc(
data.getValue("file").getOf(String.class),
data.getValue("line").getOf(Integer.class)
);
}
} }

View File

@@ -12,6 +12,7 @@ import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory; import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory;
import de.dhbwstuttgart.syntaxtree.type.*; import de.dhbwstuttgart.syntaxtree.type.*;
import de.dhbwstuttgart.typeinference.constraints.Pair; import de.dhbwstuttgart.typeinference.constraints.Pair;
import de.dhbwstuttgart.typeinference.unify.PlaceholderRegistry;
import de.dhbwstuttgart.typeinference.unify.model.*; import de.dhbwstuttgart.typeinference.unify.model.*;
import java.util.*; import java.util.*;
@@ -26,16 +27,21 @@ public class FCGenerator {
* *
* @param availableClasses - Alle geparsten Klassen * @param availableClasses - Alle geparsten Klassen
*/ */
public static Set<UnifyPair> toUnifyFC(JavaTXCompiler compiler, Collection<ClassOrInterface> availableClasses, ClassLoader classLoader) throws ClassNotFoundException { public static Set<UnifyPair> toUnifyFC(JavaTXCompiler compiler, Collection<ClassOrInterface> availableClasses, ClassLoader classLoader, PlaceholderRegistry placeholderRegistry) throws ClassNotFoundException {
return toFC(availableClasses, classLoader).stream().map(t -> UnifyTypeFactory.convert(compiler, t)).collect(Collectors.toSet()); return toFC(
availableClasses,
classLoader,
placeholderRegistry
).stream().map(t -> UnifyTypeFactory.convert(compiler, t, placeholderRegistry))
.collect(Collectors.toSet());
} }
public static Set<Pair> toFC(Collection<ClassOrInterface> availableClasses, ClassLoader classLoader) throws ClassNotFoundException { public static Set<Pair> toFC(Collection<ClassOrInterface> availableClasses, ClassLoader classLoader, PlaceholderRegistry placeholderRegistry) throws ClassNotFoundException {
HashSet<Pair> pairs = new HashSet<>(); HashSet<Pair> pairs = new HashSet<>();
//PL 2018-09-18: gtvs vor die for-Schleife gezogen, damit immer die gleichen Typeplaceholder eingesetzt werden. //PL 2018-09-18: gtvs vor die for-Schleife gezogen, damit immer die gleichen Typeplaceholder eingesetzt werden.
HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> gtvs = new HashMap<>(); HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> gtvs = new HashMap<>();
for(ClassOrInterface cly : availableClasses){ for(ClassOrInterface cly : availableClasses){
List<Pair> newPairs = getSuperTypes(cly, availableClasses, gtvs, classLoader); List<Pair> newPairs = getSuperTypes(cly, availableClasses, gtvs, classLoader, placeholderRegistry);
pairs.addAll(newPairs); pairs.addAll(newPairs);
//For all Functional Interfaces FI: FunN$$<... args auf dem Functional Interface ...> <. FI is added to FC //For all Functional Interfaces FI: FunN$$<... args auf dem Functional Interface ...> <. FI is added to FC
@@ -75,8 +81,13 @@ public class FCGenerator {
* @param forType * @param forType
* @return * @return
*/ */
private static List<Pair> getSuperTypes(ClassOrInterface forType, Collection<ClassOrInterface> availableClasses, ClassLoader classLoader) throws ClassNotFoundException { private static List<Pair> getSuperTypes(
return getSuperTypes(forType, availableClasses, new HashMap<>(), classLoader); ClassOrInterface forType,
Collection<ClassOrInterface> availableClasses,
ClassLoader classLoader,
PlaceholderRegistry placeholderRegistry
) throws ClassNotFoundException {
return getSuperTypes(forType, availableClasses, new HashMap<>(), classLoader, placeholderRegistry);
} }
/** /**
@@ -87,8 +98,13 @@ public class FCGenerator {
* @return * @return
* @throws ClassNotFoundException * @throws ClassNotFoundException
*/ */
private static List<Pair> getSuperTypes(ClassOrInterface forType, Collection<ClassOrInterface> availableClasses, private static List<Pair> getSuperTypes(
HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> gtvs, ClassLoader classLoader) throws ClassNotFoundException { ClassOrInterface forType,
Collection<ClassOrInterface> availableClasses,
HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> gtvs,
ClassLoader classLoader,
PlaceholderRegistry placeholderRegistry
) throws ClassNotFoundException {
List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>(); List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
//Die GTVs, die in forType hinzukommen: //Die GTVs, die in forType hinzukommen:
HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> newGTVs = new HashMap<>(); HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> newGTVs = new HashMap<>();
@@ -147,7 +163,7 @@ public class FCGenerator {
if(superClass.getClassName().equals(ASTFactory.createObjectClass().getClassName())){ if(superClass.getClassName().equals(ASTFactory.createObjectClass().getClassName())){
superTypes = Arrays.asList(new Pair(ASTFactory.createObjectType(), ASTFactory.createObjectType(), PairOperator.SMALLER)); superTypes = Arrays.asList(new Pair(ASTFactory.createObjectType(), ASTFactory.createObjectType(), PairOperator.SMALLER));
}else{ }else{
superTypes = getSuperTypes(superClass, availableClasses, newGTVs, classLoader); superTypes = getSuperTypes(superClass, availableClasses, newGTVs, classLoader, placeholderRegistry);
} }
retList.add(ret); retList.add(ret);

View File

@@ -1,5 +1,6 @@
package de.dhbwstuttgart.parser.SyntaxTreeGenerator; package de.dhbwstuttgart.parser.SyntaxTreeGenerator;
import de.dhbwstuttgart.parser.JavaTXParser;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@@ -259,7 +260,7 @@ public class StatementGenerator {
ret.setStatement(); ret.setStatement();
return ret; return ret;
default: default:
System.out.println(stmt.getClass()); JavaTXParser.logger.info(stmt.getClass());
throw new NotImplementedException(); throw new NotImplementedException();
} }
} }
@@ -1099,9 +1100,9 @@ public class StatementGenerator {
block = lambdaGenerator.convert(expression.lambdaBody().block(), true); block = lambdaGenerator.convert(expression.lambdaBody().block(), true);
} }
List<RefTypeOrTPHOrWildcardOrGeneric> funNParams = new ArrayList<>(); List<RefTypeOrTPHOrWildcardOrGeneric> funNParams = new ArrayList<>();
funNParams.add(TypePlaceholder.fresh(expression.getStart(), -1, false));// ret-Type funNParams.add(TypePlaceholder.fresh(expression.getStart()));// ret-Type
params.getFormalparalist().forEach(formalParameter -> // Für jeden Parameter einen TPH anfügen: params.getFormalparalist().forEach(formalParameter -> // Für jeden Parameter einen TPH anfügen:
funNParams.add(TypePlaceholder.fresh(expression.getStart(), 1, false))); funNParams.add(TypePlaceholder.fresh(expression.getStart())));
RefTypeOrTPHOrWildcardOrGeneric lambdaType = TypePlaceholder.fresh(expression.getStart()); RefTypeOrTPHOrWildcardOrGeneric lambdaType = TypePlaceholder.fresh(expression.getStart());
// RefType lambdaType = new // RefType lambdaType = new
// RefType(reg.getName("Fun"+params.getFormalparalist().size()), // RefType(reg.getName("Fun"+params.getFormalparalist().size()),

View File

@@ -74,7 +74,7 @@ public class TypeGenerator {
throw new NotImplementedException(); throw new NotImplementedException();
} }
} else if (!typeContext.LBRACK().isEmpty()) { // ArrayType über eckige Klammer prüfen } else if (!typeContext.LBRACK().isEmpty()) { // ArrayType über eckige Klammer prüfen
// System.out.println(unannTypeContext.getText()); // JavaTXParser.logger.info(unannTypeContext.getText());
throw new NotImplementedException(); throw new NotImplementedException();
} }
/* /*

View File

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

View File

@@ -0,0 +1,41 @@
package de.dhbwstuttgart.server;
import de.dhbwstuttgart.util.Logger;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import org.java_websocket.WebSocket;
public class ServerTaskLogger extends Logger {
private final WebSocket webSocket;
private final SocketServer socketServer;
private final LogLevel customLogLevel;
public ServerTaskLogger(WebSocket webSocket, SocketServer socketServer, LogLevel customLogLevel) {
this.webSocket = webSocket;
this.socketServer = socketServer;
this.customLogLevel = customLogLevel;
}
@Override
public boolean isLogLevelActive(LogLevel logLevel) {
return logLevel.isHigherOrEqualTo(customLogLevel);
}
@Override
protected void print(String s, LogLevel logLevel) {
String coloredPrefix = this.getPrefix(logLevel);
if (logLevel.isHigherOrEqualTo(LogLevel.ERROR)) {
socketServer.sendError(webSocket, coloredPrefix + s, false);
}
else {
socketServer.sendMessage(webSocket, coloredPrefix + s);
}
}
@Override
protected void write(String s) {
// under no circumstances write anything to a file
}
}

View File

@@ -0,0 +1,202 @@
package de.dhbwstuttgart.server;
import com.fasterxml.jackson.core.JsonProcessingException;
import de.dhbwstuttgart.core.ConsoleInterface;
import de.dhbwstuttgart.server.packet.IClientToServerPacket;
import de.dhbwstuttgart.server.packet.IPacket;
import de.dhbwstuttgart.server.packet.IServerToClientPacket;
import de.dhbwstuttgart.server.packet.PacketContainer;
import de.dhbwstuttgart.server.packet.UnifyRequestPacket;
import de.dhbwstuttgart.server.packet.UnifyResultPacket;
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
import de.dhbwstuttgart.typeinference.constraints.Pair;
import de.dhbwstuttgart.typeinference.result.ResultSet;
import de.dhbwstuttgart.typeinference.unify.UnifyContext;
import de.dhbwstuttgart.typeinference.unify.model.FiniteClosure;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
import de.dhbwstuttgart.util.Logger;
import java.net.URI;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.enums.ReadyState;
import org.java_websocket.handshake.ServerHandshake;
/**
* The Client-side of the websocket
*/
public class SocketClient extends WebSocketClient {
public static Logger logger = new Logger("SocketClient");
/**
* The singleton object
*/
private static SocketClient socketClient = null;
/**
* List of futures that are still waiting to be fulfilled
*/
private final Map<String, SocketFuture<?>> responseFutures = new HashMap<>();
private SocketClient(String url) {
super(
URI.create(url), // target url
//SocketServer.perMessageDeflateDraft, // enable compression
Map.of( // headers
"packetProtocolVersion", SocketServer.packetProtocolVersion
)
);
// make sure the url is in a valid format
final String regex = "^wss?://(\\w+(\\.\\w+)?)*:(\\d+)$";
final Matcher matcher = Pattern.compile(regex).matcher(url);
if (!matcher.find()) {
throw new RuntimeException("Provided string \"" + url + "\" is not a valid server URL! Use pattern ws(s?)://<host.name>:<port>");
}
try {
// wait for the connection to be set up
this.connectBlocking();
// make sure the connection has been established successfully
if (this.getReadyState() != ReadyState.OPEN) {
throw new RuntimeException("WebSocket Client could not connect to remote host at " + this.uri);
}
} catch (InterruptedException exception) {
throw new RuntimeException(exception);
}
// add a shutdown hook to close the connection when the process ends or is stopped by a SIGINT signal
Runtime.getRuntime().addShutdownHook(new Thread(this::close));
}
private SocketClient(String host, int port, boolean secure) throws InterruptedException {
this(String.format("%s://%s:%d/", secure ? "wss" : "ws", host, port));
}
/**
* Singleton access method, creates one if none is available
*
* @return The one and only socketClient
*/
private static SocketClient initializeClient() {
if (socketClient == null) {
socketClient = new SocketClient(ConsoleInterface.unifyServerUrl.get());
}
return socketClient;
}
/**
* Send a packet to the server (connection will be created, if none is found) and return a future
* for the response packet
*/
synchronized public static <T extends IServerToClientPacket> SocketFuture<T> execute(IClientToServerPacket<T> packet) {
SocketClient client = initializeClient();
/*
* Create a future that will be associated with the packet and eventually completed
*/
SocketFuture<T> future = packet.getFuture();
if (!future.isDone()) {
client.responseFutures.put(future.futureId, future);
}
/*
* Establish connection, if not already done.
* Serialize the packet and send it to the server.
* Return the future to be handled by the caller.
*/
try {
String json = PacketContainer.serialize(packet);
client.send(json);
} catch (Exception exception) {
logger.exception(exception);
throw new RuntimeException("Exception occurred in server connection: ", exception);
}
return future;
}
/**
* Shortcut for waiting and retrieving the response immediately
*
* @param packet The packet to send
* @param <T> The type of response packet to await
* @return The response packet, once it is received
*/
public static <T extends IServerToClientPacket> T executeAndGet(IClientToServerPacket<T> packet) {
return SocketClient.execute(packet).get();
}
/**
* Specific client-side implementations to handle incoming packets
*/
protected void handleReceivedPacket(IPacket packet) {
if (!(packet instanceof IServerToClientPacket serverToClientPacket)) {
System.err.println("Received package of invalid type + " + packet.getClass().getName());
this.close();
return;
}
serverToClientPacket.onHandle(this.getConnection(), this);
}
/**
* Complete a registered future, so it can be handled by whoever executed the creator task
*
* @param id The associated id for this future
* @param trigger The object triggering the completion
*/
public void completeResponseFuture(String id, IServerToClientPacket trigger) {
SocketFuture<?> future = this.responseFutures.remove(id);
if (future == null) return;
if (!future.accept(trigger)) {
throw new RuntimeException("Packet " + trigger.getClass().getName() + " tried to complete future, but was not allowed to");
}
}
public static void closeIfOpen() {
if (socketClient != null && socketClient.isOpen()) {
socketClient.close();
}
}
@Override
public void onOpen(ServerHandshake handshakedata) {
logger.success("Connected to server with status " + handshakedata.getHttpStatus());
}
@Override
public void onMessage(String message) {
// logger.info("received: " + message);
IPacket packet = PacketContainer.deserialize(message);
this.handleReceivedPacket(packet);
}
@Override
public void onClose(int code, String reason, boolean remote) {
logger.info(
"Disconnected from server " +
"with code " + code + " " +
(reason.isEmpty() ? "" : "and reason " + reason + " ") +
"(closed by remote: " + remote + ")"
);
if (!this.responseFutures.isEmpty()) {
throw new RuntimeException("Server closed before all required tasks were answered");
}
}
@Override
public void onError(Exception e) {
logger.exception(e);
throw new RuntimeException(e);
}
}

View File

@@ -0,0 +1,48 @@
package de.dhbwstuttgart.server;
import de.dhbwstuttgart.server.packet.IServerToClientPacket;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class SocketFuture<T extends IServerToClientPacket> extends CompletableFuture<T> {
public final String futureId = UUID.randomUUID().toString();
public final List<Class<T>> allowedTriggers;
public SocketFuture(List<Class<T>> allowedTriggers) {
this.allowedTriggers = allowedTriggers;
}
public boolean accept(IServerToClientPacket trigger) {
if (this.allowedTriggers.contains(trigger.getClass())) {
this.complete((T)trigger);
return true;
}
return false;
}
@Override
public T get() {
try {
return super.get();
}
catch (InterruptedException | ExecutionException exception) {
throw new RuntimeException(exception);
}
}
/**
* Special case where the future is immediately fulfilled without a response package similar to
* <code>CompletableFuture.completedFuture()</code> but without a value
*/
public static <R extends IServerToClientPacket> SocketFuture<R> completedFuture() {
SocketFuture<R> dummyFuture = new SocketFuture<>(new ArrayList<>(0));
dummyFuture.complete(null);
return dummyFuture;
}
}

View File

@@ -0,0 +1,235 @@
package de.dhbwstuttgart.server;
import com.fasterxml.jackson.core.JsonProcessingException;
import de.dhbwstuttgart.server.packet.ErrorPacket;
import de.dhbwstuttgart.server.packet.IClientToServerPacket;
import de.dhbwstuttgart.server.packet.IPacket;
import de.dhbwstuttgart.server.packet.MessagePacket;
import de.dhbwstuttgart.server.packet.PacketContainer;
import de.dhbwstuttgart.util.Logger;
import java.net.InetSocketAddress;
import java.util.Collections;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.java_websocket.WebSocket;
import org.java_websocket.drafts.Draft;
import org.java_websocket.drafts.Draft_6455;
import org.java_websocket.extensions.permessage_deflate.PerMessageDeflateExtension;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;
public class SocketServer extends WebSocketServer {
public static Logger logger = new Logger("SocketServer");
public static final int maxTasksPerSession = 100;
private static boolean serverRunning = false;
/**
* Increase this every time a breaking change to the server communication is done.
* This will prevent errors when the server version and client version do not match.
*/
public static final String packetProtocolVersion = "1";
// create an executor for tasks that will always keep at least one task around
private final ThreadPoolExecutor taskExecutor = new ThreadPoolExecutor(1, Integer.MAX_VALUE,60L, TimeUnit.SECONDS, new SynchronousQueue<>());
// create an executor for scheduling timeouts
private final ScheduledExecutorService timeoutExecutor = Executors.newSingleThreadScheduledExecutor();
public SocketServer(int port) {
super(new InetSocketAddress(port));
this.setConnectionLostTimeout(30);
serverRunning = true;
// add a shutdown hook to close all connections when the process ends or is stopped by a SIGINT signal
Runtime.getRuntime().addShutdownHook(new Thread(this::onShutdown));
}
public static boolean isServerRunning() {
return serverRunning;
}
private void onShutdown() {
serverRunning = false;
try {
for (var webSocket : this.getConnections()) {
this.sendError(webSocket, "Sorry, i am shutting down. You are now on your own, good Luck!", true);
webSocket.close();
}
this.stop();
taskExecutor.shutdown();
timeoutExecutor.shutdown();
} catch (InterruptedException exception) {
// we are shutting down anyway
}
}
@Override
public void onOpen(WebSocket webSocket, ClientHandshake clientHandshake) {
String ppv = clientHandshake.getFieldValue("packetProtocolVersion");
if (!ppv.equals(packetProtocolVersion)) {
this.sendError(webSocket,
"Mismatch in packet protocol version! Client (you): \"" + ppv + "\" and Server (me): \"" + packetProtocolVersion + "\"",
true
);
webSocket.close(1);
return;
}
SocketData socketData = new SocketData(webSocket);
logger.info("New connection: " + socketData.id + " (with ppv " + ppv + ")");
try {
sendMessage(webSocket, "Welcome to the server!");
// wait 10 seconds for the client to send a task and close the connection if nothing has been received until then
final int secondsUntilTimeout = 10;
timeoutExecutor.schedule(() -> {
if (webSocket.<SocketData>getAttachment().totalTasks.get() > 0 || !webSocket.isOpen()) {
return;
}
sendMessage(webSocket, "No task received after " + secondsUntilTimeout + " seconds. Closing connection...");
webSocket.close();
},
secondsUntilTimeout,
TimeUnit.SECONDS
);
// and finally, when your program wants to exit
} catch (Exception e) {
logger.exception(e);
webSocket.close(1, e.getMessage());
}
}
@Override
public void onClose(WebSocket webSocket, int code, String reason, boolean remote) {
SocketData socketData = webSocket.getAttachment();
logger.info("Connection closed: " + socketData.id);
logger.info(
"Disconnected client " + socketData.id + " " +
"with code " + code + " " +
(reason.isEmpty() ? "" : "and reason " + reason + " ") +
"(closed by client: " + remote + ")"
);
}
@Override
public void onMessage(WebSocket webSocket, String s) {
// logger.info("Received: " + s.substring(0, 50));
IPacket reconstructedPacket = PacketContainer.deserialize(s);
try {
this.onPacketReceived(webSocket, reconstructedPacket);
} catch (JsonProcessingException e) {
logger.exception(e);
this.log(webSocket, "Error on processing incoming package: " + e.getMessage());
}
}
@Override
public void onError(WebSocket webSocket, Exception e) {
if (webSocket != null) {
log(webSocket, e.getMessage());
webSocket.close();
}
logger.exception(e);
}
@Override
public void onStart() {
logger.success("Websocket server started on port " + this.getPort());
}
/**
* A shorthand method for sending informational messages to the client
*/
public void sendMessage(WebSocket webSocket, String text) {
try {
MessagePacket message = MessagePacket.create(text);
webSocket.send(PacketContainer.serialize(message));
} catch (Exception e) {
System.err.println("Failed to send message: " + text);
logger.exception(e);
}
}
/**
* A shorthand method for sending error messages to the client
*/
public void sendError(WebSocket webSocket, String text, boolean isFatal) {
try {
ErrorPacket error = ErrorPacket.create(text, isFatal);
webSocket.send(PacketContainer.serialize(error));
} catch (Exception e) {
logger.exception(e);
log(webSocket, "Failed to send error: " + text);
}
}
/**
* The server-side implementation on how to handle certain packets when received
*/
private void onPacketReceived(WebSocket webSocket, IPacket packet) throws JsonProcessingException {
SocketData socketData = webSocket.getAttachment();
// limit the number of tasks per connection
if (socketData.totalTasks.get() >= maxTasksPerSession) {
sendError(webSocket, "Exceeded the maximum amount of " + maxTasksPerSession + " tasks per session", true);
webSocket.close();
return;
}
// only allow packets that are meant to be handled by the server
if (!(packet instanceof IClientToServerPacket<?> clientToServerPacket)) {
sendMessage(webSocket, "The package of type " + packet.getClass().getName() + " is not handled by the server!");
return;
}
// update the socket data
socketData.unhandledTasks.incrementAndGet();
socketData.totalTasks.incrementAndGet();
// add the packet to the queue so it can be started by the worker
CompletableFuture.runAsync(() -> {
clientToServerPacket.onHandle(webSocket, this);
int remainingUnhandledTasks = socketData.unhandledTasks.decrementAndGet();
if (socketData.closeIfNoTasksLeft) {
// if the websocket has 0 unhandled Tasks, close the connection
if (remainingUnhandledTasks <= 0) {
sendMessage(webSocket, "All requested tasks finished! Closing connection...");
webSocket.close();
}
}
}, taskExecutor);
}
public void log(WebSocket webSocket, String msg) {
String socketId = (webSocket == null) ? "???" : webSocket.<SocketData>getAttachment().id;
logger.info("[" + socketId + "] " + msg);
}
/**
* The data that is associated server-side with any connected client.
* This makes it possible to store information that can be mapped to any existing connection.
*/
public static class SocketData {
public final String id;
public final AtomicInteger unhandledTasks = new AtomicInteger(0);
public final AtomicInteger totalTasks = new AtomicInteger(0);
public boolean closeIfNoTasksLeft = false;
public SocketData(WebSocket webSocket) {
this.id = UUID.randomUUID().toString();
webSocket.setAttachment(this);
}
}
}

View File

@@ -0,0 +1,35 @@
package de.dhbwstuttgart.server.packet;
import com.fasterxml.jackson.annotation.JsonIgnore;
import de.dhbwstuttgart.server.SocketClient;
import de.dhbwstuttgart.server.SocketFuture;
import de.dhbwstuttgart.server.SocketServer;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.ISerialNode;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialList;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialMap;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialUUID;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialValue;
import org.java_websocket.WebSocket;
public class DebugPacket implements IClientToServerPacket.Void, IServerToClientPacket {
public SerialUUID a1;
public SerialUUID a2;
public SerialMap b1;
public SerialMap b2;
public SerialList<? extends ISerialNode> c1;
public SerialList<? extends ISerialNode> c2;
public SerialValue<?> d1;
public SerialValue<?> d2;
@JsonIgnore
public void onHandle(WebSocket webSocket, SocketClient socketClient) {}
@JsonIgnore
public void onHandle(WebSocket webSocket, SocketServer socketServer) {}
@JsonIgnore
public SocketFuture<IServerToClientPacket> getFuture() {
return SocketFuture.completedFuture();
}
}

View File

@@ -0,0 +1,36 @@
package de.dhbwstuttgart.server.packet;
import com.fasterxml.jackson.annotation.JsonIgnore;
import de.dhbwstuttgart.server.SocketClient;
import de.dhbwstuttgart.server.SocketFuture;
import de.dhbwstuttgart.server.SocketServer;
import org.java_websocket.WebSocket;
/**
* A packet to send simple error messages between the client and the server
*/
public class ErrorPacket implements IServerToClientPacket {
/**
* The error endpoint for messages from the server that should be logged out as errors and possibly abort the process
*/
public String error;
public boolean isFatal;
@JsonIgnore
public static ErrorPacket create(String error, boolean isFatal) {
ErrorPacket packet = new ErrorPacket();
packet.error = error;
packet.isFatal = isFatal;
return packet;
}
@JsonIgnore
public void onHandle(WebSocket webSocket, SocketClient socketClient) {
SocketClient.logger.exception(new RuntimeException(this.error));
if (this.isFatal) {
socketClient.close(1, "Received fatal error from server");
}
}
}

View File

@@ -0,0 +1,26 @@
package de.dhbwstuttgart.server.packet;
import com.fasterxml.jackson.annotation.JsonIgnore;
import de.dhbwstuttgart.server.SocketFuture;
import de.dhbwstuttgart.server.SocketServer;
import org.java_websocket.WebSocket;
/**
* A packet that will be sent to the server. Use <code>Void</code> Sub-Interface for packets without response
*
* @param <T> The response packet that will fulfill the future.
*/
public interface IClientToServerPacket<T extends IServerToClientPacket> extends IPacket {
@JsonIgnore
void onHandle(WebSocket webSocket, SocketServer socketServer);
@JsonIgnore
SocketFuture<T> getFuture();
/**
* Special case, where the packet will remain unanswered by the server
*/
interface Void extends IClientToServerPacket<IServerToClientPacket> {}
}

View File

@@ -0,0 +1,12 @@
package de.dhbwstuttgart.server.packet;
/**
* The shared interface for all packet of the client-server connection.
* A packet must always:
* - Have a default / no-parameter constructor
* - Have only serializable public properties (or disable them via jackson annotations)
*
*/
public interface IPacket {
}

View File

@@ -0,0 +1,12 @@
package de.dhbwstuttgart.server.packet;
import com.fasterxml.jackson.annotation.JsonIgnore;
import de.dhbwstuttgart.server.SocketClient;
import org.java_websocket.WebSocket;
public interface IServerToClientPacket extends IPacket {
@JsonIgnore
void onHandle(WebSocket webSocket, SocketClient socketClient);
}

View File

@@ -0,0 +1,35 @@
package de.dhbwstuttgart.server.packet;
import com.fasterxml.jackson.annotation.JsonIgnore;
import de.dhbwstuttgart.server.SocketClient;
import de.dhbwstuttgart.server.SocketFuture;
import de.dhbwstuttgart.server.SocketServer;
import org.java_websocket.WebSocket;
/**
* A fallback packet that is generated if the received JSON could not be mapped to an existing package
*/
public class InvalidPacket implements IClientToServerPacket.Void, IServerToClientPacket {
/**
* If available, the error that caused this package to appear
*/
public String error = "<unknown error>";
@JsonIgnore
public void onHandle(WebSocket webSocket, SocketClient socketClient) {
SocketClient.logger.error("InvalidPacket: " + this.error);
}
@JsonIgnore
public void onHandle(WebSocket webSocket, SocketServer socketServer) {
socketServer.log(webSocket, "InvalidPacket: " + this.error);
}
@JsonIgnore
public SocketFuture<IServerToClientPacket> getFuture() {
return SocketFuture.completedFuture();
}
}

View File

@@ -0,0 +1,40 @@
package de.dhbwstuttgart.server.packet;
import com.fasterxml.jackson.annotation.JsonIgnore;
import de.dhbwstuttgart.server.SocketClient;
import de.dhbwstuttgart.server.SocketFuture;
import de.dhbwstuttgart.server.SocketServer;
import org.java_websocket.WebSocket;
/**
* A packet to send simple informational messages between the client and the server
*/
public class MessagePacket implements IClientToServerPacket.Void, IServerToClientPacket {
/**
* The informational message from the server that should be logged out outputted
*/
public String message;
@JsonIgnore
public static MessagePacket create(String message) {
MessagePacket packet = new MessagePacket();
packet.message = message;
return packet;
}
@JsonIgnore
public void onHandle(WebSocket webSocket, SocketClient socketClient) {
SocketClient.logger.info("SocketMessage: " + this.message);
}
@JsonIgnore
public void onHandle(WebSocket webSocket, SocketServer socketServer) {
socketServer.log(webSocket, this.message);
}
@JsonIgnore
public SocketFuture<IServerToClientPacket> getFuture() {
return SocketFuture.completedFuture();
}
}

View File

@@ -0,0 +1,98 @@
package de.dhbwstuttgart.server.packet;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import de.dhbwstuttgart.util.Logger;
/**
* A wrapper for the packet to ensure correct serialization/deserialization and make it possible to detect the matching
* packet type for deserialization.
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public class PacketContainer {
// The jackson serializer / deserializer tool
private static final ObjectMapper objectMapper = new ObjectMapper();
/*
* The available packet types. The one type that is represented in the JSON should always be the ONLY non-null value.
* They have to be public (for the moment) to let jackson fill them in while deserializing
*/
public ErrorPacket errorPacket = null;
public MessagePacket messagePacket = null;
public InvalidPacket invalidPacket = null;
public UnifyRequestPacket unifyRequestPacket = null;
public UnifyResultPacket unifyResultPacket = null;
public DebugPacket debugPacket = null;
public SetAutoclosePacket setAutoclosePacket = null;
/**
* Generate the JSON string for the given packet
*
* @param packet The packet to serialize
* @return The JSON representation of the packet
*/
public static String serialize(IPacket packet) throws JsonProcessingException {
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
PacketContainer container = new PacketContainer();
if (packet instanceof ErrorPacket)
container.errorPacket = (ErrorPacket) packet;
else if (packet instanceof MessagePacket)
container.messagePacket = (MessagePacket) packet;
else if (packet instanceof UnifyRequestPacket)
container.unifyRequestPacket = (UnifyRequestPacket) packet;
else if (packet instanceof UnifyResultPacket)
container.unifyResultPacket = (UnifyResultPacket) packet;
else if (packet instanceof DebugPacket)
container.debugPacket = (DebugPacket) packet;
else if (packet instanceof SetAutoclosePacket)
container.setAutoclosePacket = (SetAutoclosePacket) packet;
// Add new packets here and in the deserialize method
else
throw new RuntimeException("Cannot map packet to any known packet class");
return objectMapper.writeValueAsString(container);
}
/**
* Use the JSON string to generate the matching packet object
*
* @param json The serialized representation of a packet container
* @return The deserialized Packet object
*/
public static IPacket deserialize(String json) {
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
try {
PacketContainer container = objectMapper.readValue(json, PacketContainer.class);
if (container.errorPacket != null)
return container.errorPacket;
if (container.messagePacket != null)
return container.messagePacket;
if (container.invalidPacket != null)
return container.invalidPacket;
if (container.unifyRequestPacket != null)
return container.unifyRequestPacket;
if (container.unifyResultPacket != null)
return container.unifyResultPacket;
if (container.debugPacket != null)
return container.debugPacket;
if (container.setAutoclosePacket != null)
return container.setAutoclosePacket;
// Add new packets here and in the serialize method
throw new RuntimeException("Cannot map received json to any known packet class");
} catch (Exception e) {
(new Logger()).exception(e);
InvalidPacket packet = new InvalidPacket();
packet.error = e.getMessage();
return packet;
}
}
}

View File

@@ -0,0 +1,32 @@
package de.dhbwstuttgart.server.packet;
import com.fasterxml.jackson.annotation.JsonIgnore;
import de.dhbwstuttgart.server.SocketClient;
import de.dhbwstuttgart.server.SocketFuture;
import de.dhbwstuttgart.server.SocketServer;
import org.java_websocket.WebSocket;
/**
* Normally, a connection stays open until either the client or the server process ends.
* Send this packet to inform the server that the connection can be closed once all tasks are done
*/
public class SetAutoclosePacket implements IClientToServerPacket.Void {
public int dummyProperty = 1;
@JsonIgnore
public static SetAutoclosePacket create() {
return new SetAutoclosePacket();
}
@JsonIgnore
public void onHandle(WebSocket webSocket, SocketServer socketServer) {
webSocket.<SocketServer.SocketData>getAttachment().closeIfNoTasksLeft = true;
socketServer.log(webSocket, "Marked connection as autoclose");
}
@JsonIgnore
public SocketFuture<IServerToClientPacket> getFuture() {
return SocketFuture.completedFuture();
}
}

View File

@@ -0,0 +1,164 @@
package de.dhbwstuttgart.server.packet;
import com.fasterxml.jackson.annotation.JsonIgnore;
import de.dhbwstuttgart.core.ConsoleInterface;
import de.dhbwstuttgart.server.ServerTaskLogger;
import de.dhbwstuttgart.server.SocketFuture;
import de.dhbwstuttgart.server.SocketServer;
import de.dhbwstuttgart.server.packet.dataContainers.KeyStorage;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialList;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialMap;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialValue;
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
import de.dhbwstuttgart.typeinference.constraints.Pair;
import de.dhbwstuttgart.typeinference.unify.PlaceholderRegistry;
import de.dhbwstuttgart.typeinference.unify.TypeUnify;
import de.dhbwstuttgart.typeinference.unify.UnifyContext;
import de.dhbwstuttgart.typeinference.unify.UnifyResultListenerImpl;
import de.dhbwstuttgart.typeinference.unify.UnifyResultModel;
import de.dhbwstuttgart.typeinference.unify.UnifyTaskModel;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unify.model.FiniteClosure;
import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
import de.dhbwstuttgart.typeinference.unify.model.UnifyType;
import de.dhbwstuttgart.util.Logger;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import org.java_websocket.WebSocket;
/**
* A packet to send all required data for the unification algorithm to the server and request the unification
*/
public class UnifyRequestPacket implements IClientToServerPacket<UnifyResultPacket> {
public SerialMap finiteClosure;
public SerialMap constraintSet;
public SerialMap unifyConstraintSet;
public SerialMap serialKeyStorage;
public SerialValue<?> placeholders;
public SerialList<SerialMap> factoryplaceholders;
public String futureId;
public int logLevel;
@JsonIgnore
private KeyStorage keyStorage = new KeyStorage();
@JsonIgnore
private boolean keyStorageLoaded = false;
public static UnifyRequestPacket create(
FiniteClosure finiteClosure,
ConstraintSet<Pair> constraintSet,
ConstraintSet<UnifyPair> unifyConstraintSet,
PlaceholderRegistry placeholderRegistry
) {
UnifyRequestPacket packet = new UnifyRequestPacket();
// store constraint and finite closure
packet.finiteClosure = finiteClosure.toSerial(packet.keyStorage);
packet.constraintSet = constraintSet.toSerial(packet.keyStorage);
packet.unifyConstraintSet = unifyConstraintSet.toSerial(packet.keyStorage);
// store placeholder registry
var serialRegistry = placeholderRegistry.toSerial(packet.keyStorage);
packet.placeholders = serialRegistry.getValue("ph");
packet.factoryplaceholders = serialRegistry.getList("factoryPh").assertListOfMaps();
// store referenced objects separately
packet.serialKeyStorage = packet.keyStorage.toSerial(packet.keyStorage);
packet.logLevel = ConsoleInterface.logLevel.getValue();
return packet;
}
@JsonIgnore
public void loadKeyStorage(UnifyContext context) {
if (!keyStorageLoaded) {
keyStorageLoaded = true;
keyStorage = KeyStorage.fromSerial(this.serialKeyStorage, context);
}
}
@JsonIgnore
private FiniteClosure retrieveFiniteClosure(UnifyContext context) {
this.loadKeyStorage(context);
return FiniteClosure.fromSerial(this.finiteClosure, context, keyStorage);
}
@JsonIgnore
private ConstraintSet<Pair> retrieveConstraintSet(UnifyContext context) {
this.loadKeyStorage(context);
return ConstraintSet.fromSerial(this.constraintSet, context, Pair.class, keyStorage);
}
@JsonIgnore
private ConstraintSet<UnifyPair> retrieveUnifyConstraintSet(UnifyContext context) {
this.loadKeyStorage(context);
return ConstraintSet.fromSerial(this.unifyConstraintSet, context, UnifyPair.class, keyStorage);
}
@JsonIgnore
public void onHandle(WebSocket webSocket, SocketServer socketServer) {
socketServer.sendMessage(webSocket, "You requested a unify! Please wait until I calculated everything...");
socketServer.log(webSocket, "Client requested a unification. Starting now...");
try {
var placeholderRegistry = new PlaceholderRegistry();
ArrayList<String> existingPlaceholders = (ArrayList) this.placeholders.getOf(ArrayList.class);
existingPlaceholders.forEach(placeholderRegistry::addPlaceholder);
Logger logger = new ServerTaskLogger(
webSocket,
socketServer,
Logger.LogLevel.fromValue(
Math.max(this.logLevel, Logger.LogLevel.INFO.getValue())
)
);
var unifyContext = new UnifyContext(logger, true,
new UnifyResultModel(new ConstraintSet<>(), new FiniteClosure(new HashSet<>(), logger, placeholderRegistry)),
new UnifyTaskModel(), ForkJoinPool.commonPool(), placeholderRegistry
);
this.factoryplaceholders.stream()
.map(p -> (PlaceholderType)UnifyType.fromSerial(p, unifyContext))
.forEach(placeholderRegistry.UnifyTypeFactory_PLACEHOLDERS::add);
// start the unification algorithm from the received data
IFiniteClosure finiteClosure = this.retrieveFiniteClosure(unifyContext);
ConstraintSet<Pair> constraintSet = this.retrieveConstraintSet(unifyContext);
ConstraintSet<UnifyPair> unifyConstraintSet = this.retrieveUnifyConstraintSet(unifyContext);
var resultModel = new UnifyResultModel(constraintSet, finiteClosure);
UnifyResultListenerImpl resultListener = new UnifyResultListenerImpl();
resultModel.addUnifyResultListener(resultListener);
TypeUnify.unifyParallel(
unifyConstraintSet.getUndConstraints(),
unifyConstraintSet.getOderConstraints(),
finiteClosure,
unifyContext.newWithResultModel(resultModel)
);
var resultSets = resultListener.getResults();
socketServer.log(webSocket, "Finished unification");
socketServer.sendMessage(webSocket, "Unification finished. Found " + resultSets.size() + " result sets");
if (webSocket.isOpen()) {
UnifyResultPacket resultPacket = UnifyResultPacket.create(resultSets, futureId);
webSocket.send(PacketContainer.serialize(resultPacket));
}
} catch (Exception e) {
SocketServer.logger.exception(e);
socketServer.log(webSocket, e.getMessage());
}
}
@JsonIgnore
public SocketFuture<UnifyResultPacket> getFuture() {
var future = new SocketFuture<>(List.of(UnifyResultPacket.class));
futureId = future.futureId;
return future;
}
}

View File

@@ -0,0 +1,45 @@
package de.dhbwstuttgart.server.packet;
import com.fasterxml.jackson.annotation.JsonIgnore;
import de.dhbwstuttgart.server.SocketClient;
import de.dhbwstuttgart.server.packet.dataContainers.KeyStorage;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.ISerialNode;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialList;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialMap;
import de.dhbwstuttgart.typeinference.result.ResultSet;
import de.dhbwstuttgart.typeinference.unify.UnifyContext;
import java.util.List;
import org.java_websocket.WebSocket;
/**
* A packet to send all calculated data from the unification algorithm back to the client
*/
public class UnifyResultPacket implements IServerToClientPacket {
public SerialList<ISerialNode> results;
public SerialMap keyStorage;
public String futureId;
public static UnifyResultPacket create(List<ResultSet> resultSets, String futureId) {
UnifyResultPacket serialized = new UnifyResultPacket();
KeyStorage keyStorage = new KeyStorage();
serialized.results = SerialList.fromMapped(resultSets, resultSet -> resultSet.toSerial(keyStorage));
serialized.keyStorage = keyStorage.toSerial(keyStorage);
serialized.futureId = futureId;
return serialized;
}
@JsonIgnore
public List<ResultSet> getResultSet(UnifyContext context) {
return this.results.assertListOfMaps().stream()
.map(resultData -> ResultSet.fromSerial(resultData, context)).toList();
}
@JsonIgnore
public void onHandle(WebSocket webSocket, SocketClient socketClient) {
SocketClient.logger.info("Received unify result");
socketClient.completeResponseFuture(futureId, this);
}
}

View File

@@ -0,0 +1,16 @@
package de.dhbwstuttgart.server.packet.dataContainers;
import de.dhbwstuttgart.exceptions.NotImplementedException;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.ISerialNode;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialMap;
import de.dhbwstuttgart.typeinference.unify.UnifyContext;
public interface ISerializableData {
public abstract ISerialNode toSerial(KeyStorage keyStorage);
public static Object fromSerial(SerialMap data, UnifyContext context) {
throw new NotImplementedException("Missing implementation of \"fromSerial\" for a serializable element");
}
}

View File

@@ -0,0 +1,103 @@
package de.dhbwstuttgart.server.packet.dataContainers;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialMap;
import de.dhbwstuttgart.typeinference.unify.UnifyContext;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
public class KeyStorage implements ISerializableData {
/**
* Store a unique identifier for every element, so it can be referenced in the json
*/
protected AtomicInteger identifierCount = new AtomicInteger();
/**
* Store the serialized element per identifier when serializing
*/
protected SerialMap serializedElements = new SerialMap();
/**
* Store the unserialized element per identifier when unserializing
*/
protected Map<String, ISerializableData> unserializedElements = new HashMap<>();
/**
* Retrieve or generate a new identifier for a constraint
*/
public String getIdentifier() {
return this.identifierCount.incrementAndGet() + "_";
}
/**
* Checks if the given element identifier belongs to an element that was already serialized
*/
public boolean isAlreadySerialized(String identifier) {
return this.serializedElements.containsKey(identifier);
}
/**
* Checks if the given element identifier belongs to a element that was already unserialized
*/
public boolean isAlreadyUnserialized(String identifier) {
return this.unserializedElements.containsKey(identifier);
}
/**
* Register a serialized element to prevent it from being serialized again
*/
public void putSerialized(String identifier, SerialMap serializedElement) {
this.serializedElements.put(identifier, serializedElement);
}
/**
* Retrieve a serialized element
*/
public SerialMap getSerialized(String identifier) {
if (!this.serializedElements.containsKey(identifier)) {
throw new RuntimeException("No serialized element of identifier " + identifier + " available to get");
}
return this.serializedElements.getMap(identifier);
}
/**
* Register an unserialized element to prevent it from being unserialized again
*/
public void putUnserialized(String identifier, ISerializableData element) {
this.unserializedElements.put(identifier, element);
}
/**
* Retrieve an unserialized element
*/
public <T extends ISerializableData> T getUnserialized(String identifier, Class<T> target) {
if (!this.unserializedElements.containsKey(identifier)) {
throw new RuntimeException("No unserialized element of identifier " + identifier + " available to get");
}
var element = this.unserializedElements.get(identifier);
if (target.isInstance(element)) {
return (T) element;
}
throw new RuntimeException("Failed to get unserialized element from KeyStorage. Expected instance of " +
target.getName() + " but found " + element.getClass().getName());
}
@Override
public SerialMap toSerial(KeyStorage keyStorage) {
SerialMap serialized = new SerialMap();
serialized.put("serializedElements", this.serializedElements);
return serialized;
}
public static KeyStorage fromSerial(SerialMap data, UnifyContext context) {
var serializedConstraintsData = data.getMap("serializedElements");
var constraintContext = new KeyStorage();
for (var entry : serializedConstraintsData.entrySet()) {
if (entry.getValue() instanceof SerialMap valueMap) {
constraintContext.putSerialized(entry.getKey(), valueMap);
}
}
return constraintContext;
}
}

View File

@@ -0,0 +1,31 @@
package de.dhbwstuttgart.server.packet.dataContainers.serialized;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
/**
* Use the following classes for an intermediate serialized tree structure
*/
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "_t"
)
@JsonSubTypes({
@JsonSubTypes.Type(value = SerialMap.class, name = "m"),
@JsonSubTypes.Type(value = SerialList.class, name = "l"),
@JsonSubTypes.Type(value = SerialValue.class, name = "v"),
@JsonSubTypes.Type(value = SerialUUID.class, name = "u")
})
public interface ISerialNode {
default <T extends ISerialNode> T assertType(Class<T> type) {
if (type.isInstance(this)) {
return (T) this;
}
throw new RuntimeException("Expected ISerialNode to be of type " + type.getName()
+ " but found " + this.getClass().getName() + " instead");
}
}

View File

@@ -0,0 +1,74 @@
package de.dhbwstuttgart.server.packet.dataContainers.serialized;
import com.fasterxml.jackson.annotation.JsonIgnore;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.function.Function;
import java.util.stream.Stream;
public class SerialList<I extends ISerialNode> extends ArrayList<I> implements ISerialNode {
public SerialList() {}
public SerialList(Collection<I> data) {
this.addAll(data);
}
public SerialList(Stream<I> data) {
this(data.toList());
}
public SerialList(I[] data) {
this(Arrays.stream(data).toList());
}
@SafeVarargs
@JsonIgnore
public static <A extends ISerialNode> ArrayList<A> from(A ...values) {
ArrayList<A> list = new SerialList<>();
Collections.addAll(list, values);
return list;
}
@JsonIgnore
public static <A,B extends ISerialNode> SerialList<B> fromMapped(Stream<A> data, Function<A,B> mapper) {
return new SerialList<>(data.map(mapper).toList());
}
@JsonIgnore
public static <A,B extends ISerialNode> SerialList<B> fromMapped(Collection<A> data, Function<A,B> mapper) {
return SerialList.fromMapped(data.stream(), mapper);
}
@JsonIgnore
public static <A,B extends ISerialNode> SerialList<B> fromMapped(A[] data, Function<A,B> mapper) {
return SerialList.fromMapped(Arrays.stream(data), mapper);
}
@JsonIgnore
public SerialList<SerialMap> assertListOfMaps() {
if (this.isEmpty() || this.get(0) instanceof SerialMap) {
return (SerialList<SerialMap>) this;
}
throw new RuntimeException("Required List to contain SerialMap elements but condition failed");
}
@JsonIgnore
public SerialList<SerialList<?>> assertListOfLists() {
if (this.isEmpty() || this.get(0) instanceof SerialList) {
return (SerialList<SerialList<?>>) this;
}
throw new RuntimeException("Required List to contain SerialList elements but condition failed");
}
@JsonIgnore
public SerialList<SerialValue<?>> assertListOfValues() {
if (this.isEmpty() || this.get(0) instanceof SerialValue) {
return (SerialList<SerialValue<?>>) this;
}
throw new RuntimeException("Required List to contain SerialValue elements but condition failed");
}
@JsonIgnore
public SerialList<SerialUUID> assertListOfUUIDs() {
if (this.isEmpty() || this.get(0) instanceof SerialUUID) {
return (SerialList<SerialUUID>) this;
}
throw new RuntimeException("Required List to contain SerialUUID elements but condition failed");
}
}

View File

@@ -0,0 +1,84 @@
package de.dhbwstuttgart.server.packet.dataContainers.serialized;
import com.fasterxml.jackson.annotation.JsonIgnore;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nullable;
public class SerialMap extends HashMap<String, ISerialNode> implements ISerialNode {
public SerialMap() {
super();
}
public SerialMap(Map<String, ISerialNode> data) {
super(data);
}
@JsonIgnore
public void put(String key, Boolean value) {
this.put(key, new SerialValue<>(value));
}
@JsonIgnore
public void put(String key, String value) {
this.put(key, new SerialValue<>(value));
}
@JsonIgnore
public void put(String key, Number value) {
this.put(key, new SerialValue<>(value));
}
@JsonIgnore
private <T> T get(String key, Class<T> expectedType) {
if (!this.containsKey(key)) {
throw new RuntimeException("Missing required value " + key + " in ObjectMap");
}
var element = this.get(key);
if (element != null && element.getClass() != expectedType) {
throw new RuntimeException(
"Required value " + key + " to be of type " + expectedType.getName() + " but found " + element.getClass().getName()
);
}
return (T)element;
}
@JsonIgnore
public SerialList<?> getList(String key) {
return this.get(key, SerialList.class);
}
@Nullable
@JsonIgnore
public SerialList<?> getListOrNull(String key) {
return this.containsKey(key) ? this.getList(key) : null;
}
@JsonIgnore
public SerialMap getMap(String key) {
return this.get(key, SerialMap.class);
}
@Nullable
@JsonIgnore
public SerialMap getMapOrNull(String key) {
return this.containsKey(key) ? this.getMap(key) : null;
}
@JsonIgnore
public SerialValue<?> getValue(String key) {
return this.get(key, SerialValue.class);
}
@JsonIgnore
public SerialUUID getUUID(String key) {
return this.get(key, SerialUUID.class);
}
@Nullable
@JsonIgnore
public SerialUUID getUUIDOrNull(String key) {
return this.containsKey(key) ? this.getUUID(key) : null;
}
}

View File

@@ -0,0 +1,13 @@
package de.dhbwstuttgart.server.packet.dataContainers.serialized;
public class SerialUUID implements ISerialNode {
public String uuid;
public SerialUUID() {}
public SerialUUID(String uuid) {
this.uuid = uuid;
}
}

View File

@@ -0,0 +1,28 @@
package de.dhbwstuttgart.server.packet.dataContainers.serialized;
import com.fasterxml.jackson.annotation.JsonIgnore;
public class SerialValue<T> implements ISerialNode {
public T value;
public static final SerialValue<Object> NULL = new SerialValue<>(null);
public SerialValue() {}
public SerialValue(T value) {
this.value = value;
}
@JsonIgnore
public <A> SerialValue<A> assertValueOf(Class<A> targetClass) {
if (this.value == null || targetClass.isInstance(this.value)) {
return (SerialValue<A>) this;
}
throw new RuntimeException("Required Value to contain " + targetClass.getName() + " value but condition failed on" +
" type " + this.value.getClass().getName());
}
@JsonIgnore
public <A> A getOf(Class<A> targetClass) {
return this.assertValueOf(targetClass).value;
}
}

View File

@@ -0,0 +1,8 @@
package de.dhbwstuttgart.syntaxtree;
import de.dhbwstuttgart.util.Logger;
public class SyntaxTree {
public static Logger logger = new Logger("SyntaxTree");
}

View File

@@ -1,5 +1,8 @@
package de.dhbwstuttgart.syntaxtree.factory; package de.dhbwstuttgart.syntaxtree.factory;
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.core.JavaTXServer;
public class NameGenerator { public class NameGenerator {
private static String strNextName = "A"; private static String strNextName = "A";
@@ -27,6 +30,10 @@ public class NameGenerator {
// n�chster Name berechnen und in strNextName speichern // n�chster Name berechnen und in strNextName speichern
inc( strNextName.length() - 1 ); inc( strNextName.length() - 1 );
if (JavaTXServer.isRunning) {
throw new RuntimeException("Using the NameGenerator on a server is not allowed");
}
JavaTXCompiler.defaultClientPlaceholderRegistry.addPlaceholder(strReturn);
return strReturn; return strReturn;
} }

View File

@@ -1,5 +1,8 @@
package de.dhbwstuttgart.syntaxtree.factory; package de.dhbwstuttgart.syntaxtree.factory;
import de.dhbwstuttgart.syntaxtree.SyntaxTree;
import de.dhbwstuttgart.typeinference.unify.PlaceholderRegistry;
import de.dhbwstuttgart.util.Logger;
import java.io.Writer; import java.io.Writer;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.*; import java.util.*;
@@ -31,9 +34,13 @@ import org.antlr.v4.runtime.Token;
public class UnifyTypeFactory { public class UnifyTypeFactory {
private static ArrayList<PlaceholderType> PLACEHOLDERS = new ArrayList<>(); public static FiniteClosure generateFC(
List<ClassOrInterface> fromClasses,
public static FiniteClosure generateFC(List<ClassOrInterface> fromClasses, Writer logFile, ClassLoader classLoader, JavaTXCompiler compiler) throws ClassNotFoundException { Logger logger,
ClassLoader classLoader,
JavaTXCompiler compiler,
PlaceholderRegistry placeholderRegistry
) throws ClassNotFoundException {
/* /*
Die transitive Hülle muss funktionieren. Die transitive Hülle muss funktionieren.
Man darf schreiben List<A> extends AL<A> Man darf schreiben List<A> extends AL<A>
@@ -44,7 +51,7 @@ public class UnifyTypeFactory {
Generell dürfen sie immer die gleichen Namen haben. Generell dürfen sie immer die gleichen Namen haben.
TODO: die transitive Hülle bilden TODO: die transitive Hülle bilden
*/ */
return new FiniteClosure(FCGenerator.toUnifyFC(compiler, fromClasses, classLoader), logFile, compiler); return new FiniteClosure(FCGenerator.toUnifyFC(compiler, fromClasses, classLoader, placeholderRegistry), logger, compiler, placeholderRegistry);
} }
public static UnifyPair generateSmallerPair(UnifyType tl, UnifyType tr, SourceLoc location){ public static UnifyPair generateSmallerPair(UnifyType tl, UnifyType tr, SourceLoc location){
@@ -67,23 +74,23 @@ public class UnifyTypeFactory {
* Convert from * Convert from
* ASTType -> UnifyType * ASTType -> UnifyType
*/ */
public static UnifyType convert(JavaTXCompiler compiler, RefTypeOrTPHOrWildcardOrGeneric t, Boolean innerType){ public static UnifyType convert(JavaTXCompiler compiler, RefTypeOrTPHOrWildcardOrGeneric t, Boolean innerType, PlaceholderRegistry placeholderRegistry){
if (t instanceof GenericRefType){ if (t instanceof GenericRefType){
return UnifyTypeFactory.convert(compiler, (GenericRefType)t, innerType); return UnifyTypeFactory.convert(compiler, (GenericRefType)t, innerType, placeholderRegistry);
} else if (t instanceof TypePlaceholder){ } else if (t instanceof TypePlaceholder){
return UnifyTypeFactory.convert(compiler, (TypePlaceholder)t, innerType); return UnifyTypeFactory.convert(compiler, (TypePlaceholder)t, innerType, placeholderRegistry);
} else if (t instanceof ExtendsWildcardType){ } else if (t instanceof ExtendsWildcardType){
return UnifyTypeFactory.convert(compiler, (ExtendsWildcardType)t, innerType); return UnifyTypeFactory.convert(compiler, (ExtendsWildcardType)t, innerType, placeholderRegistry);
} else if (t instanceof SuperWildcardType) { } else if (t instanceof SuperWildcardType) {
return UnifyTypeFactory.convert(compiler, (SuperWildcardType) t, innerType); return UnifyTypeFactory.convert(compiler, (SuperWildcardType) t, innerType, placeholderRegistry);
} else if (t instanceof RefType){ } else if (t instanceof RefType){
return UnifyTypeFactory.convert(compiler, (RefType)t, innerType); return UnifyTypeFactory.convert(compiler, (RefType)t, innerType, placeholderRegistry);
} }
//Es wurde versucht ein Typ umzuwandeln, welcher noch nicht von der Factory abgedeckt ist //Es wurde versucht ein Typ umzuwandeln, welcher noch nicht von der Factory abgedeckt ist
throw new NotImplementedException("Der Typ "+t+" kann nicht umgewandelt werden"); throw new NotImplementedException("Der Typ "+t+" kann nicht umgewandelt werden");
} }
public static UnifyType convert(JavaTXCompiler compiler, RefType t, Boolean innerType){ public static UnifyType convert(JavaTXCompiler compiler, RefType t, Boolean innerType, PlaceholderRegistry placeholderRegistry){
//Check if it is a FunN Type: //Check if it is a FunN Type:
Pattern p = Pattern.compile("Fun(\\d+)[$][$]"); Pattern p = Pattern.compile("Fun(\\d+)[$][$]");
Matcher m = p.matcher(t.getName().toString()); Matcher m = p.matcher(t.getName().toString());
@@ -91,76 +98,76 @@ public class UnifyTypeFactory {
if(b){ if(b){
Integer N = Integer.valueOf(m.group(1)); Integer N = Integer.valueOf(m.group(1));
if((N + 1) == t.getParaList().size()){ if((N + 1) == t.getParaList().size()){
return convertFunN(compiler, t.getParaList(), false); return convertFunN(compiler, t.getParaList(), false, placeholderRegistry);
} }
} }
UnifyType ret; UnifyType ret;
List<UnifyType> params = new ArrayList<>(); List<UnifyType> params = new ArrayList<>();
if (t.getParaList() != null) { if (t.getParaList() != null) {
for (RefTypeOrTPHOrWildcardOrGeneric pT : t.getParaList()) { for (RefTypeOrTPHOrWildcardOrGeneric pT : t.getParaList()) {
params.add(UnifyTypeFactory.convert(compiler, pT, true)); params.add(UnifyTypeFactory.convert(compiler, pT, true, placeholderRegistry));
} }
} }
var clazz = compiler.getClass(t.getName()); var clazz = compiler.getClass(t.getName());
if (clazz != null && clazz.isInterface() && clazz.isFunctionalInterface()) { if (clazz != null && clazz.isInterface() && clazz.isFunctionalInterface()) {
var method = clazz.getMethods().stream().filter(x -> Modifier.isAbstract(x.modifier)).findFirst().orElseThrow(); var method = clazz.getMethods().stream().filter(x -> Modifier.isAbstract(x.modifier)).findFirst().orElseThrow();
var methodParams = method.getParameterList().getFormalparalist().stream().map(x -> convert(compiler, x.getType(), true)).toList(); var methodParams = method.getParameterList().getFormalparalist().stream().map(x -> convert(compiler, x.getType(), true, placeholderRegistry)).toList();
var generics = StreamSupport.stream(clazz.getGenerics().spliterator(), false).map(GenericTypeVar::getName).toList(); var generics = StreamSupport.stream(clazz.getGenerics().spliterator(), false).map(GenericTypeVar::getName).toList();
return new FunInterfaceType(t.getName().toString(), new TypeParams(params), methodParams, convert(compiler, method.getReturnType(), true), generics); return new FunInterfaceType(t.getName().toString(), new TypeParams(params), methodParams, convert(compiler, method.getReturnType(), true, placeholderRegistry), generics);
} }
return new ReferenceType(t.getName().toString(),new TypeParams(params)); return new ReferenceType(t.getName().toString(),new TypeParams(params));
} }
public static UnifyType convertFunN(JavaTXCompiler compiler, List<RefTypeOrTPHOrWildcardOrGeneric> paraList, Boolean innerType){ public static UnifyType convertFunN(JavaTXCompiler compiler, List<RefTypeOrTPHOrWildcardOrGeneric> paraList, Boolean innerType, PlaceholderRegistry placeholderRegistry){
UnifyType ret; UnifyType ret;
List<UnifyType> params = new ArrayList<>(); List<UnifyType> params = new ArrayList<>();
if(paraList != null && paraList.size() > 0){ if(paraList != null && paraList.size() > 0){
for(RefTypeOrTPHOrWildcardOrGeneric pT : paraList){ for(RefTypeOrTPHOrWildcardOrGeneric pT : paraList){
params.add(UnifyTypeFactory.convert(compiler, pT, false)); params.add(UnifyTypeFactory.convert(compiler, pT, false, placeholderRegistry));
} }
} }
ret = FunNType.getFunNType(new TypeParams(params)); ret = FunNType.getFunNType(new TypeParams(params));
return ret; return ret;
} }
public static UnifyType convert(JavaTXCompiler compiler, TypePlaceholder tph, Boolean innerType){ public static UnifyType convert(JavaTXCompiler compiler, TypePlaceholder tph, Boolean innerType, PlaceholderRegistry placeholderRegistry) {
if (tph.getName().equals("AFR")) { if (tph.getName().equals("AFR")) {
System.out.println("XXX"+innerType); SyntaxTree.logger.info("XXX"+innerType);
} }
PlaceholderType ntph = new PlaceholderType(tph.getName(), tph.getVariance()); PlaceholderType ntph = new PlaceholderType(tph.getName(), tph.getVariance(), placeholderRegistry);
ntph.setVariance(tph.getVariance()); ntph.setVariance(tph.getVariance());
ntph.setOrCons(tph.getOrCons()); ntph.setOrCons(tph.getOrCons());
ntph.setWildcardtable(tph.getWildcardtable()); ntph.setWildcardtable(tph.getWildcardtable());
int in = PLACEHOLDERS.indexOf(ntph); int in = placeholderRegistry.UnifyTypeFactory_PLACEHOLDERS.indexOf(ntph);
if (in == -1) { if (in == -1) {
PLACEHOLDERS.add(ntph); placeholderRegistry.UnifyTypeFactory_PLACEHOLDERS.add(ntph);
ntph.setInnerType(innerType); ntph.setInnerType(innerType);
return ntph; return ntph;
} }
else { else {
PlaceholderType oldpht = PLACEHOLDERS.get(in); PlaceholderType oldpht = placeholderRegistry.UnifyTypeFactory_PLACEHOLDERS.get(in);
oldpht.setInnerType(oldpht.isInnerType() || innerType); oldpht.setInnerType(oldpht.isInnerType() || innerType);
return oldpht; return oldpht;
} }
} }
public static UnifyType convert(JavaTXCompiler compiler, GenericRefType t, Boolean innerType){ public static UnifyType convert(JavaTXCompiler compiler, GenericRefType t, Boolean innerType, PlaceholderRegistry placeholderRegistry){
return new ReferenceType(t.getParsedName(), true); return new ReferenceType(t.getParsedName(), true);
} }
public static UnifyType convert(JavaTXCompiler compiler, WildcardType t, Boolean innerType){ public static UnifyType convert(JavaTXCompiler compiler, WildcardType t, Boolean innerType, PlaceholderRegistry placeholderRegistry){
if(t.isExtends()) if(t.isExtends())
return new ExtendsType(UnifyTypeFactory.convert(compiler, t.getInnerType(), false)); return new ExtendsType(UnifyTypeFactory.convert(compiler, t.getInnerType(), false, placeholderRegistry));
else if(t.isSuper()) else if(t.isSuper())
return new SuperType(UnifyTypeFactory.convert(compiler, t.getInnerType(), false)); return new SuperType(UnifyTypeFactory.convert(compiler, t.getInnerType(), false, placeholderRegistry));
else throw new NotImplementedException(); else throw new NotImplementedException();
} }
public static ConstraintSet<UnifyPair> convert(JavaTXCompiler compiler, ConstraintSet<Pair> constraints) { public static ConstraintSet<UnifyPair> convert(JavaTXCompiler compiler, ConstraintSet<Pair> constraints, PlaceholderRegistry placeholderRegistry) {
return constraints.map(c -> UnifyTypeFactory.convert(compiler, c)); return constraints.map(c -> UnifyTypeFactory.convert(compiler, c, placeholderRegistry));
} }
//NEVER USED //NEVER USED
@@ -171,30 +178,30 @@ public class UnifyTypeFactory {
// return unifyPairConstraint; // return unifyPairConstraint;
//} //}
public static UnifyPair convert(JavaTXCompiler compiler, Pair p) { public static UnifyPair convert(JavaTXCompiler compiler, Pair p, PlaceholderRegistry placeholderRegistry) {
UnifyPair ret = null; UnifyPair ret = null;
if(p.GetOperator().equals(PairOperator.SMALLERDOT)) { if(p.GetOperator().equals(PairOperator.SMALLERDOT)) {
ret = generateSmallerDotPair(UnifyTypeFactory.convert(compiler, p.TA1, false) ret = generateSmallerDotPair(UnifyTypeFactory.convert(compiler, p.TA1, false, placeholderRegistry)
, UnifyTypeFactory.convert(compiler, p.TA2, false), p.getLocation()); , UnifyTypeFactory.convert(compiler, p.TA2, false, placeholderRegistry), p.getLocation());
//return ret; //return ret;
}else if(p.GetOperator().equals(PairOperator.SMALLERNEQDOT)) { }else if(p.GetOperator().equals(PairOperator.SMALLERNEQDOT)) {
ret = generateSmallNotEqualDotPair(UnifyTypeFactory.convert(compiler, p.TA1, false) ret = generateSmallNotEqualDotPair(UnifyTypeFactory.convert(compiler, p.TA1, false, placeholderRegistry)
, UnifyTypeFactory.convert(compiler, p.TA2, false), p.getLocation()); , UnifyTypeFactory.convert(compiler, p.TA2, false, placeholderRegistry), p.getLocation());
//return ret; //return ret;
}else if(p.GetOperator().equals(PairOperator.EQUALSDOT)) { }else if(p.GetOperator().equals(PairOperator.EQUALSDOT)) {
ret = generateEqualDotPair(UnifyTypeFactory.convert(compiler, p.TA1, false) ret = generateEqualDotPair(UnifyTypeFactory.convert(compiler, p.TA1, false, placeholderRegistry)
, UnifyTypeFactory.convert(compiler, p.TA2, false), p.getLocation()); , UnifyTypeFactory.convert(compiler, p.TA2, false, placeholderRegistry), p.getLocation());
//return ret; //return ret;
}else if(p.GetOperator().equals(PairOperator.SMALLER)){ }else if(p.GetOperator().equals(PairOperator.SMALLER)){
ret = generateSmallerPair(UnifyTypeFactory.convert(compiler, p.TA1, false), ret = generateSmallerPair(UnifyTypeFactory.convert(compiler, p.TA1, false, placeholderRegistry),
UnifyTypeFactory.convert(compiler, p.TA2, false), p.getLocation()); UnifyTypeFactory.convert(compiler, p.TA2, false, placeholderRegistry), p.getLocation());
}else throw new NotImplementedException(); }else throw new NotImplementedException();
UnifyType lhs, rhs; UnifyType lhs, rhs;
if (((lhs = ret.getLhsType()) instanceof PlaceholderType) if (((lhs = ret.getLhsType()) instanceof PlaceholderType)
&& ((PlaceholderType)lhs).isWildcardable() && ((PlaceholderType)lhs).isWildcardable()
&& (rhs = ret.getLhsType()) instanceof PlaceholderType) { && (rhs = ret.getLhsType()) instanceof PlaceholderType) {
if (lhs.getName().equals("AQ")) { if (lhs.getName().equals("AQ")) {
System.out.println(""); // SyntaxTree.logger.info("");
} }
((PlaceholderType)rhs).enableWildcardtable(); ((PlaceholderType)rhs).enableWildcardtable();
} }
@@ -203,7 +210,7 @@ public class UnifyTypeFactory {
&& ((PlaceholderType)rhs).isWildcardable() && ((PlaceholderType)rhs).isWildcardable()
&& (lhs = ret.getLhsType()) instanceof PlaceholderType) { && (lhs = ret.getLhsType()) instanceof PlaceholderType) {
if (rhs.getName().equals("AQ")) { if (rhs.getName().equals("AQ")) {
System.out.println(""); // SyntaxTree.logger.info("");
} }
((PlaceholderType)lhs).enableWildcardtable(); ((PlaceholderType)lhs).enableWildcardtable();
} }
@@ -214,16 +221,16 @@ public class UnifyTypeFactory {
* Convert from * Convert from
* UnifyType -> ASTType * UnifyType -> ASTType
*/ */
public static Set<ResultPair> convert(Set<UnifyPair> unifyPairSet, Map<String,TypePlaceholder> tphs) { public static Set<ResultPair> convert(Set<UnifyPair> unifyPairSet, Map<String,TypePlaceholder> tphs, PlaceholderRegistry placeholderRegistry) {
return unifyPairSet.stream().map( return unifyPairSet.stream().map(
unifyPair -> convert(unifyPair, tphs)) unifyPair -> convert(unifyPair, tphs, placeholderRegistry))
.collect(Collectors.toSet()); .collect(Collectors.toSet());
} }
public static ResultPair convert(UnifyPair mp, Map<String,TypePlaceholder> tphs) { public static ResultPair convert(UnifyPair mp, Map<String,TypePlaceholder> tphs, PlaceholderRegistry placeholderRegistry) {
if (mp == null) { return null;} //kann bei basePairs passieren if (mp == null) { return null;} //kann bei basePairs passieren
RefTypeOrTPHOrWildcardOrGeneric tl = UnifyTypeFactory.convert(mp.getLhsType(), tphs); RefTypeOrTPHOrWildcardOrGeneric tl = UnifyTypeFactory.convert(mp.getLhsType(), tphs, placeholderRegistry);
RefTypeOrTPHOrWildcardOrGeneric tr = UnifyTypeFactory.convert(mp.getRhsType(), tphs); RefTypeOrTPHOrWildcardOrGeneric tr = UnifyTypeFactory.convert(mp.getRhsType(), tphs, placeholderRegistry);
if(tl instanceof TypePlaceholder){ if(tl instanceof TypePlaceholder){
if(tr instanceof TypePlaceholder) { if(tr instanceof TypePlaceholder) {
@@ -232,7 +239,7 @@ public class UnifyTypeFactory {
//Einfach ignorieren TODO: Das hier muss ausgebessert werden: //Einfach ignorieren TODO: Das hier muss ausgebessert werden:
//return new PairTPHequalRefTypeOrWildcardType((TypePlaceholder)tl, ASTFactory.createObjectType()); //return new PairTPHequalRefTypeOrWildcardType((TypePlaceholder)tl, ASTFactory.createObjectType());
}else{ }else{
return new PairTPHsmallerTPH((TypePlaceholder)tl, (TypePlaceholder)tr, convert(mp.getBasePair(), tphs)); return new PairTPHsmallerTPH((TypePlaceholder)tl, (TypePlaceholder)tr, convert(mp.getBasePair(), tphs, placeholderRegistry));
} }
}else if(tr instanceof RefType){ }else if(tr instanceof RefType){
return new PairTPHequalRefTypeOrWildcardType((TypePlaceholder)tl, (RefType) tr); return new PairTPHequalRefTypeOrWildcardType((TypePlaceholder)tl, (RefType) tr);
@@ -244,51 +251,51 @@ public class UnifyTypeFactory {
}else return new PairNoResult(tl, tr);//throw new NotImplementedException(); }else return new PairNoResult(tl, tr);//throw new NotImplementedException();
} }
public static RefTypeOrTPHOrWildcardOrGeneric convert(ReferenceType t, Map<String,TypePlaceholder> tphs) { public static RefTypeOrTPHOrWildcardOrGeneric convert(ReferenceType t, Map<String,TypePlaceholder> tphs, PlaceholderRegistry placeholderRegistry) {
if(JavaClassName.Void.equals(t.getName()))return new Void(new NullToken()); if(JavaClassName.Void.equals(t.getName()))return new Void(new NullToken());
if (t.isGenTypeVar()) return new GenericRefType(t.getName(),new NullToken()); if (t.isGenTypeVar()) return new GenericRefType(t.getName(),new NullToken());
RefType ret = new RefType(new JavaClassName(t.getName()),convert(t.getTypeParams(), tphs),new NullToken()); RefType ret = new RefType(new JavaClassName(t.getName()),convert(t.getTypeParams(), tphs, placeholderRegistry),new NullToken());
return ret; return ret;
} }
public static RefTypeOrTPHOrWildcardOrGeneric convert(FunNType t, Map<String,TypePlaceholder> tphs) { public static RefTypeOrTPHOrWildcardOrGeneric convert(FunNType t, Map<String,TypePlaceholder> tphs, PlaceholderRegistry placeholderRegistry) {
RefType ret = new RefType(new JavaClassName(t.getName()), convert(t.getTypeParams(), tphs), new NullToken()); RefType ret = new RefType(new JavaClassName(t.getName()), convert(t.getTypeParams(), tphs, placeholderRegistry), new NullToken());
return ret; return ret;
} }
public static RefTypeOrTPHOrWildcardOrGeneric convert(SuperType t, Map<String,TypePlaceholder> tphs) { public static RefTypeOrTPHOrWildcardOrGeneric convert(SuperType t, Map<String,TypePlaceholder> tphs, PlaceholderRegistry placeholderRegistry) {
RefTypeOrTPHOrWildcardOrGeneric innerType = convert(t.getSuperedType(), tphs); RefTypeOrTPHOrWildcardOrGeneric innerType = convert(t.getSuperedType(), tphs, placeholderRegistry);
return new SuperWildcardType(innerType, new NullToken()); return new SuperWildcardType(innerType, new NullToken());
} }
public static RefTypeOrTPHOrWildcardOrGeneric convert(ExtendsType t, Map<String,TypePlaceholder> tphs) { public static RefTypeOrTPHOrWildcardOrGeneric convert(ExtendsType t, Map<String,TypePlaceholder> tphs, PlaceholderRegistry placeholderRegistry) {
RefTypeOrTPHOrWildcardOrGeneric innerType = convert(t.getExtendedType(), tphs); RefTypeOrTPHOrWildcardOrGeneric innerType = convert(t.getExtendedType(), tphs, placeholderRegistry);
return new ExtendsWildcardType(innerType, new NullToken()); return new ExtendsWildcardType(innerType, new NullToken());
} }
public static RefTypeOrTPHOrWildcardOrGeneric convert(PlaceholderType t, Map<String,TypePlaceholder> tphs) { public static RefTypeOrTPHOrWildcardOrGeneric convert(PlaceholderType t, Map<String,TypePlaceholder> tphs, PlaceholderRegistry placeholderRegistry) {
TypePlaceholder ret = tphs.get(t.getName()); TypePlaceholder ret = tphs.get(t.getName());
if(ret == null){ //Dieser TPH wurde vom Unifikationsalgorithmus erstellt if(ret == null){ //Dieser TPH wurde vom Unifikationsalgorithmus erstellt
ret = TypePlaceholder.fresh(new NullToken()); ret = TypePlaceholder.fresh(new NullToken(), placeholderRegistry);
tphs.put(t.getName(), ret); tphs.put(t.getName(), ret);
} }
ret.setVariance(t.getVariance()); ret.setVariance(t.getVariance());
return ret; return ret;
} }
public static RefTypeOrTPHOrWildcardOrGeneric convert(UnifyType t, Map<String,TypePlaceholder> tphs) { public static RefTypeOrTPHOrWildcardOrGeneric convert(UnifyType t, Map<String,TypePlaceholder> tphs, PlaceholderRegistry placeholderRegistry) {
if(t instanceof FunNType)return convert((FunNType) t, tphs); if(t instanceof FunNType)return convert((FunNType) t, tphs, placeholderRegistry);
if(t instanceof ReferenceType)return convert((ReferenceType) t, tphs); if(t instanceof ReferenceType)return convert((ReferenceType) t, tphs, placeholderRegistry);
if(t instanceof SuperType)return convert((SuperType) t, tphs); if(t instanceof SuperType)return convert((SuperType) t, tphs, placeholderRegistry);
if(t instanceof ExtendsType)return convert((ExtendsType) t, tphs); if(t instanceof ExtendsType)return convert((ExtendsType) t, tphs, placeholderRegistry);
if(t instanceof PlaceholderType)return convert((PlaceholderType) t, tphs); if(t instanceof PlaceholderType)return convert((PlaceholderType) t, tphs, placeholderRegistry);
throw new NotImplementedException("Der Typ "+t+" kann nicht umgewandelt werden"); throw new NotImplementedException("Der Typ "+t+" kann nicht umgewandelt werden");
} }
private static List<RefTypeOrTPHOrWildcardOrGeneric> convert(TypeParams typeParams, Map<String,TypePlaceholder> tphs) { private static List<RefTypeOrTPHOrWildcardOrGeneric> convert(TypeParams typeParams, Map<String,TypePlaceholder> tphs, PlaceholderRegistry placeholderRegistry) {
List<RefTypeOrTPHOrWildcardOrGeneric> ret = new ArrayList<>(); List<RefTypeOrTPHOrWildcardOrGeneric> ret = new ArrayList<>();
for(UnifyType uT : typeParams){ for(UnifyType uT : typeParams){
RefTypeOrTPHOrWildcardOrGeneric toAdd = convert(uT, tphs); RefTypeOrTPHOrWildcardOrGeneric toAdd = convert(uT, tphs, placeholderRegistry);
ret.add(toAdd); ret.add(toAdd);
} }
return ret; return ret;

View File

@@ -1,8 +1,13 @@
package de.dhbwstuttgart.syntaxtree.type; package de.dhbwstuttgart.syntaxtree.type;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.server.packet.dataContainers.ISerializableData;
import de.dhbwstuttgart.server.packet.dataContainers.KeyStorage;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialMap;
import de.dhbwstuttgart.syntaxtree.ASTVisitor; import de.dhbwstuttgart.syntaxtree.ASTVisitor;
import de.dhbwstuttgart.typeinference.result.ResultSetVisitor; import de.dhbwstuttgart.typeinference.result.ResultSetVisitor;
import de.dhbwstuttgart.typeinference.unify.UnifyContext;
import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.Token;
import java.util.Objects; import java.util.Objects;
@@ -15,7 +20,7 @@ import java.util.Objects;
* *
*/ */
public class ExtendsWildcardType extends WildcardType{ public class ExtendsWildcardType extends WildcardType implements ISerializableData {
/** /**
* Author: Arne Lüdtke<br/> * Author: Arne Lüdtke<br/>
@@ -68,4 +73,22 @@ public class ExtendsWildcardType extends WildcardType{
ExtendsWildcardType that = (ExtendsWildcardType) o; ExtendsWildcardType that = (ExtendsWildcardType) o;
return that.innerType.equals(this.innerType); return that.innerType.equals(this.innerType);
} }
@Override
public SerialMap toSerial(KeyStorage keyStorage) {
SerialMap serialized = new SerialMap();
serialized.put("innerType", this.innerType.toSerial(keyStorage));
// create the wrapper and put this as the object
var serializedWrapper = super.toSerial(keyStorage).assertType(SerialMap.class);
serializedWrapper.put("object", serialized);
return serializedWrapper;
}
public static ExtendsWildcardType fromSerial(SerialMap data, UnifyContext context) {
return new ExtendsWildcardType(
RefTypeOrTPHOrWildcardOrGeneric.fromSerial(data.getMap("innerType"), context),
new NullToken()
);
}
} }

View File

@@ -1,22 +1,25 @@
package de.dhbwstuttgart.syntaxtree.type; package de.dhbwstuttgart.syntaxtree.type;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.server.packet.dataContainers.ISerializableData;
import de.dhbwstuttgart.server.packet.dataContainers.KeyStorage;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialMap;
import de.dhbwstuttgart.syntaxtree.ASTVisitor; import de.dhbwstuttgart.syntaxtree.ASTVisitor;
import de.dhbwstuttgart.typeinference.result.ResultSetVisitor; import de.dhbwstuttgart.typeinference.result.ResultSetVisitor;
import de.dhbwstuttgart.typeinference.unify.UnifyContext;
import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.Token;
import java.util.Objects; import java.util.Objects;
public class GenericRefType extends RefTypeOrTPHOrWildcardOrGeneric public class GenericRefType extends RefTypeOrTPHOrWildcardOrGeneric implements ISerializableData {
{
private String name; private String name;
public GenericRefType(String name, Token offset) public GenericRefType(String name, Token offset) {
{
super(offset); super(offset);
this.name = name; this.name = name;
} }
public String getParsedName(){ public String getParsedName() {
return name.toString(); return name.toString();
} }
@@ -49,9 +52,26 @@ public class GenericRefType extends RefTypeOrTPHOrWildcardOrGeneric
} }
@Override @Override
public String toString() public String toString() {
{
return "GTV " + this.name; return "GTV " + this.name;
} }
@Override
public SerialMap toSerial(KeyStorage keyStorage) {
SerialMap serialized = new SerialMap();
serialized.put("name", this.name);
// create the wrapper and put this as the object
var serializedWrapper = super.toSerial(keyStorage).assertType(SerialMap.class);
serializedWrapper.put("object", serialized);
return serializedWrapper;
}
public static GenericRefType fromSerial(SerialMap data, UnifyContext context) {
return new GenericRefType(
data.getValue("name").getOf(String.class),
new NullToken()
);
}
} }

View File

@@ -1,8 +1,15 @@
package de.dhbwstuttgart.syntaxtree.type; package de.dhbwstuttgart.syntaxtree.type;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.parser.scope.JavaClassName; import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.server.packet.dataContainers.ISerializableData;
import de.dhbwstuttgart.server.packet.dataContainers.KeyStorage;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.ISerialNode;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialList;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialMap;
import de.dhbwstuttgart.syntaxtree.ASTVisitor; import de.dhbwstuttgart.syntaxtree.ASTVisitor;
import de.dhbwstuttgart.typeinference.result.ResultSetVisitor; import de.dhbwstuttgart.typeinference.result.ResultSetVisitor;
import de.dhbwstuttgart.typeinference.unify.UnifyContext;
import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.Token;
import java.util.ArrayList; import java.util.ArrayList;
@@ -11,20 +18,18 @@ import java.util.List;
import java.util.Objects; import java.util.Objects;
public class RefType extends RefTypeOrTPHOrWildcardOrGeneric public class RefType extends RefTypeOrTPHOrWildcardOrGeneric implements ISerializableData {
{
protected final JavaClassName name; protected final JavaClassName name;
protected final List<RefTypeOrTPHOrWildcardOrGeneric> parameter; protected final List<RefTypeOrTPHOrWildcardOrGeneric> parameter;
/** /**
* Ist primitiveFlag auf true, muss beim Codegen dieser Reftype durch * Ist primitiveFlag auf true, muss beim Codegen dieser Reftype durch
* den primitiven Datentyp ersetzt werden * den primitiven Datentyp ersetzt werden
* * <p>
* Bsp: java.lang.Integer mit Flag wird dann zu [int] * Bsp: java.lang.Integer mit Flag wird dann zu [int]
*/ */
boolean primitiveFlag = false; // TODO Should be final boolean primitiveFlag = false; // TODO Should be final
public RefType(JavaClassName fullyQualifiedName, Token offset) public RefType(JavaClassName fullyQualifiedName, Token offset) {
{
this(fullyQualifiedName, new ArrayList<>(), offset); this(fullyQualifiedName, new ArrayList<>(), offset);
} }
@@ -33,15 +38,15 @@ public class RefType extends RefTypeOrTPHOrWildcardOrGeneric
} }
@Override @Override
public String toString(){ public String toString() {
String params = ""; String params = "";
if(parameter.size()>0){ if (parameter.size() > 0) {
params += "<"; params += "<";
Iterator<RefTypeOrTPHOrWildcardOrGeneric> it = parameter.iterator(); Iterator<RefTypeOrTPHOrWildcardOrGeneric> it = parameter.iterator();
while(it.hasNext()){ while (it.hasNext()) {
RefTypeOrTPHOrWildcardOrGeneric param = it.next(); RefTypeOrTPHOrWildcardOrGeneric param = it.next();
params += param.toString(); params += param.toString();
if(it.hasNext())params += ", "; if (it.hasNext()) params += ", ";
} }
params += ">"; params += ">";
} }
@@ -64,53 +69,46 @@ public class RefType extends RefTypeOrTPHOrWildcardOrGeneric
this.primitiveFlag = primitiveFlag; this.primitiveFlag = primitiveFlag;
} }
public JavaClassName getName() public JavaClassName getName() {
{
return name; return name;
} }
public List<RefTypeOrTPHOrWildcardOrGeneric> getParaList(){ public List<RefTypeOrTPHOrWildcardOrGeneric> getParaList() {
if(this.parameter==null)return new ArrayList<>(); if (this.parameter == null) return new ArrayList<>();
return this.parameter; return this.parameter;
} }
/** /**
* Author: Jrg Buerle<br/> * Author: Jrg Buerle<br/>
*
* @return * @return
*/ */
public boolean equals(Object obj) public boolean equals(Object obj) {
{ if (!(obj instanceof RefType refObj)) {
if(obj instanceof RefType){ return false;
if (!Objects.equals(this.name, ((RefType) obj).name)) return false; }
if (!Objects.equals(this.name, refObj.name)) return false;
boolean ret = true; boolean ret = true;
//if(!(super.equals(obj))) PL 2020-03-12 muss vll. einkommentiert werden //if(!(super.equals(obj))) PL 2020-03-12 muss vll. einkommentiert werden
// return false; // return false;
if(parameter==null || parameter.size()==0){ if (parameter == null || parameter.size() == 0) {
ret &= (((RefType)obj).getParaList()==null || ((RefType)obj).getParaList().size()==0); ret &= (refObj.getParaList() == null || refObj.getParaList().isEmpty());
} } else {
else{ if (refObj.getParaList() == null) {
if(((RefType)obj).getParaList()==null){
ret = false; ret = false;
} } else if (parameter.size() != refObj.getParaList().size()) {
else if(parameter.size() != ((RefType)obj).getParaList().size())
{
ret = false; ret = false;
} } else {
else for (int i = 0; i < parameter.size(); i++) {
{ ret &= parameter.get(i).equals(refObj.getParaList().get(i));
for(int i = 0; i<parameter.size(); i++)
{
ret &= parameter.get(i).equals(((RefType)obj).getParaList().get(i));
} }
} }
} }
return ret; return ret;
}
else{
return false;
}
} }
@@ -128,5 +126,29 @@ public class RefType extends RefTypeOrTPHOrWildcardOrGeneric
public void accept(ResultSetVisitor visitor) { public void accept(ResultSetVisitor visitor) {
visitor.visit(this); visitor.visit(this);
} }
@Override
public ISerialNode toSerial(KeyStorage keyStorage) {
SerialMap serialized = new SerialMap();
serialized.put("isPrimitive", this.primitiveFlag);
serialized.put("name", this.name.toString());
serialized.put("parameters", SerialList.fromMapped(this.parameter, param -> param.toSerial(keyStorage)));
// create the wrapper and put this as the object
var serializedWrapper = super.toSerial(keyStorage).assertType(SerialMap.class);
serializedWrapper.put("object", serialized);
return serializedWrapper;
}
public static RefType fromSerial(SerialMap data, UnifyContext context) {
return new RefType(
new JavaClassName(data.getValue("name").getOf(String.class)),
data.getList("parameters").assertListOfMaps().stream()
.map(param -> RefTypeOrTPHOrWildcardOrGeneric.fromSerial(param, context))
.toList(),
new NullToken(),
data.getValue("isPrimitive").getOf(Boolean.class)
);
}
} }

View File

@@ -1,11 +1,17 @@
package de.dhbwstuttgart.syntaxtree.type; package de.dhbwstuttgart.syntaxtree.type;
import de.dhbwstuttgart.server.packet.dataContainers.ISerializableData;
import de.dhbwstuttgart.server.packet.dataContainers.KeyStorage;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.ISerialNode;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialMap;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialValue;
import de.dhbwstuttgart.syntaxtree.ASTVisitor; import de.dhbwstuttgart.syntaxtree.ASTVisitor;
import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode;
import de.dhbwstuttgart.typeinference.result.ResultSetVisitor; import de.dhbwstuttgart.typeinference.result.ResultSetVisitor;
import de.dhbwstuttgart.typeinference.unify.UnifyContext;
import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.Token;
public abstract class RefTypeOrTPHOrWildcardOrGeneric extends SyntaxTreeNode{ public abstract class RefTypeOrTPHOrWildcardOrGeneric extends SyntaxTreeNode implements ISerializableData {
public RefTypeOrTPHOrWildcardOrGeneric(Token offset) { public RefTypeOrTPHOrWildcardOrGeneric(Token offset) {
super(offset); super(offset);
} }
@@ -19,4 +25,25 @@ public abstract class RefTypeOrTPHOrWildcardOrGeneric extends SyntaxTreeNode{
@Override @Override
public abstract boolean equals(Object o); public abstract boolean equals(Object o);
@Override
public ISerialNode toSerial(KeyStorage keyStorage) {
SerialMap serialized = new SerialMap();
serialized.put("type", this.getClass().getSimpleName());
// we only insert null for the object and expect the child classes to call this and override the value with themselves
serialized.put("object", SerialValue.NULL);
return serialized;
}
public static RefTypeOrTPHOrWildcardOrGeneric fromSerial(SerialMap data, UnifyContext context) {
String type = data.getValue("type").getOf(String.class);
SerialMap object = data.getMap("object");
if (type.equals(ExtendsWildcardType.class.getSimpleName())) return ExtendsWildcardType.fromSerial(object, context);
else if (type.equals(GenericRefType.class.getSimpleName())) return GenericRefType.fromSerial(object, context);
else if (type.equals(SuperWildcardType.class.getSimpleName())) return SuperWildcardType.fromSerial(object, context);
else if (type.equals(RefType.class.getSimpleName())) return RefType.fromSerial(object, context);
else if (type.equals(Void.class.getSimpleName())) return Void.fromSerial(object, context);
else if (type.equals(TypePlaceholder.class.getSimpleName())) return TypePlaceholder.fromSerial(object, context);
else throw new RuntimeException("Could not unserialize class of unhandled type " + type);
}
} }

View File

@@ -1,9 +1,13 @@
package de.dhbwstuttgart.syntaxtree.type; package de.dhbwstuttgart.syntaxtree.type;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.server.packet.dataContainers.ISerializableData;
import de.dhbwstuttgart.server.packet.dataContainers.KeyStorage;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialMap;
import de.dhbwstuttgart.syntaxtree.ASTVisitor; import de.dhbwstuttgart.syntaxtree.ASTVisitor;
import de.dhbwstuttgart.syntaxtree.GenericTypeVar;
import de.dhbwstuttgart.typeinference.result.ResultSetVisitor; import de.dhbwstuttgart.typeinference.result.ResultSetVisitor;
import de.dhbwstuttgart.typeinference.unify.UnifyContext;
import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.Token;
import java.util.Objects; import java.util.Objects;
@@ -16,7 +20,7 @@ import java.util.Objects;
* *
*/ */
public class SuperWildcardType extends WildcardType{ public class SuperWildcardType extends WildcardType implements ISerializableData {
/** /**
* Author: Arne Lüdtke<br/> * Author: Arne Lüdtke<br/>
@@ -80,4 +84,22 @@ public class SuperWildcardType extends WildcardType{
SuperWildcardType that = (SuperWildcardType) o; SuperWildcardType that = (SuperWildcardType) o;
return that.innerType.equals(this.innerType); return that.innerType.equals(this.innerType);
} }
@Override
public SerialMap toSerial(KeyStorage keyStorage) {
SerialMap serialized = new SerialMap();
serialized.put("innerType", this.innerType.toSerial(keyStorage));
// create the wrapper and put this as the object
var serializedWrapper = super.toSerial(keyStorage).assertType(SerialMap.class);
serializedWrapper.put("object", serialized);
return serializedWrapper;
}
public static SuperWildcardType fromSerial(SerialMap data, UnifyContext context) {
return new SuperWildcardType(
RefTypeOrTPHOrWildcardOrGeneric.fromSerial(data.getMap("innerType"), context),
new NullToken()
);
}
} }

View File

@@ -1,9 +1,12 @@
package de.dhbwstuttgart.syntaxtree.type; package de.dhbwstuttgart.syntaxtree.type;
import java.util.Hashtable; import de.dhbwstuttgart.server.packet.dataContainers.ISerializableData;
import de.dhbwstuttgart.server.packet.dataContainers.KeyStorage;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialMap;
import de.dhbwstuttgart.typeinference.unify.PlaceholderRegistry;
import de.dhbwstuttgart.typeinference.unify.UnifyContext;
import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.syntaxtree.ASTVisitor; import de.dhbwstuttgart.syntaxtree.ASTVisitor;
import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode;
import de.dhbwstuttgart.syntaxtree.factory.NameGenerator; import de.dhbwstuttgart.syntaxtree.factory.NameGenerator;
import de.dhbwstuttgart.typeinference.result.ResultSetVisitor; import de.dhbwstuttgart.typeinference.result.ResultSetVisitor;
import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.Token;
@@ -16,7 +19,7 @@ import org.antlr.v4.runtime.Token;
* @author J�rg B�uerle * @author J�rg B�uerle
* @version $Date: 2013/06/19 12:45:37 $ * @version $Date: 2013/06/19 12:45:37 $
*/ */
public class TypePlaceholder extends RefTypeOrTPHOrWildcardOrGeneric public class TypePlaceholder extends RefTypeOrTPHOrWildcardOrGeneric implements ISerializableData
{ {
private final String name; private final String name;
@@ -66,6 +69,11 @@ public class TypePlaceholder extends RefTypeOrTPHOrWildcardOrGeneric
return new TypePlaceholder(NameGenerator.makeNewName(), position, 0, true); return new TypePlaceholder(NameGenerator.makeNewName(), position, 0, true);
} }
public static TypePlaceholder fresh(Token position, PlaceholderRegistry placeholderRegistry){
String newName = placeholderRegistry.generateFreshPlaceholderName();
return new TypePlaceholder(newName, position, 0, true);
}
public static TypePlaceholder fresh(Token position, int variance, boolean wildcardable){ public static TypePlaceholder fresh(Token position, int variance, boolean wildcardable){
return new TypePlaceholder(NameGenerator.makeNewName(), position, variance, wildcardable); return new TypePlaceholder(NameGenerator.makeNewName(), position, variance, wildcardable);
} }
@@ -139,4 +147,26 @@ public class TypePlaceholder extends RefTypeOrTPHOrWildcardOrGeneric
public Boolean getWildcardtable() { public Boolean getWildcardtable() {
return wildcardable; return wildcardable;
} }
@Override
public SerialMap toSerial(KeyStorage keyStorage) {
SerialMap serialized = new SerialMap();
serialized.put("name", this.name);
serialized.put("variance", this.variance);
serialized.put("wildcardable", this.wildcardable);
// create the wrapper and put this as the object
var serializedWrapper = super.toSerial(keyStorage).assertType(SerialMap.class);
serializedWrapper.put("object", serialized);
return serializedWrapper;
}
public static TypePlaceholder fromSerial(SerialMap data, UnifyContext context) {
return new TypePlaceholder(
data.getValue("name").getOf(String.class),
new NullToken(),
data.getValue("variance").getOf(Integer.class),
data.getValue("wildcardable").getOf(Boolean.class)
);
}
} }

View File

@@ -1,14 +1,32 @@
package de.dhbwstuttgart.syntaxtree.type; package de.dhbwstuttgart.syntaxtree.type;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.server.packet.dataContainers.ISerializableData;
import de.dhbwstuttgart.server.packet.dataContainers.KeyStorage;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.ISerialNode;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialMap;
import de.dhbwstuttgart.typeinference.unify.UnifyContext;
import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.Token;
import de.dhbwstuttgart.parser.scope.JavaClassName; import de.dhbwstuttgart.parser.scope.JavaClassName;
public class Void extends RefType public class Void extends RefType implements ISerializableData
{ {
public Void(Token offset) { public Void(Token offset) {
super(JavaClassName.Void, offset); super(JavaClassName.Void, offset);
} }
@Override
public ISerialNode toSerial(KeyStorage keyStorage) {
// create the wrapper and put this as the object
var serializedWrapper = super.toSerial(keyStorage).assertType(SerialMap.class);
serializedWrapper.put("object", new SerialMap());
return serializedWrapper;
}
public static Void fromSerial(SerialMap data, UnifyContext context) {
return new Void(new NullToken());
}
} }

View File

@@ -0,0 +1,8 @@
package de.dhbwstuttgart.target;
import de.dhbwstuttgart.util.Logger;
public class Target {
public static Logger logger = new Logger("Target");
}

View File

@@ -2,6 +2,7 @@ package de.dhbwstuttgart.target.generate;
import de.dhbwstuttgart.bytecode.FunNGenerator; import de.dhbwstuttgart.bytecode.FunNGenerator;
import de.dhbwstuttgart.core.JavaTXCompiler; import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.environment.ByteArrayClassLoader;
import de.dhbwstuttgart.environment.IByteArrayClassLoader; import de.dhbwstuttgart.environment.IByteArrayClassLoader;
import de.dhbwstuttgart.exceptions.DebugException; import de.dhbwstuttgart.exceptions.DebugException;
import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.parser.NullToken;
@@ -11,14 +12,12 @@ import de.dhbwstuttgart.syntaxtree.Record;
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
import de.dhbwstuttgart.syntaxtree.statement.*; import de.dhbwstuttgart.syntaxtree.statement.*;
import de.dhbwstuttgart.syntaxtree.type.*; import de.dhbwstuttgart.syntaxtree.type.*;
import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter; import de.dhbwstuttgart.target.Target;
import de.dhbwstuttgart.syntaxtree.visual.OutputGenerator;
import de.dhbwstuttgart.target.tree.*; import de.dhbwstuttgart.target.tree.*;
import de.dhbwstuttgart.target.tree.expression.*; import de.dhbwstuttgart.target.tree.expression.*;
import de.dhbwstuttgart.target.tree.type.*; import de.dhbwstuttgart.target.tree.type.*;
import de.dhbwstuttgart.typeinference.result.*; import de.dhbwstuttgart.typeinference.result.*;
import java.lang.annotation.Target;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
@@ -33,9 +32,9 @@ public class ASTToTargetAST {
public static RefType OBJECT = ASTFactory.createObjectType(); // TODO It would be better if I could call this directly but the hashcode seems to change public static RefType OBJECT = ASTFactory.createObjectType(); // TODO It would be better if I could call this directly but the hashcode seems to change
public List<Generics> all; protected List<Generics> all;
//public Generics generics; public Generics generics;
//public List<Generics> currentMethodOverloads; public List<Generics> currentMethodOverloads;
final Map<ClassOrInterface, Set<GenericTypeVar>> userDefinedGenerics = new HashMap<>(); final Map<ClassOrInterface, Set<GenericTypeVar>> userDefinedGenerics = new HashMap<>();
final Map<Method, Set<SignaturePair>> tphsInMethods = new HashMap<>(); final Map<Method, Set<SignaturePair>> tphsInMethods = new HashMap<>();
@@ -55,24 +54,24 @@ public class ASTToTargetAST {
return all.stream().map(generics -> new GenericsResult(generics.javaGenerics)).toList(); return all.stream().map(generics -> new GenericsResult(generics.javaGenerics)).toList();
} }
public TargetExpression convert(Pattern pattern, IGenerics generics) { public TargetExpression convert(Pattern pattern) {
var converter = new StatementToTargetExpression(this, generics); var converter = new StatementToTargetExpression(this);
pattern.accept(converter); pattern.accept(converter);
return converter.result; return converter.result;
} }
public record Generics(IGenerics javaGenerics, IGenerics txGenerics) { public record Generics(JavaGenerics javaGenerics, TxGenerics txGenerics) {
} }
public IByteArrayClassLoader classLoader; public IByteArrayClassLoader classLoader;
protected SourceFile sourceFile; protected SourceFile sourceFile;
public ASTToTargetAST(List<ResultSet> resultSets, IByteArrayClassLoader classLoader) { public ASTToTargetAST(List<ResultSet> resultSets) {
this(null, resultSets, classLoader); this(null, resultSets);
} }
public ASTToTargetAST(JavaTXCompiler compiler, List<ResultSet> resultSets, IByteArrayClassLoader classLoader) { public ASTToTargetAST(JavaTXCompiler compiler, List<ResultSet> resultSets) {
this(compiler, resultSets, null, classLoader); this(compiler, resultSets, null, new ByteArrayClassLoader());
} }
public ASTToTargetAST(JavaTXCompiler compiler, List<ResultSet> resultSets, SourceFile sourceFile, IByteArrayClassLoader classLoader) { public ASTToTargetAST(JavaTXCompiler compiler, List<ResultSet> resultSets, SourceFile sourceFile, IByteArrayClassLoader classLoader) {
@@ -84,6 +83,7 @@ public class ASTToTargetAST {
for (var set : resultSets) { for (var set : resultSets) {
all.add(new Generics(new JavaGenerics(this, set), new TxGenerics(this, set))); all.add(new Generics(new JavaGenerics(this, set), new TxGenerics(this, set)));
} }
this.generics = all.get(0);
} }
public void addSignaturePair(TypePlaceholder signature, RefTypeOrTPHOrWildcardOrGeneric parameter) { public void addSignaturePair(TypePlaceholder signature, RefTypeOrTPHOrWildcardOrGeneric parameter) {
@@ -112,23 +112,20 @@ public class ASTToTargetAST {
return false; return false;
for (var i = 0; i < pars.size(); i++) { for (var i = 0; i < pars.size(); i++) {
var type1 = pars.get(i).getType(); var type1 = convert(pars.get(i).getType(), generics.javaGenerics);
var type2 = arguments.get(i); var type2 = arguments.get(i);
//if (type1 instanceof GenericRefType) if (type1 instanceof TargetGenericType)
// return true; return true;
//if (TargetType.toPrimitive(type2).equals(type1)) if (TargetType.toPrimitive(type2).equals(type1))
// return true; return true;
if (type1 instanceof RefType rt) { if (!type1.equals(type2))
if (type2 instanceof TargetRefType rt2 && !rt2.name().equals(rt.getName().toString())) {
return false; return false;
} }
}
}
return true; return true;
} }
Set<TargetGeneric> convert(Set<GenerateGenerics.Pair> result, IGenerics generics) { Set<TargetGeneric> convert(Set<GenerateGenerics.Pair> result, GenerateGenerics generics) {
return result.stream().map(p -> { return result.stream().map(p -> {
if (p instanceof GenerateGenerics.PairLT pair) { if (p instanceof GenerateGenerics.PairLT pair) {
return new TargetGeneric(pair.left.resolve().getName(), convert(pair.right.resolve(), generics)); return new TargetGeneric(pair.left.resolve().getName(), convert(pair.right.resolve(), generics));
@@ -140,7 +137,7 @@ public class ASTToTargetAST {
}).collect(Collectors.toSet()); }).collect(Collectors.toSet());
} }
public List<TargetGeneric> convert(GenericTypeVar typeVar, IGenerics generics) { public List<TargetGeneric> convert(GenericTypeVar typeVar, GenerateGenerics generics) {
var ret = new ArrayList<TargetGeneric>(); var ret = new ArrayList<TargetGeneric>();
for (var bound : typeVar.getBounds()) { for (var bound : typeVar.getBounds()) {
ret.add(new TargetGeneric(typeVar.getName(), generics.getTargetType(bound))); ret.add(new TargetGeneric(typeVar.getName(), generics.getTargetType(bound)));
@@ -149,7 +146,6 @@ public class ASTToTargetAST {
} }
// This finds a common sealed interface type to group together methods that use different records // This finds a common sealed interface type to group together methods that use different records
// This function should do matching or unification
private List<ClassOrInterface> commonSuperInterfaceTypes(TargetType a, TargetType b) { private List<ClassOrInterface> commonSuperInterfaceTypes(TargetType a, TargetType b) {
if (a instanceof TargetGenericType && b instanceof TargetGenericType) return List.of(ASTFactory.createObjectClass()); if (a instanceof TargetGenericType && b instanceof TargetGenericType) return List.of(ASTFactory.createObjectClass());
if (a instanceof TargetRefType ta && b instanceof TargetGenericType) if (a instanceof TargetRefType ta && b instanceof TargetGenericType)
@@ -187,28 +183,44 @@ public class ASTToTargetAST {
return List.of(); return List.of();
} }
private boolean canCombine(Signature m1, Signature m2) { // TODO This is ugly and probably doesn't work right
var pl1 = m1.java.parameters(); private boolean patternStrictlyEquals(TargetComplexPattern a, TargetComplexPattern b) {
var pl2 = m2.java.parameters(); if (!a.name().equals(b.name())) return false;
if (pl1.size() != pl2.size()) return false; if (a.subPatterns().size() != b.subPatterns().size()) return false;
if (pl1.isEmpty()) return false; for (var i = 0; i < a.subPatterns().size(); i++) {
for (var i = 0; i < pl1.size(); i++) { var p1 = a.subPatterns().get(i);
var p1 = pl1.get(i).pattern(); var p2 = b.subPatterns().get(i);
var p2 = pl2.get(i).pattern();
// TPH <> RefType sind nicht unterscheidbar
if (p1.type() instanceof TargetGenericType || p2.type() instanceof TargetGenericType) continue;
// Pattern(X) <> Pattern(Y) ist nicht unterscheidbar
if (p1 instanceof TargetComplexPattern pc1 && p2 instanceof TargetComplexPattern pc2 && if (p1 instanceof TargetComplexPattern pc1 && p2 instanceof TargetComplexPattern pc2 &&
pc1.type().equals(pc2.type())) continue; patternStrictlyEquals(pc1, pc2)) return false;
if (!p1.equals(p2)) 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; return true;
} }
private record Combination(MethodWithTphs a, MethodWithTphs b) { 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 @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (!(o instanceof Combination(MethodWithTphs a1, MethodWithTphs b1))) return false; if (!(o instanceof Combination(TargetMethod a1, TargetMethod b1))) return false;
return this.a.equals(a1) && this.b.equals(b1) || return this.a.equals(a1) && this.b.equals(b1) ||
this.a.equals(b1) && this.b.equals(a1); this.a.equals(b1) && this.b.equals(a1);
} }
@@ -219,10 +231,10 @@ public class ASTToTargetAST {
} }
} }
private List<List<MethodWithTphs>> groupOverloads(ClassOrInterface input, List<Method> methods) { public List<List<TargetMethod>> groupOverloads(ClassOrInterface input, List<Method> methods) {
var mapOfTargetMethods = new HashMap<Generics, MethodWithTphs[]>(); var mapOfTargetMethods = new HashMap<Generics, TargetMethod[]>();
for (var gen : all) { for (var generics : all) {
mapOfTargetMethods.put(gen, new MethodWithTphs[methods.size()]); mapOfTargetMethods.put(generics, new TargetMethod[methods.size()]);
} }
for (var i = 0; i < methods.size(); i++) { for (var i = 0; i < methods.size(); i++) {
@@ -231,14 +243,14 @@ public class ASTToTargetAST {
var methodsWithTphs = convert(input, method); var methodsWithTphs = convert(input, method);
for (var m : methodsWithTphs) { for (var m : methodsWithTphs) {
var resultMethods = mapOfTargetMethods.get(m.generics); var resultMethods = mapOfTargetMethods.get(m.generics);
resultMethods[i] = new MethodWithTphs(m.method, m.generics, m.signature); resultMethods[i] = m.method;
} }
} }
System.out.println("============== INPUT =============="); /*System.out.println("============== INPUT ==============");
for (var m : mapOfTargetMethods.values()) { for (var m : mapOfTargetMethods.values()) {
for (var v : m) if (v != null) System.out.println(v.method.name + " " + v.signature.java.getSignature()); for (var v : m) System.out.println(v.name() + " " + v.getSignature());
System.out.println(); System.out.println();
} }*/
var allCombinations = new HashSet<Set<Combination>>(); var allCombinations = new HashSet<Set<Combination>>();
// Combine methods based on their signature and position in the result set // Combine methods based on their signature and position in the result set
@@ -256,8 +268,8 @@ public class ASTToTargetAST {
var combinations = new HashSet<Combination>(); var combinations = new HashSet<Combination>();
if (canCombine(m1.signature, m2.signature)) { if (canCombine(m1, m2)) {
System.out.println(" Combining " + m1.signature.java.getSignature() + " and " + m2.signature.java.getSignature()); //System.out.println(" Combining " + m1.getSignature() + " and " + m2.getSignature());
combinations.add(new Combination(m1, m2)); combinations.add(new Combination(m1, m2));
for (var j = 0; j < methods.size(); j++) { for (var j = 0; j < methods.size(); j++) {
if (j == i) continue; if (j == i) continue;
@@ -266,10 +278,10 @@ public class ASTToTargetAST {
var m4 = resMeth1[j]; var m4 = resMeth1[j];
if (m4 == null) continue; if (m4 == null) continue;
combinations.add(new Combination(m4, m3)); combinations.add(new Combination(m4, m3));
System.out.println("Also Combining " + m4.signature.java.getSignature() + " and " + m3.signature.java.getSignature()); //System.out.println("Also Combining " + m4.getSignature() + " and " + m3.getSignature());
} }
} else { } else {
System.out.println(" Not Combining " + m1.signature.java.getSignature() + " and " + m2.signature.java.getSignature()); //System.out.println(" Not Combining " + m1.getSignature() + " and " + m2.getSignature());
} }
if (!combinations.isEmpty()) allCombinations.add(combinations); if (!combinations.isEmpty()) allCombinations.add(combinations);
} }
@@ -279,14 +291,14 @@ public class ASTToTargetAST {
if (allCombinations.isEmpty()) allCombinations.add(new HashSet<>()); if (allCombinations.isEmpty()) allCombinations.add(new HashSet<>());
// Combine back into output format // Combine back into output format
var r0 = new HashSet<Set<MethodWithTphs>>(); var r0 = new HashSet<Set<TargetMethod>>();
for (var combinations : allCombinations) { for (var combinations : allCombinations) {
var r1 = new HashSet<Set<MethodWithTphs>>(); var r1 = new HashSet<Set<TargetMethod>>();
// This is used to weed out duplicates // This is used to weed out duplicates
var uniqued = new HashSet<MethodWithTphs>(); var uniqued = new HashSet<TargetMethod>();
// We go over all methods in the result // We go over all methods in the result
for (var g : all) for (var i = 0; i < methods.size(); i++) { for (var g : all) for (var i = 0; i < methods.size(); i++) {
var r2 = new HashSet<MethodWithTphs>(); var r2 = new HashSet<TargetMethod>();
var m = mapOfTargetMethods.get(g)[i]; var m = mapOfTargetMethods.get(g)[i];
if (m == null) continue; if (m == null) continue;
if (!uniqued.contains(m)) { if (!uniqued.contains(m)) {
@@ -326,16 +338,15 @@ public class ASTToTargetAST {
var result = r0.stream().map(l -> l.stream().toList()).toList(); var result = r0.stream().map(l -> l.stream().toList()).toList();
System.out.println("============== OUTPUT =============="); Target.logger.info("============== OUTPUT ==============");
for (var l : result) { for (var l : result) {
for (var m : l) System.out.println(m.method.name + " " + m.signature.java.getSignature()); for (var m : l) Target.logger.info(m.name() + " " + m.getSignature());
System.out.println(); Target.logger.info("");
} }
return result; return result;
} }
public TargetStructure convert(ClassOrInterface input) { public TargetStructure convert(ClassOrInterface input) {
var generics = all.getFirst();
Set<TargetGeneric> javaGenerics = new HashSet<>(); Set<TargetGeneric> javaGenerics = new HashSet<>();
Set<TargetGeneric> txGenerics = new HashSet<>(); Set<TargetGeneric> txGenerics = new HashSet<>();
@@ -348,7 +359,7 @@ public class ASTToTargetAST {
var next = genericsIter.next(); var next = genericsIter.next();
userDefinedGenerics.add(next); userDefinedGenerics.add(next);
// TODO Support multiple bounds // TODO Support multiple bounds
javaGenerics.add(new TargetGeneric(next.getName(), convert(next.getBounds().getFirst(), generics.javaGenerics))); javaGenerics.add(new TargetGeneric(next.getName(), convert(next.getBounds().get(0))));
} }
} else { } else {
this.userDefinedGenerics.put(input, new HashSet<>()); this.userDefinedGenerics.put(input, new HashSet<>());
@@ -359,20 +370,18 @@ public class ASTToTargetAST {
TargetBlock fieldInitializer = null; TargetBlock fieldInitializer = null;
if (input.getfieldInitializations().isPresent()) if (input.getfieldInitializations().isPresent())
fieldInitializer = convert(input.getfieldInitializations().get().block, generics.javaGenerics); fieldInitializer = convert(input.getfieldInitializations().get().block);
TargetBlock finalFieldInitializer = fieldInitializer; TargetBlock finalFieldInitializer = fieldInitializer;
var superInterfaces = input.getSuperInterfaces().stream().map(clazz -> convert(clazz, generics.javaGenerics)).toList(); var superInterfaces = input.getSuperInterfaces().stream().map(clazz -> convert(clazz, generics.javaGenerics)).toList();
var constructors = input.getConstructors().stream().map(constructor -> this.convert(input, constructor, finalFieldInitializer, generics)).flatMap(List::stream).toList(); var constructors = input.getConstructors().stream().map(constructor -> this.convert(input, constructor, finalFieldInitializer)).flatMap(List::stream).toList();
var fields = input.getFieldDecl().stream().map(f -> convert(f, generics.javaGenerics)).toList(); var fields = input.getFieldDecl().stream().map(this::convert).toList();
var methods = groupOverloads(input, input.getMethods()).stream().map(m -> generatePatternOverloads(input, m)).flatMap(List::stream) var methods = groupOverloads(input, input.getMethods()).stream().map(m -> generatePatternOverloads(input, m)).flatMap(List::stream)
.collect(Collectors.toSet()).stream().toList(); // Unique generated methods .collect(Collectors.toSet()).stream().toList(); // Unique generated methods
TargetMethod staticConstructor = null; TargetMethod staticConstructor = null;
if (input.getStaticInitializer().isPresent()) { if (input.getStaticInitializer().isPresent())
var init = this.convert(input, input.getStaticInitializer().get()).stream().findFirst().orElseThrow(); staticConstructor = this.convert(input, input.getStaticInitializer().get()).stream().findFirst().orElseThrow().method;
staticConstructor = this.convert(init, init.generics.javaGenerics);
}
if (input instanceof Record) if (input instanceof Record)
return new TargetRecord(input.getModifiers(), input.getClassName(), javaGenerics, txGenerics, superInterfaces, constructors, staticConstructor, fields, methods); return new TargetRecord(input.getModifiers(), input.getClassName(), javaGenerics, txGenerics, superInterfaces, constructors, staticConstructor, fields, methods);
@@ -381,16 +390,11 @@ public class ASTToTargetAST {
else return new TargetClass(input.getModifiers(), input.getClassName(), convert(input.getSuperClass(), generics.javaGenerics), javaGenerics, txGenerics, superInterfaces, constructors, staticConstructor, fields, methods); else return new TargetClass(input.getModifiers(), input.getClassName(), convert(input.getSuperClass(), generics.javaGenerics), javaGenerics, txGenerics, superInterfaces, constructors, staticConstructor, fields, methods);
} }
@Deprecated public List<MethodParameter> convert(ParameterList input, GenerateGenerics generics) {
public List<MethodParameter> convert(ParameterList input) {
return convert(input, all.getFirst().javaGenerics);
}
public List<MethodParameter> convert(ParameterList input, IGenerics generics) {
var res = new ArrayList<MethodParameter>(); var res = new ArrayList<MethodParameter>();
for (var i = 0; i < input.getFormalparalist().size(); i++) { for (var i = 0; i < input.getFormalparalist().size(); i++) {
var param = input.getFormalparalist().get(i); var param = input.getFormalparalist().get(i);
var pattern = (TargetPattern) convert(param, generics); var pattern = (TargetPattern) convert(param);
if (pattern instanceof TargetComplexPattern) pattern = pattern.withName("__var" + i); if (pattern instanceof TargetComplexPattern) pattern = pattern.withName("__var" + i);
res.add(new MethodParameter(pattern)); res.add(new MethodParameter(pattern));
} }
@@ -401,7 +405,7 @@ public class ASTToTargetAST {
return generics.stream().anyMatch(g -> g.name().equals(type.getParsedName())); return generics.stream().anyMatch(g -> g.name().equals(type.getParsedName()));
} }
private Set<TargetGeneric> collectMethodGenerics(ClassOrInterface clazz, IGenerics generateGenerics, Set<GenerateGenerics.Pair> generics, Method input) { private Set<TargetGeneric> collectMethodGenerics(ClassOrInterface clazz, GenerateGenerics generateGenerics, Set<GenerateGenerics.Pair> generics, Method input) {
var convertedGenerics = new HashSet<>(convert(generics, generateGenerics)); var convertedGenerics = new HashSet<>(convert(generics, generateGenerics));
outer: for (GenericTypeVar typeVar : input.getGenerics()) { outer: for (GenericTypeVar typeVar : input.getGenerics()) {
for (var classGeneric : clazz.getGenerics()) { for (var classGeneric : clazz.getGenerics()) {
@@ -419,7 +423,7 @@ public class ASTToTargetAST {
return convertedGenerics; return convertedGenerics;
} }
private List<TargetConstructor> convert(ClassOrInterface currentClass, Constructor input, TargetBlock fieldInitializer, Generics generics) { private List<TargetConstructor> convert(ClassOrInterface currentClass, Constructor input, TargetBlock fieldInitializer) {
generics = all.get(0); generics = all.get(0);
List<TargetConstructor> result = new ArrayList<>(); List<TargetConstructor> result = new ArrayList<>();
Set<List<MethodParameter>> parameterSet = new HashSet<>(); Set<List<MethodParameter>> parameterSet = new HashSet<>();
@@ -427,15 +431,15 @@ public class ASTToTargetAST {
for (var s : all) { for (var s : all) {
generics = s; generics = s;
var javaGenerics = generics.javaGenerics.generics(currentClass, input); var javaGenerics = this.generics.javaGenerics.generics(currentClass, input);
var txGenerics = generics.txGenerics.generics(currentClass, input); var txGenerics = this.generics.txGenerics.generics(currentClass, input);
List<MethodParameter> params = convert(input.getParameterList(), generics.javaGenerics); List<MethodParameter> params = convert(input.getParameterList(), this.generics.javaGenerics);
if (parameterSet.stream().noneMatch(p -> p.equals(params))) { if (parameterSet.stream().noneMatch(p -> p.equals(params))) {
List<MethodParameter> txParams = convert(input.getParameterList(), generics.txGenerics); List<MethodParameter> txParams = convert(input.getParameterList(), this.generics.txGenerics);
var javaMethodGenerics = collectMethodGenerics(currentClass, generics.javaGenerics(), javaGenerics, input); var javaMethodGenerics = collectMethodGenerics(currentClass, generics.javaGenerics(), javaGenerics, input);
var txMethodGenerics = collectMethodGenerics(currentClass, generics.txGenerics(), txGenerics, input); var txMethodGenerics = collectMethodGenerics(currentClass, generics.txGenerics(), txGenerics, input);
result.add(new TargetConstructor(input.modifier, javaMethodGenerics, txMethodGenerics, params, txParams, convert(input.block, generics.javaGenerics), fieldInitializer)); result.add(new TargetConstructor(input.modifier, javaMethodGenerics, txMethodGenerics, params, txParams, convert(input.block), fieldInitializer));
parameterSet.add(params); parameterSet.add(params);
} }
} }
@@ -443,13 +447,10 @@ public class ASTToTargetAST {
return result; return result;
} }
private static int counter = 0;
private String encodeName(String name, TargetMethod.Signature params) { private String encodeName(String name, TargetMethod.Signature params) {
var res = new StringBuilder(); var res = new StringBuilder();
res.append(name); res.append(name);
res.append('$'); res.append('$');
res.append(counter++);
res.append('$');
for (var param : params.parameters()) { for (var param : params.parameters()) {
encodeName(param.pattern(), res); encodeName(param.pattern(), res);
} }
@@ -525,14 +526,12 @@ public class ASTToTargetAST {
var j = 0; var j = 0;
for (var param : m.signature().parameters()) { for (var param : m.signature().parameters()) {
if (j >= patternsRec.size()) return true; if (j >= patternsRec.size()) return true;
if (!patternsRec.get(j).equals(param.pattern())) return false; if (!patternsRec.get(j).type().equals(param.pattern().type())) return false;
j++; j++;
} }
return true; return true;
}).toList(); }).toList();
//System.out.println(offset + " -> " + lastPattern);
//candidates.forEach(m -> System.out.println(m.getSignature()));
var caseBody = generatePatternOverloadsRec(offset + 1, expr, params, patternsRec, candidates, classType); var caseBody = generatePatternOverloadsRec(offset + 1, expr, params, patternsRec, candidates, classType);
var body = new TargetBlock(List.of(caseBody)); var body = new TargetBlock(List.of(caseBody));
var case_ = new TargetSwitch.Case(List.of(lastPattern), body); var case_ = new TargetSwitch.Case(List.of(lastPattern), body);
@@ -543,14 +542,19 @@ public class ASTToTargetAST {
return new TargetSwitch(switchExpr, cases, null, true); return new TargetSwitch(switchExpr, cases, null, true);
} }
private List<TargetMethod> generatePatternOverloads(ClassOrInterface clazz, List<MethodWithTphs> overloadedMethods) { private List<TargetMethod> generatePatternOverloads(ClassOrInterface clazz, List<TargetMethod> overloadedMethods) {
if (overloadedMethods.isEmpty()) return List.of(); if (overloadedMethods.size() <= 1) return overloadedMethods;
// Check if we have a pattern as a parameter // Check if we have a pattern as a parameter
var firstMethod = convert(overloadedMethods.getFirst(), overloadedMethods.getFirst().generics.javaGenerics); var firstMethod = overloadedMethods.getFirst();
if (overloadedMethods.size() == 1) return List.of(firstMethod); var secondMethod = overloadedMethods.get(1);
var secondMethod = convert(overloadedMethods.get(1), overloadedMethods.get(1).generics.javaGenerics); if (firstMethod.signature().parameters().stream().noneMatch(mp -> mp.pattern() instanceof TargetComplexPattern)) return overloadedMethods;
if (firstMethod.signature().parameters().stream().noneMatch(mp -> mp.pattern() instanceof TargetComplexPattern)) // Rename existing methods
return overloadedMethods.stream().map(m -> convert(m, m.generics.javaGenerics)).toList();
var res = new ArrayList<TargetMethod>();
for (var method : overloadedMethods) {
var name = encodeName(method.name(), method.signature());
res.add(new TargetMethod(method.access(), name, method.block(), method.signature(), method.txSignature()));
}
var signatureParams = new ArrayList<MethodParameter>(); var signatureParams = new ArrayList<MethodParameter>();
for (var i = 0; i < firstMethod.signature().parameters().size(); i++) { for (var i = 0; i < firstMethod.signature().parameters().size(); i++) {
@@ -559,7 +563,7 @@ public class ASTToTargetAST {
var t2 = secondMethod.signature().parameters().get(i).pattern().type(); var t2 = secondMethod.signature().parameters().get(i).pattern().type();
var commonSubTypes = new HashSet<>(commonSuperInterfaceTypes(t1, t2)); var commonSubTypes = new HashSet<>(commonSuperInterfaceTypes(t1, t2));
for (var m : overloadedMethods.subList(2, overloadedMethods.size())) { for (var m : overloadedMethods.subList(2, overloadedMethods.size())) {
var t3 = m.signature().java.parameters().get(i).pattern().type(); var t3 = m.signature().parameters().get(i).pattern().type();
commonSubTypes.retainAll(commonSuperInterfaceTypes(t1, t3)); commonSubTypes.retainAll(commonSuperInterfaceTypes(t1, t3));
} }
if (commonSubTypes.size() > 1) throw new DebugException("Invalid overload"); if (commonSubTypes.size() > 1) throw new DebugException("Invalid overload");
@@ -574,28 +578,9 @@ public class ASTToTargetAST {
signatureParams.add(new MethodParameter(new TargetRefType(superType.getClassName().toString()), name)); signatureParams.add(new MethodParameter(new TargetRefType(superType.getClassName().toString()), name));
} }
// Rename existing methods
var res = new ArrayList<TargetMethod>();
for (var method : overloadedMethods) {
var name = encodeName(method.method.name, method.signature.java);
var generics = new OverlayGenerics(method.generics.javaGenerics, this);
var m = overloadedMethods.getFirst();
var params = m.method.getParameterList().getFormalparalist();
for (var i = 0; i < params.size(); i++) {
var param = params.get(i);
if (param.getType() instanceof TypePlaceholder tph) {
generics.addOverlay(tph, signatureParams.get(i).pattern().type());
}
}
var tMethod = convert(method, generics);
res.add(new TargetMethod(tMethod.access(), name, tMethod.block(), tMethod.signature(), tMethod.txSignature()));
}
var commonSubTypes = new HashSet<>(commonSuperInterfaceTypes(firstMethod.signature().returnType(), secondMethod.signature().returnType())); var commonSubTypes = new HashSet<>(commonSuperInterfaceTypes(firstMethod.signature().returnType(), secondMethod.signature().returnType()));
for (var m : overloadedMethods.subList(2, overloadedMethods.size())) { for (var m : overloadedMethods.subList(2, overloadedMethods.size())) {
commonSubTypes.retainAll(commonSuperInterfaceTypes(firstMethod.signature().returnType(), m.signature().java.returnType())); commonSubTypes.retainAll(commonSuperInterfaceTypes(firstMethod.signature().returnType(), m.signature().returnType()));
} }
var returnType = commonSubTypes.isEmpty() ? TargetType.Object : new TargetRefType(commonSubTypes.iterator().next().getClassName().toString()); var returnType = commonSubTypes.isEmpty() ? TargetType.Object : new TargetRefType(commonSubTypes.iterator().next().getClassName().toString());
@@ -616,7 +601,7 @@ public class ASTToTargetAST {
} }
private Expression makeRecordSwitch(RefTypeOrTPHOrWildcardOrGeneric returnType, ParameterList params, List<Method> overloadedMethods) { private Expression makeRecordSwitch(RefTypeOrTPHOrWildcardOrGeneric returnType, ParameterList params, List<Method> overloadedMethods) {
var param = params.getFormalparalist().getFirst(); var param = params.getFormalparalist().get(0);
assert param instanceof RecordPattern; // TODO assert param instanceof RecordPattern; // TODO
var cases = new ArrayList<SwitchBlock>(); var cases = new ArrayList<SwitchBlock>();
@@ -636,7 +621,7 @@ public class ASTToTargetAST {
return swtch; return swtch;
} }
private Optional<Method> findSuperMethodToOverride(ClassOrInterface currentClass, String name, List<MethodParameter> params, IGenerics generics) { private Optional<Method> findSuperMethodToOverride(ClassOrInterface currentClass, String name, List<MethodParameter> params) {
var superClass = compiler.getClass(currentClass.getSuperClass().getName()); var superClass = compiler.getClass(currentClass.getSuperClass().getName());
var methodStream = superClass.getMethods().stream(); var methodStream = superClass.getMethods().stream();
for (var superInterface : currentClass.getSuperInterfaces()) { for (var superInterface : currentClass.getSuperInterfaces()) {
@@ -649,106 +634,115 @@ public class ASTToTargetAST {
if (sParams.getFormalparalist().size() != params.size()) return false; if (sParams.getFormalparalist().size() != params.size()) return false;
for (var i = 0; i < params.size(); i++) { for (var i = 0; i < params.size(); i++) {
var a = TargetType.toPrimitive(params.get(i).pattern().type()); var a = TargetType.toPrimitive(params.get(i).pattern().type());
var b = convert(sParams.getFormalparalist().get(i).getType(), generics); var b = convert(sParams.getFormalparalist().get(i).getType());
if (!Objects.equals(a, b)) return false; if (!Objects.equals(a, b)) return false;
} }
return true; return true;
}).findFirst(); }).findFirst();
} }
record MethodWithTphs(Method method, Generics generics, Signature signature) { record MethodWithTphs(TargetMethod method, Generics generics, List<SignaturePairTarget> args) {
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) return true; if (this == o) return true;
if (!(o instanceof MethodWithTphs that)) return false; if (!(o instanceof MethodWithTphs that)) return false;
return Objects.equals(method, that.method) && Objects.equals(signature, that.signature); return Objects.equals(method, that.method) && Objects.equals(args, that.args);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(method, signature); return Objects.hash(method, args);
} }
} }
private TargetMethod convert(MethodWithTphs mtph, IGenerics generics) {
return new TargetMethod(mtph.method.modifier, mtph.method.name, convert(mtph.method.block, generics), mtph.signature.java(), mtph.signature.tx());
}
record Signature(TargetMethod.Signature java, TargetMethod.Signature tx, Generics generics) {} record Signature(TargetMethod.Signature java, TargetMethod.Signature tx, Generics generics) {}
private List<MethodWithTphs> convert(ClassOrInterface currentClass, Method method) { private List<MethodWithTphs> convert(ClassOrInterface currentClass, Method method) {
generics = all.getFirst();
List<MethodWithTphs> result = new ArrayList<>(); List<MethodWithTphs> result = new ArrayList<>();
this.currentMethod = method; this.currentMethod = method;
List<Signature> signatures = new ArrayList<>(); List<Signature> signatures = new ArrayList<>();
for (var generics : all) { HashMap<TargetMethod.Signature, List<Generics>> collectedGenerics = new HashMap<>();
var javaGenerics = generics.javaGenerics.generics(currentClass, method);
var txGenerics = generics.txGenerics.generics(currentClass, method); for (var s : all) {
List<MethodParameter> params = convert(method.getParameterList(), generics.javaGenerics); generics = s;
var returnType = convert(method.getReturnType(), generics.javaGenerics); var javaGenerics = this.generics.javaGenerics.generics(currentClass, method);
var superMethod = findSuperMethodToOverride(currentClass, method.getName(), params, generics.javaGenerics); var txGenerics = this.generics.txGenerics.generics(currentClass, method);
List<MethodParameter> params = convert(method.getParameterList(), this.generics.javaGenerics);
var returnType = convert(method.getReturnType(), this.generics.javaGenerics);
var superMethod = findSuperMethodToOverride(currentClass, method.getName(), params);
if (superMethod.isPresent()) { if (superMethod.isPresent()) {
// If we find a super method to override, use its parameters and return types // If we find a super method to override, use its parameters and return types
var newReturnType = convert(superMethod.get().getReturnType(), generics.javaGenerics); var newReturnType = convert(superMethod.get().getReturnType(), this.generics.javaGenerics);
if (newReturnType instanceof TargetPrimitiveType && TargetType.toPrimitive(returnType).equals(newReturnType)) { if (newReturnType instanceof TargetPrimitiveType && TargetType.toPrimitive(returnType).equals(newReturnType)) {
returnType = newReturnType; returnType = newReturnType;
params = convert(superMethod.get().getParameterList(), method.getParameterList(), generics.javaGenerics); params = convert(superMethod.get().getParameterList(), method.getParameterList(), this.generics.javaGenerics);
} }
} }
List<MethodParameter> txParams = convert(method.getParameterList(), generics.txGenerics); List<MethodParameter> txParams = convert(method.getParameterList(), this.generics.txGenerics);
var javaMethodGenerics = collectMethodGenerics(currentClass, generics.javaGenerics(), javaGenerics, method); var javaMethodGenerics = collectMethodGenerics(currentClass, generics.javaGenerics(), javaGenerics, method);
var txMethodGenerics = collectMethodGenerics(currentClass, generics.txGenerics(), txGenerics, method); var txMethodGenerics = collectMethodGenerics(currentClass, generics.txGenerics(), txGenerics, method);
var javaSignature = new TargetMethod.Signature(javaMethodGenerics, params, returnType); var javaSignature = new TargetMethod.Signature(javaMethodGenerics, params, returnType);
var txSignature = new TargetMethod.Signature(txMethodGenerics, txParams, convert(method.getReturnType(), generics.txGenerics)); var txSignature = new TargetMethod.Signature(txMethodGenerics, txParams, convert(method.getReturnType(), this.generics.txGenerics));
signatures.add(new Signature(javaSignature, txSignature, generics)); signatures.add(new Signature(javaSignature, txSignature, generics));
var listOfGenerics = collectedGenerics.getOrDefault(javaSignature, new ArrayList<>());
listOfGenerics.add(generics);
collectedGenerics.put(javaSignature, listOfGenerics);
} }
for (var signature : signatures) { for (var signature : signatures) {
result.add(new MethodWithTphs(method, signature.generics, signature)); generics = signature.generics;
currentMethodOverloads = collectedGenerics.get(signature.java);
var newMethod = new TargetMethod(method.modifier, method.name, convert(method.block), signature.java, signature.tx);
var concreteParams = tphsInMethods.getOrDefault(method, new HashSet<>()).stream().map(sig -> new SignaturePairTarget(convert(sig.signature), convert(sig.parameter))).toList();
result.add(new MethodWithTphs(newMethod, generics, concreteParams));
} }
return result; return result;
} }
private List<MethodParameter> convert(ParameterList superList, ParameterList paraList, IGenerics generics) { private List<MethodParameter> convert(ParameterList superList, ParameterList paraList, JavaGenerics generics) {
var list = new ArrayList<MethodParameter>(); var list = new ArrayList<MethodParameter>();
for (var i = 0; i < paraList.getFormalparalist().size(); i++) { for (var i = 0; i < paraList.getFormalparalist().size(); i++) {
var param = paraList.getParameterAt(i); var param = paraList.getParameterAt(i);
var pattern = (TargetPattern) convert(param, generics); var pattern = (TargetPattern) convert(param);
if (pattern instanceof TargetComplexPattern) pattern = pattern.withName("__var" + i); if (pattern instanceof TargetComplexPattern) pattern = pattern.withName("__var" + i);
list.add(new MethodParameter(pattern).withType(convert(superList.getParameterAt(i).getType(), generics))); list.add(new MethodParameter(pattern).withType(convert(superList.getParameterAt(i).getType(), generics)));
} }
return list; return list;
} }
protected TargetSwitch.Case convert(SwitchBlock block, IGenerics generics) { protected TargetSwitch.Case convert(SwitchBlock block) {
return new TargetSwitch.Case(block.getLabels().stream().map(s -> convert(s, generics)).toList(), convert((Block) block, generics), block.isExpression); return new TargetSwitch.Case(block.getLabels().stream().map(this::convert).toList(), convert((Block) block), block.isExpression);
} }
protected TargetBlock convert(Block block, IGenerics generics) { protected TargetBlock convert(Block block) {
if (block == null) return null; if (block == null) return null;
return new TargetBlock(block.statements.stream().map(s -> convert(s, generics)).toList()); return new TargetBlock(block.statements.stream().map(this::convert).toList());
} }
protected TargetBlock convertWrapInBlock(Expression expression, IGenerics generics) { protected TargetBlock convertWrapInBlock(Expression expression) {
var res = convert(expression, generics); var res = convert(expression);
if (!(res instanceof TargetBlock)) if (!(res instanceof TargetBlock))
return new TargetBlock(List.of(res)); return new TargetBlock(List.of(res));
return (TargetBlock) res; return (TargetBlock) res;
} }
protected TargetExpression convert(Expression expr, IGenerics generics) { protected TargetExpression convert(Expression expr) {
var converter = new StatementToTargetExpression(this, generics); var converter = new StatementToTargetExpression(this);
expr.accept(converter); expr.accept(converter);
return converter.result; return converter.result;
} }
private TargetField convert(Field input, IGenerics generics) { private TargetField convert(Field input) {
return new TargetField(input.modifier, convert(input.getType(), generics), input.getName()); return new TargetField(input.modifier, convert(input.getType(), generics.javaGenerics), input.getName());
} }
private final Map<String, FunNGenerator.GenericParameters> usedFunN = new HashMap<>(); private final Map<String, FunNGenerator.GenericParameters> usedFunN = new HashMap<>();
@@ -756,6 +750,9 @@ public class ASTToTargetAST {
public Map<String, byte[]> auxiliaries = new HashMap<>(); public Map<String, byte[]> auxiliaries = new HashMap<>();
public TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input) {
return convert(input, generics.javaGenerics);
}
private static void collectArguments(TargetSpecializedType tspec, List<TargetType> newParams) { private static void collectArguments(TargetSpecializedType tspec, List<TargetType> newParams) {
for (var i = 0; i < tspec.params().size(); i++) { for (var i = 0; i < tspec.params().size(); i++) {
@@ -785,15 +782,7 @@ public class ASTToTargetAST {
return TargetFunNType.fromParams(params, filteredParams, gep.getReturnType() != null ? 1 : 0); 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) { 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 testClass = compiler.getClass(new JavaClassName(test.name()));
var otherClass = compiler.getClass(new JavaClassName(other.name())); var otherClass = compiler.getClass(new JavaClassName(other.name()));
if (testClass == null) return false; if (testClass == null) return false;
@@ -830,17 +819,19 @@ public class ASTToTargetAST {
.toList(); .toList();
var code = FunNGenerator.generateSpecializedBytecode(gep, superInterfaces); 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); auxiliaries.put(entry.getKey(), code);
} }
} }
// FIXME This method shouldn't be used protected TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input, GenerateGenerics generics) {
@Deprecated
public TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input) {
return convert(input, all.getFirst().javaGenerics);
}
public TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input, IGenerics generics) {
return input.acceptTV(new TypeVisitor<>() { return input.acceptTV(new TypeVisitor<>() {
@Override @Override
public TargetType visit(RefType refType) { public TargetType visit(RefType refType) {
@@ -866,7 +857,7 @@ public class ASTToTargetAST {
classLoader.findClass(superClassName); classLoader.findClass(superClassName);
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
try { try {
classLoader.loadClass(superClassName, code); classLoader.loadClass(code);
} catch (LinkageError ignored) {} } catch (LinkageError ignored) {}
} }
auxiliaries.put(superClassName, code); auxiliaries.put(superClassName, code);

View File

@@ -1,10 +1,12 @@
package de.dhbwstuttgart.target.generate; package de.dhbwstuttgart.target.generate;
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.syntaxtree.*; import de.dhbwstuttgart.syntaxtree.*;
import de.dhbwstuttgart.syntaxtree.statement.*; import de.dhbwstuttgart.syntaxtree.statement.*;
import de.dhbwstuttgart.syntaxtree.type.*; import de.dhbwstuttgart.syntaxtree.type.*;
import de.dhbwstuttgart.syntaxtree.type.Void; import de.dhbwstuttgart.syntaxtree.type.Void;
import de.dhbwstuttgart.target.Target;
import de.dhbwstuttgart.target.tree.type.TargetGenericType; import de.dhbwstuttgart.target.tree.type.TargetGenericType;
import de.dhbwstuttgart.target.tree.type.TargetType; import de.dhbwstuttgart.target.tree.type.TargetType;
import de.dhbwstuttgart.typeinference.result.PairTPHEqualTPH; import de.dhbwstuttgart.typeinference.result.PairTPHEqualTPH;
@@ -16,7 +18,7 @@ import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
public abstract class GenerateGenerics implements IGenerics { public abstract class GenerateGenerics {
private final ASTToTargetAST astToTargetAST; private final ASTToTargetAST astToTargetAST;
@@ -138,19 +140,35 @@ public abstract class GenerateGenerics implements IGenerics {
this.astToTargetAST = astToTargetAST; this.astToTargetAST = astToTargetAST;
for (var constraint : constraints.results) { for (var constraint : constraints.results) {
if (constraint instanceof PairTPHsmallerTPH p) { if (constraint instanceof PairTPHsmallerTPH p) {
System.out.println(p.left + " " + p.left.getVariance()); Target.logger.info(p.left + " " + p.left.getVariance());
simplifiedConstraints.add(new PairLT(new TPH(p.left), new TPH(p.right))); simplifiedConstraints.add(new PairLT(new TPH(p.left), new TPH(p.right)));
} else if (constraint instanceof PairTPHEqualTPH p) { } else if (constraint instanceof PairTPHEqualTPH p) {
equality.put(p.getLeft(), p.getRight()); equality.put(p.getLeft(), p.getRight());
} else if (constraint instanceof PairTPHequalRefTypeOrWildcardType p) { } else if (constraint instanceof PairTPHequalRefTypeOrWildcardType p) {
System.out.println(p.left + " = " + p.right); Target.logger.info(p.left + " = " + p.right);
concreteTypes.put(new TPH(p.left), p.right); concreteTypes.put(new TPH(p.left), p.right);
} }
} }
System.out.println("Simplified constraints: " + simplifiedConstraints); Target.logger.info("Simplified constraints: " + simplifiedConstraints);
} }
/*public record GenericsState(Map<TPH, RefTypeOrTPHOrWildcardOrGeneric> concreteTypes, Map<TypePlaceholder, TypePlaceholder> equality) {}
public GenericsState store() {
return new GenericsState(new HashMap<>(concreteTypes), new HashMap<>(equality));
}
public void restore(GenericsState state) {
this.concreteTypes = state.concreteTypes;
this.equality = state.equality;
}
public void addOverlay(TypePlaceholder from, RefTypeOrTPHOrWildcardOrGeneric to) {
if (to instanceof TypePlaceholder t) equality.put(from, t);
else if (to instanceof RefType t) concreteTypes.put(new TPH(from), t);
}*/
Set<TPH> findTypeVariables(ParameterList params) { Set<TPH> findTypeVariables(ParameterList params) {
var res = new HashSet<TPH>(); var res = new HashSet<TPH>();
for (var param : params.getFormalparalist()) { for (var param : params.getFormalparalist()) {
@@ -232,7 +250,7 @@ public abstract class GenerateGenerics implements IGenerics {
equality.put(entry.getKey(), to); equality.put(entry.getKey(), to);
} }
} }
System.out.println(from + " -> " + to + " " + from.getVariance()); Target.logger.info(from + " -> " + to + " " + from.getVariance());
//from.setVariance(to.getVariance()); //from.setVariance(to.getVariance());
equality.put(from, to); equality.put(from, to);
referenced.remove(new TPH(from)); referenced.remove(new TPH(from));
@@ -266,7 +284,6 @@ public abstract class GenerateGenerics implements IGenerics {
Set<Pair> result Set<Pair> result
) { ) {
var userDefinedGenericsOfClass = astToTargetAST.userDefinedGenerics.get(owner); var userDefinedGenericsOfClass = astToTargetAST.userDefinedGenerics.get(owner);
var generics = this;
// Type variables with bounds that are also type variables of the method // Type variables with bounds that are also type variables of the method
for (var typeVariable : new HashSet<>(typeVariables)) { for (var typeVariable : new HashSet<>(typeVariables)) {
@@ -302,7 +319,7 @@ public abstract class GenerateGenerics implements IGenerics {
Set<TPH> T2s = new HashSet<>(); Set<TPH> T2s = new HashSet<>();
findTphs(superType, T2s); findTphs(superType, T2s);
System.out.println("T1s: " + T1s + " T2s: " + T2s); Target.logger.info("T1s: " + T1s + " T2s: " + T2s);
//Ende //Ende
superType = methodCall.receiverType; superType = methodCall.receiverType;
@@ -314,10 +331,10 @@ public abstract class GenerateGenerics implements IGenerics {
if (methodCall.receiver instanceof ExpressionReceiver expressionReceiver) { if (methodCall.receiver instanceof ExpressionReceiver expressionReceiver) {
if (expressionReceiver.expr instanceof This) { if (expressionReceiver.expr instanceof This) {
var optMethod = astToTargetAST.findMethod(owner, methodCall.name, methodCall.signatureArguments().stream().map(sa -> astToTargetAST.convert(sa, generics)).toList()); var optMethod = astToTargetAST.findMethod(owner, methodCall.name, methodCall.signatureArguments().stream().map(astToTargetAST::convert).toList());
if (optMethod.isEmpty()) return; if (optMethod.isEmpty()) return;
var method2 = optMethod.get(); var method2 = optMethod.get();
System.out.println("In: " + method.getName() + " Method: " + method2.getName()); Target.logger.info("In: " + method.getName() + " Method: " + method2.getName());
var generics = family(owner, method2); var generics = family(owner, method2);
// transitive and // transitive and
@@ -350,7 +367,7 @@ public abstract class GenerateGenerics implements IGenerics {
if (!T1s.contains(R1) || !T2s.contains(R2)) continue; if (!T1s.contains(R1) || !T2s.contains(R2)) continue;
var newPair = new PairLT(R1, R2); var newPair = new PairLT(R1, R2);
System.out.println("New pair: " + newPair); Target.logger.info("New pair: " + newPair);
newPairs.add(newPair); newPairs.add(newPair);
if (!containsRelation(result, newPair)) if (!containsRelation(result, newPair))
@@ -524,6 +541,8 @@ public abstract class GenerateGenerics implements IGenerics {
}); });
} }
abstract void generics(ClassOrInterface owner, Method method, Set<Pair> result, Set<TPH> javaTypeVariablesOfClass);
Set<Pair> family(ClassOrInterface owner, Method method) { Set<Pair> family(ClassOrInterface owner, Method method) {
Set<Pair> result = new HashSet<>(); Set<Pair> result = new HashSet<>();
if (familyOfMethods.containsKey(method)) if (familyOfMethods.containsKey(method))
@@ -547,11 +566,10 @@ public abstract class GenerateGenerics implements IGenerics {
return result; return result;
} }
@Override Set<Pair> generics(ClassOrInterface owner, Method method) {
public Set<Pair> generics(ClassOrInterface owner, Method method) {
if (computedGenericsOfMethods.containsKey(method)) { if (computedGenericsOfMethods.containsKey(method)) {
var cached = computedGenericsOfMethods.get(method); var cached = computedGenericsOfMethods.get(method);
System.out.println("Cached " + method.getName() + ": " + cached); Target.logger.info("Cached " + method.getName() + ": " + cached);
return cached; return cached;
} }
@@ -580,7 +598,7 @@ public abstract class GenerateGenerics implements IGenerics {
normalize(result, classGenerics, usedTphs); normalize(result, classGenerics, usedTphs);
System.out.println(this.getClass().getSimpleName() + " " + method.name + ": " + result); Target.logger.info(this.getClass().getSimpleName() + " " + method.name + ": " + result);
return result; return result;
} }
@@ -636,10 +654,8 @@ public abstract class GenerateGenerics implements IGenerics {
} }
abstract void generics(ClassOrInterface classOrInterface, Set<Pair> result, Set<TPH> referenced); abstract void generics(ClassOrInterface classOrInterface, Set<Pair> result, Set<TPH> referenced);
abstract void generics(ClassOrInterface owner, Method method, Set<Pair> result, Set<TPH> referenced);
@Override Set<Pair> generics(ClassOrInterface classOrInterface) {
public Set<Pair> generics(ClassOrInterface classOrInterface) {
if (computedGenericsOfClasses.containsKey(classOrInterface)) if (computedGenericsOfClasses.containsKey(classOrInterface))
return computedGenericsOfClasses.get(classOrInterface); return computedGenericsOfClasses.get(classOrInterface);
@@ -661,7 +677,7 @@ public abstract class GenerateGenerics implements IGenerics {
normalize(javaResult, null, referencedByClass); normalize(javaResult, null, referencedByClass);
System.out.println(this.getClass().getSimpleName() + " Class " + classOrInterface.getClassName().getClassName() + ": " + javaResult); Target.logger.info(this.getClass().getSimpleName() + " Class " + classOrInterface.getClassName().getClassName() + ": " + javaResult);
return javaResult; return javaResult;
} }
@@ -712,7 +728,7 @@ public abstract class GenerateGenerics implements IGenerics {
if (!added) break; if (!added) break;
} }
System.out.println(chain + " " + chain.stream().map(e -> e.resolve().getVariance()).toList()); Target.logger.info(chain + " " + chain.stream().map(e -> e.resolve().getVariance()).toList());
var variance = chain.get(0).resolve().getVariance(); var variance = chain.get(0).resolve().getVariance();
if (variance != 1) continue; if (variance != 1) continue;
var index = 0; var index = 0;
@@ -750,7 +766,7 @@ public abstract class GenerateGenerics implements IGenerics {
} }
for (var pair : elementsToAddToEquality) { for (var pair : elementsToAddToEquality) {
System.out.println(pair); Target.logger.info(pair);
addToEquality(pair.left, pair.right, referenced); addToEquality(pair.left, pair.right, referenced);
} }
} }
@@ -903,11 +919,11 @@ public abstract class GenerateGenerics implements IGenerics {
} }
} }
if (infima.size() > 1) { if (infima.size() > 1) {
System.out.println(infima); Target.logger.info(infima);
for (var pair : infima) { for (var pair : infima) {
var returnTypes = findTypeVariables(method.getReturnType()); var returnTypes = findTypeVariables(method.getReturnType());
var chain = findConnectionToReturnType(returnTypes, input, new HashSet<>(), pair.left); var chain = findConnectionToReturnType(returnTypes, input, new HashSet<>(), pair.left);
System.out.println("Find: " + pair.left + " " + chain); Target.logger.info("Find: " + pair.left + " " + chain);
chain.remove(pair.left); chain.remove(pair.left);
if (chain.size() > 0) { if (chain.size() > 0) {
for (var tph : chain) for (var tph : chain)
@@ -945,8 +961,8 @@ public abstract class GenerateGenerics implements IGenerics {
} }
} }
newTph.setVariance(variance); newTph.setVariance(variance);
System.out.println(infima + " " + infima.stream().map(i -> i.right.resolve().getVariance()).toList()); Target.logger.info(infima + " " + infima.stream().map(i -> i.right.resolve().getVariance()).toList());
System.out.println("Infima new TPH " + newTph + " variance " + variance); Target.logger.info("Infima new TPH " + newTph + " variance " + variance);
//referenced.add(newTph); //referenced.add(newTph);
addToPairs(input, new PairLT(left, new TPH(newTph))); addToPairs(input, new PairLT(left, new TPH(newTph)));
@@ -974,13 +990,7 @@ public abstract class GenerateGenerics implements IGenerics {
} while (foundInfima); } while (foundInfima);
} }
@Override RefTypeOrTPHOrWildcardOrGeneric getType(RefTypeOrTPHOrWildcardOrGeneric type) {
public TypePlaceholder getEqualType(TypePlaceholder tph) {
return this.equality.getOrDefault(tph, tph);
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric getType(RefTypeOrTPHOrWildcardOrGeneric type) {
if (type instanceof TypePlaceholder tph) { if (type instanceof TypePlaceholder tph) {
if (equality.containsKey(tph)) { if (equality.containsKey(tph)) {
return getType(equality.get(tph)); return getType(equality.get(tph));
@@ -990,8 +1000,7 @@ public abstract class GenerateGenerics implements IGenerics {
return type; return type;
} }
@Override TargetType getTargetType(RefTypeOrTPHOrWildcardOrGeneric in) {
public TargetType getTargetType(RefTypeOrTPHOrWildcardOrGeneric in) {
if (in instanceof TypePlaceholder tph) { if (in instanceof TypePlaceholder tph) {
if (equality.containsKey(tph)) { if (equality.containsKey(tph)) {
return getTargetType(equality.get(tph)); return getTargetType(equality.get(tph));

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -9,13 +9,8 @@ import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
import de.dhbwstuttgart.syntaxtree.factory.NameGenerator; import de.dhbwstuttgart.syntaxtree.factory.NameGenerator;
import de.dhbwstuttgart.syntaxtree.type.GenericRefType; import de.dhbwstuttgart.syntaxtree.type.GenericRefType;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import org.antlr.v4.runtime.Token;
import javax.swing.text.html.Option;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;

View File

@@ -19,11 +19,11 @@ public class MethodAssumption extends Assumption{
private ClassOrInterface receiver; private ClassOrInterface receiver;
private RefTypeOrTPHOrWildcardOrGeneric retType; private RefTypeOrTPHOrWildcardOrGeneric retType;
List<? extends RefTypeOrTPHOrWildcardOrGeneric> params; List<? extends RefTypeOrTPHOrWildcardOrGeneric> params;
private final Boolean isInherited; private final boolean isInherited;
private final Boolean isOverridden; private final boolean isOverridden;
public MethodAssumption(ClassOrInterface receiver, RefTypeOrTPHOrWildcardOrGeneric retType, public MethodAssumption(ClassOrInterface receiver, RefTypeOrTPHOrWildcardOrGeneric retType,
List<? extends RefTypeOrTPHOrWildcardOrGeneric> params, TypeScope scope, Boolean isInherited, Boolean isOverridden){ List<? extends RefTypeOrTPHOrWildcardOrGeneric> params, TypeScope scope, boolean isInherited, boolean isOverridden){
super(scope); super(scope);
this.receiver = receiver; this.receiver = receiver;
this.retType = retType; this.retType = retType;
@@ -73,11 +73,11 @@ public class MethodAssumption extends Assumption{
return TYPEStmt.getReceiverType(receiver, resolver); return TYPEStmt.getReceiverType(receiver, resolver);
} }
public Boolean isInherited() { public boolean isInherited() {
return isInherited; return isInherited;
} }
public Boolean isOverridden() { public boolean isOverridden() {
return isOverridden; return isOverridden;
} }
} }

View File

@@ -1,15 +1,29 @@
package de.dhbwstuttgart.typeinference.constraints; package de.dhbwstuttgart.typeinference.constraints;
import de.dhbwstuttgart.server.packet.dataContainers.ISerializableData;
import de.dhbwstuttgart.server.packet.dataContainers.KeyStorage;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.ISerialNode;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialList;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialMap;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialUUID;
import de.dhbwstuttgart.typeinference.unify.UnifyContext;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
import java.util.Collection; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
public class Constraint<A> extends HashSet<A> implements Comparable<Constraint<A>> { public class Constraint<A extends IConstraintElement> extends HashSet<A> implements ISerializableData {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private Boolean isInherited = false;//wird beides nur für die Method-Constraints benoetigt private boolean isInherited = false;//wird beides nur für die Method-Constraints benoetigt
private Boolean isImplemented = false; private boolean isImplemented = false;
/* /*
* wird verwendet um bei der Codegenerierung die richtige Methoden - Signatur * wird verwendet um bei der Codegenerierung die richtige Methoden - Signatur
@@ -23,27 +37,31 @@ public class Constraint<A> extends HashSet<A> implements Comparable<Constraint<A
super(); super();
} }
public Constraint(Boolean isInherited, Boolean isImplemented) { public Constraint(int initialCapacity) {
super(initialCapacity);
}
public Constraint(boolean isInherited, boolean isImplemented) {
this.isInherited = isInherited; this.isInherited = isInherited;
this.isImplemented = isImplemented; this.isImplemented = isImplemented;
} }
public Constraint(Boolean isInherited, Boolean isImplemented, Constraint<A> extendConstraint, Set<A> methodSignatureConstraint) { public Constraint(boolean isInherited, boolean isImplemented, Constraint<A> extendConstraint, Set<A> methodSignatureConstraint) {
this.isInherited = isInherited; this.isInherited = isInherited;
this.isImplemented = isImplemented; this.isImplemented = isImplemented;
this.extendConstraint = extendConstraint; this.extendConstraint = extendConstraint;
this.methodSignatureConstraint = methodSignatureConstraint; this.methodSignatureConstraint = methodSignatureConstraint;
} }
public void setIsInherited(Boolean isInherited) { public void setIsInherited(boolean isInherited) {
this.isInherited = isInherited; this.isInherited = isInherited;
} }
public Boolean isInherited() { public boolean isInherited() {
return isInherited; return isInherited;
} }
public Boolean isImplemented() { public boolean isImplemented() {
return isImplemented; return isImplemented;
} }
@@ -63,19 +81,91 @@ public class Constraint<A> extends HashSet<A> implements Comparable<Constraint<A
methodSignatureConstraint = c; methodSignatureConstraint = c;
} }
public <B extends IConstraintElement> Constraint<B> createdMapped(Function<A,B> mapper) {
Constraint<B> result = new Constraint<>(this.size());
for (A element : this) {
result.add(mapper.apply(element));
}
return result;
}
public String toString() { public String toString() {
return super.toString() + "\nisInherited = " + isInherited + " isOveridden = " + isImplemented return super.toString() + "\nisInherited = " + isInherited
+ methodSignatureConstraint + " isOveridden = " + isImplemented
+ " msc[" + methodSignatureConstraint.size() + "] = " + methodSignatureConstraint
//" + extendsContraint: " + (extendConstraint != null ? extendConstraint.toStringBase() : "null" ) //" + extendsContraint: " + (extendConstraint != null ? extendConstraint.toStringBase() : "null" )
+ "\n" ; + "\n";
} }
public String toStringBase() { public String toStringBase() {
return super.toString(); return super.toString();
} }
private String serialUUID = null;
@Override @Override
public int compareTo(Constraint<A> o) { public SerialUUID toSerial(KeyStorage keyStorage) {
return this.toString().compareTo(o.toString()); final String uuid = serialUUID == null ? keyStorage.getIdentifier() : serialUUID;
if (serialUUID == null) serialUUID = uuid;
if (!keyStorage.isAlreadySerialized(uuid)) {
SerialMap serialized = new SerialMap();
keyStorage.putSerialized(uuid, serialized);
serialized.put("isInherited", isInherited);
serialized.put("isImplemented", isImplemented);
serialized.put("extendedConstraint", extendConstraint == null ? null :
extendConstraint.toSerial(keyStorage));
Function<A, ISerialNode> pairMapper = pair -> {
if (pair instanceof Pair simplePair) return simplePair.toSerial(keyStorage);
if (pair instanceof UnifyPair unifyPair) return unifyPair.toSerial(keyStorage);
throw new RuntimeException("No serialization is supported for type " + pair.getClass().getName());
};
serialized.put("methodSignatureConstraint", methodSignatureConstraint == null ? null :
SerialList.fromMapped(methodSignatureConstraint, pairMapper));
serialized.put("setElements", SerialList.fromMapped(this, pairMapper));
} }
// return only the unique key
return new SerialUUID(uuid);
}
public static <T extends IConstraintElement> Constraint<T> fromSerial(SerialUUID serialUUID, UnifyContext context, Class<T> target, KeyStorage keyStorage) {
String uuid = serialUUID.uuid;
if (!keyStorage.isAlreadyUnserialized(uuid)) {
Constraint<T> constraint = new Constraint<>();
// immediately add the object to the context to prevent infinite recursion
keyStorage.putUnserialized(uuid, constraint);
// retrieve the serialized data und start unserializing it
SerialMap data = keyStorage.getSerialized(uuid);
constraint.isInherited = data.getValue("isInherited").getOf(Boolean.class);
constraint.isImplemented = data.getValue("isImplemented").getOf(Boolean.class);
constraint.extendConstraint = Optional.ofNullable(data.getUUIDOrNull("extendedConstraint"))
.map(v -> Constraint.fromSerial(v, context, target, keyStorage))
.orElse(null);
// to convert the maps back to elements, we sadly have to do some assumptions about the generic types...
Function<ISerialNode, T> pairUnmapper = pairData -> {
if (target == Pair.class && pairData instanceof SerialMap pairMap) {
return (T) Pair.fromSerial(pairMap, context);
}
if (target == UnifyPair.class && pairData instanceof SerialUUID pairUUID) {
return (T) UnifyPair.fromSerial(pairUUID, context, keyStorage);
}
throw new RuntimeException("No serialization is supported for target type " + target.getName());
};
constraint.methodSignatureConstraint =
Optional.ofNullable(data.getListOrNull("methodSignatureConstraint"))
.map(l -> l.stream().map(pairUnmapper).collect(Collectors.toSet()))
.orElse(null);
constraint.addAll(
data.getList("setElements")
.stream().map(pairUnmapper).toList());
}
return keyStorage.getUnserialized(uuid, Constraint.class);
}
} }

View File

@@ -1,21 +1,25 @@
package de.dhbwstuttgart.typeinference.constraints; package de.dhbwstuttgart.typeinference.constraints;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.server.packet.dataContainers.ISerializableData;
import de.dhbwstuttgart.server.packet.dataContainers.KeyStorage;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialList;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialMap;
import de.dhbwstuttgart.typeinference.unify.GuavaSetOperations; import de.dhbwstuttgart.typeinference.unify.GuavaSetOperations;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; import de.dhbwstuttgart.typeinference.unify.UnifyContext;
import de.dhbwstuttgart.typeinference.unify.model.FiniteClosure;
import java.util.*; import java.util.*;
import java.util.function.BinaryOperator; import java.util.function.BinaryOperator;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class ConstraintSet<A> { public class ConstraintSet<A extends IConstraintElement> implements ISerializableData {
Constraint<A> undConstraints = new Constraint<>(); Constraint<A> undConstraints = new Constraint<>();
List<Set<Constraint<A>>> oderConstraints = new ArrayList<>(); List<Set<Constraint<A>>> oderConstraints = new ArrayList<>();
public void addUndConstraint(A p){ public void addUndConstraint(A p) {
undConstraints.add(p); undConstraints.add(p);
} }
@@ -23,11 +27,11 @@ public class ConstraintSet<A> {
oderConstraints.add(methodConstraints); oderConstraints.add(methodConstraints);
} }
public void addAllUndConstraint(Constraint<A> allUndConstraints){ public void addAllUndConstraint(Constraint<A> allUndConstraints) {
undConstraints.addAll(allUndConstraints); undConstraints.addAll(allUndConstraints);
} }
public void addAllOderConstraint(List<Set<Constraint<A>>> allOderConstraints){ public void addAllOderConstraint(List<Set<Constraint<A>>> allOderConstraints) {
this.oderConstraints.addAll(allOderConstraints); this.oderConstraints.addAll(allOderConstraints);
} }
@@ -37,14 +41,27 @@ public class ConstraintSet<A> {
} }
@Override @Override
public String toString(){ public String toString() {
BinaryOperator<String> b = (x,y) -> x+y; BinaryOperator<String> b = (x, y) -> x + y;
return "\nUND:" + this.undConstraints.toString() + "\n" + return "\nUND:\n" + this.undConstraints.toString() +
"ODER:" + this.oderConstraints.stream().reduce("", (x,y) -> x.toString()+ "\n" +y, b); "ODER:" + this.oderConstraints.stream().reduce("", (x, y) -> x + "\n\t" + y, b) +
"\n";
//cartesianProduct().toString(); //cartesianProduct().toString();
} }
public Set<List<Constraint<A>>> cartesianProduct(){ @Override
public boolean equals(Object obj) {
if (!(obj instanceof ConstraintSet<?> other)) return false;
return Objects.equals(undConstraints, other.undConstraints)
&& Objects.equals(oderConstraints, other.oderConstraints);
}
@Override
public int hashCode() {
return Objects.hash(undConstraints, oderConstraints);
}
public Set<List<Constraint<A>>> cartesianProduct() {
Set<Constraint<A>> toAdd = new HashSet<>(); Set<Constraint<A>> toAdd = new HashSet<>();
toAdd.add(undConstraints); toAdd.add(undConstraints);
List<Set<Constraint<A>>> allConstraints = new ArrayList<>(); List<Set<Constraint<A>>> allConstraints = new ArrayList<>();
@@ -53,8 +70,8 @@ public class ConstraintSet<A> {
return new GuavaSetOperations().cartesianProduct(allConstraints); return new GuavaSetOperations().cartesianProduct(allConstraints);
} }
public <B> ConstraintSet<B> map(Function<? super A, ? extends B> o) { public <B extends IConstraintElement> ConstraintSet<B> map(Function<? super A, ? extends B> o) {
Hashtable<Constraint<A>,Constraint<B>> CSA2CSB = new Hashtable<>(); Hashtable<Constraint<A>, Constraint<B>> CSA2CSB = new Hashtable<>();
ConstraintSet<B> ret = new ConstraintSet<>(); ConstraintSet<B> ret = new ConstraintSet<>();
ret.undConstraints = undConstraints.stream().map(o).collect(Collectors.toCollection(Constraint<B>::new)); ret.undConstraints = undConstraints.stream().map(o).collect(Collectors.toCollection(Constraint<B>::new));
List<Set<Constraint<B>>> newOder = new ArrayList<>(); List<Set<Constraint<B>>> newOder = new ArrayList<>();
@@ -69,14 +86,14 @@ public class ConstraintSet<A> {
} }
*/ */
for(Set<Constraint<A>> oderConstraint : oderConstraints){ for (Set<Constraint<A>> oderConstraint : oderConstraints) {
newOder.add( newOder.add(
oderConstraint.stream().map((Constraint<A> as) -> { oderConstraint.stream().map((Constraint<A> as) -> {
Constraint<B> newConst = as.stream() Constraint<B> newConst = as.stream()
.map(o) .map(o)
.collect(Collectors.toCollection(( .collect(Collectors.toCollection((
() -> new Constraint<B> (as.isInherited(), () -> new Constraint<B>(as.isInherited(),
as.isImplemented(), as.isImplemented(),
(as.getExtendConstraint() != null) (as.getExtendConstraint() != null)
? as.getExtendConstraint().stream().map(o).collect(Collectors.toCollection(Constraint::new)) ? as.getExtendConstraint().stream().map(o).collect(Collectors.toCollection(Constraint::new))
@@ -103,19 +120,18 @@ public class ConstraintSet<A> {
return ret; return ret;
} }
public void forEach (Consumer<? super A> c) { public void forEach(Consumer<? super A> c) {
undConstraints.stream().forEach(c); undConstraints.stream().forEach(c);
for(Set<Constraint<A>> oderConstraint : oderConstraints){ for (Set<Constraint<A>> oderConstraint : oderConstraints) {
oderConstraint.parallelStream().forEach((Constraint<A> as) -> oderConstraint.parallelStream().forEach((Constraint<A> as) ->
as.stream().forEach(c)); as.stream().forEach(c));
} }
} }
public Set<A> getAll () { public Set<A> getAll() {
Set<A> ret = new HashSet<>(); Set<A> ret = new HashSet<>(undConstraints);
ret.addAll(undConstraints); for (Set<Constraint<A>> oderConstraint : oderConstraints) {
for(Set<Constraint<A>> oderConstraint : oderConstraints){ oderConstraint.parallelStream().forEach(ret::addAll);
oderConstraint.parallelStream().forEach((Constraint<A> as) -> ret.addAll(as));
} }
return ret; return ret;
} }
@@ -127,4 +143,29 @@ public class ConstraintSet<A> {
public Set<A> getUndConstraints() { public Set<A> getUndConstraints() {
return undConstraints; return undConstraints;
} }
@Override
public SerialMap toSerial(KeyStorage keyStorage) {
SerialMap serialized = new SerialMap();
serialized.put("undConstraints", undConstraints.toSerial(keyStorage));
serialized.put("oderConstraints", SerialList.fromMapped(oderConstraints, oderConstraintSet ->
SerialList.fromMapped(oderConstraintSet, oderConstraint ->
oderConstraint.toSerial(keyStorage))
));
return serialized;
}
public static <T extends IConstraintElement> ConstraintSet<T> fromSerial(SerialMap data, UnifyContext context, Class<T> target, KeyStorage keyStorage) {
ConstraintSet<T> constraintSet = new ConstraintSet<>();
constraintSet.undConstraints = Constraint.fromSerial(data.getUUID("undConstraints"), context, target, keyStorage);
constraintSet.oderConstraints = data.getList("oderConstraints").assertListOfLists().stream()
.map(oderConstraintSetData -> oderConstraintSetData.assertListOfUUIDs().stream()
.map(oderConstraintData -> Constraint.fromSerial(oderConstraintData, context, target, keyStorage))
.collect(Collectors.toSet())
).toList();
return constraintSet;
}
} }

View File

@@ -0,0 +1,4 @@
package de.dhbwstuttgart.typeinference.constraints;
public interface IConstraintElement {
}

View File

@@ -1,40 +1,40 @@
package de.dhbwstuttgart.typeinference.constraints; package de.dhbwstuttgart.typeinference.constraints;
import de.dhbwstuttgart.server.packet.dataContainers.ISerializableData;
import de.dhbwstuttgart.server.packet.dataContainers.KeyStorage;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialMap;
import de.dhbwstuttgart.typeinference.unify.UnifyContext;
import java.io.Serializable; import java.io.Serializable;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.parser.SourceLoc; import de.dhbwstuttgart.parser.SourceLoc;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.unify.model.PairOperator; import de.dhbwstuttgart.typeinference.unify.model.PairOperator;
import org.antlr.v4.runtime.Token;
public class Pair implements Serializable public class Pair implements Serializable, IConstraintElement, ISerializableData {
{
public final RefTypeOrTPHOrWildcardOrGeneric TA1; public final RefTypeOrTPHOrWildcardOrGeneric TA1;
public final RefTypeOrTPHOrWildcardOrGeneric TA2; public final RefTypeOrTPHOrWildcardOrGeneric TA2;
private SourceLoc location; private SourceLoc location;
private PairOperator eOperator = PairOperator.SMALLER; private PairOperator eOperator = PairOperator.SMALLER;
private Boolean noUnification = false; private boolean noUnification = false;
private Pair(RefTypeOrTPHOrWildcardOrGeneric TA1, RefTypeOrTPHOrWildcardOrGeneric TA2 ) private Pair(RefTypeOrTPHOrWildcardOrGeneric TA1, RefTypeOrTPHOrWildcardOrGeneric TA2) {
{
this.TA1 = TA1; this.TA1 = TA1;
this.TA2 = TA2; this.TA2 = TA2;
if(TA1 == null || TA2 == null) if (TA1 == null || TA2 == null)
throw new NullPointerException(); throw new NullPointerException();
eOperator = PairOperator.SMALLER; eOperator = PairOperator.SMALLER;
} }
public Pair(RefTypeOrTPHOrWildcardOrGeneric TA1, RefTypeOrTPHOrWildcardOrGeneric TA2, PairOperator eOp) public Pair(RefTypeOrTPHOrWildcardOrGeneric TA1, RefTypeOrTPHOrWildcardOrGeneric TA2, PairOperator eOp) {
{
// Konstruktor // Konstruktor
this(TA1,TA2); this(TA1, TA2);
this.eOperator = eOp; this.eOperator = eOp;
} }
@@ -43,10 +43,9 @@ public class Pair implements Serializable
this.location = location; this.location = location;
} }
public Pair(RefTypeOrTPHOrWildcardOrGeneric TA1, RefTypeOrTPHOrWildcardOrGeneric TA2, PairOperator eOp, Boolean noUnification) public Pair(RefTypeOrTPHOrWildcardOrGeneric TA1, RefTypeOrTPHOrWildcardOrGeneric TA2, PairOperator eOp, boolean noUnification) {
{
// Konstruktor // Konstruktor
this(TA1,TA2); this(TA1, TA2);
this.eOperator = eOp; this.eOperator = eOp;
this.noUnification = noUnification; this.noUnification = noUnification;
} }
@@ -55,17 +54,16 @@ public class Pair implements Serializable
return this.location; return this.location;
} }
public String toString() public String toString() {
{
// otth: Gibt ein Paar als String aus --> zum Debuggen und Vergleichen // otth: Gibt ein Paar als String aus --> zum Debuggen und Vergleichen
String strElement1 = "NULL"; String strElement1 = "NULL";
String strElement2 = "NULL"; String strElement2 = "NULL";
String Operator = "<."; String Operator = "<.";
if( TA1 != null ) if (TA1 != null)
strElement1 = TA1.toString(); strElement1 = TA1.toString();
if( TA2 != null ) if (TA2 != null)
strElement2 = TA2.toString(); strElement2 = TA2.toString();
/* PL ausskommentiert 2018-05-24 /* PL ausskommentiert 2018-05-24
@@ -77,32 +75,30 @@ public class Pair implements Serializable
Operator = "<?"; Operator = "<?";
*/ */
return "\n(" + strElement1 + " " + eOperator.toString() + " " + strElement2 + ")"; return "\n(P: " + strElement1 + " " + eOperator.toString() + " " + strElement2 + ")";
/*- Equals: " + bEqual*/ /*- Equals: " + bEqual*/
} }
/** /**
* <br/>Author: J�rg B�uerle * <br/>Author: J�rg B�uerle
*
* @param obj * @param obj
* @return * @return
*/ */
public boolean equals(Object obj) public boolean equals(Object obj) {
{ return (
boolean ret = true; (obj instanceof Pair pairObj) &&
ret &= (obj instanceof Pair); pairObj.TA1.equals(this.TA1) &&
if(!ret)return ret; pairObj.TA2.equals(this.TA2)
ret &= ((Pair)obj).TA1.equals(this.TA1); );
ret &= ((Pair)obj).TA2.equals(this.TA2);
return ret;
} }
/** /**
* Author: Arne Lüdtke<br/> * Author: Arne Lüdtke<br/>
* Abfrage, ob Operator vom Typ Equal ist. * Abfrage, ob Operator vom Typ Equal ist.
*/ */
public boolean OperatorEqual() public boolean OperatorEqual() {
{
return eOperator == PairOperator.EQUALSDOT; return eOperator == PairOperator.EQUALSDOT;
} }
@@ -110,8 +106,7 @@ public class Pair implements Serializable
* Author: Arne Lüdtke<br/> * Author: Arne Lüdtke<br/>
* Abfrage, ob Operator vom Typ Smaller ist. * Abfrage, ob Operator vom Typ Smaller ist.
*/ */
public boolean OperatorSmaller() public boolean OperatorSmaller() {
{
return eOperator == PairOperator.SMALLER; return eOperator == PairOperator.SMALLER;
} }
@@ -119,8 +114,7 @@ public class Pair implements Serializable
* Author: Arne Lüdtke<br/> * Author: Arne Lüdtke<br/>
* Abfrage, ob Operator vom Typ SmallerExtends ist. * Abfrage, ob Operator vom Typ SmallerExtends ist.
*/ */
public boolean OperatorSmallerExtends() public boolean OperatorSmallerExtends() {
{
return eOperator == PairOperator.SMALLERDOTWC; return eOperator == PairOperator.SMALLERDOTWC;
} }
@@ -128,8 +122,7 @@ public class Pair implements Serializable
* Author: Arne Lüdtke<br/> * Author: Arne Lüdtke<br/>
* Gibt den Operator zurück. * Gibt den Operator zurück.
*/ */
public PairOperator GetOperator() public PairOperator GetOperator() {
{
return eOperator; return eOperator;
} }
@@ -151,5 +144,34 @@ public class Pair implements Serializable
}); });
return ret; return ret;
} }
@Override
public SerialMap toSerial(KeyStorage keyStorage) {
// because toString() will output TA1 and TA2 recursively, we can ignore potential infinite recursion here too
SerialMap serialized = new SerialMap();
serialized.put("ta1", this.TA1.toSerial(keyStorage));
serialized.put("ta2", this.TA2.toSerial(keyStorage));
serialized.put("op", this.eOperator.toString());
serialized.put("noUnification", this.noUnification ? 1 : 0);
serialized.put("location", this.location == null ? null : this.location.toSerial(keyStorage));
return serialized;
}
public static Pair fromSerial(SerialMap data, UnifyContext context) {
String op = data.getValue("op").getOf(String.class);
SerialMap ta1 = data.getMap("ta1");
SerialMap ta2 = data.getMap("ta2");
boolean noUnification = data.getValue("noUnification").getOf(Integer.class) == 1;
SerialMap location = data.getMapOrNull("location");
var pair = new Pair(
RefTypeOrTPHOrWildcardOrGeneric.fromSerial(ta1, context),
RefTypeOrTPHOrWildcardOrGeneric.fromSerial(ta2, context),
PairOperator.fromString(op),
noUnification
);
if (location != null) pair.location = SourceLoc.fromSerial(location);
return pair;
}
} }
// ino.end // ino.end

View File

@@ -1,15 +1,19 @@
package de.dhbwstuttgart.typeinference.result; package de.dhbwstuttgart.typeinference.result;
import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.exceptions.NotImplementedException;
import de.dhbwstuttgart.server.packet.dataContainers.ISerializableData;
import de.dhbwstuttgart.server.packet.dataContainers.KeyStorage;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialMap;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.typeinference.unify.UnifyContext;
/** /**
* enthaelt alle Paare, die in einem Ergebnis nicht vorkommen koennen * enthaelt alle Paare, die in einem Ergebnis nicht vorkommen koennen
* sie sind noetig fuer origPairs in PairTPHsmallerTPH, da hier auch * sie sind noetig fuer origPairs in PairTPHsmallerTPH, da hier auch
* Paare vorkommen koennen die keine Result sind (z.B. bei FunN$$) * Paare vorkommen koennen die keine Result sind (z.B. bei FunN$$)
*/ */
public class PairNoResult extends ResultPair<RefTypeOrTPHOrWildcardOrGeneric, RefTypeOrTPHOrWildcardOrGeneric>{ public class PairNoResult extends ResultPair<RefTypeOrTPHOrWildcardOrGeneric, RefTypeOrTPHOrWildcardOrGeneric>
implements ISerializableData {
//public final TypePlaceholder left; //public final TypePlaceholder left;
//public final TypePlaceholder right; //public final TypePlaceholder right;
@@ -17,7 +21,7 @@ public class PairNoResult extends ResultPair<RefTypeOrTPHOrWildcardOrGeneric, Re
* urspruengliches Paar aus diesem dieses Resultpair erzeugt wurde * urspruengliches Paar aus diesem dieses Resultpair erzeugt wurde
* wichtig fuer generated Generics * wichtig fuer generated Generics
*/ */
ResultPair origPair; ResultPair<?,?> origPair;
public PairNoResult(RefTypeOrTPHOrWildcardOrGeneric left, RefTypeOrTPHOrWildcardOrGeneric right){ public PairNoResult(RefTypeOrTPHOrWildcardOrGeneric left, RefTypeOrTPHOrWildcardOrGeneric right){
super(left, right); super(left, right);
@@ -29,4 +33,24 @@ public class PairNoResult extends ResultPair<RefTypeOrTPHOrWildcardOrGeneric, Re
throw new NotImplementedException(); throw new NotImplementedException();
//visitor.visit(this); //visitor.visit(this);
} }
@Override
public SerialMap toSerial(KeyStorage keyStorage) {
SerialMap serialized = new SerialMap();
serialized.put("left", this.getLeft().toSerial(keyStorage));
serialized.put("right", this.getRight().toSerial(keyStorage));
// create the wrapper and put this as the object
var serializedWrapper = super.toSerial(keyStorage);
serializedWrapper.put("object", serialized);
return serializedWrapper;
}
public static PairNoResult fromSerial2(SerialMap data, UnifyContext context) {
SerialMap left = data.getMap("left");
SerialMap right = data.getMap("right");
return new PairNoResult(
RefTypeOrTPHOrWildcardOrGeneric.fromSerial(left, context),
RefTypeOrTPHOrWildcardOrGeneric.fromSerial(right, context)
);
}
} }

View File

@@ -1,9 +1,13 @@
package de.dhbwstuttgart.typeinference.result; package de.dhbwstuttgart.typeinference.result;
import de.dhbwstuttgart.server.packet.dataContainers.ISerializableData;
import de.dhbwstuttgart.server.packet.dataContainers.KeyStorage;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialMap;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.unify.UnifyContext;
public class PairTPHEqualTPH extends ResultPair<TypePlaceholder, TypePlaceholder> { public class PairTPHEqualTPH extends ResultPair<TypePlaceholder, TypePlaceholder> implements ISerializableData {
public PairTPHEqualTPH(TypePlaceholder tl, TypePlaceholder tr) { public PairTPHEqualTPH(TypePlaceholder tl, TypePlaceholder tr) {
super(tl, tr); super(tl, tr);
} }
@@ -12,4 +16,24 @@ public class PairTPHEqualTPH extends ResultPair<TypePlaceholder, TypePlaceholder
public void accept(ResultPairVisitor visitor) { public void accept(ResultPairVisitor visitor) {
visitor.visit(this); visitor.visit(this);
} }
@Override
public SerialMap toSerial(KeyStorage keyStorage) {
SerialMap serialized = new SerialMap();
serialized.put("left", this.getLeft().toSerial(keyStorage));
serialized.put("right", this.getRight().toSerial(keyStorage));
// create the wrapper and put this as the object
var serializedWrapper = super.toSerial(keyStorage);
serializedWrapper.put("object", serialized);
return serializedWrapper;
}
public static PairTPHEqualTPH fromSerial2(SerialMap data, UnifyContext context) {
SerialMap left = data.getMap("left");
SerialMap right = data.getMap("right");
return new PairTPHEqualTPH(
(TypePlaceholder) RefTypeOrTPHOrWildcardOrGeneric.fromSerial(left, context),
(TypePlaceholder) RefTypeOrTPHOrWildcardOrGeneric.fromSerial(right, context)
);
}
} }

View File

@@ -1,13 +1,17 @@
package de.dhbwstuttgart.typeinference.result; package de.dhbwstuttgart.typeinference.result;
import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.server.packet.dataContainers.ISerializableData;
import de.dhbwstuttgart.server.packet.dataContainers.KeyStorage;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialMap;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.unify.UnifyContext;
/** /**
* Steht für A =. RefType * Steht für A =. RefType
*/ */
public class PairTPHequalRefTypeOrWildcardType extends ResultPair{ public class PairTPHequalRefTypeOrWildcardType extends ResultPair<TypePlaceholder, RefTypeOrTPHOrWildcardOrGeneric>
implements ISerializableData {
public final TypePlaceholder left; public final TypePlaceholder left;
public final RefTypeOrTPHOrWildcardOrGeneric right; public final RefTypeOrTPHOrWildcardOrGeneric right;
@@ -26,4 +30,24 @@ public class PairTPHequalRefTypeOrWildcardType extends ResultPair{
public String toString() { public String toString() {
return "(" + left.toString() + " = " + right.toString() + ")"; return "(" + left.toString() + " = " + right.toString() + ")";
} }
@Override
public SerialMap toSerial(KeyStorage keyStorage) {
SerialMap serialized = new SerialMap();
serialized.put("left", this.getLeft().toSerial(keyStorage));
serialized.put("right", this.getRight().toSerial(keyStorage));
// create the wrapper and put this as the object
var serializedWrapper = super.toSerial(keyStorage);
serializedWrapper.put("object", serialized);
return serializedWrapper;
}
public static PairTPHequalRefTypeOrWildcardType fromSerial2(SerialMap data, UnifyContext context) {
SerialMap left = data.getMap("left");
SerialMap right = data.getMap("right");
return new PairTPHequalRefTypeOrWildcardType(
(TypePlaceholder)RefTypeOrTPHOrWildcardOrGeneric.fromSerial(left, context),
RefTypeOrTPHOrWildcardOrGeneric.fromSerial(right, context)
);
}
} }

View File

@@ -1,12 +1,17 @@
package de.dhbwstuttgart.typeinference.result; package de.dhbwstuttgart.typeinference.result;
import de.dhbwstuttgart.server.packet.dataContainers.ISerializableData;
import de.dhbwstuttgart.server.packet.dataContainers.KeyStorage;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialMap;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.unify.UnifyContext;
/** /**
* Steht für: A <. B * Steht für: A <. B
*/ */
public class PairTPHsmallerTPH extends ResultPair{ public class PairTPHsmallerTPH extends ResultPair<TypePlaceholder,TypePlaceholder>
implements ISerializableData {
public final TypePlaceholder left; public final TypePlaceholder left;
public final TypePlaceholder right; public final TypePlaceholder right;
@@ -14,7 +19,7 @@ public class PairTPHsmallerTPH extends ResultPair{
* urspruengliches Paar aus diesem dieses Resultpair erzeugt wurde * urspruengliches Paar aus diesem dieses Resultpair erzeugt wurde
* wichtig fuer generated Generics * wichtig fuer generated Generics
*/ */
ResultPair origPair; ResultPair<?,?> origPair;
public PairTPHsmallerTPH(TypePlaceholder left, TypePlaceholder right){ public PairTPHsmallerTPH(TypePlaceholder left, TypePlaceholder right){
super(left, right); super(left, right);
@@ -22,7 +27,7 @@ public class PairTPHsmallerTPH extends ResultPair{
this.right = right; this.right = right;
} }
public PairTPHsmallerTPH(TypePlaceholder left, TypePlaceholder right, ResultPair origPair){ public PairTPHsmallerTPH(TypePlaceholder left, TypePlaceholder right, ResultPair<?,?> origPair){
this(left, right); this(left, right);
this.origPair = origPair; this.origPair = origPair;
} }
@@ -36,4 +41,24 @@ public class PairTPHsmallerTPH extends ResultPair{
public String toString() { public String toString() {
return "(" + left.toString() + " < " + right.toString() + ")"; return "(" + left.toString() + " < " + right.toString() + ")";
} }
@Override
public SerialMap toSerial(KeyStorage keyStorage) {
SerialMap serialized = new SerialMap();
serialized.put("left", this.getLeft().toSerial(keyStorage));
serialized.put("right", this.getRight().toSerial(keyStorage));
// create the wrapper and put this as the object
var serializedWrapper = super.toSerial(keyStorage);
serializedWrapper.put("object", serialized);
return serializedWrapper;
}
public static PairTPHsmallerTPH fromSerial2(SerialMap data, UnifyContext context) {
SerialMap left = data.getMap("left");
SerialMap right = data.getMap("right");
return new PairTPHsmallerTPH(
(TypePlaceholder) RefTypeOrTPHOrWildcardOrGeneric.fromSerial(left, context),
(TypePlaceholder) RefTypeOrTPHOrWildcardOrGeneric.fromSerial(right, context)
);
}
} }

View File

@@ -1,11 +1,17 @@
package de.dhbwstuttgart.typeinference.result; package de.dhbwstuttgart.typeinference.result;
import de.dhbwstuttgart.server.packet.dataContainers.ISerializableData;
import de.dhbwstuttgart.server.packet.dataContainers.KeyStorage;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialMap;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialValue;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.typeinference.unify.UnifyContext;
/** /**
* Paare, welche das Unifikationsergebnis darstellen * Paare, welche das Unifikationsergebnis darstellen
*/ */
public abstract class ResultPair<A extends RefTypeOrTPHOrWildcardOrGeneric, B extends RefTypeOrTPHOrWildcardOrGeneric> implements Comparable<ResultPair<A,B>> { public abstract class ResultPair<A extends RefTypeOrTPHOrWildcardOrGeneric,B extends RefTypeOrTPHOrWildcardOrGeneric>
implements ISerializableData {
private final A left; private final A left;
private final B right; private final B right;
@@ -59,13 +65,34 @@ public abstract class ResultPair<A extends RefTypeOrTPHOrWildcardOrGeneric, B ex
return true; return true;
} }
@Override @Override
public int compareTo(ResultPair<A, B> o) { public SerialMap toSerial(KeyStorage keyStorage) {
if (o == null) { SerialMap serialized = new SerialMap();
return 1; // this is greater than null String type = switch (this) {
case PairNoResult _ -> "pnr";
case PairTPHEqualTPH _ -> "ptet";
case PairTPHsmallerTPH _ -> "ptst";
case PairTPHequalRefTypeOrWildcardType _ -> "ptertwt";
default -> throw new RuntimeException("No type defined for ResultPair of class " + this.getClass().getName());
};
serialized.put("type", type);
// we only insert null for the object and expect the child classes to call this and override the value with themselves
serialized.put("object", SerialValue.NULL);
return serialized;
} }
return o.left.toString().compareTo(this.left.toString()); public static <A extends RefTypeOrTPHOrWildcardOrGeneric,B extends RefTypeOrTPHOrWildcardOrGeneric> ResultPair<A,B>
} fromSerial(SerialMap data, UnifyContext context) {
String type = data.getValue("type").getOf(String.class);
SerialMap object = data.getMap("object");
return switch (type) {
case "pnr" -> (ResultPair) PairNoResult.fromSerial2(object, context);
case "ptet" -> (ResultPair) PairTPHEqualTPH.fromSerial2(object, context);
case "ptst" -> (ResultPair) PairTPHsmallerTPH.fromSerial2(object, context);
case "ptertwt" -> (ResultPair) PairTPHequalRefTypeOrWildcardType.fromSerial2(object, context);
default -> throw new RuntimeException("Could not unserialize class of unhandled type " + type);
};
}
} }

View File

@@ -1,8 +1,16 @@
package de.dhbwstuttgart.typeinference.result; package de.dhbwstuttgart.typeinference.result;
import java.util.Collections; import com.google.common.collect.Ordering;
import de.dhbwstuttgart.server.packet.dataContainers.ISerializableData;
import de.dhbwstuttgart.server.packet.dataContainers.KeyStorage;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialList;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialMap;
import de.dhbwstuttgart.typeinference.unify.TypeUnifyTaskHelper;
import de.dhbwstuttgart.typeinference.unify.UnifyContext;
import de.dhbwstuttgart.util.Logger;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Set; import java.util.Set;
import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.exceptions.NotImplementedException;
@@ -12,21 +20,22 @@ import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType; import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import java.util.stream.Collectors;
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
public class ResultSet implements Comparable<ResultSet>{ public class ResultSet implements ISerializableData {
public final Set<ResultPair> results; public final Set<ResultPair> results;
public Set<ResultPair<TypePlaceholder, TypePlaceholder>> genIns; public Set<ResultPair<TypePlaceholder, TypePlaceholder>> genIns;
public ResultSet(Set<ResultPair> set){ public ResultSet(Set<ResultPair> set) {
this.results = set; this.results = set;
this.genIns = new HashSet<>(); this.genIns = TypeUnifyTaskHelper.getPresizedHashSet(results.size());
results.forEach(x -> { if (x instanceof PairTPHsmallerTPH) { this.genIns.add(x);}} ); results.forEach(x -> {
if (x instanceof PairTPHsmallerTPH) {
this.genIns.add(x);
} }
});
public List<ResultPair> getSortedResults() {
return results.stream().sorted().toList();
} }
public boolean contains(ResultPair toCheck) { public boolean contains(ResultPair toCheck) {
@@ -38,10 +47,10 @@ public class ResultSet implements Comparable<ResultSet>{
} }
public ResolvedType resolveType(RefTypeOrTPHOrWildcardOrGeneric type) { public ResolvedType resolveType(RefTypeOrTPHOrWildcardOrGeneric type) {
if(type instanceof TypePlaceholder) if (type instanceof TypePlaceholder)
return new Resolver(this).resolve((TypePlaceholder)type); return new Resolver(this).resolve((TypePlaceholder) type);
if(type instanceof GenericRefType)return new ResolvedType(type, new HashSet<>()); if (type instanceof GenericRefType) return new ResolvedType(type, new HashSet<>());
if(type instanceof RefType) { if (type instanceof RefType) {
RelatedTypeWalker related = new RelatedTypeWalker(null, this); RelatedTypeWalker related = new RelatedTypeWalker(null, this);
type.accept(related); type.accept(related);
return new ResolvedType(type, related.relatedTPHs); return new ResolvedType(type, related.relatedTPHs);
@@ -52,14 +61,27 @@ public class ResultSet implements Comparable<ResultSet>{
} }
public String toString() { public String toString() {
var results = new ArrayList<>(this.results);
results.sort(
Comparator
.comparingInt((ResultPair o) -> o.getLeft().toString().length())
.thenComparing(o -> o.getLeft().toString())
.thenComparingInt(o -> o.getRight().toString().length())
.thenComparing(o -> o.getRight().toString())
);
return results.toString(); return results.toString();
} }
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (o instanceof ResultSet) { if (o instanceof ResultSet other) {
ResultSet other = (ResultSet)o; // sort both result lists
return this.results.equals(other.results); var thisElements = new ArrayList<>(this.results);
thisElements.sort(Ordering.usingToString());
var otherElements = new ArrayList<>(other.results);
otherElements.sort(Ordering.usingToString());
return thisElements.equals(otherElements);
} else { } else {
return false; return false;
} }
@@ -71,18 +93,15 @@ public class ResultSet implements Comparable<ResultSet>{
} }
@Override @Override
public int compareTo(ResultSet o) { public SerialMap toSerial(KeyStorage keyStorage) {
List<ResultPair> thisSorted = this.getSortedResults(); SerialMap serialized = new SerialMap();;
List<ResultPair> otherSorted = o.getSortedResults(); serialized.put("results", SerialList.fromMapped(results, result -> result.toSerial(keyStorage)));
int sizeCompare = Integer.compare(thisSorted.size(), otherSorted.size()); return serialized;
if (sizeCompare != 0) return sizeCompare;
for (int i = 0; i < thisSorted.size(); i++) {
int cmp = thisSorted.get(i).compareTo(otherSorted.get(i));
if (cmp != 0) return cmp;
} }
return 0; public static ResultSet fromSerial(SerialMap data, UnifyContext context) {
var resultsData = data.getList("results").assertListOfMaps();
return new ResultSet(resultsData.stream().map(resultData -> ResultPair.fromSerial(resultData, context)).collect(Collectors.toSet()));
} }
} }
@@ -91,27 +110,29 @@ class Resolver implements ResultSetVisitor {
private TypePlaceholder toResolve; private TypePlaceholder toResolve;
private RefTypeOrTPHOrWildcardOrGeneric resolved; private RefTypeOrTPHOrWildcardOrGeneric resolved;
private final Set<GenericInsertPair> additionalTPHs = new HashSet<>(); private final Set<GenericInsertPair> additionalTPHs = new HashSet<>();
private ResultPair<?,?> currentPair; private ResultPair<?, ?> currentPair;
public Resolver(ResultSet resultPairs){ public static Logger logger = new Logger("Resolver");
public Resolver(ResultSet resultPairs) {
this.result = resultPairs; this.result = resultPairs;
} }
public ResolvedType resolve(TypePlaceholder tph){ public ResolvedType resolve(TypePlaceholder tph) {
toResolve = tph; toResolve = tph;
resolved = null; resolved = null;
System.out.println(tph.toString()); logger.info(tph.toString());
for(ResultPair<?,?> resultPair : result.results) { for (ResultPair<?, ?> resultPair : result.results) {
if(resultPair instanceof PairTPHEqualTPH && ((PairTPHEqualTPH) resultPair).getLeft().equals(toResolve)){ if (resultPair instanceof PairTPHEqualTPH && ((PairTPHEqualTPH) resultPair).getLeft().equals(toResolve)) {
currentPair = resultPair; currentPair = resultPair;
return resolve(((PairTPHEqualTPH) resultPair).getRight()); return resolve(((PairTPHEqualTPH) resultPair).getRight());
} }
} }
for(ResultPair<?,?> resultPair : result.results){ for (ResultPair<?, ?> resultPair : result.results) {
currentPair = resultPair; currentPair = resultPair;
resultPair.accept(this); resultPair.accept(this);
} }
if(resolved==null){//TPH kommt nicht im Result vor: if (resolved == null) {//TPH kommt nicht im Result vor:
resolved = tph; resolved = tph;
} }
@@ -123,18 +144,18 @@ class Resolver implements ResultSetVisitor {
@Override @Override
public void visit(PairTPHsmallerTPH p) { public void visit(PairTPHsmallerTPH p) {
currentPair = p; currentPair = p;
if(p.left.equals(toResolve)){ if (p.left.equals(toResolve)) {
additionalTPHs.add(new GenericInsertPair(p.left, p.right)); additionalTPHs.add(new GenericInsertPair(p.left, p.right));
additionalTPHs.addAll(new RelatedTypeWalker(p.right, result).relatedTPHs); additionalTPHs.addAll(new RelatedTypeWalker(p.right, result).relatedTPHs);
} }
if(p.right.equals(toResolve)) if (p.right.equals(toResolve))
additionalTPHs.addAll(new RelatedTypeWalker(p.left, result).relatedTPHs); additionalTPHs.addAll(new RelatedTypeWalker(p.left, result).relatedTPHs);
} }
@Override @Override
public void visit(PairTPHequalRefTypeOrWildcardType p) { public void visit(PairTPHequalRefTypeOrWildcardType p) {
currentPair = p; currentPair = p;
if(p.left.equals(toResolve)){ if (p.left.equals(toResolve)) {
resolved = p.right; resolved = p.right;
RelatedTypeWalker related = new RelatedTypeWalker(null, result); RelatedTypeWalker related = new RelatedTypeWalker(null, result);
p.right.accept(related); p.right.accept(related);
@@ -173,7 +194,6 @@ class Resolver implements ResultSetVisitor {
} }
} }
/** /**
@@ -186,20 +206,20 @@ class TPHResolver implements ResultSetVisitor {
Set<GenericInsertPair> resolved = new HashSet<>(); Set<GenericInsertPair> resolved = new HashSet<>();
private final ResultSet resultSet; private final ResultSet resultSet;
TPHResolver(TypePlaceholder tph, ResultSet resultSet){ TPHResolver(TypePlaceholder tph, ResultSet resultSet) {
this.resultSet = resultSet; this.resultSet = resultSet;
this.tph = tph; this.tph = tph;
for(ResultPair p : resultSet.results){ for (ResultPair p : resultSet.results) {
p.accept(this); p.accept(this);
} }
if(resolved.size() == 0){ if (resolved.size() == 0) {
resolved.add(new GenericInsertPair(tph, null)); resolved.add(new GenericInsertPair(tph, null));
} }
} }
@Override @Override
public void visit(PairTPHsmallerTPH p) { public void visit(PairTPHsmallerTPH p) {
if(p.left.equals(tph) || p.right.equals(tph)){ if (p.left.equals(tph) || p.right.equals(tph)) {
resolved.add(new GenericInsertPair(p.left, p.right)); resolved.add(new GenericInsertPair(p.left, p.right));
} }
} }
@@ -207,10 +227,10 @@ class TPHResolver implements ResultSetVisitor {
@Override @Override
public void visit(PairTPHequalRefTypeOrWildcardType p) { public void visit(PairTPHequalRefTypeOrWildcardType p) {
TypePlaceholder otherSide = null; TypePlaceholder otherSide = null;
if(p.right.equals(tph)){ if (p.right.equals(tph)) {
otherSide = p.left; otherSide = p.left;
} }
if(otherSide != null){ if (otherSide != null) {
Set<ResultPair> newResultSet = new HashSet<>(this.resultSet.results); Set<ResultPair> newResultSet = new HashSet<>(this.resultSet.results);
newResultSet.remove(p); newResultSet.remove(p);
resolved.addAll(new TPHResolver(otherSide, new ResultSet(newResultSet)).resolved); resolved.addAll(new TPHResolver(otherSide, new ResultSet(newResultSet)).resolved);
@@ -257,29 +277,30 @@ class RelatedTypeWalker implements ResultSetVisitor {
/** /**
* Läuft über das resultSet und speichert alle TPHs, welche mit start in Verbindung stehen * Läuft über das resultSet und speichert alle TPHs, welche mit start in Verbindung stehen
*
* @param start - kann null sein, wenn der Walker für einen RefType benutzt wird * @param start - kann null sein, wenn der Walker für einen RefType benutzt wird
* @param resultSet * @param resultSet
*/ */
RelatedTypeWalker(TypePlaceholder start, ResultSet resultSet){ RelatedTypeWalker(TypePlaceholder start, ResultSet resultSet) {
this.toResolve = start; this.toResolve = start;
this.resultSet = resultSet; this.resultSet = resultSet;
int resolved = 0; int resolved = 0;
do{ do {
resolved = relatedTPHs.size(); resolved = relatedTPHs.size();
for(ResultPair p : resultSet.results){ for (ResultPair p : resultSet.results) {
p.accept(this); p.accept(this);
p.accept(this); p.accept(this);
} }
}while(resolved - relatedTPHs.size() > 0); } while (resolved - relatedTPHs.size() > 0);
} }
@Override @Override
public void visit(PairTPHsmallerTPH p) { public void visit(PairTPHsmallerTPH p) {
if(p.getRight().equals(toResolve)){ if (p.getRight().equals(toResolve)) {
relatedTPHs.addAll(new TPHResolver(p.right, resultSet).resolved); relatedTPHs.addAll(new TPHResolver(p.right, resultSet).resolved);
//relatedTPHs.addAll(new RelatedTypeWalker(p.right, resultSet).relatedTPHs); //relatedTPHs.addAll(new RelatedTypeWalker(p.right, resultSet).relatedTPHs);
} }
if(p.getLeft().equals(toResolve)){ if (p.getLeft().equals(toResolve)) {
relatedTPHs.addAll(new TPHResolver(p.left, resultSet).resolved); relatedTPHs.addAll(new TPHResolver(p.left, resultSet).resolved);
//relatedTPHs.addAll(new RelatedTypeWalker(p.left, resultSet).relatedTPHs); //relatedTPHs.addAll(new RelatedTypeWalker(p.left, resultSet).relatedTPHs);
} }
@@ -287,7 +308,7 @@ class RelatedTypeWalker implements ResultSetVisitor {
@Override @Override
public void visit(PairTPHequalRefTypeOrWildcardType p) { public void visit(PairTPHequalRefTypeOrWildcardType p) {
if(p.getLeft().equals(toResolve)){ if (p.getLeft().equals(toResolve)) {
p.getRight().accept(this); p.getRight().accept(this);
} }
} }
@@ -304,7 +325,7 @@ class RelatedTypeWalker implements ResultSetVisitor {
@Override @Override
public void visit(RefType refType) { public void visit(RefType refType) {
for(RefTypeOrTPHOrWildcardOrGeneric param : refType.getParaList()){ for (RefTypeOrTPHOrWildcardOrGeneric param : refType.getParaList()) {
param.accept(this); param.accept(this);
} }
} }

View File

@@ -1,7 +1,6 @@
package de.dhbwstuttgart.typeinference.typeAlgo; package de.dhbwstuttgart.typeinference.typeAlgo;
import de.dhbwstuttgart.exceptions.DebugException; import de.dhbwstuttgart.exceptions.DebugException;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.parser.SourceLoc; import de.dhbwstuttgart.parser.SourceLoc;
import de.dhbwstuttgart.parser.antlr.Java17Parser; import de.dhbwstuttgart.parser.antlr.Java17Parser;
import de.dhbwstuttgart.parser.scope.JavaClassName; import de.dhbwstuttgart.parser.scope.JavaClassName;
@@ -10,18 +9,16 @@ import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
import de.dhbwstuttgart.syntaxtree.statement.Statement; import de.dhbwstuttgart.syntaxtree.statement.Statement;
import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.target.tree.type.TargetRefType;
import de.dhbwstuttgart.typeinference.assumptions.FieldAssumption; import de.dhbwstuttgart.typeinference.assumptions.FieldAssumption;
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation;
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation; import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation;
import de.dhbwstuttgart.typeinference.constraints.Constraint;
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
import de.dhbwstuttgart.typeinference.constraints.Pair; import de.dhbwstuttgart.typeinference.constraints.Pair;
import de.dhbwstuttgart.typeinference.unify.TypeUnifyTaskHelper;
import de.dhbwstuttgart.typeinference.unify.model.PairOperator; import de.dhbwstuttgart.typeinference.unify.model.PairOperator;
import de.dhbwstuttgart.util.BiRelation; import de.dhbwstuttgart.util.BiRelation;
import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.Token;
import java.lang.reflect.Modifier;
import java.util.*; import java.util.*;
public class TYPE { public class TYPE {
@@ -37,7 +34,7 @@ public class TYPE {
public ConstraintSet getConstraints() { public ConstraintSet getConstraints() {
ConstraintSet ret = new ConstraintSet(); ConstraintSet ret = new ConstraintSet();
for (ClassOrInterface cl : sf.KlassenVektor) { for (ClassOrInterface cl : sf.KlassenVektor) {
var allClasses = new HashSet<ClassOrInterface>(); Set<ClassOrInterface> allClasses = TypeUnifyTaskHelper.getPresizedHashSet(allAvailableClasses.size() + sf.availableClasses.size());
allClasses.addAll(allAvailableClasses); allClasses.addAll(allAvailableClasses);
allClasses.addAll(sf.availableClasses); allClasses.addAll(sf.availableClasses);
ret.addAll(getConstraintsClass(cl, new TypeInferenceInformation(allClasses))); ret.addAll(getConstraintsClass(cl, new TypeInferenceInformation(allClasses)));
@@ -72,7 +69,7 @@ public class TYPE {
for(SourceFile sourceFile : sfs){ for(SourceFile sourceFile : sfs){
for(JavaClassName importName : sourceFile.imports){ for(JavaClassName importName : sourceFile.imports){
System.out.println(importName); context.logger().info(importName);
try { try {
classes.add(ASTFactory.createClass(classLoader.loadClass(importName.toString()))); classes.add(ASTFactory.createClass(classLoader.loadClass(importName.toString())));
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
@@ -91,25 +88,12 @@ public class TYPE {
TypeInferenceBlockInformation blockInfo = new TypeInferenceBlockInformation(info.getAvailableClasses(), currentClass, m); TypeInferenceBlockInformation blockInfo = new TypeInferenceBlockInformation(info.getAvailableClasses(), currentClass, m);
TYPEStmt methodScope = new TYPEStmt(blockInfo); TYPEStmt methodScope = new TYPEStmt(blockInfo);
ConstraintSet constraintSet = new ConstraintSet(); ConstraintSet constraintSet = new ConstraintSet();
if (m.name.equals("main") && Modifier.isStatic(m.modifier) && m.getParameterList().getFormalparalist().size() == 1) {
// Add constraint for main method
var firstParam = m.getParameterList().getParameterAt(0);
constraintSet.addUndConstraint(new Pair(firstParam.getType(),
new RefType(new JavaClassName("java.util.List"),
List.of(new RefType(new JavaClassName("java.lang.String"), new NullToken())),
new NullToken()),
PairOperator.EQUALSDOT));
} else {
m.getParameterList().getFormalparalist().forEach(el -> { m.getParameterList().getFormalparalist().forEach(el -> {
if (el instanceof RecordPattern rp){ if(el instanceof RecordPattern){
constraintSet.addAll(addRecursiveParameterConstraints(rp, blockInfo)); constraintSet.addAll(addRecursiveParameterConstraints((RecordPattern) el, blockInfo));
} }
}); });
}
m.block.accept(methodScope); m.block.accept(methodScope);
constraintSet.addAll(methodScope.getConstraints()); constraintSet.addAll(methodScope.getConstraints());
return constraintSet; return constraintSet;

View File

@@ -1,6 +1,8 @@
//PL 2018-12-19: Merge chekcen //PL 2018-12-19: Merge chekcen
package de.dhbwstuttgart.typeinference.typeAlgo; package de.dhbwstuttgart.typeinference.typeAlgo;
import de.dhbwstuttgart.typeinference.unify.PlaceholderRegistry;
import de.dhbwstuttgart.typeinference.unify.TypeUnifyTaskHelper;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -73,7 +75,7 @@ public class TYPEStmt implements StatementVisitor {
@Override @Override
public void visit(LambdaExpression lambdaExpression) { public void visit(LambdaExpression lambdaExpression) {
TypePlaceholder tphRetType = TypePlaceholder.fresh(new NullToken(), -1, false); TypePlaceholder tphRetType = TypePlaceholder.fresh(new NullToken());
List<RefTypeOrTPHOrWildcardOrGeneric> lambdaParams = lambdaExpression.params.getFormalparalist().stream().map((formalParameter -> formalParameter.getType())).collect(Collectors.toList()); List<RefTypeOrTPHOrWildcardOrGeneric> lambdaParams = lambdaExpression.params.getFormalparalist().stream().map((formalParameter -> formalParameter.getType())).collect(Collectors.toList());
lambdaParams.add(tphRetType); lambdaParams.add(tphRetType);
// lambdaParams.add(0,tphRetType); // lambdaParams.add(0,tphRetType);
@@ -116,17 +118,18 @@ public class TYPEStmt implements StatementVisitor {
@Override @Override
public void visit(FieldVar fieldVar) { public void visit(FieldVar fieldVar) {
fieldVar.receiver.accept(this); fieldVar.receiver.accept(this);
Set<Constraint> oderConstraints = new HashSet<>(); List<FieldAssumption> fieldAssumptions = info.getFields(fieldVar.fieldVarName);
Set<Constraint> oderConstraints = TypeUnifyTaskHelper.getPresizedHashSet(fieldAssumptions.size());
for (FieldAssumption fieldAssumption : info.getFields(fieldVar.fieldVarName)) { for (FieldAssumption fieldAssumption : fieldAssumptions) {
Constraint constraint = new Constraint(); Constraint constraint = new Constraint();
GenericsResolver resolver = getResolverInstance(); GenericsResolver resolver = getResolverInstance();
constraint.add(new Pair(fieldVar.receiver.getType(), fieldAssumption.getReceiverType(resolver), PairOperator.SMALLERDOT, loc(fieldVar.getOffset()))); // PL 2019-12-09: SMALLERDOT eingefuegt, EQUALSDOT entfernt, wenn ds Field privat ist muesste es EQUALSDOT lauten constraint.add(new Pair(fieldVar.receiver.getType(), fieldAssumption.getReceiverType(resolver), PairOperator.SMALLERDOT, loc(fieldVar.getOffset()))); // PL 2019-12-09: SMALLERDOT eingefuegt, EQUALSDOT entfernt, wenn ds Field privat ist muesste es EQUALSDOT lauten
constraint.add(new Pair(fieldVar.getType(), fieldAssumption.getType(resolver), PairOperator.EQUALSDOT, loc(fieldVar.getOffset()))); constraint.add(new Pair(fieldVar.getType(), fieldAssumption.getType(resolver), PairOperator.EQUALSDOT, loc(fieldVar.getOffset())));
oderConstraints.add(constraint); oderConstraints.add(constraint);
} }
if (oderConstraints.size() == 0) if (oderConstraints.isEmpty())
throw new TypeinferenceException("Kein Feld " + fieldVar.fieldVarName + " gefunden", fieldVar.getOffset()); throw new TypeinferenceException("Kein Feld " + fieldVar.fieldVarName + " gefunden", fieldVar.getOffset());
constraintsSet.addOderConstraint(oderConstraints); constraintsSet.addOderConstraint(oderConstraints);
} }
@@ -141,7 +144,7 @@ public class TYPEStmt implements StatementVisitor {
@Override @Override
public void visit(ForEachStmt forEachStmt) { public void visit(ForEachStmt forEachStmt) {
var iterableType = new RefType(ASTFactory.createClass(java.lang.Iterable.class).getClassName(), Arrays.asList(new ExtendsWildcardType(forEachStmt.statement.getType(), new NullToken())), new NullToken()); var iterableType = new RefType(ASTFactory.createClass(java.lang.Iterable.class).getClassName(), List.of(new ExtendsWildcardType(forEachStmt.statement.getType(), new NullToken())), new NullToken());
constraintsSet.addUndConstraint(new Pair(forEachStmt.expression.getType(), iterableType, PairOperator.SMALLERDOT, loc(forEachStmt.getOffset()))); constraintsSet.addUndConstraint(new Pair(forEachStmt.expression.getType(), iterableType, PairOperator.SMALLERDOT, loc(forEachStmt.getOffset())));
forEachStmt.statement.accept(this); forEachStmt.statement.accept(this);
forEachStmt.expression.accept(this); forEachStmt.expression.accept(this);
@@ -189,7 +192,7 @@ public class TYPEStmt implements StatementVisitor {
methodCall.receiver.accept(this); methodCall.receiver.accept(this);
// Overloading: // Overloading:
Set<Constraint<Pair>> methodConstraints = new HashSet<>(); Set<Constraint<Pair>> methodConstraints = new HashSet<>();
for (MethodAssumption m : this.getMethods(methodCall.name, methodCall.arglist, info)) { for (MethodAssumption m : TYPEStmt.getMethods(methodCall.name, methodCall.arglist, info)) {
GenericsResolver resolver = getResolverInstance(); GenericsResolver resolver = getResolverInstance();
Set<Constraint<Pair>> oneMethodConstraints = generateConstraint(methodCall, m, info, resolver); Set<Constraint<Pair>> oneMethodConstraints = generateConstraint(methodCall, m, info, resolver);
methodConstraints.addAll(oneMethodConstraints); methodConstraints.addAll(oneMethodConstraints);
@@ -199,7 +202,7 @@ public class TYPEStmt implements StatementVisitor {
* oneMethodConstraint.setExtendConstraint(extendsOneMethodConstraint); extendsOneMethodConstraint.setExtendConstraint(oneMethodConstraint); methodConstraints.add(extendsOneMethodConstraint); * oneMethodConstraint.setExtendConstraint(extendsOneMethodConstraint); extendsOneMethodConstraint.setExtendConstraint(oneMethodConstraint); methodConstraints.add(extendsOneMethodConstraint);
*/ */
} }
if (methodConstraints.size() < 1) { if (methodConstraints.isEmpty()) {
throw new TypeinferenceException("Methode " + methodCall.name + " ist nicht vorhanden!", methodCall.getOffset()); throw new TypeinferenceException("Methode " + methodCall.name + " ist nicht vorhanden!", methodCall.getOffset());
} }
constraintsSet.addOderConstraint(methodConstraints); constraintsSet.addOderConstraint(methodConstraints);
@@ -212,7 +215,7 @@ public class TYPEStmt implements StatementVisitor {
for (MethodAssumption m : this.getConstructors(info, (RefType) methodCall.getType(), methodCall.getArgumentList())) { for (MethodAssumption m : this.getConstructors(info, (RefType) methodCall.getType(), methodCall.getArgumentList())) {
methodConstraints.add(generateConstructorConstraint(methodCall, m, info, getResolverInstance())); methodConstraints.add(generateConstructorConstraint(methodCall, m, info, getResolverInstance()));
} }
if (methodConstraints.size() < 1) { if (methodConstraints.isEmpty()) {
throw new TypeinferenceException("Konstruktor in Klasse " + methodCall.getType().toString() + " ist nicht vorhanden!", methodCall.getOffset()); throw new TypeinferenceException("Konstruktor in Klasse " + methodCall.getType().toString() + " ist nicht vorhanden!", methodCall.getOffset());
} }
constraintsSet.addOderConstraint(methodConstraints); constraintsSet.addOderConstraint(methodConstraints);
@@ -282,8 +285,13 @@ public class TYPEStmt implements StatementVisitor {
// see: https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.17 // see: https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.17
// Expression muss zu Numeric Convertierbar sein. also von Numeric erben // Expression muss zu Numeric Convertierbar sein. also von Numeric erben
Constraint<Pair> numeric; Constraint<Pair> numeric;
HashSet<JavaClassName> classNames = TypeUnifyTaskHelper.getPresizedHashSet(info.getAvailableClasses().size());
for (var classEl : info.getAvailableClasses()) {
classNames.add(classEl.getClassName());
}
// PL eingefuegt 2018-07-17 // PL eingefuegt 2018-07-17
if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(bytee.getName())) { if (classNames.contains(bytee.getName())) {
numeric = new Constraint<>(); numeric = new Constraint<>();
numeric.add(new Pair(binary.lexpr.getType(), bytee, PairOperator.SMALLERDOT, loc(binary.getOffset()))); numeric.add(new Pair(binary.lexpr.getType(), bytee, PairOperator.SMALLERDOT, loc(binary.getOffset())));
numeric.add(new Pair(binary.rexpr.getType(), bytee, PairOperator.SMALLERDOT, loc(binary.getOffset()))); numeric.add(new Pair(binary.rexpr.getType(), bytee, PairOperator.SMALLERDOT, loc(binary.getOffset())));
@@ -291,7 +299,7 @@ public class TYPEStmt implements StatementVisitor {
numericAdditionOrStringConcatenation.add(numeric); numericAdditionOrStringConcatenation.add(numeric);
} }
// PL eingefuegt 2018-07-17 // PL eingefuegt 2018-07-17
if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(shortt.getName())) { if (classNames.contains(shortt.getName())) {
numeric = new Constraint<>(); numeric = new Constraint<>();
numeric.add(new Pair(binary.lexpr.getType(), shortt, PairOperator.SMALLERDOT, loc(binary.getOffset()))); numeric.add(new Pair(binary.lexpr.getType(), shortt, PairOperator.SMALLERDOT, loc(binary.getOffset())));
numeric.add(new Pair(binary.rexpr.getType(), shortt, PairOperator.SMALLERDOT, loc(binary.getOffset()))); numeric.add(new Pair(binary.rexpr.getType(), shortt, PairOperator.SMALLERDOT, loc(binary.getOffset())));
@@ -299,7 +307,7 @@ public class TYPEStmt implements StatementVisitor {
numericAdditionOrStringConcatenation.add(numeric); numericAdditionOrStringConcatenation.add(numeric);
} }
// PL eingefuegt 2018-07-17 // PL eingefuegt 2018-07-17
if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(integer.getName())) { if (classNames.contains(integer.getName())) {
numeric = new Constraint<>(); numeric = new Constraint<>();
numeric.add(new Pair(binary.lexpr.getType(), integer, PairOperator.SMALLERDOT, loc(binary.getOffset()))); numeric.add(new Pair(binary.lexpr.getType(), integer, PairOperator.SMALLERDOT, loc(binary.getOffset())));
numeric.add(new Pair(binary.rexpr.getType(), integer, PairOperator.SMALLERDOT, loc(binary.getOffset()))); numeric.add(new Pair(binary.rexpr.getType(), integer, PairOperator.SMALLERDOT, loc(binary.getOffset())));
@@ -307,7 +315,7 @@ public class TYPEStmt implements StatementVisitor {
numericAdditionOrStringConcatenation.add(numeric); numericAdditionOrStringConcatenation.add(numeric);
} }
// PL eingefuegt 2018-07-17 // PL eingefuegt 2018-07-17
if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(longg.getName())) { if (classNames.contains(longg.getName())) {
numeric = new Constraint<>(); numeric = new Constraint<>();
numeric.add(new Pair(binary.lexpr.getType(), longg, PairOperator.SMALLERDOT, loc(binary.getOffset()))); numeric.add(new Pair(binary.lexpr.getType(), longg, PairOperator.SMALLERDOT, loc(binary.getOffset())));
numeric.add(new Pair(binary.rexpr.getType(), longg, PairOperator.SMALLERDOT, loc(binary.getOffset()))); numeric.add(new Pair(binary.rexpr.getType(), longg, PairOperator.SMALLERDOT, loc(binary.getOffset())));
@@ -315,7 +323,7 @@ public class TYPEStmt implements StatementVisitor {
numericAdditionOrStringConcatenation.add(numeric); numericAdditionOrStringConcatenation.add(numeric);
} }
// PL eingefuegt 2018-07-17 // PL eingefuegt 2018-07-17
if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(floatt.getName())) { if (classNames.contains(floatt.getName())) {
numeric = new Constraint<>(); numeric = new Constraint<>();
numeric.add(new Pair(binary.lexpr.getType(), floatt, PairOperator.SMALLERDOT, loc(binary.getOffset()))); numeric.add(new Pair(binary.lexpr.getType(), floatt, PairOperator.SMALLERDOT, loc(binary.getOffset())));
numeric.add(new Pair(binary.rexpr.getType(), floatt, PairOperator.SMALLERDOT, loc(binary.getOffset()))); numeric.add(new Pair(binary.rexpr.getType(), floatt, PairOperator.SMALLERDOT, loc(binary.getOffset())));
@@ -323,7 +331,7 @@ public class TYPEStmt implements StatementVisitor {
numericAdditionOrStringConcatenation.add(numeric); numericAdditionOrStringConcatenation.add(numeric);
} }
// PL eingefuegt 2018-07-17 // PL eingefuegt 2018-07-17
if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(doublee.getName())) { if (classNames.contains(doublee.getName())) {
numeric = new Constraint<>(); numeric = new Constraint<>();
numeric.add(new Pair(binary.lexpr.getType(), doublee, PairOperator.SMALLERDOT, loc(binary.getOffset()))); numeric.add(new Pair(binary.lexpr.getType(), doublee, PairOperator.SMALLERDOT, loc(binary.getOffset())));
numeric.add(new Pair(binary.rexpr.getType(), doublee, PairOperator.SMALLERDOT, loc(binary.getOffset()))); numeric.add(new Pair(binary.rexpr.getType(), doublee, PairOperator.SMALLERDOT, loc(binary.getOffset())));
@@ -338,7 +346,7 @@ public class TYPEStmt implements StatementVisitor {
if (binary.operation.equals(BinaryExpr.Operator.ADD)) { if (binary.operation.equals(BinaryExpr.Operator.ADD)) {
// Dann kann der Ausdruck auch das aneinanderfügen zweier Strings sein: ("a" + "b") oder (1 + 2) // Dann kann der Ausdruck auch das aneinanderfügen zweier Strings sein: ("a" + "b") oder (1 + 2)
if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(string.getName())) { if (classNames.contains(string.getName())) {
Constraint<Pair> stringConcat = new Constraint<>(); Constraint<Pair> stringConcat = new Constraint<>();
stringConcat.add(new Pair(binary.lexpr.getType(), string, PairOperator.EQUALSDOT, loc(binary.getOffset()))); stringConcat.add(new Pair(binary.lexpr.getType(), string, PairOperator.EQUALSDOT, loc(binary.getOffset())));
stringConcat.add(new Pair(binary.rexpr.getType(), string, PairOperator.EQUALSDOT, loc(binary.getOffset()))); stringConcat.add(new Pair(binary.rexpr.getType(), string, PairOperator.EQUALSDOT, loc(binary.getOffset())));
@@ -346,7 +354,7 @@ public class TYPEStmt implements StatementVisitor {
numericAdditionOrStringConcatenation.add(stringConcat); numericAdditionOrStringConcatenation.add(stringConcat);
} }
} }
if (numericAdditionOrStringConcatenation.size() < 1) { if (numericAdditionOrStringConcatenation.isEmpty()) {
throw new TypeinferenceException("Kein Typ für " + binary.operation.toString() + " vorhanden", binary.getOffset()); throw new TypeinferenceException("Kein Typ für " + binary.operation.toString() + " vorhanden", binary.getOffset());
} }
constraintsSet.addOderConstraint(numericAdditionOrStringConcatenation); constraintsSet.addOderConstraint(numericAdditionOrStringConcatenation);
@@ -635,7 +643,6 @@ public class TYPEStmt implements StatementVisitor {
params.add(resolver.resolve(new GenericRefType(gtv.getName(), new NullToken()))); params.add(resolver.resolve(new GenericRefType(gtv.getName(), new NullToken())));
} }
RefTypeOrTPHOrWildcardOrGeneric receiverType; RefTypeOrTPHOrWildcardOrGeneric receiverType;
if (receiver instanceof FunNClass) { if (receiver instanceof FunNClass) {
receiverType = new RefType(new JavaClassName(receiver.getClassName().toString() + "$$"), params, new NullToken()); // new FunN(params); receiverType = new RefType(new JavaClassName(receiver.getClassName().toString() + "$$"), params, new NullToken()); // new FunN(params);
} else { } else {
@@ -694,8 +701,8 @@ public class TYPEStmt implements StatementVisitor {
Set<Pair> methodSignatureConstraint = generatemethodSignatureConstraint(forMethod, assumption, info, resolver); Set<Pair> methodSignatureConstraint = generatemethodSignatureConstraint(forMethod, assumption, info, resolver);
//System.out.println("methodSignatureConstraint: " + methodSignatureConstraint); //context.logger().info("methodSignatureConstraint: " + methodSignatureConstraint);
//System.out.println("methodConstraint: " + methodConstraint); //context.logger().info("methodConstraint: " + methodConstraint);
methodConstraint.setmethodSignatureConstraint(methodSignatureConstraint); methodConstraint.setmethodSignatureConstraint(methodSignatureConstraint);
extendsMethodConstraint.setmethodSignatureConstraint(methodSignatureConstraint); extendsMethodConstraint.setmethodSignatureConstraint(methodSignatureConstraint);
@@ -733,7 +740,7 @@ public class TYPEStmt implements StatementVisitor {
} }
// Zuordnung von MethodCall.signature(ReturnType) zu dem ReturnType der ausgewaehlten Methode (assumption.returnType) // Zuordnung von MethodCall.signature(ReturnType) zu dem ReturnType der ausgewaehlten Methode (assumption.returnType)
ret.add(new Pair(foMethod.signature.get(foMethod.signature.size() - 1), assumption.getReturnType(), PairOperator.EQUALSDOT)); ret.add(new Pair(foMethod.signature.getLast(), assumption.getReturnType(), PairOperator.EQUALSDOT));
return ret; return ret;
} }
@@ -746,8 +753,8 @@ public class TYPEStmt implements StatementVisitor {
// funNParams.add(TypePlaceholder.fresh(new NullToken())); // funNParams.add(TypePlaceholder.fresh(new NullToken()));
funNParams.add(new GenericRefType(NameGenerator.makeNewName(), new NullToken())); funNParams.add(new GenericRefType(NameGenerator.makeNewName(), new NullToken()));
} }
funNParams.get(funNParams.size() - 1); funNParams.getLast();
ret.add(new MethodAssumption(new FunNClass(funNParams), funNParams.get(funNParams.size() - 1), funNParams.subList(0, funNParams.size() - 1), new TypeScope() { ret.add(new MethodAssumption(new FunNClass(funNParams), funNParams.getLast(), funNParams.subList(0, funNParams.size() - 1), new TypeScope() {
@Override @Override
public Iterable<? extends GenericTypeVar> getGenerics() { public Iterable<? extends GenericTypeVar> getGenerics() {
throw new NotImplementedException(); throw new NotImplementedException();
@@ -842,7 +849,7 @@ public class TYPEStmt implements StatementVisitor {
for (var child : switchStmt.getBlocks()) { for (var child : switchStmt.getBlocks()) {
for (var label : child.getLabels()) { for (var label : child.getLabels()) {
if (label.getPattern() == null) { if (label.getPattern() == null) {
//System.out.println("DefaultCase"); //context.logger().info("DefaultCase");
} else { } else {
constraintsSet.addUndConstraint( constraintsSet.addUndConstraint(
new Pair( new Pair(
@@ -883,13 +890,9 @@ public class TYPEStmt implements StatementVisitor {
child.getLabels().forEach(el -> { child.getLabels().forEach(el -> {
if (el.getType() instanceof RefType) { if (el.getType() instanceof RefType) {
var recType = el; if (el.getPattern() instanceof RecordPattern pattern) {
if (el.getPattern() instanceof RecordPattern) {
var pattern = (RecordPattern) recType.getPattern();
recursivelyAddRecordConstraints(pattern); recursivelyAddRecordConstraints(pattern);
} }
} }
}); });
@@ -905,13 +908,13 @@ public class TYPEStmt implements StatementVisitor {
var allClasses = info.getAvailableClasses(); var allClasses = info.getAvailableClasses();
var interestingClasses = allClasses.stream().filter(as -> as.getClassName().equals(((RefType) pattern.getType()).getName())).toList(); var interestingClasses = allClasses.stream().filter(as -> as.getClassName().equals(((RefType) pattern.getType()).getName())).toList();
var constructors = interestingClasses.get(0).getConstructors(); var constructors = interestingClasses.getFirst().getConstructors();
int counter = 0; int counter = 0;
for (var subPattern : pattern.getSubPattern()) { for (var subPattern : pattern.getSubPattern()) {
for (Constructor con : constructors) { for (Constructor con : constructors) {
//System.out.println("----------------------\n" + subPattern.getType() + " | " + con.getParameterList().getParameterAt(counter).getType() + "\n----------------------\n"); //context.logger().info("----------------------\n" + subPattern.getType() + " | " + con.getParameterList().getParameterAt(counter).getType() + "\n----------------------\n");
constraintsSet.addUndConstraint(new Pair(subPattern.getType(), con.getParameterList().getParameterAt(counter).getType(), PairOperator.SMALLERDOT, loc(con.getParameterList().getParameterAt(counter).getOffset()))); constraintsSet.addUndConstraint(new Pair(subPattern.getType(), con.getParameterList().getParameterAt(counter).getType(), PairOperator.SMALLERDOT, loc(con.getParameterList().getParameterAt(counter).getOffset())));
} }
if (subPattern instanceof RecordPattern) recursivelyAddRecordConstraints((RecordPattern) subPattern); if (subPattern instanceof RecordPattern) recursivelyAddRecordConstraints((RecordPattern) subPattern);

View File

@@ -0,0 +1,91 @@
package de.dhbwstuttgart.typeinference.unify;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* An intermediate class for the recursive steps of the TypeUnifyTask:
* This allows canceling parts of the recursion tree, instead of only the whole execution as before. But in
* order for that to work, all cancellable child tasks must be added when they are created
*
* @param <T>
*/
public abstract class CancellableTask<T> extends RecursiveTask<T> {
private final AtomicBoolean executionCancelled = new AtomicBoolean(false);
private final List<CancellableTask<?>> childTasks = new LinkedList<>();
private CancellableTask<?> parentTask = null;
/**
* Set the execution for this task and all its (recursive) children to be canceled
*/
protected void cancelExecution() {
// is this branch already canceled? Then do nothing
if (this.executionCancelled.getAndSet(true)) return;
this.cancelChildExecution();
}
private void cancelChildExecution() {
synchronized (this.childTasks) {
for (var childTask : childTasks) {
// no need to cancel a branch that is already finished
if (!childTask.isDone()) {
childTask.cancelExecution();
}
}
}
}
private void cancelChildExecutionAfter(CancellableTask<?> checkpointTask) {
boolean reachedCheckpoint = false;
int i = 0;
for (var childTask : childTasks) {
if (!reachedCheckpoint) {
reachedCheckpoint = childTask == checkpointTask;
}
else {
// no need to cancel a branch that is already finished
if (!childTask.isDone()) {
childTask.cancelExecution();
}
i++;
}
}
System.out.println("Skipped " + i + " younger siblings");
}
protected void cancelSiblingTasks() {
if (this.parentTask != null) {
boolean thisWasCancelledBefore = this.executionCancelled.get();
this.parentTask.cancelChildExecution();
this.executionCancelled.set(thisWasCancelledBefore);
}
}
public void cancelYoungerSiblingTasks() {
if (this.parentTask != null) {
this.parentTask.cancelChildExecutionAfter(this);
}
}
public Boolean isExecutionCancelled() {
return executionCancelled.get();
}
public void addChildTask(CancellableTask<?> childTask) {
this.childTasks.add(childTask);
childTask.setParentTask(this);
if (this.executionCancelled.get()) {
childTask.executionCancelled.set(true);
}
}
private void setParentTask(CancellableTask<?> parentTask) {
this.parentTask = parentTask;
}
}

View File

@@ -0,0 +1,61 @@
package de.dhbwstuttgart.typeinference.unify;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.RecursiveTask;
public class ConcurrentSetMergeTask<T> extends RecursiveTask<Set<T>> {
public static <E> Set<E> merge(List<Set<E>> list) {
if (list.isEmpty()) {
return new HashSet<>();
}
var task = new ConcurrentSetMergeTask<>(list, 0, list.size());
return task.compute();
}
private static final int LIST_THRESHOLD = 3;
private static final int ELEMENT_THRESHOLD = 1000;
private final List<Set<T>> list;
private final int start;
private final int end;
private ConcurrentSetMergeTask(List<Set<T>> list, int start, int end) {
this.list = list;
this.start = start;
this.end = end;
}
@Override
protected Set<T> compute() {
int size = end - start;
int totalElements = 0;
for (int i = start+1; i < end; i++) {
totalElements += list.get(i).size();
}
// size will always be at least one
if (true || size <= LIST_THRESHOLD || totalElements < ELEMENT_THRESHOLD) {
Set<T> result = this.list.get(start);
for (int i = start+1; i < end; i++) {
result.addAll(list.get(i));
}
return result;
} else {
int mid = start + (size / 2);
ConcurrentSetMergeTask<T> leftTask = new ConcurrentSetMergeTask<>(list, start, mid);
ConcurrentSetMergeTask<T> rightTask = new ConcurrentSetMergeTask<>(list, mid, end);
leftTask.fork();
Set<T> rightResult = rightTask.compute();
Set<T> leftResult = leftTask.join();
// Merge results
leftResult.addAll(rightResult);
return leftResult;
}
}
}

View File

@@ -95,7 +95,7 @@ public class MartelliMontanariUnify implements IUnify {
if(lhsType instanceof PlaceholderType) { if(lhsType instanceof PlaceholderType) {
mgu.add((PlaceholderType) lhsType, rhsType); mgu.add((PlaceholderType) lhsType, rhsType);
//PL 2018-04-01 nach checken, ob es richtig ist, dass keine Substitutionen uebergeben werden muessen. //PL 2018-04-01 nach checken, ob es richtig ist, dass keine Substitutionen uebergeben werden muessen.
termsList = termsList.stream().map(x -> mgu.apply(x)).collect(Collectors.toCollection(ArrayList::new)); termsList.replaceAll(mgu::apply);
idx = idx+1 == termsList.size() ? 0 : idx+1; idx = idx+1 == termsList.size() ? 0 : idx+1;
continue; continue;
} }

View File

@@ -0,0 +1,84 @@
package de.dhbwstuttgart.typeinference.unify;
import de.dhbwstuttgart.server.packet.dataContainers.ISerializableData;
import de.dhbwstuttgart.server.packet.dataContainers.KeyStorage;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialList;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialMap;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialValue;
import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType;
import java.util.ArrayList;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Calculate unique placeholder names
*/
public class PlaceholderRegistry implements ISerializableData {
private final Set<String> existingPlaceholders = ConcurrentHashMap.newKeySet();
private final AtomicInteger placeholderCount = new AtomicInteger();
public ArrayList<PlaceholderType> UnifyTypeFactory_PLACEHOLDERS = new ArrayList<>();
/**
* Add a placeholder into the list of existing ones, as soon as a new PlaceholderType is created
*
* @param placeholderName The placeholder to add
*/
public void addPlaceholder(String placeholderName) {
this.existingPlaceholders.add(placeholderName);
}
/**
* Generate a random placeholder name, that is unique to this context
*
* @return The generated name
*/
public String generateFreshPlaceholderName() {
String name;
do {
int pc = placeholderCount.incrementAndGet();
name = getUppercaseTokenFromInt(pc);
}
while (existingPlaceholders.contains(name));
this.addPlaceholder(name);
return name;
}
public PlaceholderRegistry deepClone() {
PlaceholderRegistry pr2 = new PlaceholderRegistry();
this.existingPlaceholders.forEach(pr2::addPlaceholder);
pr2.UnifyTypeFactory_PLACEHOLDERS.addAll(this.UnifyTypeFactory_PLACEHOLDERS);
pr2.placeholderCount.set(this.placeholderCount.get());
return pr2;
}
/**
* Generate a token that consists of uppercase letters and contains the given prefix and suffix from the value i
*
* @param i The value that will be represented as a token
* @return The generated token
*/
private String getUppercaseTokenFromInt(int i) {
StringBuilder sb = new StringBuilder();
while (i >= 0) {
sb.append((char)(i % 26 + 65));
i = i / 26 - 1;
}
//sb.append(suffix);
return sb.toString();
}
@Override
public String toString() {
return this.existingPlaceholders.toString();
}
@Override
public SerialMap toSerial(KeyStorage keyStorage) {
SerialMap serialized = new SerialMap();
serialized.put("ph", new SerialValue<>(new ArrayList<>(this.existingPlaceholders)));
serialized.put("factoryPh", SerialList.fromMapped(this.UnifyTypeFactory_PLACEHOLDERS, t -> t.toSerial(keyStorage)));
return serialized;
}
}

View File

@@ -1,10 +1,12 @@
package de.dhbwstuttgart.typeinference.unify; package de.dhbwstuttgart.typeinference.unify;
import de.dhbwstuttgart.util.Logger;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.ListIterator;
import java.util.Optional; import java.util.Optional;
import java.util.Queue; import java.util.Queue;
import java.util.Set; import java.util.Set;
@@ -12,24 +14,16 @@ import java.util.Stack;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.exceptions.DebugException; import de.dhbwstuttgart.exceptions.DebugException;
import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory;
import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unify.interfaces.IRuleSet; import de.dhbwstuttgart.typeinference.unify.interfaces.IRuleSet;
import de.dhbwstuttgart.typeinference.unify.model.*; import de.dhbwstuttgart.typeinference.unify.model.*;
import de.dhbwstuttgart.typeinference.constraints.Constraint; import de.dhbwstuttgart.typeinference.constraints.Constraint;
import de.dhbwstuttgart.typeinference.unify.distributeVariance;
import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.Writer; import java.io.Writer;
import java.io.OutputStreamWriter; import java.io.OutputStreamWriter;
import org.apache.commons.io.output.NullOutputStream;
/** /**
* Implementation of the type inference rules. * Implementation of the type inference rules.
* @author Florian Steurer * @author Florian Steurer
@@ -37,15 +31,18 @@ import org.apache.commons.io.output.NullOutputStream;
*/ */
public class RuleSet implements IRuleSet{ public class RuleSet implements IRuleSet{
Writer logFile; Logger logger;
final PlaceholderRegistry placeholderRegistry;
public RuleSet() { public RuleSet(PlaceholderRegistry placeholderRegistry) {
super(); super();
logFile = new OutputStreamWriter(new NullOutputStream()); logger = Logger.NULL_LOGGER;
this.placeholderRegistry = placeholderRegistry;
} }
RuleSet(Writer logFile) { RuleSet(Logger logger, PlaceholderRegistry placeholderRegistry) {
this.logFile = logFile; this.logger = logger;
this.placeholderRegistry = placeholderRegistry;
} }
@Override @Override
@@ -297,8 +294,8 @@ public class RuleSet implements IRuleSet{
if(dFromFc == null || !dFromFc.getTypeParams().arePlaceholders() || dFromFc.getTypeParams().size() != cFromFc.getTypeParams().size()) if(dFromFc == null || !dFromFc.getTypeParams().arePlaceholders() || dFromFc.getTypeParams().size() != cFromFc.getTypeParams().size())
return Optional.empty(); return Optional.empty();
//System.out.println("cFromFc: " + cFromFc); //context.logger().info("cFromFc: " + cFromFc);
//System.out.println("dFromFc: " + dFromFc); //context.logger().info("dFromFc: " + dFromFc);
int[] pi = pi(cFromFc.getTypeParams(), dFromFc.getTypeParams()); int[] pi = pi(cFromFc.getTypeParams(), dFromFc.getTypeParams());
if(pi.length == 0) if(pi.length == 0)
@@ -507,17 +504,17 @@ public class RuleSet implements IRuleSet{
TypeParams typeDParams = typeD.getTypeParams(); TypeParams typeDParams = typeD.getTypeParams();
TypeParams typeDgenParams = typeDgen.getTypeParams(); TypeParams typeDgenParams = typeDgen.getTypeParams();
//System.out.println("Pair: " +pair); //context.logger().info("Pair: " +pair);
//System.out.println("typeD: " +typeD); //context.logger().info("typeD: " +typeD);
//System.out.println("typeDParams: " +typeDParams); //context.logger().info("typeDParams: " +typeDParams);
//System.out.println("typeDgen: " +typeD); //context.logger().info("typeDgen: " +typeD);
//System.out.println("typeDgenParams: " +typeDgenParams); //context.logger().info("typeDgenParams: " +typeDgenParams);
Unifier unif = Unifier.identity(); Unifier unif = Unifier.identity();
for(int i = 0; i < typeDParams.size(); i++) { for(int i = 0; i < typeDParams.size(); i++) {
//System.out.println("ADAPT" +typeDgenParams); //context.logger().info("ADAPT" +typeDgenParams);
if (typeDgenParams.get(i) instanceof PlaceholderType) if (typeDgenParams.get(i) instanceof PlaceholderType)
unif.add((PlaceholderType) typeDgenParams.get(i), typeDParams.get(i)); unif.add((PlaceholderType) typeDgenParams.get(i), typeDParams.get(i));
else System.out.println("ERROR"); else logger.exception(new Exception("ERROR in adapt rule: cannot add non placeholder type"));
} }
return Optional.of(new UnifyPair(unif.apply(newLhs), typeDs, PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); return Optional.of(new UnifyPair(unif.apply(newLhs), typeDs, PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair()));
} }
@@ -652,9 +649,11 @@ public class RuleSet implements IRuleSet{
@Override @Override
public Optional<Set<UnifyPair>> subst(Set<UnifyPair> pairs, List<Set<Constraint<UnifyPair>>> oderConstraints) { public Optional<Set<UnifyPair>> subst(Set<UnifyPair> pairs, List<Set<Constraint<UnifyPair>>> oderConstraints) {
HashMap<UnifyType, Integer> typeMap = new HashMap<>(); // Statistically, typeMap will fill up quickly and resize multiple times. To reduce this, we start with a higher capacity
HashMap<UnifyType, Integer> typeMap = new HashMap<>(200);
Stack<UnifyType> occuringTypes = new Stack<>(); Stack<UnifyType> occuringTypes = new Stack<>();
occuringTypes.ensureCapacity(pairs.size() * 3);
for(UnifyPair pair : pairs) { for(UnifyPair pair : pairs) {
occuringTypes.push(pair.getLhsType()); occuringTypes.push(pair.getLhsType());
@@ -672,9 +671,9 @@ public class RuleSet implements IRuleSet{
if(t1 instanceof SuperType) if(t1 instanceof SuperType)
occuringTypes.push(((SuperType) t1).getSuperedType()); occuringTypes.push(((SuperType) t1).getSuperedType());
else else
t1.getTypeParams().forEach(x -> occuringTypes.push(x)); t1.getTypeParams().forEach(occuringTypes::push);
} }
Queue<UnifyPair> result1 = new LinkedList<UnifyPair>(pairs); LinkedList<UnifyPair> result1 = new LinkedList<UnifyPair>(pairs);
ArrayList<UnifyPair> result = new ArrayList<UnifyPair>(); ArrayList<UnifyPair> result = new ArrayList<UnifyPair>();
boolean applied = false; boolean applied = false;
@@ -695,19 +694,30 @@ public class RuleSet implements IRuleSet{
&& !((rhsType instanceof WildcardType) && ((WildcardType)rhsType).getWildcardedType().equals(lhsType))) //PL eigefuegt 2018-02-18 && !((rhsType instanceof WildcardType) && ((WildcardType)rhsType).getWildcardedType().equals(lhsType))) //PL eigefuegt 2018-02-18
{ {
Unifier uni = new Unifier(lhsType, rhsType); Unifier uni = new Unifier(lhsType, rhsType);
result = result.stream().map(x -> uni.apply(pair,x)).collect(Collectors.toCollection(ArrayList::new)); // apply unifier to result and result1 in place
result1 = result1.stream().map(x -> uni.apply(pair,x)).collect(Collectors.toCollection(LinkedList::new)); result.replaceAll(p -> uni.apply(pair, p));
ListIterator<UnifyPair> result1Iterator = result1.listIterator();
while (result1Iterator.hasNext()) {
UnifyPair x = result1Iterator.next();
result1Iterator.set(uni.apply(pair, x));
}
Function<? super Constraint<UnifyPair>,? extends Constraint<UnifyPair>> applyUni = b -> b.stream().map( Function<? super Constraint<UnifyPair>,? extends Constraint<UnifyPair>> applyUni = b -> b.stream().map(
x -> uni.apply(pair,x)).collect(Collectors.toCollection((b.getExtendConstraint() != null) x -> uni.apply(pair,x)).collect(Collectors.toCollection((b.getExtendConstraint() != null)
? () -> new Constraint<UnifyPair>( ? () -> new Constraint<UnifyPair>(
b.isInherited(), b.isInherited(),
b.isImplemented(), b.isImplemented(),
b.getExtendConstraint().stream().map(x -> uni.apply(pair,x)).collect(Collectors.toCollection(Constraint::new)), b.getExtendConstraint().createdMapped(x -> uni.apply(pair,x)),
b.getmethodSignatureConstraint().stream().map(x -> uni.apply(pair,x)).collect(Collectors.toCollection(HashSet::new))) b.getmethodSignatureConstraint().stream().map(x -> uni.apply(pair,x)).collect(Collectors.toCollection(HashSet::new)))
: () -> new Constraint<UnifyPair>(b.isInherited(), b.isImplemented()) : () -> new Constraint<UnifyPair>(b.isInherited(), b.isImplemented())
)); ));
oderConstraints.replaceAll(oc -> oc.stream().map(applyUni).collect(Collectors.toCollection(HashSet::new))); oderConstraints.replaceAll(oc -> {
HashSet<Constraint<UnifyPair>> mapped = new HashSet<>(oc.size());
for (var element : oc) {
mapped.add(applyUni.apply(element));
}
return mapped;
});
/* /*
oderConstraints = oderConstraints.stream().map( oderConstraints = oderConstraints.stream().map(
a -> a.stream().map(applyUni a -> a.stream().map(applyUni
@@ -861,14 +871,11 @@ public class RuleSet implements IRuleSet{
UnifyType r = x.getRhsType(); UnifyType r = x.getRhsType();
if (r instanceof PlaceholderType) { ((PlaceholderType)r).disableWildcardtable(); } if (r instanceof PlaceholderType) { ((PlaceholderType)r).disableWildcardtable(); }
} ); } );
try {
logFile.write("FUNgreater: " + pair + "\n"); logger.debug(() -> "FUNgreater: " + pair);
logFile.write("FUNred: " + result + "\n"); logger.debug(() -> "FUNred: " + result);
logFile.flush();
}
catch (IOException e) {
System.out.println("logFile-Error");
}
return Optional.of(result); return Optional.of(result);
} }
@@ -934,15 +941,15 @@ public class RuleSet implements IRuleSet{
Set<UnifyPair> result = new HashSet<UnifyPair>(); Set<UnifyPair> result = new HashSet<UnifyPair>();
Integer variance = ((PlaceholderType)rhsType).getVariance(); int variance = ((PlaceholderType)rhsType).getVariance();
Integer inversVariance = distributeVariance.inverseVariance(variance); int inversVariance = distributeVariance.inverseVariance(variance);
UnifyType[] freshPlaceholders = new UnifyType[funNLhsType.getTypeParams().size()]; UnifyType[] freshPlaceholders = new UnifyType[funNLhsType.getTypeParams().size()];
for(int i = 0; i < freshPlaceholders.length-1; i++) { for(int i = 0; i < freshPlaceholders.length-1; i++) {
freshPlaceholders[i] = PlaceholderType.freshPlaceholder(); freshPlaceholders[i] = PlaceholderType.freshPlaceholder(placeholderRegistry);
((PlaceholderType)freshPlaceholders[i]).setVariance(inversVariance); ((PlaceholderType)freshPlaceholders[i]).setVariance(inversVariance);
} }
freshPlaceholders[freshPlaceholders.length-1] = PlaceholderType.freshPlaceholder(); freshPlaceholders[freshPlaceholders.length-1] = PlaceholderType.freshPlaceholder(placeholderRegistry);
((PlaceholderType)freshPlaceholders[freshPlaceholders.length-1]).setVariance(variance); ((PlaceholderType)freshPlaceholders[freshPlaceholders.length-1]).setVariance(variance);
result.add(new UnifyPair(funNLhsType.getTypeParams().get(funNLhsType.getTypeParams().size()-1), freshPlaceholders[funNLhsType.getTypeParams().size()-1], PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); result.add(new UnifyPair(funNLhsType.getTypeParams().get(funNLhsType.getTypeParams().size()-1), freshPlaceholders[funNLhsType.getTypeParams().size()-1], PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair()));
@@ -957,14 +964,10 @@ public class RuleSet implements IRuleSet{
UnifyType r = x.getRhsType(); UnifyType r = x.getRhsType();
if (r instanceof PlaceholderType) { ((PlaceholderType)r).disableWildcardtable(); } if (r instanceof PlaceholderType) { ((PlaceholderType)r).disableWildcardtable(); }
} ); } );
try {
logFile.write("FUNgreater: " + pair + "\n"); logger.debug(() -> "FUNgreater: " + pair);
logFile.write("FUNgreater: " + result + "\n"); logger.debug(() -> "FUNgreater: " + result);
logFile.flush();
}
catch (IOException e) {
System.out.println("lofFile-Error");
}
return Optional.of(result); return Optional.of(result);
} }
@@ -983,15 +986,15 @@ public class RuleSet implements IRuleSet{
Set<UnifyPair> result = new HashSet<UnifyPair>(); Set<UnifyPair> result = new HashSet<UnifyPair>();
Integer variance = ((PlaceholderType)lhsType).getVariance(); int variance = ((PlaceholderType)lhsType).getVariance();
Integer inversVariance = distributeVariance.inverseVariance(variance); int inversVariance = distributeVariance.inverseVariance(variance);
UnifyType[] freshPlaceholders = new UnifyType[funNRhsType.getTypeParams().size()]; UnifyType[] freshPlaceholders = new UnifyType[funNRhsType.getTypeParams().size()];
for(int i = 0; i < freshPlaceholders.length-1; i++) { for(int i = 0; i < freshPlaceholders.length-1; i++) {
freshPlaceholders[i] = PlaceholderType.freshPlaceholder(); freshPlaceholders[i] = PlaceholderType.freshPlaceholder(placeholderRegistry);
((PlaceholderType)freshPlaceholders[i]).setVariance(inversVariance); ((PlaceholderType)freshPlaceholders[i]).setVariance(inversVariance);
} }
freshPlaceholders[freshPlaceholders.length-1] = PlaceholderType.freshPlaceholder(); freshPlaceholders[freshPlaceholders.length-1] = PlaceholderType.freshPlaceholder(placeholderRegistry);
((PlaceholderType)freshPlaceholders[freshPlaceholders.length-1]).setVariance(variance); ((PlaceholderType)freshPlaceholders[freshPlaceholders.length-1]).setVariance(variance);
result.add(new UnifyPair(freshPlaceholders[funNRhsType.getTypeParams().size()-1], funNRhsType.getTypeParams().get(funNRhsType.getTypeParams().size()-1), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); result.add(new UnifyPair(freshPlaceholders[funNRhsType.getTypeParams().size()-1], funNRhsType.getTypeParams().get(funNRhsType.getTypeParams().size()-1), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair()));
@@ -1007,14 +1010,11 @@ public class RuleSet implements IRuleSet{
UnifyType r = x.getRhsType(); UnifyType r = x.getRhsType();
if (r instanceof PlaceholderType) { ((PlaceholderType)r).disableWildcardtable(); } if (r instanceof PlaceholderType) { ((PlaceholderType)r).disableWildcardtable(); }
} ); } );
try {
logFile.write("FUNgreater: " + pair + "\n");
logFile.write("FUNsmaller: " + result + "\n"); logger.debug(() -> "FUNgreater: " + pair);
logFile.flush(); logger.debug(() -> "FUNsmaller: " + result);
}
catch (IOException e) {
System.out.println("lofFile-Error");
}
return Optional.of(result); return Optional.of(result);
} }
@@ -1051,7 +1051,7 @@ public class RuleSet implements IRuleSet{
if(isGen) if(isGen)
result.add(new UnifyPair(rhsType, lhsType, PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); result.add(new UnifyPair(rhsType, lhsType, PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair()));
else { else {
UnifyType freshTph = PlaceholderType.freshPlaceholder(); UnifyType freshTph = PlaceholderType.freshPlaceholder(placeholderRegistry);
result.add(new UnifyPair(rhsType, new ExtendsType(freshTph), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); result.add(new UnifyPair(rhsType, new ExtendsType(freshTph), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair()));
result.add(new UnifyPair(extendedType, freshTph, PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); result.add(new UnifyPair(extendedType, freshTph, PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair()));
} }
@@ -1079,7 +1079,7 @@ public class RuleSet implements IRuleSet{
if(isGen) if(isGen)
result.add(new UnifyPair(rhsType, lhsType, PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); result.add(new UnifyPair(rhsType, lhsType, PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair()));
else { else {
UnifyType freshTph = PlaceholderType.freshPlaceholder(); UnifyType freshTph = PlaceholderType.freshPlaceholder(placeholderRegistry);
result.add(new UnifyPair(rhsType, new SuperType(freshTph), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); result.add(new UnifyPair(rhsType, new SuperType(freshTph), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair()));
Set<UnifyType> fBounded = pair.getfBounded(); Set<UnifyType> fBounded = pair.getfBounded();
fBounded.add(lhsType); fBounded.add(lhsType);

View File

@@ -1,90 +1,65 @@
package de.dhbwstuttgart.typeinference.unify; package de.dhbwstuttgart.typeinference.unify;
import java.io.FileWriter; import de.dhbwstuttgart.util.Logger;
import java.io.IOException; import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinPool;
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.typeinference.constraints.Constraint; import de.dhbwstuttgart.typeinference.constraints.Constraint;
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
import de.dhbwstuttgart.typeinference.constraints.Pair;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unify.model.FiniteClosure;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
public class TypeUnify { public class TypeUnify {
private TypeUnify() {}
private static <T> T joinFuture(CompletableFuture<T> future) {
try {
return future.get();
}
catch (InterruptedException | ExecutionException exception) {
throw new RuntimeException(exception);
}
}
/** /**
* unify parallel ohne result modell * unify parallel ohne result modell
* @param undConstrains
* @param oderConstraints
* @param fc
* @param logFile
* @param log
* @param cons
* @return
*/ */
public Set<Set<UnifyPair>> unify(Set<UnifyPair> undConstrains, List<Set<Constraint<UnifyPair>>> oderConstraints, IFiniteClosure fc, Writer logFile, Boolean log, UnifyResultModel ret, UnifyTaskModel usedTasks) { public static Set<Set<UnifyPair>> unify(Set<UnifyPair> undConstrains, List<Set<Constraint<UnifyPair>>> oderConstraints, IFiniteClosure fc, UnifyContext unifyContext) {
TypeUnifyTask unifyTask = new TypeUnifyTask(undConstrains, oderConstraints, fc, true, logFile, log, 0, ret, usedTasks); ForkJoinPool pool = TypeUnify.createThreadPool(unifyContext.logger());
ForkJoinPool pool = new ForkJoinPool(); UnifyContext context = unifyContext.newWithParallel(true).newWithExecutor(pool);
pool.invoke(unifyTask); TypeUnifyTask unifyTask = new TypeUnifyTask(undConstrains, oderConstraints, fc, context, 0);
Set<Set<UnifyPair>> res = unifyTask.join(); Set<Set<UnifyPair>> res = joinFuture(unifyTask.compute());
try {
logFile.write("\nnoShortendElements: " + unifyTask.noShortendElements + "\n"); unifyContext.logger().debug("\nnoShortendElements: " + TypeUnifyTask.noShortendElements + "\n");
logFile.flush();
}
catch (IOException e) {
System.err.println("no log-File");
}
return res; return res;
} }
/** /**
* unify asynchron mit Rückgabe UnifyResultModel ohne dass alle results gesammelt sind * unify asynchron mit Rückgabe UnifyResultModel ohne dass alle results gesammelt sind
* @param undConstrains
* @param oderConstraints
* @param fc
* @param logFile
* @param log
* @param cons
* @param ret
* @return
*/ */
public UnifyResultModel unifyAsync(Set<UnifyPair> undConstrains, List<Set<Constraint<UnifyPair>>> oderConstraints, IFiniteClosure fc, Writer logFile, Boolean log, UnifyResultModel ret, UnifyTaskModel usedTasks) { public static UnifyResultModel unifyAsync(Set<UnifyPair> undConstrains, List<Set<Constraint<UnifyPair>>> oderConstraints, IFiniteClosure fc, UnifyContext unifyContext) {
TypeUnifyTask unifyTask = new TypeUnifyTask(undConstrains, oderConstraints, fc, true, logFile, log, 0, ret, usedTasks); ForkJoinPool pool = TypeUnify.createThreadPool(unifyContext.logger());
ForkJoinPool pool = new ForkJoinPool(); UnifyContext context = unifyContext.newWithExecutor(pool);
pool.invoke(unifyTask); TypeUnifyTask unifyTask = new TypeUnifyTask(undConstrains, oderConstraints, fc, context, 0);
return ret; unifyTask.compute();
return unifyContext.resultModel();
} }
/** /**
* unify parallel mit Rückgabe UnifyResultModel nachdem alle results gesammelt sind * unify parallel mit Rückgabe UnifyResultModel nachdem alle results gesammelt sind
* @param undConstrains
* @param oderConstraints
* @param fc
* @param logFile
* @param log
* @param cons
* @param ret
* @return
*/ */
public UnifyResultModel unifyParallel(Set<UnifyPair> undConstrains, List<Set<Constraint<UnifyPair>>> oderConstraints, IFiniteClosure fc, Writer logFile, Boolean log, UnifyResultModel ret, UnifyTaskModel usedTasks) { public static Set<Set<UnifyPair>> unifyParallel(Set<UnifyPair> undConstrains, List<Set<Constraint<UnifyPair>>> oderConstraints, IFiniteClosure fc, UnifyContext unifyContext) {
TypeUnifyTask unifyTask = new TypeUnifyTask(undConstrains, oderConstraints, fc, true, logFile, log, 0, ret, usedTasks); ForkJoinPool pool = TypeUnify.createThreadPool(unifyContext.logger());
ForkJoinPool pool = new ForkJoinPool(); UnifyContext context = unifyContext.newWithParallel(true).newWithExecutor(pool);
pool.invoke(unifyTask); TypeUnifyTask unifyTask = new TypeUnifyTask(undConstrains, oderConstraints, fc, context, 0);
Set<Set<UnifyPair>> res = unifyTask.join(); var result = joinFuture(unifyTask.compute());
try {
logFile.write("\nnoShortendElements: " + unifyTask.noShortendElements +"\n"); unifyContext.logger().debug("\nnoShortendElements: " + TypeUnifyTask.noShortendElements + "\n");
logFile.flush(); return result;
}
catch (IOException e) {
System.err.println("no log-File");
}
return ret;
} }
/* /*
@@ -97,25 +72,22 @@ public class TypeUnify {
/** /**
* unify sequentiell mit oderconstraints * unify sequentiell mit oderconstraints
* @param undConstrains
* @param oderConstraints
* @param fc
* @param logFile
* @param log
* @param cons
* @return
*/ */
public Set<Set<UnifyPair>> unifyOderConstraints(Set<UnifyPair> undConstrains, List<Set<Constraint<UnifyPair>>> oderConstraints, IFiniteClosure fc, Writer logFile, Boolean log, UnifyResultModel ret, UnifyTaskModel usedTasks) { public static Set<Set<UnifyPair>> unifyOderConstraints(Set<UnifyPair> undConstrains, List<Set<Constraint<UnifyPair>>> oderConstraints, IFiniteClosure fc, UnifyContext unifyContext) {
TypeUnifyTask unifyTask = new TypeUnifyTask(undConstrains, oderConstraints, fc, false, logFile, log, 0, ret, usedTasks); TypeUnifyTask unifyTask = new TypeUnifyTask(undConstrains, oderConstraints, fc, unifyContext.newWithParallel(false), 0);
Set<Set<UnifyPair>> res = unifyTask.compute(); Set<Set<UnifyPair>> res = joinFuture(unifyTask.compute());
try { unifyContext.logger().debug("\nnoShortendElements: " + TypeUnifyTask.noShortendElements +"\n");
logFile.write("\nnoShortendElements: " + unifyTask.noShortendElements +"\n");
logFile.flush();
}
catch (IOException e) {
System.err.println("no log-File");
}
return res; return res;
} }
private static ForkJoinPool createThreadPool(Logger logger) {
logger.info("Available processors: " + Runtime.getRuntime().availableProcessors());
return new ForkJoinPool(
Runtime.getRuntime().availableProcessors(),
ForkJoinPool.defaultForkJoinWorkerThreadFactory,
null,
false
);
}
} }

View File

@@ -13,54 +13,46 @@ import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
import de.dhbwstuttgart.typeinference.constraints.Pair; import de.dhbwstuttgart.typeinference.constraints.Pair;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
import java.util.concurrent.CompletableFuture;
public class TypeUnify2Task extends TypeUnifyTask { public class TypeUnify2Task extends TypeUnifyTask {
Set<Set<UnifyPair>> setToFlatten; Set<Set<UnifyPair>> setToFlatten;
Set<UnifyPair> methodSignatureConstraintUebergabe; Set<UnifyPair> methodSignatureConstraintUebergabe;
public TypeUnify2Task(Set<Set<UnifyPair>> setToFlatten, Set<UnifyPair> eq, List<Set<Constraint<UnifyPair>>> oderConstraints, Set<UnifyPair> nextSetElement, IFiniteClosure fc, boolean parallel, Writer logFile, Boolean log, int rekTiefe, UnifyResultModel urm, UnifyTaskModel usedTasks, Set<UnifyPair> methodSignatureConstraintUebergabe) { public TypeUnify2Task(Set<Set<UnifyPair>> setToFlatten, Set<UnifyPair> eq, List<Set<Constraint<UnifyPair>>> oderConstraints, Set<UnifyPair> nextSetElement, IFiniteClosure fc, UnifyContext context, int rekTiefe, Set<UnifyPair> methodSignatureConstraintUebergabe) {
super(eq, oderConstraints, fc, parallel, logFile, log, rekTiefe, urm, usedTasks); super(eq, oderConstraints, fc, context, rekTiefe);
this.setToFlatten = setToFlatten; this.setToFlatten = setToFlatten;
this.nextSetElement = nextSetElement; this.nextSetElement = nextSetElement;
this.methodSignatureConstraintUebergabe = methodSignatureConstraintUebergabe; this.methodSignatureConstraintUebergabe = methodSignatureConstraintUebergabe;
} }
Set<UnifyPair> getNextSetElement() { public Set<UnifyPair> getNextSetElement() {
return nextSetElement; return nextSetElement;
} }
@Override @Override
protected Set<Set<UnifyPair>> compute() { public CompletableFuture<Set<Set<UnifyPair>>> compute() {
if (one) { if (one) {
System.out.println("two"); context.logger().info("two");
} }
one = true; one = true;
Set<Set<UnifyPair>> res = unify2(setToFlatten, eq, oderConstraintsField, fc, parallel, rekTiefeField, methodSignatureConstraintUebergabe); CompletableFuture<Set<Set<UnifyPair>>> res =
unify2(setToFlatten, eq, oderConstraintsField, fc, context.parallel(), rekTiefeField, methodSignatureConstraintUebergabe);
/*if (isUndefinedPairSetSet(res)) { /*if (isUndefinedPairSetSet(res)) {
return new HashSet<>(); } return new HashSet<>(); }
else else
*/ */
//writeLog("xxx"); //writeLog("xxx");
//noOfThread--; //noOfThread--;
synchronized (usedTasks) { if (this.isExecutionCancelled()) {
if (this.myIsCancelled()) { return CompletableFuture.completedFuture(new HashSet<>());
return new HashSet<>(); } else {
}
else {
return res; return res;
} }
} }
}
public void closeLogFile() { public void closeLogFile() {
context.logger().close();
try {
logFile.close();
}
catch (IOException ioE) {
System.err.println("no log-File" + thNo);
}
} }
} }

View File

@@ -0,0 +1,221 @@
package de.dhbwstuttgart.typeinference.unify;
import de.dhbwstuttgart.typeinference.unify.model.PairOperator;
import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
import de.dhbwstuttgart.typeinference.unify.model.UnifyType;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* A collection of capsuled (and thus static) functions to split up large algorithms in TypeUnifyTask
*/
public class TypeUnifyTaskHelper {
/**
* Filter all topLevelSets for those with a single element that contain only one pair:
* a <. theta,
* theta <. a or
* a =. theta
*/
public static Set<Set<UnifyPair>> getSingleElementSets(ArrayList<Set<? extends Set<UnifyPair>>> topLevelSets) {
return topLevelSets.stream()
.filter(x -> x.size() == 1)
.map(y -> y.stream().findFirst().get()).collect(Collectors.toSet());
}
/**
* Varianzbestimmung Anfang
* Oderconstraint, wenn entweder kein Basepair oder unterschiedliche Basepairs => oderConstraint = true;
* Varianz = 1 => Argumentvariable
* Varianz = -1 => Rückgabevariable
* Varianz = 0 => unklar
* Varianz = 2 => Operatoren oderConstraints
*/
public static int calculateVariance(List<Set<UnifyPair>> nextSetasList) {
Optional<Integer> xi = nextSetasList.stream().map(x -> x.stream().filter(y -> (y.getLhsType() instanceof PlaceholderType && !(y.getRhsType() instanceof PlaceholderType)))
.filter(z -> ((PlaceholderType) z.getLhsType()).getVariance() != 0)
.map(c -> ((PlaceholderType) c.getLhsType()).getVariance())
.reduce((a, b) -> {
if (a.intValue() == b.intValue()) return a;
else return 0;
})) //2 kommt insbesondere bei Oder-Constraints vor
.filter(Optional::isPresent)
.map(Optional::get)
.findAny();
return xi.orElse(0);
}
/**
*
*/
public static int calculateOderConstraintVariance(List<Set<UnifyPair>> nextSetAsList) {
Optional<Integer> optVariance =
nextSetAsList
.getFirst()
.stream()
.filter(x -> x.getGroundBasePair().getLhsType() instanceof PlaceholderType &&
!(x.getRhsType() instanceof PlaceholderType) &&
x.getPairOp() == PairOperator.EQUALSDOT)
.map(x ->
((PlaceholderType) x.getGroundBasePair().getLhsType()).getVariance())
.reduce((n, m) -> (n != 0) ? n : m);
//Fuer Operatorenaufrufe wird variance auf 2 gesetzt.
//da kein Receiver existiert also kein x.getGroundBasePair().getLhsType() instanceof PlaceholderType
//Bei Varianz = 2 werden alle Elemente des Kartesischen Produkts abgearbeitet
return optVariance.orElse(2);
}
/**
* Find the first occurrence (if any) of a UnifyPair with operator EQUALSDOT while having
* one side equal to its base pair counterpart
*/
public static Optional<UnifyPair> findEqualityConstrainedUnifyPair(Set<UnifyPair> nextSetElement) {
return nextSetElement.stream().filter(x ->
x.getPairOp()
.equals(PairOperator.EQUALSDOT))
.filter(x -> //Sicherstellen, dass bei a = ty a auch wirklich die gesuchte Typvariable ist
x.getLhsType()
.equals(x.getBasePair().getLhsType()) ||
x.getLhsType()
.equals(x.getBasePair().getRhsType())
).findFirst();
}
/**
* Find all unifyPairs, that associate the identified type variable of origPair with any concrete type. That means:
* If "a = type" is in origPair, then we get all UnifyPairs that contain either "a < typeA" or "typeB < a"
*/
public static Set<UnifyPair> findConstraintsWithSameTVAssociation(UnifyPair origPair, Set<Set<UnifyPair>> singleElementSets) {
UnifyType tyVar = origPair.getLhsType();
if (!(tyVar instanceof PlaceholderType)) {
tyVar = origPair.getRhsType();
}
UnifyType tyVarEF = tyVar;
return singleElementSets.stream()
.map(xx ->
xx.iterator().next())
.filter(x ->
(x.getLhsType().equals(tyVarEF) && !(x.getRhsType() instanceof PlaceholderType))
||
(x.getRhsType().equals(tyVarEF) && !(x.getLhsType() instanceof PlaceholderType))
)
.collect(Collectors.toCollection(HashSet::new));
}
/**
*
*/
public static boolean doesFirstNextSetHasSameBase(List<Set<UnifyPair>> nextSetAsList) {
if (nextSetAsList.isEmpty()) {
return false;
}
UnifyPair firstBasePair = null;
for (var unifyPair : nextSetAsList.getFirst().stream().toList()) {
var basePair = unifyPair.getBasePair();
// if any base pair is null, there is NOT always the same base!
if (basePair == null) {
return false;
}
if (firstBasePair == null) {
firstBasePair = basePair;
}
else if (!basePair.equals(firstBasePair)) {
return false;
}
}
return true;
}
/**
* Extracts data from every element in the nested lists of results. What data depends on the given
* extractor function
*/
public static Set<UnifyPair> collectFromThreadResult (
Set<Set<UnifyPair>> currentThreadResult,
Function<UnifyPair, Set<UnifyPair>> extractor
) {
return currentThreadResult.stream()
.map(b ->
b.stream()
.map(extractor)
.reduce((y, z) -> {
y.addAll(z);
return y;
})
.orElse(new HashSet<>()))
.reduce((y, z) -> {
y.addAll(z);
return y;
})
.orElse(new HashSet<>());
}
/**
* Extract a list of PlaceholderTypes from a set of pairs, such that each resulting element:
* - Is the LHS of a pair
* - Is a PlaceholderType
* - has a basePair Side that is a PlaceholderType with the same name
*/
public static List<PlaceholderType> extractMatchingPlaceholderTypes(Set<UnifyPair> pairs) {
return pairs.stream()
.filter(x -> {
UnifyType lhs = x.getLhsType();
UnifyType baseLhs = x.getBasePair().getLhsType();
UnifyType baseRhs = x.getBasePair().getRhsType();
return (lhs instanceof PlaceholderType) &&
((baseLhs instanceof PlaceholderType && lhs.getName().equals(baseLhs.getName())) ||
(baseRhs instanceof PlaceholderType && lhs.getName().equals(baseRhs.getName())));
})
.map(x -> (PlaceholderType) x.getLhsType())
.collect(Collectors.toCollection(ArrayList::new));
}
public static Set<UnifyPair> occursCheck(final Set<UnifyPair> eq) {
Set<UnifyPair> ocurrPairs = new HashSet<>(eq.size());
for (UnifyPair x : eq) {
UnifyType lhs = x.getLhsType();
UnifyType rhs = x.getRhsType();
if (lhs instanceof PlaceholderType lhsPlaceholder &&
!(rhs instanceof PlaceholderType) &&
rhs.getTypeParams().occurs(lhsPlaceholder))
{
x.setUndefinedPair();
ocurrPairs.add(x);
}
}
return ocurrPairs;
}
public static <T> HashSet<T> getPresizedHashSet(int minElements) {
if (minElements < 16) return new HashSet<>();
// HashSet and HashMap will resize at 75% load, so we account for that by multiplying with 1.5
int n = (int)(minElements * 1.5);
return new HashSet<>(n);
}
public static <S,T> HashMap<S,T> getPresizedHashMap(int minElements) {
if (minElements < 16) return new HashMap<>();
// HashSet and HashMap will resize at 75% load, so we account for that by multiplying with 1.5
int n = (int)(minElements * 1.5);
return new HashMap<>(n);
}
}

View File

@@ -0,0 +1,67 @@
package de.dhbwstuttgart.typeinference.unify;
import de.dhbwstuttgart.util.Logger;
import java.io.Writer;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ForkJoinPool;
public record UnifyContext(
// main logger of a unification
Logger logger,
// if the unify algorithm should run in parallel
boolean parallel,
// the model for storing calculated results
UnifyResultModel resultModel,
// the executor used for thread management in parallel execution
ExecutorService executor,
// a generator for new placeholders in this unify context
PlaceholderRegistry placeholderRegistry,
// a control structure to cancel the unification early
UnifyTaskModel usedTasks
) {
public UnifyContext(
Logger logger,
boolean parallel,
UnifyResultModel resultModel,
UnifyTaskModel usedTasks,
ExecutorService executor,
PlaceholderRegistry placeholderRegistry
) {
this(logger, parallel, resultModel, executor, placeholderRegistry, usedTasks);
}
public UnifyContext(
Logger logger,
boolean parallel,
UnifyResultModel resultModel,
UnifyTaskModel usedTasks,
PlaceholderRegistry placeholderRegistry
) {
this(logger, parallel, resultModel, usedTasks, ForkJoinPool.commonPool(), placeholderRegistry);
}
/*
* Shortcuts for creating a similar context with some properties changed. This combined with the final properties
* causes the UnifyContext to be essentially handled as a
*/
public UnifyContext newWithLogger(Logger logger) {
return new UnifyContext(logger, parallel, resultModel, executor, placeholderRegistry, usedTasks);
}
public UnifyContext newWithParallel(boolean parallel) {
if (this.parallel == parallel) return this;
return new UnifyContext(logger, parallel, resultModel, executor, placeholderRegistry, usedTasks);
}
public UnifyContext newWithExecutor(ExecutorService executor) {
return new UnifyContext(logger, parallel, resultModel, executor, placeholderRegistry, usedTasks);
}
public UnifyContext newWithResultModel(UnifyResultModel resultModel) {
return new UnifyContext(logger, parallel, resultModel, executor, placeholderRegistry, usedTasks);
}
}

View File

@@ -36,19 +36,19 @@ public class UnifyResultModel {
listeners.remove(listenerToRemove); listeners.remove(listenerToRemove);
} }
public void notify(Set<Set<UnifyPair>> eqPrimePrimeSet) { public void notify(Set<Set<UnifyPair>> eqPrimePrimeSet, UnifyContext context) {
Set<Set<UnifyPair>> eqPrimePrimeSetRet = eqPrimePrimeSet.stream().map(x -> { Set<Set<UnifyPair>> eqPrimePrimeSetRet = eqPrimePrimeSet.stream().map(x -> {
Optional<Set<UnifyPair>> res = new RuleSet().subst(x.stream().map(y -> { Optional<Set<UnifyPair>> res = new RuleSet(context.placeholderRegistry()).subst(x.stream().map(y -> {
if (y.getPairOp() == PairOperator.SMALLERDOTWC) y.setPairOp(PairOperator.EQUALSDOT); if (y.getPairOp() == PairOperator.SMALLERDOTWC) y.setPairOp(PairOperator.EQUALSDOT);
return y; //alle Paare a <.? b erden durch a =. b ersetzt return y; //alle Paare a <.? b erden durch a =. b ersetzt
}).collect(Collectors.toCollection(HashSet::new))); }).collect(Collectors.toCollection(HashSet::new)));
if (res.isPresent()) {//wenn subst ein Erg liefert wurde was veraendert if (res.isPresent()) {//wenn subst ein Erg liefert wurde was veraendert
return new TypeUnifyTask().applyTypeUnificationRules(res.get(), fc); return new TypeUnifyTask(context).applyTypeUnificationRules(res.get(), fc);
} }
else return x; //wenn nichts veraendert wurde wird x zurueckgegeben else return x; //wenn nichts veraendert wurde wird x zurueckgegeben
}).collect(Collectors.toCollection(HashSet::new)); }).collect(Collectors.toCollection(HashSet::new));
List<ResultSet> newResult = eqPrimePrimeSetRet.stream().map(unifyPairs -> List<ResultSet> newResult = eqPrimePrimeSetRet.stream().map(unifyPairs ->
new ResultSet(UnifyTypeFactory.convert(unifyPairs, de.dhbwstuttgart.typeinference.constraints.Pair.generateTPHMap(cons)))) new ResultSet(UnifyTypeFactory.convert(unifyPairs, de.dhbwstuttgart.typeinference.constraints.Pair.generateTPHMap(cons), context.placeholderRegistry())))
.collect(Collectors.toList()); .collect(Collectors.toList());
UnifyResultEvent evt = new UnifyResultEvent(newResult); UnifyResultEvent evt = new UnifyResultEvent(newResult);

View File

@@ -12,7 +12,7 @@ public class UnifyTaskModel {
public synchronized void cancel() { public synchronized void cancel() {
for(TypeUnifyTask t : usedTasks) { for(TypeUnifyTask t : usedTasks) {
t.myCancel(true); t.cancelExecution();
} }
} }
} }

View File

@@ -0,0 +1,209 @@
package de.dhbwstuttgart.typeinference.unify.cartesianproduct;
import de.dhbwstuttgart.typeinference.constraints.Constraint;
import de.dhbwstuttgart.typeinference.unify.TypeUnify2Task;
import de.dhbwstuttgart.typeinference.unify.TypeUnifyTask;
import de.dhbwstuttgart.typeinference.unify.UnifyContext;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
import de.dhbwstuttgart.util.Tuple;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
public class ContravarianceCase extends VarianceCase {
protected final int variance = 1;
protected ContravarianceCase(boolean isOderConstraint, TypeUnifyTask typeUnifyTask, UnifyContext context) {
super(isOderConstraint, typeUnifyTask, context);
}
@Override
public void selectNextData(
TypeUnifyTask typeUnifyTask,
List<Set<UnifyPair>> nextSetAsList,
Optional<UnifyPair> optOrigPair
) {
a = typeUnifyTask.oup.max(nextSetAsList.iterator());
context.logger().debug("Max: a in " + variance + " " + a);
nextSetAsList.remove(a);
if (this.isOderConstraint) {
nextSetasListOderConstraints.add(((Constraint<UnifyPair>) a).getExtendConstraint());
}
context.logger().debug(() -> "nextSetasListOderConstraints 1: " + nextSetasListOderConstraints);
//Alle maximale Elemente in nextSetasListRest bestimmen
//nur für diese wird parallele Berechnung angestossen.
Set<UnifyPair> finalA = a;
nextSetasListRest = typeUnifyTask.oup.maxElements(
nextSetAsList.stream().filter(a_next -> typeUnifyTask.oup.compare(finalA, a_next) != 1).toList()
);
}
@Override
public CompletableFuture<ComputationResults> computeParallel(
Set<Set<UnifyPair>> elems,
Set<UnifyPair> eq,
List<Set<Constraint<UnifyPair>>> oderConstraints,
IFiniteClosure fc,
int rekTiefe,
Set<UnifyPair> methodSignatureConstraint,
List<Set<UnifyPair>> nextSetAsList,
Set<UnifyPair> sameEqSet,
Set<Set<UnifyPair>> result,
Set<Set<UnifyPair>> aParDef
) {
Set<UnifyPair> newEqOrig = new HashSet<>(eq);
Set<Set<UnifyPair>> newElemsOrig = new HashSet<>(elems);
List<Set<Constraint<UnifyPair>>> newOderConstraintsOrig = new ArrayList<>(oderConstraints);
newElemsOrig.add(a);
/* FORK ANFANG */
TypeUnify2Task forkOrig = new TypeUnify2Task(newElemsOrig, newEqOrig, newOderConstraintsOrig, a, fc, context, rekTiefe, methodSignatureConstraint);
typeUnifyTask.addChildTask(forkOrig);
// schedule compute() on another thread
CompletableFuture<Set<Set<UnifyPair>>> forkOrigFuture = CompletableFuture.supplyAsync(forkOrig::compute, context.executor()).thenCompose(f -> f);
CompletableFuture<ComputationResults> resultValues = forkOrigFuture.thenApply(
(currentThreadResult) -> {
forkOrig.context.logger().debug("final Orig 1");
forkOrig.closeLogFile();
return new ComputationResults(currentThreadResult);
});
//forks.add(forkOrig);
if (typeUnifyTask.isExecutionCancelled()) {
return CompletableFuture.completedFuture(new ComputationResults());
}
/* FORK ENDE */
context.logger().debug("a in " + variance + " " + a);
context.logger().debug("nextSetasListRest: " + nextSetasListRest.toString());
while (!nextSetasListRest.isEmpty()) {
Set<UnifyPair> nSaL = nextSetasListRest.removeFirst();
nextSetAsList.remove(nSaL);
context.logger().debug("1 RM" + nSaL.toString());
if (!this.isOderConstraint) {
//ueberpruefung ob zu a =. ty \in nSaL in sameEqSet ein Widerspruch besteht
if (!sameEqSet.isEmpty() && !typeUnifyTask.checkNoContradiction(nSaL, sameEqSet, result)) {
TypeUnifyTask.noShortendElements++;
continue;
}
} else {
nextSetasListOderConstraints.add(((Constraint<UnifyPair>) nSaL).getExtendConstraint());
}
Set<UnifyPair> newEq = new HashSet<>(eq);
Set<Set<UnifyPair>> newElems = new HashSet<>(elems);
List<Set<Constraint<UnifyPair>>> newOderConstraints = new ArrayList<>(oderConstraints);
newElems.add(nSaL);
TypeUnify2Task fork = new TypeUnify2Task(newElems, newEq, newOderConstraints, nSaL, fc, context, rekTiefe, new HashSet<>(methodSignatureConstraint));
typeUnifyTask.addChildTask(fork);
// schedule compute() on another thread
CompletableFuture<Set<Set<UnifyPair>>> forkFuture = CompletableFuture.supplyAsync(fork::compute, context.executor()).thenCompose(f -> f);
resultValues = resultValues.thenCombine(forkFuture,
(prevResults, fork_res) -> {
if (typeUnifyTask.isExecutionCancelled()) {
return new ComputationResults();
}
context.logger().debug("fork_res: " + fork_res.toString());
context.logger().debug(Boolean.valueOf((typeUnifyTask.isUndefinedPairSetSet(fork_res))).toString());
prevResults.addForkResult(fork_res);
if (!typeUnifyTask.isUndefinedPairSetSet(fork_res)) {
aParDef.add(fork.getNextSetElement());
}
fork.context.logger().debug("final 1");
fork.closeLogFile();
return prevResults;
}
);
if (typeUnifyTask.isExecutionCancelled()) {
return CompletableFuture.completedFuture(new ComputationResults());
}
}
return resultValues;
}
@Override
public void applyComputedResults(
Set<Set<UnifyPair>> result,
Set<Set<UnifyPair>> currentThreadResult,
Set<UnifyPair> compResult,
Set<UnifyPair> compRes
) {
int resOfCompare = typeUnifyTask.oup.compare(compResult, compRes);
if (resOfCompare == -1) {
context.logger().debug("Geloescht result: " + result);
result.clear();
result.addAll(currentThreadResult);
}
else if (resOfCompare == 0) {
result.addAll(currentThreadResult);
}
else if (resOfCompare == 1) {
context.logger().debug("Geloescht currentThreadResult: " + currentThreadResult);
//result = result;
}
}
@Override
public boolean eraseInvalidSets(
int rekTiefe,
Set<Set<UnifyPair>> aParDef,
List<Set<UnifyPair>> nextSetAsList
) {
// context.logger().info("");
context.logger().debug("a: " + rekTiefe + " variance: " + variance + a.toString());
context.logger().debug("aParDef: " + aParDef.toString());
aParDef.add(a);
Iterator<Set<UnifyPair>> aParDefIt = aParDef.iterator();
if (this.isOderConstraint) {
nextSetAsList.removeAll(nextSetasListOderConstraints);
nextSetasListOderConstraints = new ArrayList<>();
context.logger().debug("Removed: " + nextSetasListOderConstraints);
while (aParDefIt.hasNext()) {
Set<UnifyPair> a_new = aParDefIt.next();
List<Set<UnifyPair>> smallerSetasList = typeUnifyTask.oup.smallerThan(a_new, nextSetAsList);
context.logger().debug("smallerSetasList: " + smallerSetasList);
List<Set<UnifyPair>> notInherited = smallerSetasList.stream()
.filter(x -> !((Constraint<UnifyPair>) x).isInherited() && !((Constraint<UnifyPair>) x).isImplemented())
.collect(Collectors.toCollection(ArrayList::new));
context.logger().debug("notInherited: " + notInherited + "\n");
List<Set<UnifyPair>> notErased = new ArrayList<>();
notInherited.forEach(x -> {
notErased.addAll(typeUnifyTask.oup.smallerEqThan(x, smallerSetasList));
});
List<Set<UnifyPair>> erased = new ArrayList<>(smallerSetasList);
context.logger().debug("notErased: " + notErased + "\n");
erased.removeAll(notErased);
nextSetAsList.removeAll(erased);
context.logger().debug("Removed: " + erased);
context.logger().debug("Not Removed: " + nextSetAsList);
}
} else {
while (aParDefIt.hasNext()) {
//nextSetasListIt = nextSetasList.iterator(); Sollte eingefuegt werden PL 2020-04-28
Set<UnifyPair> a_new = aParDefIt.next();
List<Set<UnifyPair>> erased = typeUnifyTask.oup.smallerEqThan(a_new, nextSetAsList);
nextSetAsList.removeAll(erased);
context.logger().debug("Removed: " + erased);
context.logger().debug("Not Removed: " + nextSetAsList);
}
}
return false;
}
}

View File

@@ -0,0 +1,226 @@
package de.dhbwstuttgart.typeinference.unify.cartesianproduct;
import de.dhbwstuttgart.typeinference.constraints.Constraint;
import de.dhbwstuttgart.typeinference.unify.TypeUnify2Task;
import de.dhbwstuttgart.typeinference.unify.TypeUnifyTask;
import de.dhbwstuttgart.typeinference.unify.UnifyContext;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
import de.dhbwstuttgart.util.Tuple;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
public class CovarianceCase extends VarianceCase {
protected final int variance = -1;
protected CovarianceCase(boolean isOderConstraint, TypeUnifyTask typeUnifyTask, UnifyContext context) {
super(isOderConstraint, typeUnifyTask, context);
}
@Override
public void selectNextData(
TypeUnifyTask typeUnifyTask,
List<Set<UnifyPair>> nextSetAsList,
Optional<UnifyPair> optOrigPair
) {
a = typeUnifyTask.oup.min(nextSetAsList.iterator());
context.logger().debug(() -> "Min: a in " + variance + " " + a);
if (this.isOderConstraint) {
nextSetasListOderConstraints.add(((Constraint<UnifyPair>) a).getExtendConstraint());
}
context.logger().debug(() -> "nextSetasListOderConstraints -1: " + nextSetasListOderConstraints);
nextSetAsList.remove(a);
//Alle minimalen Elemente in nextSetasListRest bestimmen
//nur für diese wird parallele Berechnung angestossen.
Set<UnifyPair> finalA = a;
nextSetasListRest = typeUnifyTask.oup.minElements(
nextSetAsList.stream().filter(a_next -> typeUnifyTask.oup.compare(finalA, a_next) != -1).toList()
);
}
@Override
public CompletableFuture<ComputationResults> computeParallel(
Set<Set<UnifyPair>> elems,
Set<UnifyPair> eq,
List<Set<Constraint<UnifyPair>>> oderConstraints,
IFiniteClosure fc,
int rekTiefe,
Set<UnifyPair> methodSignatureConstraint,
List<Set<UnifyPair>> nextSetAsList,
Set<UnifyPair> sameEqSet,
Set<Set<UnifyPair>> result,
Set<Set<UnifyPair>> aParDef
) {
Set<UnifyPair> newEqOrig = new HashSet<>(eq);
Set<Set<UnifyPair>> newElemsOrig = new HashSet<>(elems);
List<Set<Constraint<UnifyPair>>> newOderConstraintsOrig = new ArrayList<>(oderConstraints);
newElemsOrig.add(a);
/* FORK ANFANG */
TypeUnify2Task forkOrig = new TypeUnify2Task(newElemsOrig, newEqOrig, newOderConstraintsOrig, a, fc, context, rekTiefe, methodSignatureConstraint);
typeUnifyTask.addChildTask(forkOrig);
// schedule compute() on another thread
CompletableFuture<Set<Set<UnifyPair>>> forkOrigFuture = CompletableFuture.supplyAsync(forkOrig::compute, context.executor()).thenCompose(f -> f);
CompletableFuture<ComputationResults> resultValues = forkOrigFuture.thenApply(
(currentThreadResult) -> {
forkOrig.context.logger().debug("final Orig -1");
forkOrig.closeLogFile();
return new ComputationResults(currentThreadResult);
});
//forks.add(forkOrig);
if (typeUnifyTask.isExecutionCancelled()) {
return resultValues;
}
/* FORK ENDE */
context.logger().debug(() -> "a in " + variance + " " + a);
context.logger().debug(() -> "nextSetasListRest: " + nextSetasListRest.toString());
while (!nextSetasListRest.isEmpty()) {
Set<UnifyPair> nSaL = nextSetasListRest.removeFirst();
nextSetAsList.remove(nSaL);
context.logger().debug(() -> "-1 RM" + nSaL.toString());
if (!this.isOderConstraint) {
//ueberpruefung ob zu a =. ty \in nSaL in sameEqSet ein Widerspruch besteht
if (!sameEqSet.isEmpty() && !typeUnifyTask.checkNoContradiction(nSaL, sameEqSet, result)) {
TypeUnifyTask.noShortendElements++;
continue;
}
} else {
nextSetasListOderConstraints.add(((Constraint<UnifyPair>) nSaL).getExtendConstraint());
}
Set<UnifyPair> newEq = new HashSet<>(eq);
Set<Set<UnifyPair>> newElems = new HashSet<>(elems);
List<Set<Constraint<UnifyPair>>> newOderConstraints = new ArrayList<>(oderConstraints);
newElems.add(nSaL);
TypeUnify2Task fork = new TypeUnify2Task(newElems, newEq, newOderConstraints, nSaL, fc, context, rekTiefe, new HashSet<>(methodSignatureConstraint));
typeUnifyTask.addChildTask(fork);
// schedule compute() on another thread
CompletableFuture<Set<Set<UnifyPair>>> forkFuture = CompletableFuture.supplyAsync(fork::compute, context.executor()).thenCompose(f -> f);
resultValues = resultValues.thenCombine(forkFuture,
(prevResults, fork_res) -> {
if (typeUnifyTask.isExecutionCancelled()) {
return prevResults;
}
context.logger().debug(() -> "fork_res: " + fork_res.toString());
context.logger().debug(() -> Boolean.valueOf((typeUnifyTask.isUndefinedPairSetSet(fork_res))).toString());
prevResults.addForkResult(fork_res);
if (!typeUnifyTask.isUndefinedPairSetSet(fork_res)) {
aParDef.add(fork.getNextSetElement());
}
fork.context.logger().debug("final -1");
fork.closeLogFile();
return prevResults;
}
);
if (typeUnifyTask.isExecutionCancelled()) {
return resultValues;
}
}
return resultValues;
}
@Override
public void applyComputedResults(
Set<Set<UnifyPair>> result,
Set<Set<UnifyPair>> currentThreadResult,
Set<UnifyPair> compResult,
Set<UnifyPair> compRes
) {
int resOfCompare = typeUnifyTask.oup.compare(compResult, compRes);
if (resOfCompare == 1) {
context.logger().debug(() -> "Geloescht result: " + result);
result.clear();
result.addAll(currentThreadResult);
} else if (resOfCompare == 0) {
result.addAll(currentThreadResult);
} else if (resOfCompare == -1) {
context.logger().debug(() -> "Geloescht currentThreadResult: " + currentThreadResult);
//result = result;
}
}
@Override
public boolean eraseInvalidSets(
int rekTiefe,
Set<Set<UnifyPair>> aParDef,
List<Set<UnifyPair>> nextSetAsList
) {
// context.logger().info("");
context.logger().debug(() -> "a: " + rekTiefe + " variance: " + variance + a.toString());
context.logger().debug(() -> "aParDef: " + aParDef.toString());
aParDef.add(a);
Iterator<Set<UnifyPair>> aParDefIt = aParDef.iterator();
if (this.isOderConstraint) {
nextSetAsList.removeAll(nextSetasListOderConstraints);
context.logger().debug(() -> "Removed: " + nextSetasListOderConstraints);
nextSetasListOderConstraints = new ArrayList<>();
while (aParDefIt.hasNext()) {
Set<UnifyPair> a_new = aParDefIt.next();
List<Set<UnifyPair>> greaterSetasList = typeUnifyTask.oup.greaterThan(a_new, nextSetAsList);
//a_new muss hingefuegt werden, wenn es nicht vererbt ist, dann wird es spaeter wieder geloescht
if (!((Constraint<UnifyPair>) a_new).isInherited()) {
greaterSetasList.add(a_new);
}
List<Set<UnifyPair>> notInherited = greaterSetasList.stream()
.filter(x -> !((Constraint<UnifyPair>) x).isInherited())
.collect(Collectors.toCollection(ArrayList::new));
List<Set<UnifyPair>> notErased = new ArrayList<>();
//Wenn x nicht vererbt ist, beginnt beim naechstgroesseren Element die naechste Ueberladung
notInherited.forEach(x -> {
notErased.addAll(typeUnifyTask.oup.greaterEqThan(x, greaterSetasList));
});
//das kleineste Element ist das Element von dem a_new geerbt hat
//muss deshalb geloescht werden
Iterator<Set<UnifyPair>> notErasedIt = notErased.iterator();
if (notErasedIt.hasNext()) {
Set<UnifyPair> min = typeUnifyTask.oup.min(notErasedIt);
notErased.remove(min);
notErased.remove(((Constraint<UnifyPair>) min).getExtendConstraint());
}
List<Set<UnifyPair>> erased = new ArrayList<>(greaterSetasList);
erased.removeAll(notErased);
nextSetAsList.removeAll(erased);
context.logger().debug(() -> "Removed: " + erased);
context.logger().debug(() -> "Not Removed: " + nextSetAsList);
}
} else {
while (aParDefIt.hasNext()) {
//nextSetasListIt = nextSetasList.iterator(); Sollte eingefuegt werden PL 2020-04-28
Set<UnifyPair> a_new = aParDefIt.next();
List<Set<UnifyPair>> erased = typeUnifyTask.oup.greaterEqThan(a_new, nextSetAsList);
nextSetAsList.removeAll(erased);
context.logger().debug(() -> "Removed: " + erased);
context.logger().debug(() -> "Not Removed: " + nextSetAsList);
}
}
return false;
}
}

Some files were not shown because too many files have changed in this diff Show More