Compare commits
130 Commits
3567bae0d7
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 3d50924c98 | |||
| eb0b4f42c3 | |||
| 6e0c85632f | |||
| 3c606b8f6a | |||
| a5b2d14481 | |||
| 6ae5d7ce0b | |||
| ff77630cdf | |||
| 2d9456317e | |||
| 6f18180567 | |||
| ed1be59546 | |||
| 42fabc115e | |||
| cfc419b98e | |||
| 3b2df3c186 | |||
| ed1feda8bf | |||
| 44d72a54e4 | |||
| 12f8dd162d | |||
| 6e37131fb2 | |||
| eb09117a67 | |||
| c7891b4965 | |||
| f7891b1196 | |||
| 1e926e4996 | |||
| acdaa1185b | |||
| a20a45d7c3 | |||
| a68035748c | |||
| 8c476b9e29 | |||
| 6bb462cd06 | |||
| 71555486b0 | |||
| 4048902442 | |||
|
|
4cfc070289 | ||
|
|
2920dfe68f | ||
| acce38e8b1 | |||
| dbd7f4fcfe | |||
| 9114642370 | |||
| 8ac0f96bd6 | |||
|
|
c9d38728af | ||
|
|
b7fad6e3c7 | ||
|
|
3cb9b74df1 | ||
|
|
effc31782f | ||
|
|
2a24eab9d3 | ||
|
|
b29eb71238 | ||
|
|
e9ce071e2b | ||
|
|
a314013f40 | ||
|
|
37c58be1f3 | ||
|
|
24920330c6 | ||
|
|
bc43ea749d | ||
|
|
af15a1b90c | ||
|
|
3d99f282f5 | ||
|
|
303c91dc87 | ||
|
|
c479b044b3 | ||
|
|
9046fb09e5 | ||
|
|
603a8b176a | ||
|
|
f396189a4b | ||
|
|
e7f4a94908 | ||
|
|
ce49a4b9a5 | ||
|
|
03b3692724 | ||
|
|
f0022d2b6f | ||
|
|
b1015cfa82 | ||
|
|
b63a27a0a0 | ||
|
|
3b0a53d3c4 | ||
|
|
50dbbf5f86 | ||
|
|
130c491ac0 | ||
|
|
9f9b264ac4 | ||
|
|
1393db05c2 | ||
|
|
93e1a8787c | ||
|
|
0129d7540f | ||
|
|
7ea8337aee | ||
|
|
28458d405f | ||
|
|
1b905cb3e2 | ||
|
|
d02c3583e9 | ||
|
|
ca98e83fd2 | ||
|
|
c80a0c8596 | ||
|
|
2278fb1b91 | ||
|
|
32b16cd5fd | ||
|
|
fd30c5f63f | ||
|
|
8bfd6ae255 | ||
|
|
ad2dfb13bd | ||
|
|
501633a90c | ||
|
|
4defa50ca2 | ||
|
|
d65e90536a | ||
|
|
3de7f1aa61 | ||
|
|
029e40b775 | ||
|
|
459bfcdd5f | ||
|
|
02886c38ea | ||
|
|
57ffae0481 | ||
|
|
d084d74a25 | ||
|
|
cd15016f61 | ||
|
|
b0e5eee25c | ||
|
|
d1bd285be7 | ||
|
|
a902fd5bee | ||
|
|
ced9fdc9f7 | ||
|
|
53417bf298 | ||
|
|
2d4da03f00 | ||
|
|
f7a13f5faa | ||
|
|
8fe80b4396 | ||
|
|
eb1201ae5e | ||
|
|
963ad76593 | ||
|
|
1eba09e3b0 | ||
|
|
fc82125d14 | ||
|
|
dad468368b | ||
|
|
fdd4f3aa59 | ||
|
|
a0c11b60e8 | ||
|
|
4cddf73e6d | ||
|
|
5024a02447 | ||
|
|
6c2d97b770 | ||
|
|
426c2916d3 | ||
|
|
f722a00fbb | ||
|
|
32797c9b9f | ||
|
|
87f655c85a | ||
|
|
613dceae1d | ||
|
|
81cac06e16 | ||
|
|
a47d5bc024 | ||
|
|
e5916d455a | ||
|
|
ebb639e72e | ||
|
|
f0a4a51ce6 | ||
|
|
7442880452 | ||
|
|
c4dc3b4245 | ||
|
|
42e31a3471 | ||
|
|
d3b3f92193 | ||
|
|
8208abcaea | ||
|
|
e4a3939ce9 | ||
|
|
d903ec0ebb | ||
|
|
61de81cf92 | ||
|
|
59888006e0 | ||
|
|
94034912b4 | ||
|
|
f303163118 | ||
|
|
7d99fba044 | ||
|
|
3740d34954 | ||
|
|
d8b861ea95 | ||
|
|
cf45ea68bd | ||
|
|
be72e4d7fb |
@@ -18,7 +18,7 @@ jobs:
|
|||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
distribution: 'temurin'
|
distribution: 'temurin'
|
||||||
java-version: '24'
|
java-version: '25'
|
||||||
cache: 'maven'
|
cache: 'maven'
|
||||||
- name: Compile project
|
- name: Compile project
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ jobs:
|
|||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
distribution: 'temurin'
|
distribution: 'temurin'
|
||||||
java-version: '24'
|
java-version: '25'
|
||||||
cache: 'maven'
|
cache: 'maven'
|
||||||
- name: Compile project
|
- name: Compile project
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
40
independentTest.sh
Executable file
40
independentTest.sh
Executable 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 "
|
||||||
|
|
||||||
32
pom.xml
32
pom.xml
@@ -44,6 +44,31 @@ http://maven.apache.org/maven-v4_0_0.xsd">
|
|||||||
<artifactId>asm</artifactId>
|
<artifactId>asm</artifactId>
|
||||||
<version>9.8</version>
|
<version>9.8</version>
|
||||||
</dependency>
|
</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>
|
||||||
|
<groupId>org.jcommander</groupId>
|
||||||
|
<artifactId>jcommander</artifactId>
|
||||||
|
<version>3.0</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
@@ -72,9 +97,8 @@ http://maven.apache.org/maven-v4_0_0.xsd">
|
|||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<version>3.14.0</version>
|
<version>3.14.0</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<compilerArgs>--enable-preview</compilerArgs>
|
<source>25</source>
|
||||||
<source>24</source>
|
<target>25</target>
|
||||||
<target>24</target>
|
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
@@ -157,4 +181,4 @@ http://maven.apache.org/maven-v4_0_0.xsd">
|
|||||||
<url>file:///${project.basedir}/maven-repository/</url>
|
<url>file:///${project.basedir}/maven-repository/</url>
|
||||||
</repository>
|
</repository>
|
||||||
</distributionManagement>
|
</distributionManagement>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
3
resources/bytecode/javFiles/Bug378Id.jav
Normal file
3
resources/bytecode/javFiles/Bug378Id.jav
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
class Bug378Id {
|
||||||
|
id2 = x -> x;
|
||||||
|
}
|
||||||
8
resources/bytecode/javFiles/Bug378Main.jav
Normal file
8
resources/bytecode/javFiles/Bug378Main.jav
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import Bug378Id;
|
||||||
|
import java.lang.Integer;
|
||||||
|
|
||||||
|
public class Bug378Main {
|
||||||
|
public static main(args) {
|
||||||
|
var hallo = (new Bug378Id<Integer>().id2).apply(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
24
resources/bytecode/javFiles/Bug379.jav
Normal file
24
resources/bytecode/javFiles/Bug379.jav
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import java.lang.Integer;
|
||||||
|
import java.lang.Double;
|
||||||
|
import java.lang.System;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
|
public class Bug379 {
|
||||||
|
public Fun1$$<Double, Double> fact = (x) -> {
|
||||||
|
if (x == 1) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return x * (fact.apply(x-1));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public getFact(x) {
|
||||||
|
return fact.apply(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(x) {
|
||||||
|
var f = new Bug379();
|
||||||
|
var intRes = f.getFact(3);
|
||||||
|
System.out.println(intRes);
|
||||||
|
}
|
||||||
|
}
|
||||||
12
resources/bytecode/javFiles/Bug380.jav
Normal file
12
resources/bytecode/javFiles/Bug380.jav
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
sealed interface List<T> permits Cons, Empty {}
|
||||||
|
record Cons<T>(T a , List<T> l ) implements List <T> {}
|
||||||
|
record Empty<T>() implements List <T> {}
|
||||||
|
|
||||||
|
public class Bug380 {
|
||||||
|
public <T> List<T> append(l1, List<T> l2) {
|
||||||
|
return switch ( l1 ) {
|
||||||
|
case Cons(e, rest) -> new Cons<>(e, append(rest, l2)); //::Typ TPH A
|
||||||
|
case Empty() -> l2;//::TPH B
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
13
resources/bytecode/javFiles/Bug382.jav
Normal file
13
resources/bytecode/javFiles/Bug382.jav
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import java.lang.Runnable;
|
||||||
|
import java.lang.String;
|
||||||
|
import java.lang.System;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.lang.Thread;
|
||||||
|
|
||||||
|
public class Bug382 {
|
||||||
|
public static main(a) {
|
||||||
|
var f = () -> System.out.println("Hallo Welt!");
|
||||||
|
new Thread(f).run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
10
resources/bytecode/javFiles/Bug383.jav
Normal file
10
resources/bytecode/javFiles/Bug383.jav
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import java.lang.String;
|
||||||
|
import java.lang.System;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
|
public class Bug383 {
|
||||||
|
public static main(a) {
|
||||||
|
var f = () -> System.out.println("Hello from Thread!");
|
||||||
|
f.apply();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ import java.lang.Integer;
|
|||||||
import java.lang.Boolean;
|
import java.lang.Boolean;
|
||||||
|
|
||||||
public class MatrixOP extends Vector<Vector<Integer>> {
|
public class MatrixOP extends Vector<Vector<Integer>> {
|
||||||
|
|
||||||
MatrixOP () {
|
MatrixOP () {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,8 +36,8 @@ public class MatrixOP extends Vector<Vector<Integer>> {
|
|||||||
v2.addElement(erg);
|
v2.addElement(erg);
|
||||||
j++; }
|
j++; }
|
||||||
ret.addElement(v2);
|
ret.addElement(v2);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -1,17 +1,18 @@
|
|||||||
import java.lang.Integer;
|
import java.lang.Integer;
|
||||||
import java.lang.Double;
|
|
||||||
import java.lang.Number;
|
|
||||||
import java.lang.String;
|
import java.lang.String;
|
||||||
|
|
||||||
public record R(Number n) {}
|
public record R(String n) {}
|
||||||
|
|
||||||
public class SwitchOverload {
|
public class SwitchOverload {
|
||||||
|
|
||||||
public f(){}
|
f() { return 10; }
|
||||||
|
g() { return 20; }
|
||||||
|
|
||||||
public m(r) {
|
public m(r) {
|
||||||
return switch(r) {
|
return switch(r) {
|
||||||
case R("test") -> f();
|
case R("test") -> f();
|
||||||
|
case R("foo") -> g();
|
||||||
|
case R r -> 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8,6 +8,7 @@ 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.*;
|
||||||
@@ -20,6 +21,8 @@ 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;
|
||||||
@@ -125,34 +128,36 @@ public class Codegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void popValue(State state, TargetType type) {
|
private void popValue(State state, TargetType type) {
|
||||||
if (type.equals(TargetType.Double) || type.equals(TargetType.Long))
|
if (type.equals(TargetType.double_) || type.equals(TargetType.long_))
|
||||||
state.mv.visitInsn(POP2);
|
state.mv.visitInsn(POP2);
|
||||||
else
|
else
|
||||||
state.mv.visitInsn(POP);
|
state.mv.visitInsn(POP);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void boxPrimitive(State state, TargetType type) {
|
private void boxPrimitive(State state, TargetType type) {
|
||||||
|
if (type instanceof TargetExtendsWildcard ew) type = ew.innerType();
|
||||||
var mv = state.mv;
|
var mv = state.mv;
|
||||||
if (type.equals(TargetType.Boolean) || type.equals(TargetType.boolean_)) {
|
if (type.equals(TargetType.boolean_)) {
|
||||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false);
|
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false);
|
||||||
} else if (type.equals(TargetType.Byte) || type.equals(TargetType.byte_)) {
|
} else if (type.equals(TargetType.byte_)) {
|
||||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false);
|
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false);
|
||||||
} else if (type.equals(TargetType.Double) || type.equals(TargetType.double_)) {
|
} else if (type.equals(TargetType.double_)) {
|
||||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false);
|
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false);
|
||||||
} else if (type.equals(TargetType.Long) || type.equals(TargetType.long_)) {
|
} else if (type.equals(TargetType.long_)) {
|
||||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false);
|
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false);
|
||||||
} else if (type.equals(TargetType.Integer) || type.equals(TargetType.int_)) {
|
} else if (type.equals(TargetType.int_)) {
|
||||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
|
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
|
||||||
} else if (type.equals(TargetType.Float) || type.equals(TargetType.float_)) {
|
} else if (type.equals(TargetType.float_)) {
|
||||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false);
|
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false);
|
||||||
} else if (type.equals(TargetType.Short) || type.equals(TargetType.short_)) {
|
} else if (type.equals(TargetType.short_)) {
|
||||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false);
|
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false);
|
||||||
} else if (type.equals(TargetType.Char) || type.equals(TargetType.char_)) {
|
} else if (type.equals(TargetType.char_)) {
|
||||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false);
|
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void unboxPrimitive(State state, TargetType type) {
|
private void unboxPrimitive(State state, TargetType type) {
|
||||||
|
if (type instanceof TargetExtendsWildcard ew) type = ew.innerType();
|
||||||
var mv = state.mv;
|
var mv = state.mv;
|
||||||
if (type.equals(TargetType.Boolean)) {
|
if (type.equals(TargetType.Boolean)) {
|
||||||
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false);
|
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false);
|
||||||
@@ -183,9 +188,11 @@ public class Codegen {
|
|||||||
convertTo(state, op.right().type(), type);
|
convertTo(state, op.right().type(), type);
|
||||||
mv.visitJumpInsn(code, if_true);
|
mv.visitJumpInsn(code, if_true);
|
||||||
mv.visitInsn(ICONST_0);
|
mv.visitInsn(ICONST_0);
|
||||||
|
boxPrimitive(state, TargetType.toPrimitive(op.type()));
|
||||||
mv.visitJumpInsn(GOTO, end);
|
mv.visitJumpInsn(GOTO, end);
|
||||||
mv.visitLabel(if_true);
|
mv.visitLabel(if_true);
|
||||||
mv.visitInsn(ICONST_1);
|
mv.visitInsn(ICONST_1);
|
||||||
|
boxPrimitive(state, TargetType.toPrimitive(op.type()));
|
||||||
mv.visitLabel(end);
|
mv.visitLabel(end);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,9 +207,11 @@ public class Codegen {
|
|||||||
mv.visitInsn(cmp);
|
mv.visitInsn(cmp);
|
||||||
mv.visitJumpInsn(code, if_true);
|
mv.visitJumpInsn(code, if_true);
|
||||||
mv.visitInsn(ICONST_0);
|
mv.visitInsn(ICONST_0);
|
||||||
|
boxPrimitive(state, TargetType.toPrimitive(op.type()));
|
||||||
mv.visitJumpInsn(GOTO, end);
|
mv.visitJumpInsn(GOTO, end);
|
||||||
mv.visitLabel(if_true);
|
mv.visitLabel(if_true);
|
||||||
mv.visitInsn(ICONST_1);
|
mv.visitInsn(ICONST_1);
|
||||||
|
boxPrimitive(state, TargetType.toPrimitive(op.type()));
|
||||||
mv.visitLabel(end);
|
mv.visitLabel(end);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,65 +237,88 @@ public class Codegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void convertTo(State state, TargetType source, TargetType dest) {
|
private void convertTo(State state, TargetType source, TargetType dest) {
|
||||||
var mv = state.mv;
|
if (source instanceof TargetExtendsWildcard ew) source = ew.innerType();
|
||||||
|
if (dest instanceof TargetExtendsWildcard ew) dest = ew.innerType();
|
||||||
|
|
||||||
if (source.equals(dest))
|
if (source.equals(dest))
|
||||||
return;
|
return;
|
||||||
if (source.equals(TargetType.Long)) {
|
|
||||||
if (dest.equals(TargetType.Integer))
|
if (isFunctionalInterface(source) && isFunctionalInterface(dest) &&
|
||||||
mv.visitInsn(L2I);
|
|
||||||
else if (dest.equals(TargetType.Float))
|
|
||||||
mv.visitInsn(L2F);
|
|
||||||
else if (dest.equals(TargetType.Double))
|
|
||||||
mv.visitInsn(L2D);
|
|
||||||
else if (dest.equals(TargetType.Byte) || dest.equals(TargetType.Char) || dest.equals(TargetType.Short)) {
|
|
||||||
mv.visitInsn(L2I);
|
|
||||||
convertTo(state, TargetType.Integer, dest);
|
|
||||||
}
|
|
||||||
} else if (source.equals(TargetType.Float)) {
|
|
||||||
if (dest.equals(TargetType.Integer))
|
|
||||||
mv.visitInsn(F2I);
|
|
||||||
else if (dest.equals(TargetType.Double))
|
|
||||||
mv.visitInsn(F2D);
|
|
||||||
else if (dest.equals(TargetType.Long))
|
|
||||||
mv.visitInsn(F2L);
|
|
||||||
else if (dest.equals(TargetType.Byte) || dest.equals(TargetType.Char) || dest.equals(TargetType.Short)) {
|
|
||||||
mv.visitInsn(F2I);
|
|
||||||
convertTo(state, TargetType.Integer, dest);
|
|
||||||
}
|
|
||||||
} else if (source.equals(TargetType.Double)) {
|
|
||||||
if (dest.equals(TargetType.Integer))
|
|
||||||
mv.visitInsn(D2I);
|
|
||||||
else if (dest.equals(TargetType.Float))
|
|
||||||
mv.visitInsn(D2F);
|
|
||||||
else if (dest.equals(TargetType.Long))
|
|
||||||
mv.visitInsn(D2L);
|
|
||||||
else if (dest.equals(TargetType.Byte) || dest.equals(TargetType.Char) || dest.equals(TargetType.Short)) {
|
|
||||||
mv.visitInsn(D2I);
|
|
||||||
convertTo(state, TargetType.Integer, dest);
|
|
||||||
}
|
|
||||||
} else if (source.equals(TargetType.Byte) || source.equals(TargetType.Char) || source.equals(TargetType.Short) || source.equals(TargetType.Integer)) {
|
|
||||||
if (dest.equals(TargetType.Byte))
|
|
||||||
mv.visitInsn(I2B);
|
|
||||||
else if (dest.equals(TargetType.Char))
|
|
||||||
mv.visitInsn(I2C);
|
|
||||||
else if (dest.equals(TargetType.Short))
|
|
||||||
mv.visitInsn(I2S);
|
|
||||||
else if (dest.equals(TargetType.Long))
|
|
||||||
mv.visitInsn(I2L);
|
|
||||||
else if (dest.equals(TargetType.Float))
|
|
||||||
mv.visitInsn(I2F);
|
|
||||||
else if (dest.equals(TargetType.Double))
|
|
||||||
mv.visitInsn(I2D);
|
|
||||||
} else if (source.equals(TargetType.Boolean)) {
|
|
||||||
unboxPrimitive(state, dest);
|
|
||||||
} else if (isFunctionalInterface(source) && isFunctionalInterface(dest) &&
|
|
||||||
!(source instanceof TargetFunNType && dest instanceof TargetFunNType)) {
|
!(source instanceof TargetFunNType && dest instanceof TargetFunNType)) {
|
||||||
boxFunctionalInterface(state, source, dest);
|
boxFunctionalInterface(state, source, dest);
|
||||||
} else if (!(dest instanceof TargetGenericType)) {
|
return;
|
||||||
//boxPrimitive(state, source);
|
}
|
||||||
|
|
||||||
|
var mv = state.mv;
|
||||||
|
if ((source instanceof TargetRefType || source instanceof TargetGenericType) &&
|
||||||
|
(dest instanceof TargetRefType || dest instanceof TargetGenericType)) {
|
||||||
|
if (dest instanceof TargetGenericType) return;
|
||||||
mv.visitTypeInsn(CHECKCAST, dest.getInternalName());
|
mv.visitTypeInsn(CHECKCAST, dest.getInternalName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(source instanceof TargetPrimitiveType)) {
|
||||||
|
unboxPrimitive(state, source);
|
||||||
|
source = TargetType.toPrimitive(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
var origDest = dest;
|
||||||
|
dest = TargetType.toPrimitive(dest);
|
||||||
|
if (source.equals(TargetType.long_)) {
|
||||||
|
if (dest.equals(TargetType.int_))
|
||||||
|
mv.visitInsn(L2I);
|
||||||
|
else if (dest.equals(TargetType.float_))
|
||||||
|
mv.visitInsn(L2F);
|
||||||
|
else if (dest.equals(TargetType.double_))
|
||||||
|
mv.visitInsn(L2D);
|
||||||
|
else if (dest.equals(TargetType.byte_) || dest.equals(TargetType.char_) || dest.equals(TargetType.short_)) {
|
||||||
|
mv.visitInsn(L2I);
|
||||||
|
convertTo(state, TargetType.int_, dest);
|
||||||
|
}
|
||||||
|
} else if (source.equals(TargetType.float_)) {
|
||||||
|
if (dest.equals(TargetType.int_))
|
||||||
|
mv.visitInsn(F2I);
|
||||||
|
else if (dest.equals(TargetType.double_))
|
||||||
|
mv.visitInsn(F2D);
|
||||||
|
else if (dest.equals(TargetType.long_))
|
||||||
|
mv.visitInsn(F2L);
|
||||||
|
else if (dest.equals(TargetType.byte_) || dest.equals(TargetType.char_) || dest.equals(TargetType.short_)) {
|
||||||
|
mv.visitInsn(F2I);
|
||||||
|
convertTo(state, TargetType.int_, dest);
|
||||||
|
}
|
||||||
|
} else if (source.equals(TargetType.double_)) {
|
||||||
|
if (dest.equals(TargetType.int_))
|
||||||
|
mv.visitInsn(D2I);
|
||||||
|
else if (dest.equals(TargetType.float_))
|
||||||
|
mv.visitInsn(D2F);
|
||||||
|
else if (dest.equals(TargetType.long_))
|
||||||
|
mv.visitInsn(D2L);
|
||||||
|
else if (dest.equals(TargetType.byte_) || dest.equals(TargetType.char_) || dest.equals(TargetType.short_)) {
|
||||||
|
mv.visitInsn(D2I);
|
||||||
|
convertTo(state, TargetType.int_, dest);
|
||||||
|
}
|
||||||
|
} else if (source.equals(TargetType.byte_) || source.equals(TargetType.char_) || source.equals(TargetType.short_) || source.equals(TargetType.int_)) {
|
||||||
|
if (dest.equals(TargetType.byte_))
|
||||||
|
mv.visitInsn(I2B);
|
||||||
|
else if (dest.equals(TargetType.char_))
|
||||||
|
mv.visitInsn(I2C);
|
||||||
|
else if (dest.equals(TargetType.short_))
|
||||||
|
mv.visitInsn(I2S);
|
||||||
|
else if (dest.equals(TargetType.long_))
|
||||||
|
mv.visitInsn(I2L);
|
||||||
|
else if (dest.equals(TargetType.float_))
|
||||||
|
mv.visitInsn(I2F);
|
||||||
|
else if (dest.equals(TargetType.double_))
|
||||||
|
mv.visitInsn(I2D);
|
||||||
|
} else if (source.equals(TargetType.boolean_)) {
|
||||||
unboxPrimitive(state, dest);
|
unboxPrimitive(state, dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(origDest instanceof TargetPrimitiveType)) {
|
||||||
|
if (dest instanceof TargetPrimitiveType)
|
||||||
|
boxPrimitive(state, dest);
|
||||||
|
else boxPrimitive(state, source);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
record TypePair(TargetType from, TargetType to) {}
|
record TypePair(TargetType from, TargetType to) {}
|
||||||
@@ -345,9 +377,9 @@ public class Codegen {
|
|||||||
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "(Ljava/lang/String;)V", false);
|
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "(Ljava/lang/String;)V", false);
|
||||||
} else {
|
} else {
|
||||||
generate(state, add.left());
|
generate(state, add.left());
|
||||||
convertTo(state, add.left().type(), add.type());
|
convertTo(state, add.left().type(), TargetType.toPrimitive(add.type()));
|
||||||
generate(state, add.right());
|
generate(state, add.right());
|
||||||
convertTo(state, add.right().type(), add.type());
|
convertTo(state, add.right().type(), TargetType.toPrimitive(add.type()));
|
||||||
var type = add.type();
|
var type = add.type();
|
||||||
if (type.equals(TargetType.Byte) || type.equals(TargetType.Char) || type.equals(TargetType.Integer) || type.equals(TargetType.Short)) {
|
if (type.equals(TargetType.Byte) || type.equals(TargetType.Char) || type.equals(TargetType.Integer) || type.equals(TargetType.Short)) {
|
||||||
mv.visitInsn(IADD);
|
mv.visitInsn(IADD);
|
||||||
@@ -360,6 +392,7 @@ public class Codegen {
|
|||||||
} else {
|
} else {
|
||||||
throw new CodeGenException("Invalid argument to Add expression, type: " + add.type());
|
throw new CodeGenException("Invalid argument to Add expression, type: " + add.type());
|
||||||
}
|
}
|
||||||
|
boxPrimitive(state, TargetType.toPrimitive(op.type()));
|
||||||
}
|
}
|
||||||
if (add.type().equals(TargetType.String)) {
|
if (add.type().equals(TargetType.String)) {
|
||||||
generate(state, add.right());
|
generate(state, add.right());
|
||||||
@@ -371,9 +404,9 @@ public class Codegen {
|
|||||||
}
|
}
|
||||||
case Sub sub: {
|
case Sub sub: {
|
||||||
generate(state, sub.left());
|
generate(state, sub.left());
|
||||||
convertTo(state, sub.left().type(), op.type());
|
convertTo(state, sub.left().type(), TargetType.toPrimitive(op.type()));
|
||||||
generate(state, sub.right());
|
generate(state, sub.right());
|
||||||
convertTo(state, sub.right().type(), op.type());
|
convertTo(state, sub.right().type(), TargetType.toPrimitive(op.type()));
|
||||||
var type = sub.type();
|
var type = sub.type();
|
||||||
if (type.equals(TargetType.Byte) || type.equals(TargetType.Char) || type.equals(TargetType.Integer) || type.equals(TargetType.Short)) {
|
if (type.equals(TargetType.Byte) || type.equals(TargetType.Char) || type.equals(TargetType.Integer) || type.equals(TargetType.Short)) {
|
||||||
mv.visitInsn(ISUB);
|
mv.visitInsn(ISUB);
|
||||||
@@ -386,13 +419,14 @@ public class Codegen {
|
|||||||
} else {
|
} else {
|
||||||
throw new CodeGenException("Invalid argument to Sub expression");
|
throw new CodeGenException("Invalid argument to Sub expression");
|
||||||
}
|
}
|
||||||
|
boxPrimitive(state, TargetType.toPrimitive(op.type()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Div div: {
|
case Div div: {
|
||||||
generate(state, div.left());
|
generate(state, div.left());
|
||||||
convertTo(state, div.left().type(), op.type());
|
convertTo(state, div.left().type(), TargetType.toPrimitive(op.type()));
|
||||||
generate(state, div.right());
|
generate(state, div.right());
|
||||||
convertTo(state, div.right().type(), op.type());
|
convertTo(state, div.right().type(), TargetType.toPrimitive(op.type()));
|
||||||
var type = div.type();
|
var type = div.type();
|
||||||
if (type.equals(TargetType.Byte) || type.equals(TargetType.Char) || type.equals(TargetType.Integer) || type.equals(TargetType.Short)) {
|
if (type.equals(TargetType.Byte) || type.equals(TargetType.Char) || type.equals(TargetType.Integer) || type.equals(TargetType.Short)) {
|
||||||
mv.visitInsn(IDIV);
|
mv.visitInsn(IDIV);
|
||||||
@@ -405,13 +439,14 @@ public class Codegen {
|
|||||||
} else {
|
} else {
|
||||||
throw new CodeGenException("Invalid argument to Div expression");
|
throw new CodeGenException("Invalid argument to Div expression");
|
||||||
}
|
}
|
||||||
|
boxPrimitive(state, TargetType.toPrimitive(op.type()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Mul mul: {
|
case Mul mul: {
|
||||||
generate(state, mul.left());
|
generate(state, mul.left());
|
||||||
convertTo(state, mul.left().type(), op.type());
|
convertTo(state, mul.left().type(), TargetType.toPrimitive(op.type()));
|
||||||
generate(state, mul.right());
|
generate(state, mul.right());
|
||||||
convertTo(state, mul.right().type(), op.type());
|
convertTo(state, mul.right().type(), TargetType.toPrimitive(op.type()));
|
||||||
var type = mul.type();
|
var type = mul.type();
|
||||||
if (type.equals(TargetType.Byte) || type.equals(TargetType.Char) || type.equals(TargetType.Integer) || type.equals(TargetType.Short)) {
|
if (type.equals(TargetType.Byte) || type.equals(TargetType.Char) || type.equals(TargetType.Integer) || type.equals(TargetType.Short)) {
|
||||||
mv.visitInsn(IMUL);
|
mv.visitInsn(IMUL);
|
||||||
@@ -424,13 +459,14 @@ public class Codegen {
|
|||||||
} else {
|
} else {
|
||||||
throw new CodeGenException("Invalid argument to Mul expression");
|
throw new CodeGenException("Invalid argument to Mul expression");
|
||||||
}
|
}
|
||||||
|
boxPrimitive(state, TargetType.toPrimitive(op.type()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Rem rem: {
|
case Rem rem: {
|
||||||
generate(state, rem.left());
|
generate(state, rem.left());
|
||||||
convertTo(state, rem.left().type(), op.type());
|
convertTo(state, rem.left().type(), TargetType.toPrimitive(op.type()));
|
||||||
generate(state, rem.right());
|
generate(state, rem.right());
|
||||||
convertTo(state, rem.right().type(), op.type());
|
convertTo(state, rem.right().type(), TargetType.toPrimitive(op.type()));
|
||||||
var type = rem.type();
|
var type = rem.type();
|
||||||
if (type.equals(TargetType.Byte) || type.equals(TargetType.Char) || type.equals(TargetType.Integer) || type.equals(TargetType.Short)) {
|
if (type.equals(TargetType.Byte) || type.equals(TargetType.Char) || type.equals(TargetType.Integer) || type.equals(TargetType.Short)) {
|
||||||
mv.visitInsn(IREM);
|
mv.visitInsn(IREM);
|
||||||
@@ -443,6 +479,7 @@ public class Codegen {
|
|||||||
} else {
|
} else {
|
||||||
throw new CodeGenException("Invalid argument to Rem expression");
|
throw new CodeGenException("Invalid argument to Rem expression");
|
||||||
}
|
}
|
||||||
|
boxPrimitive(state, TargetType.toPrimitive(op.type()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Or or: {
|
case Or or: {
|
||||||
@@ -450,14 +487,18 @@ public class Codegen {
|
|||||||
Label or_true = new Label();
|
Label or_true = new Label();
|
||||||
Label end = new Label();
|
Label end = new Label();
|
||||||
generate(state, or.left());
|
generate(state, or.left());
|
||||||
|
convertTo(state, or.left().type(), TargetType.toPrimitive(op.type()));
|
||||||
mv.visitJumpInsn(IFNE, or_true);
|
mv.visitJumpInsn(IFNE, or_true);
|
||||||
generate(state, or.right());
|
generate(state, or.right());
|
||||||
|
convertTo(state, or.right().type(), TargetType.toPrimitive(op.type()));
|
||||||
mv.visitJumpInsn(IFEQ, or_false);
|
mv.visitJumpInsn(IFEQ, or_false);
|
||||||
mv.visitLabel(or_true);
|
mv.visitLabel(or_true);
|
||||||
mv.visitInsn(ICONST_1);
|
mv.visitInsn(ICONST_1);
|
||||||
|
boxPrimitive(state, TargetType.toPrimitive(op.type()));
|
||||||
mv.visitJumpInsn(GOTO, end);
|
mv.visitJumpInsn(GOTO, end);
|
||||||
mv.visitLabel(or_false);
|
mv.visitLabel(or_false);
|
||||||
mv.visitInsn(ICONST_0);
|
mv.visitInsn(ICONST_0);
|
||||||
|
boxPrimitive(state, TargetType.toPrimitive(op.type()));
|
||||||
mv.visitLabel(end);
|
mv.visitLabel(end);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -465,47 +506,54 @@ public class Codegen {
|
|||||||
Label and_false = new Label();
|
Label and_false = new Label();
|
||||||
Label end = new Label();
|
Label end = new Label();
|
||||||
generate(state, and.left());
|
generate(state, and.left());
|
||||||
|
convertTo(state, and.left().type(), TargetType.toPrimitive(op.type()));
|
||||||
mv.visitJumpInsn(IFEQ, and_false);
|
mv.visitJumpInsn(IFEQ, and_false);
|
||||||
generate(state, and.right());
|
generate(state, and.right());
|
||||||
|
convertTo(state, and.right().type(), TargetType.toPrimitive(op.type()));
|
||||||
mv.visitJumpInsn(IFEQ, and_false);
|
mv.visitJumpInsn(IFEQ, and_false);
|
||||||
mv.visitInsn(ICONST_1);
|
mv.visitInsn(ICONST_1);
|
||||||
|
boxPrimitive(state, TargetType.toPrimitive(op.type()));
|
||||||
mv.visitJumpInsn(GOTO, end);
|
mv.visitJumpInsn(GOTO, end);
|
||||||
mv.visitLabel(and_false);
|
mv.visitLabel(and_false);
|
||||||
mv.visitInsn(ICONST_0);
|
mv.visitInsn(ICONST_0);
|
||||||
|
boxPrimitive(state, TargetType.toPrimitive(op.type()));
|
||||||
mv.visitLabel(end);
|
mv.visitLabel(end);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BAnd band: {
|
case BAnd band: {
|
||||||
generate(state, band.left());
|
generate(state, band.left());
|
||||||
convertTo(state, band.left().type(), op.type());
|
convertTo(state, band.left().type(), TargetType.toPrimitive(op.type()));
|
||||||
generate(state, band.right());
|
generate(state, band.right());
|
||||||
convertTo(state, band.right().type(), op.type());
|
convertTo(state, band.right().type(), TargetType.toPrimitive(op.type()));
|
||||||
if (band.type().equals(TargetType.Long))
|
if (band.type().equals(TargetType.Long))
|
||||||
mv.visitInsn(LAND);
|
mv.visitInsn(LAND);
|
||||||
else
|
else
|
||||||
mv.visitInsn(IAND);
|
mv.visitInsn(IAND);
|
||||||
|
boxPrimitive(state, TargetType.toPrimitive(op.type()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BOr bor: {
|
case BOr bor: {
|
||||||
generate(state, bor.left());
|
generate(state, bor.left());
|
||||||
convertTo(state, bor.left().type(), op.type());
|
convertTo(state, bor.left().type(), TargetType.toPrimitive(op.type()));
|
||||||
generate(state, bor.right());
|
generate(state, bor.right());
|
||||||
convertTo(state, bor.right().type(), op.type());
|
convertTo(state, bor.right().type(), TargetType.toPrimitive(op.type()));
|
||||||
if (bor.type().equals(TargetType.Long))
|
if (bor.type().equals(TargetType.Long))
|
||||||
mv.visitInsn(LOR);
|
mv.visitInsn(LOR);
|
||||||
else
|
else
|
||||||
mv.visitInsn(IOR);
|
mv.visitInsn(IOR);
|
||||||
|
boxPrimitive(state, TargetType.toPrimitive(op.type()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case XOr xor: {
|
case XOr xor: {
|
||||||
generate(state, xor.left());
|
generate(state, xor.left());
|
||||||
convertTo(state, xor.left().type(), op.type());
|
convertTo(state, xor.left().type(), TargetType.toPrimitive(op.type()));
|
||||||
generate(state, xor.right());
|
generate(state, xor.right());
|
||||||
convertTo(state, xor.right().type(), op.type());
|
convertTo(state, xor.right().type(), TargetType.toPrimitive(op.type()));
|
||||||
if (xor.type().equals(TargetType.Long))
|
if (xor.type().equals(TargetType.Long))
|
||||||
mv.visitInsn(LXOR);
|
mv.visitInsn(LXOR);
|
||||||
else
|
else
|
||||||
mv.visitInsn(IXOR);
|
mv.visitInsn(IXOR);
|
||||||
|
boxPrimitive(state, TargetType.toPrimitive(op.type()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Instof instof: {
|
case Instof instof: {
|
||||||
@@ -514,44 +562,47 @@ public class Codegen {
|
|||||||
}
|
}
|
||||||
case Shl shl: {
|
case Shl shl: {
|
||||||
generate(state, shl.left());
|
generate(state, shl.left());
|
||||||
convertTo(state, shl.left().type(), op.type());
|
convertTo(state, shl.left().type(), TargetType.toPrimitive(op.type()));
|
||||||
generate(state, shl.right());
|
generate(state, shl.right());
|
||||||
convertTo(state, shl.right().type(), op.type());
|
convertTo(state, shl.right().type(), TargetType.toPrimitive(op.type()));
|
||||||
if (shl.type().equals(TargetType.Long))
|
if (shl.type().equals(TargetType.Long))
|
||||||
mv.visitInsn(LSHL);
|
mv.visitInsn(LSHL);
|
||||||
else
|
else
|
||||||
mv.visitInsn(ISHL);
|
mv.visitInsn(ISHL);
|
||||||
|
boxPrimitive(state, TargetType.toPrimitive(op.type()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Shr shr: {
|
case Shr shr: {
|
||||||
generate(state, shr.left());
|
generate(state, shr.left());
|
||||||
convertTo(state, shr.left().type(), op.type());
|
convertTo(state, shr.left().type(), TargetType.toPrimitive(op.type()));
|
||||||
generate(state, shr.right());
|
generate(state, shr.right());
|
||||||
convertTo(state, shr.right().type(), op.type());
|
convertTo(state, shr.right().type(), TargetType.toPrimitive(op.type()));
|
||||||
if (shr.type().equals(TargetType.Long))
|
if (shr.type().equals(TargetType.Long))
|
||||||
mv.visitInsn(LSHR);
|
mv.visitInsn(LSHR);
|
||||||
else
|
else
|
||||||
mv.visitInsn(ISHR);
|
mv.visitInsn(ISHR);
|
||||||
|
boxPrimitive(state, TargetType.toPrimitive(op.type()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case UShr ushr: {
|
case UShr ushr: {
|
||||||
generate(state, ushr.left());
|
generate(state, ushr.left());
|
||||||
convertTo(state, ushr.left().type(), op.type());
|
convertTo(state, ushr.left().type(), TargetType.toPrimitive(op.type()));
|
||||||
generate(state, ushr.right());
|
generate(state, ushr.right());
|
||||||
convertTo(state, ushr.right().type(), op.type());
|
convertTo(state, ushr.right().type(), TargetType.toPrimitive(op.type()));
|
||||||
if (ushr.type().equals(TargetType.Long))
|
if (ushr.type().equals(TargetType.Long))
|
||||||
mv.visitInsn(LUSHR);
|
mv.visitInsn(LUSHR);
|
||||||
else
|
else
|
||||||
mv.visitInsn(IUSHR);
|
mv.visitInsn(IUSHR);
|
||||||
|
boxPrimitive(state, TargetType.toPrimitive(op.type()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Greater greater: {
|
case Greater greater: {
|
||||||
var type = largerType(greater.left().type(), greater.right().type());
|
var type = TargetType.toPrimitive(largerType(greater.left().type(), greater.right().type()));
|
||||||
if (type.equals(TargetType.Long)) {
|
if (type.equals(TargetType.long_)) {
|
||||||
generateRelationalOperator(state, greater, type, LCMP, IFGT);
|
generateRelationalOperator(state, greater, type, LCMP, IFGT);
|
||||||
} else if (type.equals(TargetType.Float)) {
|
} else if (type.equals(TargetType.float_)) {
|
||||||
generateRelationalOperator(state, greater, type, FCMPL, IFGT);
|
generateRelationalOperator(state, greater, type, FCMPL, IFGT);
|
||||||
} else if (type.equals(TargetType.Double)) {
|
} else if (type.equals(TargetType.double_)) {
|
||||||
generateRelationalOperator(state, greater, type, DCMPL, IFGT);
|
generateRelationalOperator(state, greater, type, DCMPL, IFGT);
|
||||||
} else {
|
} else {
|
||||||
generateRelationalOperator(state, greater, type, IF_ICMPGT);
|
generateRelationalOperator(state, greater, type, IF_ICMPGT);
|
||||||
@@ -559,12 +610,12 @@ public class Codegen {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Less less: {
|
case Less less: {
|
||||||
var type = largerType(less.left().type(), less.right().type());
|
var type = TargetType.toPrimitive(largerType(less.left().type(), less.right().type()));
|
||||||
if (type.equals(TargetType.Long)) {
|
if (type.equals(TargetType.long_)) {
|
||||||
generateRelationalOperator(state, less, type, LCMP, IFLT);
|
generateRelationalOperator(state, less, type, LCMP, IFLT);
|
||||||
} else if (type.equals(TargetType.Float)) {
|
} else if (type.equals(TargetType.float_)) {
|
||||||
generateRelationalOperator(state, less, type, FCMPL, IFLT);
|
generateRelationalOperator(state, less, type, FCMPL, IFLT);
|
||||||
} else if (type.equals(TargetType.Double)) {
|
} else if (type.equals(TargetType.double_)) {
|
||||||
generateRelationalOperator(state, less, type, DCMPL, IFLT);
|
generateRelationalOperator(state, less, type, DCMPL, IFLT);
|
||||||
} else {
|
} else {
|
||||||
generateRelationalOperator(state, less, type, IF_ICMPLT);
|
generateRelationalOperator(state, less, type, IF_ICMPLT);
|
||||||
@@ -572,12 +623,12 @@ public class Codegen {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GreaterOrEqual greaterOrEqual: {
|
case GreaterOrEqual greaterOrEqual: {
|
||||||
var type = largerType(greaterOrEqual.left().type(), greaterOrEqual.right().type());
|
var type = TargetType.toPrimitive(largerType(greaterOrEqual.left().type(), greaterOrEqual.right().type()));
|
||||||
if (type.equals(TargetType.Long)) {
|
if (type.equals(TargetType.long_)) {
|
||||||
generateRelationalOperator(state, greaterOrEqual, type, LCMP, IFGE);
|
generateRelationalOperator(state, greaterOrEqual, type, LCMP, IFGE);
|
||||||
} else if (type.equals(TargetType.Float)) {
|
} else if (type.equals(TargetType.float_)) {
|
||||||
generateRelationalOperator(state, greaterOrEqual, type, FCMPL, IFGE);
|
generateRelationalOperator(state, greaterOrEqual, type, FCMPL, IFGE);
|
||||||
} else if (type.equals(TargetType.Double)) {
|
} else if (type.equals(TargetType.double_)) {
|
||||||
generateRelationalOperator(state, greaterOrEqual, type, DCMPL, IFGE);
|
generateRelationalOperator(state, greaterOrEqual, type, DCMPL, IFGE);
|
||||||
} else {
|
} else {
|
||||||
generateRelationalOperator(state, greaterOrEqual, type, IF_ICMPGE);
|
generateRelationalOperator(state, greaterOrEqual, type, IF_ICMPGE);
|
||||||
@@ -585,12 +636,12 @@ public class Codegen {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LessOrEqual lessOrEqual: {
|
case LessOrEqual lessOrEqual: {
|
||||||
var type = largerType(lessOrEqual.left().type(), lessOrEqual.right().type());
|
var type = TargetType.toPrimitive(largerType(lessOrEqual.left().type(), lessOrEqual.right().type()));
|
||||||
if (type.equals(TargetType.Long)) {
|
if (type.equals(TargetType.long_)) {
|
||||||
generateRelationalOperator(state, lessOrEqual, type, LCMP, IFLE);
|
generateRelationalOperator(state, lessOrEqual, type, LCMP, IFLE);
|
||||||
} else if (type.equals(TargetType.Float)) {
|
} else if (type.equals(TargetType.float_)) {
|
||||||
generateRelationalOperator(state, lessOrEqual, type, FCMPL, IFLE);
|
generateRelationalOperator(state, lessOrEqual, type, FCMPL, IFLE);
|
||||||
} else if (type.equals(TargetType.Double)) {
|
} else if (type.equals(TargetType.double_)) {
|
||||||
generateRelationalOperator(state, lessOrEqual, type, DCMPL, IFLE);
|
generateRelationalOperator(state, lessOrEqual, type, DCMPL, IFLE);
|
||||||
} else {
|
} else {
|
||||||
generateRelationalOperator(state, lessOrEqual, type, IF_ICMPLE);
|
generateRelationalOperator(state, lessOrEqual, type, IF_ICMPLE);
|
||||||
@@ -598,30 +649,30 @@ public class Codegen {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Equal equal: {
|
case Equal equal: {
|
||||||
var type = largerType(equal.left().type(), equal.right().type());
|
var type = TargetType.toPrimitive(largerType(equal.left().type(), equal.right().type()));
|
||||||
if (type.equals(TargetType.Long)) {
|
if (type.equals(TargetType.long_)) {
|
||||||
generateRelationalOperator(state, equal, type, LCMP, IFEQ);
|
generateRelationalOperator(state, equal, TargetType.long_, LCMP, IFEQ);
|
||||||
} else if (type.equals(TargetType.Float)) {
|
} else if (type.equals(TargetType.float_)) {
|
||||||
generateRelationalOperator(state, equal, type, FCMPL, IFEQ);
|
generateRelationalOperator(state, equal, TargetType.float_, FCMPL, IFEQ);
|
||||||
} else if (type.equals(TargetType.Double)) {
|
} else if (type.equals(TargetType.double_)) {
|
||||||
generateRelationalOperator(state, equal, type, DCMPL, IFEQ);
|
generateRelationalOperator(state, equal, TargetType.double_, DCMPL, IFEQ);
|
||||||
} else if (type.equals(TargetType.Char) || type.equals(TargetType.Short) || type.equals(TargetType.Byte) || type.equals(TargetType.Integer) || type.equals(TargetType.Boolean)) {
|
} else if (type.equals(TargetType.char_) || type.equals(TargetType.short_) || type.equals(TargetType.byte_) || type.equals(TargetType.int_) || type.equals(TargetType.boolean_)) {
|
||||||
generateRelationalOperator(state, equal, type, IF_ICMPEQ);
|
generateRelationalOperator(state, equal, TargetType.int_, IF_ICMPEQ);
|
||||||
} else {
|
} else {
|
||||||
generateRelationalOperator(state, equal, type, IF_ACMPEQ);
|
generateRelationalOperator(state, equal, type, IF_ACMPEQ);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NotEqual notEqual: {
|
case NotEqual notEqual: {
|
||||||
var type = largerType(notEqual.left().type(), notEqual.right().type());
|
var type = TargetType.toPrimitive(largerType(notEqual.left().type(), notEqual.right().type()));
|
||||||
if (type.equals(TargetType.Long)) {
|
if (type.equals(TargetType.long_)) {
|
||||||
generateRelationalOperator(state, notEqual, type, LCMP, IFNE);
|
generateRelationalOperator(state, notEqual, TargetType.long_, LCMP, IFNE);
|
||||||
} else if (type.equals(TargetType.Float)) {
|
} else if (type.equals(TargetType.float_)) {
|
||||||
generateRelationalOperator(state, notEqual, type, FCMPL, IFNE);
|
generateRelationalOperator(state, notEqual, TargetType.float_, FCMPL, IFNE);
|
||||||
} else if (type.equals(TargetType.Double)) {
|
} else if (type.equals(TargetType.double_)) {
|
||||||
generateRelationalOperator(state, notEqual, type, DCMPL, IFNE);
|
generateRelationalOperator(state, notEqual, TargetType.double_, DCMPL, IFNE);
|
||||||
} else if (type.equals(TargetType.Char) || type.equals(TargetType.Short) || type.equals(TargetType.Byte) || type.equals(TargetType.Integer)) {
|
} else if (type.equals(TargetType.char_) || type.equals(TargetType.short_) || type.equals(TargetType.byte_) || type.equals(TargetType.int_) || type.equals(TargetType.boolean_)) {
|
||||||
generateRelationalOperator(state, notEqual, type, IF_ICMPNE);
|
generateRelationalOperator(state, notEqual, TargetType.int_, IF_ICMPNE);
|
||||||
} else {
|
} else {
|
||||||
generateRelationalOperator(state, notEqual, type, IF_ACMPNE);
|
generateRelationalOperator(state, notEqual, type, IF_ACMPNE);
|
||||||
}
|
}
|
||||||
@@ -640,7 +691,7 @@ public class Codegen {
|
|||||||
} else if (op.expr() instanceof TargetFieldVar fieldVar) {
|
} else if (op.expr() instanceof TargetFieldVar fieldVar) {
|
||||||
generate(state, fieldVar.left());
|
generate(state, fieldVar.left());
|
||||||
mv.visitInsn(SWAP);
|
mv.visitInsn(SWAP);
|
||||||
mv.visitFieldInsn(PUTFIELD, fieldVar.owner().getInternalName(), fieldVar.right(), fieldVar.type().toSignature());
|
mv.visitFieldInsn(PUTFIELD, fieldVar.owner().getInternalName(), fieldVar.right(), fieldVar.type().toDescriptor());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -652,6 +703,7 @@ public class Codegen {
|
|||||||
generate(state, add.expr());
|
generate(state, add.expr());
|
||||||
case TargetUnaryOp.Negate negate -> {
|
case TargetUnaryOp.Negate negate -> {
|
||||||
generate(state, negate.expr());
|
generate(state, negate.expr());
|
||||||
|
convertTo(state, negate.expr().type(), TargetType.boolean_);
|
||||||
if (negate.type().equals(TargetType.Double))
|
if (negate.type().equals(TargetType.Double))
|
||||||
mv.visitInsn(DNEG);
|
mv.visitInsn(DNEG);
|
||||||
else if (negate.type().equals(TargetType.Float))
|
else if (negate.type().equals(TargetType.Float))
|
||||||
@@ -660,9 +712,11 @@ public class Codegen {
|
|||||||
mv.visitInsn(LNEG);
|
mv.visitInsn(LNEG);
|
||||||
else
|
else
|
||||||
mv.visitInsn(INEG);
|
mv.visitInsn(INEG);
|
||||||
|
boxPrimitive(state, TargetType.toPrimitive(negate.expr().type()));
|
||||||
}
|
}
|
||||||
case TargetUnaryOp.Not not -> {
|
case TargetUnaryOp.Not not -> {
|
||||||
generate(state, not.expr());
|
generate(state, not.expr());
|
||||||
|
convertTo(state, not.expr().type(), TargetType.boolean_);
|
||||||
if (not.type().equals(TargetType.Long)) {
|
if (not.type().equals(TargetType.Long)) {
|
||||||
mv.visitLdcInsn(-1L);
|
mv.visitLdcInsn(-1L);
|
||||||
mv.visitInsn(LXOR);
|
mv.visitInsn(LXOR);
|
||||||
@@ -670,93 +724,86 @@ public class Codegen {
|
|||||||
mv.visitInsn(ICONST_M1);
|
mv.visitInsn(ICONST_M1);
|
||||||
mv.visitInsn(IXOR);
|
mv.visitInsn(IXOR);
|
||||||
}
|
}
|
||||||
|
boxPrimitive(state, TargetType.toPrimitive(not.expr().type()));
|
||||||
}
|
}
|
||||||
case TargetUnaryOp.PreIncrement preIncrement -> {
|
case TargetUnaryOp.PreIncrement preIncrement -> {
|
||||||
generate(state, preIncrement.expr());
|
generate(state, preIncrement.expr());
|
||||||
|
convertTo(state, preIncrement.expr().type(), TargetType.toPrimitive(op.type()));
|
||||||
if (preIncrement.type().equals(TargetType.Float)) {
|
if (preIncrement.type().equals(TargetType.Float)) {
|
||||||
mv.visitLdcInsn(1F);
|
mv.visitLdcInsn(1F);
|
||||||
mv.visitInsn(FADD);
|
mv.visitInsn(FADD);
|
||||||
mv.visitInsn(DUP);
|
|
||||||
} else if (preIncrement.type().equals(TargetType.Double)) {
|
} else if (preIncrement.type().equals(TargetType.Double)) {
|
||||||
mv.visitLdcInsn(1D);
|
mv.visitLdcInsn(1D);
|
||||||
mv.visitInsn(DADD);
|
mv.visitInsn(DADD);
|
||||||
mv.visitInsn(DUP2);
|
|
||||||
} else if (preIncrement.type().equals(TargetType.Long)) {
|
} else if (preIncrement.type().equals(TargetType.Long)) {
|
||||||
mv.visitLdcInsn(1L);
|
mv.visitLdcInsn(1L);
|
||||||
mv.visitInsn(LADD);
|
mv.visitInsn(LADD);
|
||||||
mv.visitInsn(DUP2);
|
|
||||||
} else {
|
} else {
|
||||||
mv.visitLdcInsn(1);
|
mv.visitLdcInsn(1);
|
||||||
mv.visitInsn(IADD);
|
mv.visitInsn(IADD);
|
||||||
mv.visitInsn(DUP);
|
|
||||||
}
|
}
|
||||||
boxPrimitive(state, preIncrement.type());
|
boxPrimitive(state, TargetType.toPrimitive(op.type()));
|
||||||
|
mv.visitInsn(DUP);
|
||||||
afterIncDec(state, preIncrement);
|
afterIncDec(state, preIncrement);
|
||||||
}
|
}
|
||||||
case TargetUnaryOp.PreDecrement preDecrement -> {
|
case TargetUnaryOp.PreDecrement preDecrement -> {
|
||||||
generate(state, preDecrement.expr());
|
generate(state, preDecrement.expr());
|
||||||
|
convertTo(state, preDecrement.expr().type(), TargetType.toPrimitive(op.type()));
|
||||||
if (preDecrement.type().equals(TargetType.Float)) {
|
if (preDecrement.type().equals(TargetType.Float)) {
|
||||||
mv.visitLdcInsn(1F);
|
mv.visitLdcInsn(1F);
|
||||||
mv.visitInsn(FSUB);
|
mv.visitInsn(FSUB);
|
||||||
mv.visitInsn(DUP);
|
|
||||||
} else if (preDecrement.type().equals(TargetType.Double)) {
|
} else if (preDecrement.type().equals(TargetType.Double)) {
|
||||||
mv.visitLdcInsn(1D);
|
mv.visitLdcInsn(1D);
|
||||||
mv.visitInsn(DSUB);
|
mv.visitInsn(DSUB);
|
||||||
mv.visitInsn(DUP2);
|
|
||||||
} else if (preDecrement.type().equals(TargetType.Long)) {
|
} else if (preDecrement.type().equals(TargetType.Long)) {
|
||||||
mv.visitLdcInsn(1L);
|
mv.visitLdcInsn(1L);
|
||||||
mv.visitInsn(LSUB);
|
mv.visitInsn(LSUB);
|
||||||
mv.visitInsn(DUP2);
|
|
||||||
} else {
|
} else {
|
||||||
mv.visitLdcInsn(1);
|
mv.visitLdcInsn(1);
|
||||||
mv.visitInsn(ISUB);
|
mv.visitInsn(ISUB);
|
||||||
mv.visitInsn(DUP);
|
|
||||||
}
|
}
|
||||||
boxPrimitive(state, preDecrement.type());
|
boxPrimitive(state, TargetType.toPrimitive(op.type()));
|
||||||
|
mv.visitInsn(DUP);
|
||||||
afterIncDec(state, preDecrement);
|
afterIncDec(state, preDecrement);
|
||||||
}
|
}
|
||||||
case TargetUnaryOp.PostIncrement postIncrement -> {
|
case TargetUnaryOp.PostIncrement postIncrement -> {
|
||||||
generate(state, postIncrement.expr());
|
generate(state, postIncrement.expr());
|
||||||
|
mv.visitInsn(DUP);
|
||||||
|
convertTo(state, postIncrement.expr().type(), TargetType.toPrimitive(op.type()));
|
||||||
if (postIncrement.type().equals(TargetType.Float)) {
|
if (postIncrement.type().equals(TargetType.Float)) {
|
||||||
mv.visitInsn(DUP);
|
|
||||||
mv.visitLdcInsn(1F);
|
mv.visitLdcInsn(1F);
|
||||||
mv.visitInsn(FADD);
|
mv.visitInsn(FADD);
|
||||||
} else if (postIncrement.type().equals(TargetType.Double)) {
|
} else if (postIncrement.type().equals(TargetType.Double)) {
|
||||||
mv.visitInsn(DUP2);
|
|
||||||
mv.visitLdcInsn(1D);
|
mv.visitLdcInsn(1D);
|
||||||
mv.visitInsn(DADD);
|
mv.visitInsn(DADD);
|
||||||
} else if (postIncrement.type().equals(TargetType.Long)) {
|
} else if (postIncrement.type().equals(TargetType.Long)) {
|
||||||
mv.visitInsn(DUP2);
|
|
||||||
mv.visitLdcInsn(1L);
|
mv.visitLdcInsn(1L);
|
||||||
mv.visitInsn(LADD);
|
mv.visitInsn(LADD);
|
||||||
} else {
|
} else {
|
||||||
mv.visitInsn(DUP);
|
|
||||||
mv.visitLdcInsn(1);
|
mv.visitLdcInsn(1);
|
||||||
mv.visitInsn(IADD);
|
mv.visitInsn(IADD);
|
||||||
}
|
}
|
||||||
boxPrimitive(state, postIncrement.type());
|
boxPrimitive(state, TargetType.toPrimitive(op.type()));
|
||||||
afterIncDec(state, postIncrement);
|
afterIncDec(state, postIncrement);
|
||||||
}
|
}
|
||||||
case TargetUnaryOp.PostDecrement postDecrement -> {
|
case TargetUnaryOp.PostDecrement postDecrement -> {
|
||||||
generate(state, postDecrement.expr());
|
generate(state, postDecrement.expr());
|
||||||
|
mv.visitInsn(DUP);
|
||||||
|
convertTo(state, postDecrement.expr().type(), TargetType.toPrimitive(op.type()));
|
||||||
if (postDecrement.type().equals(TargetType.Float)) {
|
if (postDecrement.type().equals(TargetType.Float)) {
|
||||||
mv.visitInsn(DUP);
|
|
||||||
mv.visitLdcInsn(1F);
|
mv.visitLdcInsn(1F);
|
||||||
mv.visitInsn(FSUB);
|
mv.visitInsn(FSUB);
|
||||||
} else if (postDecrement.type().equals(TargetType.Double)) {
|
} else if (postDecrement.type().equals(TargetType.Double)) {
|
||||||
mv.visitInsn(DUP2);
|
|
||||||
mv.visitLdcInsn(1D);
|
mv.visitLdcInsn(1D);
|
||||||
mv.visitInsn(DSUB);
|
mv.visitInsn(DSUB);
|
||||||
} else if (postDecrement.type().equals(TargetType.Long)) {
|
} else if (postDecrement.type().equals(TargetType.Long)) {
|
||||||
mv.visitInsn(DUP2);
|
|
||||||
mv.visitLdcInsn(1L);
|
mv.visitLdcInsn(1L);
|
||||||
mv.visitInsn(LSUB);
|
mv.visitInsn(LSUB);
|
||||||
} else {
|
} else {
|
||||||
mv.visitInsn(DUP);
|
|
||||||
mv.visitLdcInsn(1);
|
mv.visitLdcInsn(1);
|
||||||
mv.visitInsn(ISUB);
|
mv.visitInsn(ISUB);
|
||||||
}
|
}
|
||||||
boxPrimitive(state, postDecrement.type());
|
boxPrimitive(state, TargetType.toPrimitive(op.type()));
|
||||||
afterIncDec(state, postDecrement);
|
afterIncDec(state, postDecrement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -803,7 +850,7 @@ public class Codegen {
|
|||||||
var handle = new Handle(state.isStatic ? H_INVOKESTATIC : H_INVOKEVIRTUAL, clazz.getName(), impl.name(), implSignature.getDescriptor(), false);
|
var handle = new Handle(state.isStatic ? H_INVOKESTATIC : H_INVOKEVIRTUAL, clazz.getName(), impl.name(), implSignature.getDescriptor(), false);
|
||||||
|
|
||||||
var params = new ArrayList<TargetType>();
|
var params = new ArrayList<TargetType>();
|
||||||
if(!state.isStatic) params.add(new TargetRefType(clazz.qualifiedName().getClassName()));
|
if(!state.isStatic) params.add(new TargetRefType(clazz.qualifiedName().toString()));
|
||||||
params.addAll(lambda.captures().stream().map(mp -> mp.pattern().type()).toList());
|
params.addAll(lambda.captures().stream().map(mp -> mp.pattern().type()).toList());
|
||||||
|
|
||||||
if (!state.isStatic)
|
if (!state.isStatic)
|
||||||
@@ -904,7 +951,7 @@ public class Codegen {
|
|||||||
var local = state.createVariable(varDecl.name(), varDecl.varType());
|
var local = state.createVariable(varDecl.name(), varDecl.varType());
|
||||||
if (varDecl.value() != null) {
|
if (varDecl.value() != null) {
|
||||||
generate(state, varDecl.value());
|
generate(state, varDecl.value());
|
||||||
boxPrimitive(state, varDecl.varType());
|
boxPrimitive(state, varDecl.value().type());
|
||||||
mv.visitVarInsn(ASTORE, local.index());
|
mv.visitVarInsn(ASTORE, local.index());
|
||||||
} else {
|
} else {
|
||||||
mv.visitInsn(ACONST_NULL);
|
mv.visitInsn(ACONST_NULL);
|
||||||
@@ -942,7 +989,7 @@ public class Codegen {
|
|||||||
mv.visitInsn(DUP);
|
mv.visitInsn(DUP);
|
||||||
else
|
else
|
||||||
mv.visitInsn(DUP_X1);
|
mv.visitInsn(DUP_X1);
|
||||||
mv.visitFieldInsn(dot.isStatic() ? PUTSTATIC : PUTFIELD, dot.owner().getInternalName(), dot.right(), fieldType.toSignature());
|
mv.visitFieldInsn(dot.isStatic() ? PUTSTATIC : PUTFIELD, dot.owner().getInternalName(), dot.right(), fieldType.toDescriptor());
|
||||||
}
|
}
|
||||||
default -> throw new CodeGenException("Invalid assignment");
|
default -> throw new CodeGenException("Invalid assignment");
|
||||||
}
|
}
|
||||||
@@ -953,14 +1000,14 @@ public class Codegen {
|
|||||||
mv.visitVarInsn(ALOAD, local.index());
|
mv.visitVarInsn(ALOAD, local.index());
|
||||||
// This is a bit weird but sometimes the types don't match (see lambda expressions)
|
// This is a bit weird but sometimes the types don't match (see lambda expressions)
|
||||||
convertTo(state, local.type(), localVar.type());
|
convertTo(state, local.type(), localVar.type());
|
||||||
unboxPrimitive(state, local.type());
|
//unboxPrimitive(state, local.type());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TargetFieldVar dot: {
|
case TargetFieldVar dot: {
|
||||||
if (!dot.isStatic())
|
if (!dot.isStatic())
|
||||||
generate(state, dot.left());
|
generate(state, dot.left());
|
||||||
mv.visitFieldInsn(dot.isStatic() ? GETSTATIC : GETFIELD, dot.left().type().getInternalName(), dot.right(), dot.type().toSignature());
|
mv.visitFieldInsn(dot.isStatic() ? GETSTATIC : GETFIELD, dot.left().type().getInternalName(), dot.right(), dot.type().toDescriptor());
|
||||||
unboxPrimitive(state, dot.type());
|
//unboxPrimitive(state, dot.type());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TargetFor _for: {
|
case TargetFor _for: {
|
||||||
@@ -976,11 +1023,14 @@ public class Codegen {
|
|||||||
Label start = new Label();
|
Label start = new Label();
|
||||||
Label end = new Label();
|
Label end = new Label();
|
||||||
mv.visitLabel(start);
|
mv.visitLabel(start);
|
||||||
if (_for.termination() != null)
|
if (_for.termination() != null) {
|
||||||
generate(state, _for.termination());
|
generate(state, _for.termination());
|
||||||
else
|
convertTo(state, _for.termination().type(), TargetType.boolean_);
|
||||||
|
mv.visitJumpInsn(IFEQ, end);
|
||||||
|
} else {
|
||||||
mv.visitInsn(ICONST_1);
|
mv.visitInsn(ICONST_1);
|
||||||
mv.visitJumpInsn(IFEQ, end);
|
mv.visitJumpInsn(IFEQ, end);
|
||||||
|
}
|
||||||
|
|
||||||
var env = new BreakEnv();
|
var env = new BreakEnv();
|
||||||
env.startLabel = start;
|
env.startLabel = start;
|
||||||
@@ -1012,6 +1062,7 @@ public class Codegen {
|
|||||||
Label end = new Label();
|
Label end = new Label();
|
||||||
mv.visitLabel(start);
|
mv.visitLabel(start);
|
||||||
generate(state, _while.cond());
|
generate(state, _while.cond());
|
||||||
|
convertTo(state, _while.cond().type(), TargetType.boolean_);
|
||||||
mv.visitJumpInsn(IFEQ, end);
|
mv.visitJumpInsn(IFEQ, end);
|
||||||
|
|
||||||
var env = new BreakEnv();
|
var env = new BreakEnv();
|
||||||
@@ -1042,6 +1093,7 @@ public class Codegen {
|
|||||||
|
|
||||||
mv.visitLabel(check);
|
mv.visitLabel(check);
|
||||||
generate(state, _do.cond());
|
generate(state, _do.cond());
|
||||||
|
convertTo(state, _do.cond().type(), TargetType.boolean_);
|
||||||
mv.visitJumpInsn(IFEQ, end);
|
mv.visitJumpInsn(IFEQ, end);
|
||||||
mv.visitJumpInsn(GOTO, start);
|
mv.visitJumpInsn(GOTO, start);
|
||||||
mv.visitLabel(end);
|
mv.visitLabel(end);
|
||||||
@@ -1049,6 +1101,7 @@ public class Codegen {
|
|||||||
}
|
}
|
||||||
case TargetIf _if: {
|
case TargetIf _if: {
|
||||||
generate(state, _if.cond());
|
generate(state, _if.cond());
|
||||||
|
convertTo(state, _if.cond().type(), TargetType.boolean_);
|
||||||
Label _else = new Label();
|
Label _else = new Label();
|
||||||
Label end = new Label();
|
Label end = new Label();
|
||||||
mv.visitJumpInsn(IFEQ, _else);
|
mv.visitJumpInsn(IFEQ, _else);
|
||||||
@@ -1062,20 +1115,23 @@ public class Codegen {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TargetReturn ret: {
|
case TargetReturn ret: {
|
||||||
if (ret.expression() != null && state.returnType != null) {
|
if (ret.expression() != null) {
|
||||||
if (state.returnType instanceof TargetPrimitiveType) {
|
if (state.returnType instanceof TargetPrimitiveType) {
|
||||||
generate(state, ret.expression());
|
generate(state, ret.expression());
|
||||||
|
// Lambdas wrap the expression in a return if they are a single expression
|
||||||
unboxPrimitive(state, state.returnType);
|
// It means we have to execute the code anyway but not return anything
|
||||||
mv.visitInsn(findReturnCode(state.returnType));
|
if (state.returnType != null) {
|
||||||
|
convertTo(state, ret.expression().type(), state.returnType);
|
||||||
|
mv.visitInsn(findReturnCode(state.returnType));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
generate(state, ret.expression());
|
generate(state, ret.expression());
|
||||||
boxPrimitive(state, ret.expression().type());
|
if (state.returnType != null) {
|
||||||
convertTo(state, ret.expression().type(), state.returnType);
|
convertTo(state, ret.expression().type(), state.returnType);
|
||||||
mv.visitInsn(ARETURN);
|
mv.visitInsn(ARETURN);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else
|
} else mv.visitInsn(RETURN);
|
||||||
mv.visitInsn(RETURN);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TargetYield yield: {
|
case TargetYield yield: {
|
||||||
@@ -1122,12 +1178,14 @@ public class Codegen {
|
|||||||
var arg = call.parameterTypes().get(i);
|
var arg = call.parameterTypes().get(i);
|
||||||
generate(state, e);
|
generate(state, e);
|
||||||
convertTo(state, e.type(), arg);
|
convertTo(state, e.type(), arg);
|
||||||
if (!(arg instanceof TargetPrimitiveType))
|
|
||||||
boxPrimitive(state, e.type());
|
|
||||||
}
|
}
|
||||||
var descriptor = call.getDescriptor();
|
var descriptor = call.getDescriptor();
|
||||||
if (call.owner() instanceof TargetFunNType) // Decay FunN
|
if (call.owner() instanceof TargetFunNType owner) {
|
||||||
descriptor = TargetMethod.getDescriptor(call.returnType() == null ? null : TargetType.Object, call.parameterTypes().stream().map(x -> TargetType.Object).toArray(TargetType[]::new));
|
// Decay FunN
|
||||||
|
descriptor = TargetMethod.getDescriptor(
|
||||||
|
(owner.returnArguments() == 0 ? null : TargetType.Object),
|
||||||
|
call.parameterTypes().stream().map(x -> TargetType.Object).toArray(TargetType[]::new));
|
||||||
|
}
|
||||||
|
|
||||||
int insn = INVOKEVIRTUAL;
|
int insn = INVOKEVIRTUAL;
|
||||||
if (call.isStatic()) insn = INVOKESTATIC;
|
if (call.isStatic()) insn = INVOKESTATIC;
|
||||||
@@ -1136,11 +1194,13 @@ public class Codegen {
|
|||||||
|
|
||||||
mv.visitMethodInsn(insn, call.owner().getInternalName(), call.name(), descriptor, call.isInterface());
|
mv.visitMethodInsn(insn, call.owner().getInternalName(), call.name(), descriptor, call.isInterface());
|
||||||
|
|
||||||
if (call.type() != null && call.returnType() != null && !(call.returnType() instanceof TargetPrimitiveType)) {
|
/*if (call.type() != null && call.returnType() != null && !(call.returnType() instanceof TargetPrimitiveType)) {
|
||||||
if (!call.returnType().equals(call.type()) && !(call.type() instanceof TargetGenericType))
|
if (!call.returnType().equals(call.type()) && !(call.type() instanceof TargetGenericType))
|
||||||
mv.visitTypeInsn(CHECKCAST, call.type().getInternalName());
|
mv.visitTypeInsn(CHECKCAST, call.type().getInternalName());
|
||||||
unboxPrimitive(state, call.type());
|
unboxPrimitive(state, call.type());
|
||||||
}
|
}*/
|
||||||
|
if (call.type() != null)
|
||||||
|
convertTo(state, call.returnType(), call.type());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TargetLambdaExpression lambda:
|
case TargetLambdaExpression lambda:
|
||||||
@@ -1149,9 +1209,10 @@ public class Codegen {
|
|||||||
case TargetNew _new: {
|
case TargetNew _new: {
|
||||||
mv.visitTypeInsn(NEW, _new.type().getInternalName());
|
mv.visitTypeInsn(NEW, _new.type().getInternalName());
|
||||||
mv.visitInsn(DUP);
|
mv.visitInsn(DUP);
|
||||||
for (TargetExpression e : _new.params()) {
|
for (var i = 0; i < _new.params().size(); i++) {
|
||||||
|
var e = _new.params().get(i);
|
||||||
generate(state, e);
|
generate(state, e);
|
||||||
boxPrimitive(state, e.type());
|
convertTo(state, e.type(), _new.signature().get(i));
|
||||||
}
|
}
|
||||||
mv.visitMethodInsn(INVOKESPECIAL, _new.type().getInternalName(), "<init>", _new.getDescriptor(), false);
|
mv.visitMethodInsn(INVOKESPECIAL, _new.type().getInternalName(), "<init>", _new.getDescriptor(), false);
|
||||||
break;
|
break;
|
||||||
@@ -1163,6 +1224,7 @@ public class Codegen {
|
|||||||
}
|
}
|
||||||
case TargetTernary ternary: {
|
case TargetTernary ternary: {
|
||||||
generate(state, ternary.cond());
|
generate(state, ternary.cond());
|
||||||
|
convertTo(state, ternary.cond().type(), TargetType.boolean_);
|
||||||
var iffalse = new Label();
|
var iffalse = new Label();
|
||||||
var end = new Label();
|
var end = new Label();
|
||||||
mv.visitJumpInsn(IFEQ, iffalse);
|
mv.visitJumpInsn(IFEQ, iffalse);
|
||||||
@@ -1216,6 +1278,7 @@ public class Codegen {
|
|||||||
if (instanceOf.right() instanceof TargetTypePattern right && right.name() == null) {
|
if (instanceOf.right() instanceof TargetTypePattern right && right.name() == null) {
|
||||||
generate(state, instanceOf.left());
|
generate(state, instanceOf.left());
|
||||||
mv.visitTypeInsn(INSTANCEOF, right.type().getInternalName());
|
mv.visitTypeInsn(INSTANCEOF, right.type().getInternalName());
|
||||||
|
boxPrimitive(state, TargetType.boolean_);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1223,6 +1286,7 @@ public class Codegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void yieldValue(State state, TargetType type) {
|
private void yieldValue(State state, TargetType type) {
|
||||||
|
if (type == null) return;
|
||||||
boxPrimitive(state, type);
|
boxPrimitive(state, type);
|
||||||
state.mv.visitVarInsn(ASTORE, state.switchResultValue.peek());
|
state.mv.visitVarInsn(ASTORE, state.switchResultValue.peek());
|
||||||
}
|
}
|
||||||
@@ -1238,6 +1302,7 @@ public class Codegen {
|
|||||||
state.pushSwitch();
|
state.pushSwitch();
|
||||||
|
|
||||||
generate(state, aSwitch.expr());
|
generate(state, aSwitch.expr());
|
||||||
|
unboxPrimitive(state, aSwitch.expr().type());
|
||||||
|
|
||||||
state.enterScope();
|
state.enterScope();
|
||||||
|
|
||||||
@@ -1334,7 +1399,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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1373,6 +1438,7 @@ public class Codegen {
|
|||||||
|
|
||||||
if (label instanceof TargetGuard gd) {
|
if (label instanceof TargetGuard gd) {
|
||||||
generate(state, gd.expression());
|
generate(state, gd.expression());
|
||||||
|
unboxPrimitive(state, TargetType.Boolean);
|
||||||
var next = new Label();
|
var next = new Label();
|
||||||
mv.visitJumpInsn(IFNE, next);
|
mv.visitJumpInsn(IFNE, next);
|
||||||
mv.visitVarInsn(ALOAD, tmp);
|
mv.visitVarInsn(ALOAD, tmp);
|
||||||
@@ -1410,7 +1476,7 @@ public class Codegen {
|
|||||||
if (aSwitch.isExpression()) {
|
if (aSwitch.isExpression()) {
|
||||||
if (aSwitch.type() != null) {
|
if (aSwitch.type() != null) {
|
||||||
mv.visitVarInsn(ALOAD, state.switchResultValue.peek());
|
mv.visitVarInsn(ALOAD, state.switchResultValue.peek());
|
||||||
unboxPrimitive(state, aSwitch.type());
|
//unboxPrimitive(state, aSwitch.type());
|
||||||
}
|
}
|
||||||
state.popSwitch();
|
state.popSwitch();
|
||||||
}
|
}
|
||||||
@@ -1423,12 +1489,12 @@ public class Codegen {
|
|||||||
throw new CodeGenException("Couldn't find suitable field accessor for '" + type.name() + "'");
|
throw new CodeGenException("Couldn't find suitable field accessor for '" + type.name() + "'");
|
||||||
var field = clazz.getFieldDecl().get(i);
|
var field = clazz.getFieldDecl().get(i);
|
||||||
var fieldType = converter.convert(field.getType());
|
var fieldType = converter.convert(field.getType());
|
||||||
state.mv.visitMethodInsn(INVOKEVIRTUAL, type.getInternalName(), field.getName(), "()" + fieldType.toSignature(), false);
|
state.mv.visitMethodInsn(INVOKEVIRTUAL, type.getInternalName(), field.getName(), "()" + fieldType.toDescriptor(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bindPattern(State state, TargetType type, TargetPattern pat, Label start, int index, int depth) {
|
private void bindPattern(State state, TargetType type, TargetPattern pat, Label start, int index, int depth) {
|
||||||
if (pat.type() instanceof TargetPrimitiveType)
|
//if (pat.type() instanceof TargetPrimitiveType)
|
||||||
boxPrimitive(state, pat.type());
|
// boxPrimitive(state, pat.type());
|
||||||
|
|
||||||
if (pat.type() instanceof TargetRefType) {
|
if (pat.type() instanceof TargetRefType) {
|
||||||
state.mv.visitInsn(DUP);
|
state.mv.visitInsn(DUP);
|
||||||
@@ -1449,11 +1515,14 @@ public class Codegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (pat instanceof TargetExpressionPattern ep) {
|
if (pat instanceof TargetExpressionPattern ep) {
|
||||||
var cur = state.createVariable(pat.type());
|
var cur = state.createVariable(TargetType.toWrapper(pat.type()));
|
||||||
state.mv.visitVarInsn(ASTORE, cur.index);
|
state.mv.visitVarInsn(ASTORE, cur.index);
|
||||||
|
|
||||||
var expr = new Equal(pat.type(), new TargetLocalVar(cur.type, cur.name), ep.expression());
|
// For Strings we must use equals, and why not make it work for all types?
|
||||||
generate(state, expr);
|
generate(state, new TargetLocalVar(cur.type, cur.name));
|
||||||
|
generate(state, ep.expression());
|
||||||
|
boxPrimitive(state, ep.expression().type());
|
||||||
|
state.mv.visitMethodInsn(INVOKESTATIC, "java/util/Objects", "equals", "(Ljava/lang/Object;Ljava/lang/Object;)Z", false);
|
||||||
|
|
||||||
var cont = new Label();
|
var cont = new Label();
|
||||||
state.mv.visitJumpInsn(IFNE, cont);
|
state.mv.visitJumpInsn(IFNE, cont);
|
||||||
@@ -1528,7 +1597,7 @@ public class Codegen {
|
|||||||
//if ((access & ACC_PRIVATE) == 0 && (access & ACC_PROTECTED) == 0) // TODO Implement access modifiers properly
|
//if ((access & ACC_PRIVATE) == 0 && (access & ACC_PROTECTED) == 0) // TODO Implement access modifiers properly
|
||||||
// access |= ACC_PUBLIC;
|
// access |= ACC_PUBLIC;
|
||||||
|
|
||||||
cw.visitField(access, field.name(), field.type().toSignature(), field.type().toDescriptor(), null);
|
cw.visitField(access, field.name(), field.type().toDescriptor(), field.type().toSignature(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateStaticConstructor(TargetMethod constructor) {
|
private void generateStaticConstructor(TargetMethod constructor) {
|
||||||
@@ -1604,7 +1673,7 @@ public class Codegen {
|
|||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
mv.visitVarInsn(ALOAD, 0);
|
mv.visitVarInsn(ALOAD, 0);
|
||||||
mv.visitMethodInsn(INVOKESTATIC, "java/util/List", "of", "([Ljava/lang/Object;)Ljava/util/List;", true);
|
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.visitMethodInsn(INVOKESTATIC, new TargetRefType(clazz.qualifiedName().toString()).getInternalName(), "main", "(Ljava/util/List;)V", false);
|
||||||
mv.visitInsn(RETURN);
|
mv.visitInsn(RETURN);
|
||||||
mv.visitMaxs(0, 0);
|
mv.visitMaxs(0, 0);
|
||||||
mv.visitEnd();
|
mv.visitEnd();
|
||||||
@@ -1651,7 +1720,7 @@ public class Codegen {
|
|||||||
generate(state, method.block());
|
generate(state, method.block());
|
||||||
if (method.signature().returnType() == null)
|
if (method.signature().returnType() == null)
|
||||||
mv.visitInsn(RETURN);
|
mv.visitInsn(RETURN);
|
||||||
mv.visitMaxs(0, 0);
|
mv.visitMaxs(0, 0);
|
||||||
}
|
}
|
||||||
mv.visitEnd();
|
mv.visitEnd();
|
||||||
}
|
}
|
||||||
@@ -1661,12 +1730,14 @@ public class Codegen {
|
|||||||
if (!generics.isEmpty()) {
|
if (!generics.isEmpty()) {
|
||||||
ret += "<";
|
ret += "<";
|
||||||
for (var generic : generics) {
|
for (var generic : generics) {
|
||||||
ret += generic.name() + ":" + generic.bound().toDescriptor();
|
ret += generic.name() + ":" + generic.bound().toSignature();
|
||||||
}
|
}
|
||||||
ret += ">";
|
ret += ">";
|
||||||
}
|
}
|
||||||
if (clazz.superType() != null)
|
if (clazz.superType() != null)
|
||||||
ret += clazz.superType().toDescriptor();
|
ret += clazz.superType().toSignature();
|
||||||
|
else ret += "Ljava/lang/Object;";
|
||||||
|
|
||||||
for (var intf : clazz.implementingInterfaces()) {
|
for (var intf : clazz.implementingInterfaces()) {
|
||||||
ret += intf.toSignature();
|
ret += intf.toSignature();
|
||||||
}
|
}
|
||||||
@@ -1769,8 +1840,12 @@ public class Codegen {
|
|||||||
} else convertTo(state, fromReturn, toReturn);
|
} else convertTo(state, fromReturn, toReturn);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (toReturn != null)
|
if (toReturn != null) {
|
||||||
|
if ((fromReturn instanceof TargetRefType || fromReturn instanceof TargetGenericType)
|
||||||
|
&& (toReturn instanceof TargetPrimitiveType))
|
||||||
|
unboxPrimitive(state, TargetType.toWrapper(toReturn));
|
||||||
mv.visitInsn(findReturnCode(toReturn));
|
mv.visitInsn(findReturnCode(toReturn));
|
||||||
|
}
|
||||||
|
|
||||||
else mv.visitInsn(RETURN);
|
else mv.visitInsn(RETURN);
|
||||||
mv.visitMaxs(0, 0);
|
mv.visitMaxs(0, 0);
|
||||||
@@ -1779,19 +1854,13 @@ public class Codegen {
|
|||||||
cw2.visitEnd();
|
cw2.visitEnd();
|
||||||
var bytes = cw2.toByteArray();
|
var bytes = cw2.toByteArray();
|
||||||
compiler.auxiliaries.put(className, bytes);
|
compiler.auxiliaries.put(className, bytes);
|
||||||
|
|
||||||
// TODO These class loading shenanigans happen in a few places, the tests load the classes individually.
|
|
||||||
// Instead we should just look at the folder.
|
|
||||||
try {
|
|
||||||
converter.classLoader.findClass(className);
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
try {
|
|
||||||
converter.classLoader.loadClass(className, bytes);
|
|
||||||
} catch (LinkageError ignored) {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cw.visitEnd();
|
cw.visitEnd();
|
||||||
|
//ClassReader cr = new ClassReader(cw.toByteArray());
|
||||||
|
//System.out.println("Checking class " + className);
|
||||||
|
// TODO This fails for multi class projects because it tries to load the other classes
|
||||||
|
//CheckClassAdapter.verify(cr, false, new PrintWriter(System.err));
|
||||||
return cw.toByteArray();
|
return cw.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1821,7 +1890,7 @@ public class Codegen {
|
|||||||
bootstrapArgs[1] = String.join(";", clazz.fields().stream().map(TargetField::name).toArray(String[]::new));
|
bootstrapArgs[1] = String.join(";", clazz.fields().stream().map(TargetField::name).toArray(String[]::new));
|
||||||
for (var i = 0; i < clazz.fields().size(); i++) {
|
for (var i = 0; i < clazz.fields().size(); i++) {
|
||||||
var field = clazz.fields().get(i);
|
var field = clazz.fields().get(i);
|
||||||
var fieldRef = new Handle(H_GETFIELD, clazz.getName(), field.name(), field.type().toSignature(), false);
|
var fieldRef = new Handle(H_GETFIELD, clazz.getName(), field.name(), field.type().toDescriptor(), false);
|
||||||
bootstrapArgs[i + 2] = fieldRef;
|
bootstrapArgs[i + 2] = fieldRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ public class FunNGenerator {
|
|||||||
if (type == null) return VOID;
|
if (type == null) return VOID;
|
||||||
var res = "L" + type.getInternalName();
|
var res = "L" + type.getInternalName();
|
||||||
if (type instanceof TargetSpecializedType a) {
|
if (type instanceof TargetSpecializedType a) {
|
||||||
if (a.params().size() > 0) {
|
if (!a.params().isEmpty() && !(a.params().size() == 1 && a.params().getFirst() == null)) {
|
||||||
res += "<";
|
res += "<";
|
||||||
for (var param : a.params()) {
|
for (var param : a.params()) {
|
||||||
if (param instanceof TargetGenericType gp) {
|
if (param instanceof TargetGenericType gp) {
|
||||||
@@ -98,7 +98,7 @@ public class FunNGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static String applySignature(TargetType a) { return a.toSignature(); }
|
private static String applySignature(TargetType a) { return a.toSignature(); }
|
||||||
private static String applyNameDescriptor(TargetType a){ return a instanceof TargetGenericType ? "LTPH;" : String.format("%s", applySignature(a)); }
|
private static String applyNameDescriptor(TargetType a){ return a instanceof TargetGenericType ? "LTPH;" : String.format("%s", a.toDescriptor()); }
|
||||||
|
|
||||||
public static String encodeType(TargetType type) {
|
public static String encodeType(TargetType type) {
|
||||||
if (type == null) return VOID;
|
if (type == null) return VOID;
|
||||||
@@ -115,16 +115,17 @@ public class FunNGenerator {
|
|||||||
superFunNMethodSignature.append(String.format("T%s;", argumentGenericBase + currentParameter));
|
superFunNMethodSignature.append(String.format("T%s;", argumentGenericBase + currentParameter));
|
||||||
superFunNMethodDescriptor.append(objectSignature);
|
superFunNMethodDescriptor.append(objectSignature);
|
||||||
}
|
}
|
||||||
superFunNClassSignature.append(String.format("%s:%s>%s", returnGeneric, objectSignature, objectSignature));
|
|
||||||
if (numReturnTypes > 0) {
|
if (numReturnTypes > 0) {
|
||||||
|
superFunNClassSignature.append(String.format("%s:%s>%s", returnGeneric, objectSignature, objectSignature));
|
||||||
superFunNMethodSignature.append(String.format(")T%s;", returnGeneric));
|
superFunNMethodSignature.append(String.format(")T%s;", returnGeneric));
|
||||||
superFunNMethodDescriptor.append(String.format(")%s", objectSignature));
|
superFunNMethodDescriptor.append(String.format(")%s", objectSignature));
|
||||||
} else {
|
} else {
|
||||||
|
superFunNClassSignature = new StringBuilder(objectSignature);
|
||||||
superFunNMethodSignature.append(")V");
|
superFunNMethodSignature.append(")V");
|
||||||
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;
|
||||||
|
|||||||
@@ -1,46 +1,83 @@
|
|||||||
package de.dhbwstuttgart.core;
|
package de.dhbwstuttgart.core;
|
||||||
|
|
||||||
|
import com.beust.jcommander.JCommander;
|
||||||
|
import com.beust.jcommander.Parameter;
|
||||||
|
import com.beust.jcommander.ParameterException;
|
||||||
|
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 {
|
|
||||||
private static final String directory = System.getProperty("user.dir");
|
|
||||||
|
|
||||||
public static void main(String[] args) throws IOException, ClassNotFoundException {
|
|
||||||
List<File> input = new ArrayList<>();
|
|
||||||
List<File> classpath = new ArrayList<>();
|
|
||||||
String outputPath = null;
|
|
||||||
Iterator<String> it = Arrays.asList(args).iterator();
|
|
||||||
if(args.length == 0){
|
|
||||||
System.out.println("No input files given. Get help with --help");
|
|
||||||
System.exit(1);
|
|
||||||
}else if(args.length == 1 && args[0].equals("--help")){
|
|
||||||
System.out.println("Usage: javatx [OPTION]... [FILE]...\n" +
|
|
||||||
"\t-cp\tSet Classpath\n" +
|
|
||||||
"\t-d\tSet destination directory");
|
|
||||||
System.exit(1);
|
|
||||||
}
|
|
||||||
while(it.hasNext()){
|
|
||||||
String arg = it.next();
|
|
||||||
if(arg.equals("-d")){
|
|
||||||
outputPath = it.next();
|
|
||||||
}else if(arg.startsWith("-d")) {
|
|
||||||
outputPath = arg.substring(2);
|
|
||||||
}else if(arg.equals("-cp") || arg.equals("-classpath")){
|
|
||||||
String[] cps = it.next().split(":");
|
|
||||||
for(String cp : cps){
|
|
||||||
classpath.add(new File(cp));
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
input.add(new File(arg));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
JavaTXCompiler compiler = new JavaTXCompiler(input, classpath, outputPath != null ? new File(outputPath) : null);
|
|
||||||
//compiler.typeInference();
|
|
||||||
compiler.generateBytecode();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
class Args {
|
||||||
|
@Parameter(description = "Set destination directory", names = "-d")
|
||||||
|
File outputPath;
|
||||||
|
@Parameter(description = "Set class path", names = {"-cp", "-classpath"})
|
||||||
|
String classpath;
|
||||||
|
@Parameter(description = "[FILE]...")
|
||||||
|
List<File> input;
|
||||||
|
@Parameter(description = "Server mode", names = "--server-port")
|
||||||
|
Integer serverPort;
|
||||||
|
@Parameter(description = "Unify server url", names = "--unify-server")
|
||||||
|
String serverUrl;
|
||||||
|
@Parameter(description = "Write logs", names = "--write-logs")
|
||||||
|
boolean writeLogs = false;
|
||||||
|
@Parameter(names = "-v", description = "Verbosity level")
|
||||||
|
int verbosity = 0;
|
||||||
|
@Parameter(names = "--infer-together", description = "Runs the type inference on all input files together instead of sequentially")
|
||||||
|
boolean inferTogether = false;
|
||||||
|
@Parameter(names = "--help", help = true)
|
||||||
|
boolean help;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ConsoleInterface {
|
||||||
|
public static Logger.LogLevel logLevel = Logger.LogLevel.ERROR;
|
||||||
|
public static boolean writeLogFiles = false;
|
||||||
|
public static boolean inferTogether = false;
|
||||||
|
public static Optional<String> unifyServerUrl = Optional.empty();
|
||||||
|
|
||||||
|
public static void main(String[] argv) throws IOException, ClassNotFoundException {
|
||||||
|
var args = new Args();
|
||||||
|
var builder = JCommander.newBuilder().addObject(args).build();
|
||||||
|
builder.setProgramName("javatx");
|
||||||
|
try {
|
||||||
|
builder.parse(argv);
|
||||||
|
if (args.help) {
|
||||||
|
builder.usage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (ParameterException e) {
|
||||||
|
System.err.println(e.getMessage());
|
||||||
|
System.err.println();
|
||||||
|
builder.usage();
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
inferTogether = args.inferTogether;
|
||||||
|
unifyServerUrl = Optional.ofNullable(args.serverUrl);
|
||||||
|
writeLogFiles = args.writeLogs;
|
||||||
|
switch (args.verbosity) {
|
||||||
|
case 1 -> logLevel = Logger.LogLevel.WARNING;
|
||||||
|
case 2 -> logLevel = Logger.LogLevel.INFO;
|
||||||
|
case 3 -> logLevel = Logger.LogLevel.DEBUG;
|
||||||
|
default -> logLevel = Logger.LogLevel.ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (args.serverPort != null) {
|
||||||
|
if (unifyServerUrl.isPresent()) throw new RuntimeException("Cannot use unifyServer when in server mode!");
|
||||||
|
JavaTXServer server = new JavaTXServer(args.serverPort);
|
||||||
|
server.listen();
|
||||||
|
} else {
|
||||||
|
if (args.input == null) {
|
||||||
|
System.err.println("No input files given. Get help with --help");
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
List<File> classpath = args.classpath == null ? List.of() : Arrays.stream(args.classpath.split(File.pathSeparator)).map(File::new).toList();
|
||||||
|
JavaTXCompiler compiler = new JavaTXCompiler(args.input, classpath, args.outputPath, inferTogether);
|
||||||
|
compiler.generateBytecode();
|
||||||
|
SocketClient.closeIfOpen();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,13 +6,20 @@ import de.dhbwstuttgart.bytecode.FunNGenerator;
|
|||||||
import de.dhbwstuttgart.environment.CompilationEnvironment;
|
import de.dhbwstuttgart.environment.CompilationEnvironment;
|
||||||
import de.dhbwstuttgart.environment.DirectoryClassLoader;
|
import de.dhbwstuttgart.environment.DirectoryClassLoader;
|
||||||
import de.dhbwstuttgart.exceptions.DebugException;
|
import de.dhbwstuttgart.exceptions.DebugException;
|
||||||
|
import de.dhbwstuttgart.languageServerInterface.model.LanguageServerTransferObject;
|
||||||
import de.dhbwstuttgart.parser.JavaTXParser;
|
import de.dhbwstuttgart.parser.JavaTXParser;
|
||||||
import de.dhbwstuttgart.parser.NullToken;
|
import de.dhbwstuttgart.parser.NullToken;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser;
|
||||||
import de.dhbwstuttgart.parser.scope.GenericsRegistry;
|
import de.dhbwstuttgart.parser.scope.GenericsRegistry;
|
||||||
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.SyntaxTreeGenerator;
|
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;
|
||||||
@@ -36,10 +43,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;
|
||||||
@@ -50,9 +60,11 @@ 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;
|
||||||
|
import java.sql.Array;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
@@ -62,14 +74,19 @@ 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();
|
||||||
|
private final boolean inferTogether;
|
||||||
|
|
||||||
// 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<>();
|
||||||
|
public final Set<JavaClassName> input = new HashSet<>();
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
public final List<File> classPath;
|
public final List<File> classPath;
|
||||||
private final File outputPath;
|
private final File outputPath;
|
||||||
@@ -77,39 +94,63 @@ public class JavaTXCompiler {
|
|||||||
public final Map<String, FunNGenerator.GenericParameters> usedFunN = new HashMap<>();
|
public final Map<String, FunNGenerator.GenericParameters> usedFunN = new HashMap<>();
|
||||||
public final Set<Integer> usedFunNSuperTypes = new HashSet<>();
|
public final Set<Integer> usedFunNSuperTypes = new HashSet<>();
|
||||||
|
|
||||||
|
private final Map<JavaClassName, ClassOrInterface> loadedClasses = new HashMap<>();
|
||||||
public Map<String, byte[]> auxiliaries = new HashMap<>();
|
public Map<String, byte[]> auxiliaries = new HashMap<>();
|
||||||
|
|
||||||
public DirectoryClassLoader getClassLoader() {
|
public DirectoryClassLoader getClassLoader() {
|
||||||
return classLoader;
|
return classLoader;
|
||||||
}
|
}
|
||||||
|
|
||||||
public JavaTXCompiler(File sourceFile) throws IOException, ClassNotFoundException {
|
|
||||||
this(Arrays.asList(sourceFile), List.of(), new File("."));
|
|
||||||
}
|
|
||||||
|
|
||||||
public JavaTXCompiler(File sourceFile, Boolean log) throws IOException, ClassNotFoundException {
|
public JavaTXCompiler(File sourceFile) throws IOException, ClassNotFoundException {
|
||||||
this(sourceFile);
|
this(Collections.singletonList(sourceFile), List.of(), new File("."), ConsoleInterface.inferTogether);
|
||||||
this.log = log;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public JavaTXCompiler(List<File> sourceFiles) throws IOException, ClassNotFoundException {
|
public JavaTXCompiler(List<File> sourceFiles) throws IOException, ClassNotFoundException {
|
||||||
this(sourceFiles, List.of(), new File("."));
|
this(sourceFiles, List.of(), new File("."), ConsoleInterface.inferTogether);
|
||||||
}
|
}
|
||||||
|
|
||||||
public JavaTXCompiler(List<File> sources, List<File> contextPath, File outputPath) throws IOException, ClassNotFoundException {
|
public JavaTXCompiler(List<File> sources, List<File> contextPath, File outputPath, boolean inferTogether) throws IOException, ClassNotFoundException {
|
||||||
|
// ensure new default placeholder registry for tests
|
||||||
|
defaultClientPlaceholderRegistry = new PlaceholderRegistry();
|
||||||
|
this.inferTogether = inferTogether;
|
||||||
|
|
||||||
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
|
||||||
path.add(new File(System.getProperty("user.dir")));
|
path.add(new File(System.getProperty("user.dir")));
|
||||||
}
|
}
|
||||||
if (outputPath != null) path.add(outputPath);
|
if (outputPath != null) path.add(outputPath);
|
||||||
classLoader = new DirectoryClassLoader(path, ClassLoader.getSystemClassLoader());
|
classLoader = new DirectoryClassLoader(path, ClassLoader.getSystemClassLoader().getParent());
|
||||||
environment = new CompilationEnvironment(sources, classLoader);
|
environment = new CompilationEnvironment(sources, classLoader);
|
||||||
classPath = path;
|
classPath = path;
|
||||||
this.outputPath = outputPath;
|
this.outputPath = outputPath;
|
||||||
|
|
||||||
for (File s : sources) {
|
// TODO This should maybe be moved elsewhere
|
||||||
parse(s);
|
var treeList = new ArrayList<SourceFileContext>(sources.size());
|
||||||
|
for (var s : sources) {
|
||||||
|
var tree = (Java17Parser.SrcfileContext) JavaTXParser.parse(s);
|
||||||
|
treeList.add(tree);
|
||||||
|
// Find defined classes
|
||||||
|
var pkgName = tree.packageDeclaration() != null ? tree.packageDeclaration().qualifiedName().getText(): "";
|
||||||
|
for (var ctx : tree.classOrInterface()) {
|
||||||
|
if (ctx instanceof Java17Parser.NoclassorinterfaceContext) continue;
|
||||||
|
var classContext = (Java17Parser.ClassorinterfacedeclContext) ctx;
|
||||||
|
String name = null;
|
||||||
|
if (classContext.classDeclaration() != null)
|
||||||
|
name = classContext.classDeclaration().identifier().getText();
|
||||||
|
else if (classContext.recordDeclaration() != null)
|
||||||
|
name = classContext.recordDeclaration().identifier().getText();
|
||||||
|
else if (classContext.interfaceDeclaration() != null)
|
||||||
|
name = classContext.interfaceDeclaration().identifier().getText();
|
||||||
|
|
||||||
|
var className = pkgName + (!pkgName.isEmpty() ? "." : "") + name;
|
||||||
|
classRegistry.addName(className, 0);
|
||||||
|
input.add(classRegistry.getName(className));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < sources.size(); i++) {
|
||||||
|
parse(treeList.get(i), sources.get(i));
|
||||||
}
|
}
|
||||||
// INSTANCE = this;
|
// INSTANCE = this;
|
||||||
}
|
}
|
||||||
@@ -119,21 +160,26 @@ public class JavaTXCompiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ClassOrInterface getClass(JavaClassName name) {
|
public ClassOrInterface getClass(JavaClassName name) {
|
||||||
if (loadedClasses.containsKey(name)) return loadedClasses.get(name).cif();
|
if (loadedClasses.containsKey(name)) return loadedClasses.get(name);
|
||||||
for (var sf : sourceFiles.values()) {
|
for (var sf : sourceFiles.values()) {
|
||||||
for (var clazz : sf.KlassenVektor) {
|
for (var clazz : sf.KlassenVektor) {
|
||||||
if (clazz.getClassName().equals(name)) return clazz;
|
if (clazz.getClassName().equals(name)) return clazz;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (input.contains(name)) return null;
|
||||||
try {
|
try {
|
||||||
var clazz = classLoader.loadClass(name.toString());
|
var clazz = classLoader.loadClass(name.toString());
|
||||||
if (clazz != null)
|
ClassOrInterface cif = null;
|
||||||
return ASTFactory.createClass(clazz);
|
if (clazz != null) {
|
||||||
|
cif = ASTFactory.createClass(clazz);
|
||||||
|
loadedClasses.put(name, cif);
|
||||||
|
}
|
||||||
|
return cif;
|
||||||
} catch (ClassNotFoundException ignored) {}
|
} catch (ClassNotFoundException ignored) {}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConstraintSet<Pair> getConstraints(File sourceFile) throws ClassNotFoundException, IOException {
|
public Set<ClassOrInterface> getAvailableClasses(File sourceFile) throws ClassNotFoundException, IOException {
|
||||||
Set<ClassOrInterface> allClasses = new HashSet<>();// environment.getAllAvailableClasses();
|
Set<ClassOrInterface> allClasses = new HashSet<>();// environment.getAllAvailableClasses();
|
||||||
ClassOrInterface objectClass = ASTFactory.createClass(Object.class);
|
ClassOrInterface objectClass = ASTFactory.createClass(Object.class);
|
||||||
var recordClass = ASTFactory.createClass(Record.class);
|
var recordClass = ASTFactory.createClass(Record.class);
|
||||||
@@ -159,7 +205,7 @@ public class JavaTXCompiler {
|
|||||||
for (var clazz : sf.availableClasses) {
|
for (var clazz : sf.availableClasses) {
|
||||||
if (loadedClasses.containsKey(clazz.getClassName())) {
|
if (loadedClasses.containsKey(clazz.getClassName())) {
|
||||||
allClasses.removeIf(cl -> cl.getClassName().equals(clazz.getClassName()));
|
allClasses.removeIf(cl -> cl.getClassName().equals(clazz.getClassName()));
|
||||||
var cif = loadedClasses.get(clazz.getClassName()).cif();
|
var cif = loadedClasses.get(clazz.getClassName());
|
||||||
allClasses.add(cif);
|
allClasses.add(cif);
|
||||||
isCached = true;
|
isCached = true;
|
||||||
}
|
}
|
||||||
@@ -172,7 +218,13 @@ public class JavaTXCompiler {
|
|||||||
|
|
||||||
allClasses.addAll(sf.KlassenVektor);
|
allClasses.addAll(sf.KlassenVektor);
|
||||||
|
|
||||||
TYPE ty = new TYPE(sf, allClasses);
|
return allClasses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConstraintSet<Pair> getConstraints(File sourceFile) throws ClassNotFoundException, IOException {
|
||||||
|
var sf = sourceFiles.get(sourceFile);
|
||||||
|
var allClasses = getAvailableClasses(sourceFile);
|
||||||
|
TYPE ty = new TYPE(new HashSet<>(sf.availableClasses), allClasses);
|
||||||
var constraints = ty.getConstraints();
|
var constraints = ty.getConstraints();
|
||||||
return constraints;
|
return constraints;
|
||||||
}
|
}
|
||||||
@@ -192,8 +244,9 @@ public class JavaTXCompiler {
|
|||||||
try {
|
try {
|
||||||
var className = cl.getSuperClass().getName().toString();
|
var className = cl.getSuperClass().getName().toString();
|
||||||
superclass = ASTFactory.createClass(classLoader.loadClass(className));
|
superclass = ASTFactory.createClass(classLoader.loadClass(className));
|
||||||
} catch (ClassNotFoundException ignored) {}
|
} catch (ClassNotFoundException e) {
|
||||||
// throw new ClassNotFoundException("");
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,13 +275,18 @@ public class JavaTXCompiler {
|
|||||||
|
|
||||||
private Set<ClassOrInterface> getAvailableClasses(JavaClassName name) throws ClassNotFoundException {
|
private Set<ClassOrInterface> getAvailableClasses(JavaClassName name) throws ClassNotFoundException {
|
||||||
Set<ClassOrInterface> allClasses = new HashSet<>();
|
Set<ClassOrInterface> allClasses = new HashSet<>();
|
||||||
var clazz = loadJavaTXClass(name);
|
if (input.contains(name)) {
|
||||||
if (clazz == null) {
|
for (var sf : sourceFiles.values()) {
|
||||||
ClassOrInterface importedClass = ASTFactory.createClass(classLoader.loadClass(name.toString()));
|
for (var cif : sf.KlassenVektor) {
|
||||||
allClasses.add(importedClass);
|
if (cif.getClassName().equals(name)) {
|
||||||
} else {
|
allClasses.add(cif);
|
||||||
allClasses.add(clazz);
|
return allClasses;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
ClassOrInterface importedClass = ASTFactory.createClass(classLoader.loadClass(name.toString()));
|
||||||
|
allClasses.add(importedClass);
|
||||||
return allClasses;
|
return allClasses;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,58 +364,193 @@ 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);
|
|
||||||
urm = new UnifyResultModel(cons, finiteClosure);
|
|
||||||
urm.addUnifyResultListener(resultListener);
|
|
||||||
ConstraintSet<UnifyPair> unifyCons = UnifyTypeFactory.convert(this, cons);
|
|
||||||
|
|
||||||
Function<UnifyPair, UnifyPair> distributeInnerVars = x -> {
|
IFiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses, logger, getClassLoader(), this, context.placeholderRegistry());
|
||||||
UnifyType lhs, rhs;
|
logger.info(finiteClosure.toString());
|
||||||
if (((lhs = x.getLhsType()) instanceof PlaceholderType) && ((rhs = x.getRhsType()) instanceof PlaceholderType) && (((PlaceholderType) lhs).isInnerType() || ((PlaceholderType) rhs).isInnerType())) {
|
urm = new UnifyResultModel(cons, finiteClosure);
|
||||||
((PlaceholderType) lhs).setInnerType(true);
|
urm.addUnifyResultListener(resultListener);
|
||||||
((PlaceholderType) rhs).setInnerType(true);
|
ConstraintSet<UnifyPair> unifyCons = UnifyTypeFactory.convert(this, cons, context.placeholderRegistry());
|
||||||
}
|
|
||||||
return x;
|
|
||||||
|
|
||||||
};
|
Function<UnifyPair, UnifyPair> distributeInnerVars = x -> {
|
||||||
logFile.write(unifyCons.toString());
|
UnifyType lhs, rhs;
|
||||||
unifyCons = unifyCons.map(distributeInnerVars);
|
if (((lhs = x.getLhsType()) instanceof PlaceholderType) && ((rhs = x.getRhsType()) instanceof PlaceholderType) && (((PlaceholderType) lhs).isInnerType() || ((PlaceholderType) rhs).isInnerType())) {
|
||||||
logFile.write(unifyCons.toString());
|
((PlaceholderType) lhs).setInnerType(true);
|
||||||
TypeUnify unify = new TypeUnify();
|
((PlaceholderType) rhs).setInnerType(true);
|
||||||
// Set<Set<UnifyPair>> results = new HashSet<>(); Nach vorne gezogen
|
|
||||||
logFile.write("FC:\\" + finiteClosure.toString() + "\n");
|
|
||||||
for (SourceFile f : this.sourceFiles.values()) {
|
|
||||||
logFile.write(ASTTypePrinter.print(f));
|
|
||||||
}
|
}
|
||||||
logFile.flush();
|
return x;
|
||||||
Set<PlaceholderType> varianceTPHold;
|
|
||||||
Set<PlaceholderType> varianceTPH = new HashSet<>();
|
|
||||||
varianceTPH = varianceInheritanceConstraintSet(unifyCons);
|
|
||||||
|
|
||||||
/*
|
};
|
||||||
* PL 2018-11-07 wird in varianceInheritanceConstraintSet erledigt do { //PL 2018-11-05 Huellenbildung Variance auf alle TPHs der Terme auf der jeweiligen //anderen Seite übertragen varianceTPHold = new HashSet<>(varianceTPH); varianceTPH = varianceInheritanceConstraintSet(unifyCons); unifyCons.map( y -> { if ((y.getLhsType() instanceof PlaceholderType) && (y.getRhsType() instanceof PlaceholderType)) { if (((PlaceholderType)y.getLhsType()).getVariance() != 0 &&
|
logger.debug(unifyCons.toString());
|
||||||
* ((PlaceholderType)y.getRhsType()).getVariance() == 0) { ((PlaceholderType)y.getRhsType()).setVariance(((PlaceholderType)y.getLhsType( )).getVariance()); } if (((PlaceholderType)y.getLhsType()).getVariance() == 0 && ((PlaceholderType)y.getRhsType()).getVariance() != 0) { ((PlaceholderType)y.getLhsType()).setVariance(((PlaceholderType)y.getRhsType( )).getVariance()); } } return y; } ); } while (!varianceTPHold.equals(varianceTPH));
|
unifyCons = unifyCons.map(distributeInnerVars);
|
||||||
*/
|
logger.debug(unifyCons.toString());
|
||||||
|
// Set<Set<UnifyPair>> results = new HashSet<>(); Nach vorne gezogen
|
||||||
// Set<Set<UnifyPair>> result = unify.unifySequential(xConsSet, finiteClosure,
|
logger.debug("FC:\\" + finiteClosure.toString() + "\n");
|
||||||
// logFile, log);
|
for (SourceFile f : this.sourceFiles.values()) {
|
||||||
// Set<Set<UnifyPair>> result = unify.unify(xConsSet, finiteClosure);
|
logger.debug(ASTTypePrinter.print(f));
|
||||||
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))
|
|
||||||
*/;
|
|
||||||
unify.unifyAsync(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, logFile, log, urm, usedTasks);
|
|
||||||
} catch (IOException e) {
|
|
||||||
System.err.println("kein LogFile");
|
|
||||||
}
|
}
|
||||||
|
// logFile.flush();
|
||||||
|
Set<PlaceholderType> varianceTPHold;
|
||||||
|
Set<PlaceholderType> varianceTPH = new HashSet<>();
|
||||||
|
varianceTPH = varianceInheritanceConstraintSet(unifyCons);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PL 2018-11-07 wird in varianceInheritanceConstraintSet erledigt do { //PL 2018-11-05 Huellenbildung Variance auf alle TPHs der Terme auf der jeweiligen //anderen Seite übertragen varianceTPHold = new HashSet<>(varianceTPH); varianceTPH = varianceInheritanceConstraintSet(unifyCons); unifyCons.map( y -> { if ((y.getLhsType() instanceof PlaceholderType) && (y.getRhsType() instanceof PlaceholderType)) { if (((PlaceholderType)y.getLhsType()).getVariance() != 0 &&
|
||||||
|
* ((PlaceholderType)y.getRhsType()).getVariance() == 0) { ((PlaceholderType)y.getRhsType()).setVariance(((PlaceholderType)y.getLhsType( )).getVariance()); } if (((PlaceholderType)y.getLhsType()).getVariance() == 0 && ((PlaceholderType)y.getRhsType()).getVariance() != 0) { ((PlaceholderType)y.getLhsType()).setVariance(((PlaceholderType)y.getRhsType( )).getVariance()); } } return y; } ); } while (!varianceTPHold.equals(varianceTPH));
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Set<Set<UnifyPair>> result = unify.unifySequential(xConsSet, finiteClosure,
|
||||||
|
// logFile, log);
|
||||||
|
// Set<Set<UnifyPair>> result = unify.unify(xConsSet, finiteClosure);
|
||||||
|
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))
|
||||||
|
*/;
|
||||||
|
TypeUnify.unifyAsync(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, context);
|
||||||
|
|
||||||
return urm;
|
return urm;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ResultSet> typeInference(File file) throws ClassNotFoundException, IOException {
|
public List<ResultSet> typeInference(File file) throws ClassNotFoundException, IOException {
|
||||||
|
return typeInference(List.of(file));
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ResultSet> typeInference(List<File> files) throws ClassNotFoundException, IOException {
|
||||||
|
Set<ClassOrInterface> allClasses = new HashSet<>();
|
||||||
|
|
||||||
|
var ressf = new ArrayList<SourceFile>();
|
||||||
|
var definedClasses = new HashSet<ClassOrInterface>();
|
||||||
|
for (var file : files) {
|
||||||
|
var sf = sourceFiles.get(file);
|
||||||
|
definedClasses.addAll(sf.KlassenVektor);
|
||||||
|
ressf.add(sf);
|
||||||
|
allClasses.addAll(getAvailableClasses(file));
|
||||||
|
allClasses.addAll(sf.availableClasses);
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPE ty = new TYPE(definedClasses, allClasses);
|
||||||
|
var cons = ty.getConstraints();
|
||||||
|
|
||||||
|
Set<Set<UnifyPair>> results = new HashSet<>();
|
||||||
|
PlaceholderRegistry placeholderRegistry = new PlaceholderRegistry();
|
||||||
|
|
||||||
|
var logFolder = new File(System.getProperty("user.dir") + "/logFiles/");
|
||||||
|
if (ConsoleInterface.writeLogFiles && !logFolder.mkdirs()) throw new RuntimeException("Could not create directory for log files: " + logFolder);
|
||||||
|
Writer logFile = ConsoleInterface.writeLogFiles ? new FileWriter(new File(logFolder, "log_" + sourceFiles.keySet().iterator().next().getName())) : new OutputStreamWriter(new NullOutputStream());
|
||||||
|
Logger logger = new Logger(logFile, "TypeInference");
|
||||||
|
|
||||||
|
FiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses.stream().toList(), logger, classLoader, this, placeholderRegistry);
|
||||||
|
logger.info(finiteClosure.toString());
|
||||||
|
ConstraintSet<UnifyPair> unifyCons = UnifyTypeFactory.convert(this, cons, placeholderRegistry);
|
||||||
|
logger.info("xxx1");
|
||||||
|
Function<UnifyPair, UnifyPair> distributeInnerVars = x -> {
|
||||||
|
UnifyType lhs, rhs;
|
||||||
|
if (((lhs = x.getLhsType()) instanceof PlaceholderType) && ((rhs = x.getRhsType()) instanceof PlaceholderType) && (((PlaceholderType) lhs).isInnerType() || ((PlaceholderType) rhs).isInnerType())) {
|
||||||
|
((PlaceholderType) lhs).setInnerType(true);
|
||||||
|
((PlaceholderType) rhs).setInnerType(true);
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
logger.debug("Unify:" + unifyCons.toString());
|
||||||
|
logger.info("Unify:" + unifyCons.toString());
|
||||||
|
unifyCons = unifyCons.map(distributeInnerVars);
|
||||||
|
logger.debug("\nUnify_distributeInnerVars: " + unifyCons.toString());
|
||||||
|
// Set<Set<UnifyPair>> results = new HashSet<>(); Nach vorne gezogen
|
||||||
|
logger.debug("FC:\\" + finiteClosure.toString() + "\n");
|
||||||
|
for (var sf : ressf) logger.info(ASTTypePrinter.print(sf));
|
||||||
|
// logFile.flush();
|
||||||
|
List<UnifyPair> andConstraintsSorted = unifyCons.getUndConstraints().stream()
|
||||||
|
.sorted(Comparator.comparing(UnifyPair::getPairOp).thenComparing(UnifyPair::getLhsType, Comparator.comparing(UnifyType::getName)))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
logger.info(andConstraintsSorted);
|
||||||
|
|
||||||
|
Set<PlaceholderType> varianceTPHold;
|
||||||
|
Set<PlaceholderType> varianceTPH = new HashSet<>();
|
||||||
|
varianceTPH = varianceInheritanceConstraintSet(unifyCons);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PL 2018-11-07 wird in varianceInheritanceConstraintSet erledigt do { //PL 2018-11-05 Huellenbildung Variance auf alle TPHs der Terme auf der jeweiligen //anderen Seite übertragen varianceTPHold = new HashSet<>(varianceTPH); varianceTPH = varianceInheritanceConstraintSet(unifyCons); unifyCons.map( y -> { if ((y.getLhsType() instanceof PlaceholderType) && (y.getRhsType() instanceof PlaceholderType)) { if (((PlaceholderType)y.getLhsType()).getVariance() != 0 &&
|
||||||
|
* ((PlaceholderType)y.getRhsType()).getVariance() == 0) { ((PlaceholderType)y.getRhsType()).setVariance(((PlaceholderType)y.getLhsType( )).getVariance()); } if (((PlaceholderType)y.getLhsType()).getVariance() == 0 && ((PlaceholderType)y.getRhsType()).getVariance() != 0) { ((PlaceholderType)y.getLhsType()).setVariance(((PlaceholderType)y.getRhsType( )).getVariance()); } } return y; } ); } while (!varianceTPHold.equals(varianceTPH));
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Set<Set<UnifyPair>> result = unify.unifySequential(xConsSet, finiteClosure,
|
||||||
|
// logFile, log);
|
||||||
|
// Set<Set<UnifyPair>> result = unify.unify(xConsSet, finiteClosure);
|
||||||
|
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))
|
||||||
|
*/;
|
||||||
|
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 urm = new UnifyResultModel(cons, finiteClosure);
|
||||||
|
UnifyResultListenerImpl li = new UnifyResultListenerImpl();
|
||||||
|
urm.addUnifyResultListener(li);
|
||||||
|
UnifyContext context = new UnifyContext(logger, true, urm, usedTasks, placeholderRegistry);
|
||||||
|
TypeUnify.unifyParallel(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, context);
|
||||||
|
var finalResults = li.getResults().stream().sorted().toList();
|
||||||
|
int i = 0;
|
||||||
|
logger.info("RESULT Final: ");
|
||||||
|
for (var result : finalResults){
|
||||||
|
logger.info("Result: " + i++);
|
||||||
|
logger.info(result.getSortedResults());
|
||||||
|
}
|
||||||
|
logger.info("RES_FINAL: " + li.getResults().toString() + "\n");
|
||||||
|
return li.getResults();
|
||||||
|
}
|
||||||
|
/* UnifyResultModel End */
|
||||||
|
else {
|
||||||
|
// Set<Set<UnifyPair>> result = unify.unify(unifyCons.getUndConstraints(),
|
||||||
|
// oderConstraints, finiteClosure, logFile, log, new UnifyResultModel(cons,
|
||||||
|
// finiteClosure));
|
||||||
|
UnifyContext context = new UnifyContext(logger, false, new UnifyResultModel(cons, finiteClosure), usedTasks, placeholderRegistry);
|
||||||
|
Set<Set<UnifyPair>> result = TypeUnify.unifyOderConstraints(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, context);
|
||||||
|
logger.info("RESULT: " + result);
|
||||||
|
results.addAll(result);
|
||||||
|
|
||||||
|
results = results.stream().map(x -> {
|
||||||
|
Optional<Set<UnifyPair>> res = new RuleSet(placeholderRegistry).subst(x.stream().map(y -> {
|
||||||
|
if (y.getPairOp() == PairOperator.SMALLERDOTWC)
|
||||||
|
y.setPairOp(PairOperator.EQUALSDOT);
|
||||||
|
return y; // alle Paare a <.? b erden durch a =. b ersetzt
|
||||||
|
}).collect(Collectors.toCollection(HashSet::new)));
|
||||||
|
if (res.isPresent()) {// wenn subst ein Erg liefert wurde was veraendert
|
||||||
|
return new TypeUnifyTask(context).applyTypeUnificationRules(res.get(), finiteClosure);
|
||||||
|
} else
|
||||||
|
return x; // wenn nichts veraendert wurde wird x zurueckgegeben
|
||||||
|
}).collect(Collectors.toCollection(HashSet::new));
|
||||||
|
logger.info("RESULT Final: " + results);
|
||||||
|
logger.info("Constraints for Generated Generics: " + " ???");
|
||||||
|
logger.debug("RES_FINAL: " + results.toString() + "\n");
|
||||||
|
// logFile.flush();
|
||||||
|
logger.debug("PLACEHOLDERS: " + placeholderRegistry);
|
||||||
|
// logFile.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
return results.stream().map((unifyPairs -> new ResultSet(UnifyTypeFactory.convert(unifyPairs, Pair.generateTPHMap(cons), placeholderRegistry)))).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TEMPORARY - Only for Language Server Usage
|
||||||
|
*/
|
||||||
|
public LanguageServerTransferObject getResultSetAndAbstractSyntax(File file) throws IOException, ClassNotFoundException {
|
||||||
var sf = sourceFiles.get(file);
|
var sf = sourceFiles.get(file);
|
||||||
Set<ClassOrInterface> allClasses = new HashSet<>();// environment.getAllAvailableClasses();
|
if(sf == null){
|
||||||
|
sf = sourceFiles.values().stream().findFirst().get();
|
||||||
|
}
|
||||||
|
Set<ClassOrInterface> allClasses = new HashSet<>();
|
||||||
allClasses.addAll(getAvailableClasses(sf));
|
allClasses.addAll(getAvailableClasses(sf));
|
||||||
allClasses.addAll(sf.getClasses());
|
allClasses.addAll(sf.getClasses());
|
||||||
var newClasses = CompilationEnvironment.loadDefaultPackageClasses(sf.getPkgName(), file, this).stream().map(ASTFactory::createClass).collect(Collectors.toSet());
|
var newClasses = CompilationEnvironment.loadDefaultPackageClasses(sf.getPkgName(), file, this).stream().map(ASTFactory::createClass).collect(Collectors.toSet());
|
||||||
@@ -371,14 +564,13 @@ 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<>();
|
||||||
|
|
||||||
|
Writer logFile = new OutputStreamWriter(new NullOutputStream());
|
||||||
|
Logger logger = new Logger(logFile, "TypeInferenceAsync");
|
||||||
|
UnifyContext context = new UnifyContext(logger, false, null, usedTasks, defaultClientPlaceholderRegistry);
|
||||||
try {
|
try {
|
||||||
var logFolder = new File(System.getProperty("user.dir") + "/logFiles/");
|
IFiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses.stream().toList(), logger, classLoader, this, context.placeholderRegistry());
|
||||||
if (log) logFolder.mkdirs();
|
ConstraintSet<UnifyPair> unifyCons = UnifyTypeFactory.convert(this, cons, context.placeholderRegistry());
|
||||||
Writer logFile = log ? 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);
|
|
||||||
System.out.println(finiteClosure);
|
|
||||||
ConstraintSet<UnifyPair> unifyCons = UnifyTypeFactory.convert(this, cons);
|
|
||||||
System.out.println("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())) {
|
||||||
@@ -389,92 +581,48 @@ public class JavaTXCompiler {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
logFile.write("Unify:" + unifyCons.toString());
|
|
||||||
System.out.println("Unify:" + unifyCons.toString());
|
|
||||||
unifyCons = unifyCons.map(distributeInnerVars);
|
unifyCons = unifyCons.map(distributeInnerVars);
|
||||||
logFile.write("\nUnify_distributeInnerVars: " + unifyCons.toString());
|
|
||||||
TypeUnify unify = new TypeUnify();
|
|
||||||
// Set<Set<UnifyPair>> results = new HashSet<>(); Nach vorne gezogen
|
|
||||||
logFile.write("FC:\\" + finiteClosure.toString() + "\n");
|
|
||||||
logFile.write(ASTTypePrinter.print(sf));
|
|
||||||
System.out.println(ASTTypePrinter.print(sf));
|
|
||||||
logFile.flush();
|
|
||||||
List<UnifyPair> andConstraintsSorted = unifyCons.getUndConstraints().stream()
|
|
||||||
.sorted(Comparator.comparing(UnifyPair::getPairOp).thenComparing(UnifyPair::getLhsType, Comparator.comparing(UnifyType::getName)))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
/*
|
List<Set<Constraint<UnifyPair>>> oderConstraints = unifyCons.getOderConstraints();
|
||||||
* PL 2018-11-07 wird in varianceInheritanceConstraintSet erledigt do { //PL 2018-11-05 Huellenbildung Variance auf alle TPHs der Terme auf der jeweiligen //anderen Seite übertragen varianceTPHold = new HashSet<>(varianceTPH); varianceTPH = varianceInheritanceConstraintSet(unifyCons); unifyCons.map( y -> { if ((y.getLhsType() instanceof PlaceholderType) && (y.getRhsType() instanceof PlaceholderType)) { if (((PlaceholderType)y.getLhsType()).getVariance() != 0 &&
|
|
||||||
* ((PlaceholderType)y.getRhsType()).getVariance() == 0) { ((PlaceholderType)y.getRhsType()).setVariance(((PlaceholderType)y.getLhsType( )).getVariance()); } if (((PlaceholderType)y.getLhsType()).getVariance() == 0 && ((PlaceholderType)y.getRhsType()).getVariance() != 0) { ((PlaceholderType)y.getLhsType()).setVariance(((PlaceholderType)y.getRhsType( )).getVariance()); } } return y; } ); } while (!varianceTPHold.equals(varianceTPH));
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Set<Set<UnifyPair>> result = unify.unifySequential(xConsSet, finiteClosure,
|
|
||||||
// logFile, log);
|
|
||||||
// Set<Set<UnifyPair>> result = unify.unify(xConsSet, finiteClosure);
|
|
||||||
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))
|
|
||||||
*/;
|
|
||||||
if (resultmodel) {
|
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);
|
TypeUnify.unifyParallel(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, context);
|
||||||
//System.out.println("RESULT Final: " + li.getResults());
|
generateBytecode(sf, li.getResults());
|
||||||
var finalResults = li.getResults().stream().sorted().toList();
|
return new LanguageServerTransferObject(li.getResults(), sf, ASTTypePrinter.print(sf), generatedGenerics);
|
||||||
int i = 0;
|
|
||||||
System.out.println("RESULT Final: ");
|
|
||||||
for (var result : finalResults){
|
|
||||||
System.out.println("Result: " + i++);
|
|
||||||
System.out.println(result.getSortedResults());
|
|
||||||
}
|
|
||||||
System.out.println("Constraints for Generated Generics: " + " ???");
|
|
||||||
logFile.write("RES_FINAL: " + li.getResults().toString() + "\n");
|
|
||||||
logFile.flush();
|
|
||||||
return li.getResults();
|
|
||||||
}
|
}
|
||||||
/* UnifyResultModel End */
|
/* UnifyResultModel End */
|
||||||
else {
|
else {
|
||||||
// Set<Set<UnifyPair>> result = unify.unify(unifyCons.getUndConstraints(),
|
Set<Set<UnifyPair>> result = TypeUnify.unifyOderConstraints(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, context);
|
||||||
// oderConstraints, finiteClosure, logFile, log, new UnifyResultModel(cons,
|
|
||||||
// finiteClosure));
|
|
||||||
Set<Set<UnifyPair>> result = unify.unifyOderConstraints(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, logFile, log, new UnifyResultModel(cons, finiteClosure), usedTasks);
|
|
||||||
System.out.println("RESULT: " + result);
|
|
||||||
logFile.write("RES: " + result.toString() + "\n");
|
|
||||||
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(context.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);
|
|
||||||
System.out.println("Constraints for Generated Generics: " + " ???");
|
|
||||||
logFile.write("RES_FINAL: " + results.toString() + "\n");
|
|
||||||
logFile.flush();
|
|
||||||
logFile.write("PLACEHOLDERS: " + PlaceholderType.EXISTING_PLACEHOLDERS);
|
|
||||||
logFile.flush();
|
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (ClassNotFoundException e) {
|
||||||
System.err.println("kein LogFile");
|
|
||||||
}
|
}
|
||||||
return results.stream().map((unifyPairs -> new ResultSet(UnifyTypeFactory.convert(unifyPairs, Pair.generateTPHMap(cons))))).collect(Collectors.toList());
|
generateBytecode(sf, results.stream().map((unifyPairs -> new ResultSet(UnifyTypeFactory.convert(unifyPairs, Pair.generateTPHMap(cons), context.placeholderRegistry())))).collect(Collectors.toList()));
|
||||||
|
return new LanguageServerTransferObject(results.stream().map((unifyPairs -> new ResultSet(UnifyTypeFactory.convert(unifyPairs, Pair.generateTPHMap(cons), context.placeholderRegistry())))).collect(Collectors.toList()), sf, ASTTypePrinter.print(sf), generatedGenerics);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Vererbt alle Variancen bei Paaren (a <. theta) oder (Theta <. a) wenn a eine Variance !=0 hat auf alle Typvariablen in Theta.
|
* Vererbt alle Variancen bei Paaren (a <. theta) oder (Theta <. a) wenn a eine Variance !=0 hat auf alle Typvariablen in Theta.
|
||||||
*
|
*
|
||||||
@@ -532,82 +680,39 @@ public class JavaTXCompiler {
|
|||||||
|
|
||||||
public final JavaClassRegistry classRegistry = new JavaClassRegistry();
|
public final JavaClassRegistry classRegistry = new JavaClassRegistry();
|
||||||
|
|
||||||
public record ClassEntry(File classFile, ClassOrInterface cif) {}
|
private void parse(SourceFileContext tree, File sourceFile) throws IOException, java.lang.ClassNotFoundException {
|
||||||
|
|
||||||
public final Map<JavaClassName, ClassEntry> loadedClasses = new HashMap<>();
|
|
||||||
|
|
||||||
private SourceFile parse(File sourceFile) throws IOException, java.lang.ClassNotFoundException {
|
|
||||||
if (sourceFiles.containsKey(sourceFile)) return sourceFiles.get(sourceFile);
|
|
||||||
SourceFileContext tree = JavaTXParser.parse(sourceFile);
|
|
||||||
environment.addClassesToRegistry(classRegistry, tree, sourceFile, this);
|
|
||||||
SyntaxTreeGenerator generator = new SyntaxTreeGenerator(this, classRegistry, new GenericsRegistry(null), sourceFile.getName());
|
SyntaxTreeGenerator generator = new SyntaxTreeGenerator(this, classRegistry, new GenericsRegistry(null), sourceFile.getName());
|
||||||
|
environment.addClassesToRegistry(classRegistry, tree, sourceFile, this);
|
||||||
var classes = new ArrayList<ClassOrInterface>();
|
var classes = new ArrayList<ClassOrInterface>();
|
||||||
var sf = new SourceFile("", classes, generator.imports);
|
var sf = new SourceFile("", classes, generator.imports);
|
||||||
addSourceFile(sourceFile, sf);
|
addSourceFile(sourceFile, sf);
|
||||||
generator.convert(classes, tree, environment.packageCrawler);
|
generator.convert(classes, tree, environment.packageCrawler);
|
||||||
sf.setPackageName(generator.pkgName);
|
sf.setPackageName(generator.pkgName);
|
||||||
sf.imports.addAll(generator.imports);
|
sf.imports.addAll(generator.imports);
|
||||||
return sf;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When an import tries to import a JavaTX class it first looks it up in the cache and
|
|
||||||
* if it doesn't exist it's going to compile it and add it to the source files list
|
|
||||||
* @param name
|
|
||||||
*/
|
|
||||||
public ClassOrInterface loadJavaTXClass(JavaClassName name) {
|
|
||||||
var file = findFileForClass(name);
|
|
||||||
if (file != null) {
|
|
||||||
if (loadedClasses.containsKey(name)) return loadedClasses.get(name).cif();
|
|
||||||
try {
|
|
||||||
var tree = JavaTXParser.parse(file);
|
|
||||||
classRegistry.addName(name.toString(), 0); // TODO This gets overwritten later, is it bad if we don't know this right away?
|
|
||||||
environment.addClassesToRegistry(classRegistry, tree, file, this);
|
|
||||||
SyntaxTreeGenerator generator = new SyntaxTreeGenerator(this, classRegistry, new GenericsRegistry(null), file.getName());
|
|
||||||
var classes = new ArrayList<ClassOrInterface>();
|
|
||||||
var sf = new SourceFile("", classes, generator.imports);
|
|
||||||
addSourceFile(file, sf);
|
|
||||||
generator.convert(classes, tree, environment.packageCrawler);
|
|
||||||
sf.setPackageName(generator.pkgName);
|
|
||||||
var classFiles = generateBytecode(file);
|
|
||||||
|
|
||||||
sf.setGenerated();
|
|
||||||
writeClassFile(classFiles, outputPath != null ? outputPath : new File("."), false);
|
|
||||||
var clazz = classLoader.loadClass(name.toString());
|
|
||||||
var classOrInterface = ASTFactory.createClass(clazz);
|
|
||||||
loadedClasses.put(name, new ClassEntry(new File(outputPath, clazz.getName() + ".class"), classOrInterface));
|
|
||||||
return classOrInterface;
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public File findFileForClass(JavaClassName name) {
|
|
||||||
var packageName = name.getPackageName();
|
|
||||||
var className = name.getClassName().split("\\.")[0];
|
|
||||||
for (var cp : classPath) {
|
|
||||||
var file = new File(cp, packageName.replaceAll("\\.", "/") + "/" + className + ".jav");
|
|
||||||
if (file.exists()) return file;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void generateBytecode() throws ClassNotFoundException, IOException {
|
public void generateBytecode() throws ClassNotFoundException, IOException {
|
||||||
for (var file : sourceFiles.keySet()) {
|
if (inferTogether) {
|
||||||
var sf = sourceFiles.get(file);
|
var files = sourceFiles.keySet().stream().toList();
|
||||||
if (sf.isGenerated()) continue;
|
var typeinferenceResult = this.typeInference(files);
|
||||||
var classes = generateBytecode(file);
|
for (var file : files) {
|
||||||
sf.setGenerated();
|
var sf = sourceFiles.get(file);
|
||||||
writeClassFile(classes, outputPath == null ? file.getParentFile() : outputPath, outputPath == null);
|
if (sf.isGenerated()) continue;
|
||||||
|
var classes = generateBytecode(sf, typeinferenceResult);
|
||||||
|
sf.setGenerated();
|
||||||
|
writeClassFile(classes, outputPath == null ? file.getParentFile() : outputPath, outputPath == null);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (var file : sourceFiles.keySet()) {
|
||||||
|
var sf = sourceFiles.get(file);
|
||||||
|
if (sf.isGenerated()) continue;
|
||||||
|
var classes = generateBytecode(file);
|
||||||
|
sf.setGenerated();
|
||||||
|
writeClassFile(classes, outputPath == null ? file.getParentFile() : outputPath, outputPath == null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @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;
|
||||||
@@ -662,15 +767,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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
31
src/main/java/de/dhbwstuttgart/core/JavaTXServer.java
Normal file
31
src/main/java/de/dhbwstuttgart/core/JavaTXServer.java
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@ import java.util.*;
|
|||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import de.dhbwstuttgart.core.JavaTXCompiler;
|
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||||
|
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||||
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
|
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
|
||||||
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
|
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
|
||||||
|
|
||||||
@@ -87,6 +88,8 @@ public class CompilationEnvironment {
|
|||||||
if (files != null)
|
if (files != null)
|
||||||
for (File classFile : files) {
|
for (File classFile : files) {
|
||||||
String className = classFile.getName().substring(0, classFile.getName().length() - 6);
|
String className = classFile.getName().substring(0, classFile.getName().length() - 6);
|
||||||
|
// Don't load class if its defined in the input
|
||||||
|
if (compiler.input.contains(new JavaClassName(className))) continue;
|
||||||
if (className.matches("Fun\\d+\\$\\$.*"))
|
if (className.matches("Fun\\d+\\$\\$.*"))
|
||||||
continue;
|
continue;
|
||||||
var name = packageName;
|
var name = packageName;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public class DirectoryClassLoader extends URLClassLoader implements IByteArrayCl
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
public DirectoryClassLoader(List<File> directory, java.lang.ClassLoader parent) {
|
public DirectoryClassLoader(List<File> directory, java.lang.ClassLoader parent) {
|
||||||
super(directory.stream().map(DirectoryClassLoader::dirToURL).flatMap(List::stream).collect(Collectors.toList()).toArray(new URL[0]), parent.getParent());
|
super(directory.stream().map(DirectoryClassLoader::dirToURL).flatMap(List::stream).collect(Collectors.toList()).toArray(new URL[0]), parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static URL[] generateURLArray(URL url) {
|
private static URL[] generateURLArray(URL url) {
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
package de.dhbwstuttgart.languageServerInterface;
|
||||||
|
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.bytecode.Codegen;
|
||||||
|
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||||
|
import de.dhbwstuttgart.environment.IByteArrayClassLoader;
|
||||||
|
import de.dhbwstuttgart.languageServerInterface.model.LanguageServerTransferObject;
|
||||||
|
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.SourceFile;
|
||||||
|
import de.dhbwstuttgart.syntaxtree.factory.NameGenerator;
|
||||||
|
import de.dhbwstuttgart.target.generate.ASTToTargetAST;
|
||||||
|
import de.dhbwstuttgart.target.generate.GenericsResult;
|
||||||
|
import de.dhbwstuttgart.target.tree.TargetStructure;
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.nio.file.DirectoryStream;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of an Interface for the Language-Server to get the Resultset and abstract Syntax.
|
||||||
|
*/
|
||||||
|
public class LanguageServerInterface {
|
||||||
|
|
||||||
|
|
||||||
|
public LanguageServerTransferObject getResultSetAndAbastractSyntax(String path, String resetNamesTo) throws IOException, URISyntaxException, ClassNotFoundException {
|
||||||
|
NameGenerator.resetTo(resetNamesTo);
|
||||||
|
return getResultSetAndAbstractSyntax(path);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public SourceFile getAst(String path, String resetNamesTo) throws IOException, URISyntaxException, ClassNotFoundException {
|
||||||
|
NameGenerator.resetTo(resetNamesTo);
|
||||||
|
return getAST(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the ResultSets, GenericResultSet and the AST
|
||||||
|
* You have to give the input as well as the path because of potential locks when the File is currently opened in an IDE.
|
||||||
|
* Example: file:///c:/test/main.jav -> file:///c:/test/out/main.class
|
||||||
|
*
|
||||||
|
* @param pathAsString the URI of the File. See Example.
|
||||||
|
*/
|
||||||
|
public LanguageServerTransferObject getResultSetAndAbstractSyntax(String pathAsString){
|
||||||
|
System.setOut(new PrintStream(OutputStream.nullOutputStream()));
|
||||||
|
try {
|
||||||
|
var uri = new URI(pathAsString);
|
||||||
|
var path = Path.of(uri);
|
||||||
|
var file = path.toFile();
|
||||||
|
Files.createDirectories(path.getParent().resolve("out"));
|
||||||
|
var compiler = new JavaTXCompiler(List.of(file), List.of(path.getParent().toFile()), path.getParent().resolve("out").toFile(), false);
|
||||||
|
|
||||||
|
var parsedSource = compiler.sourceFiles.get(file);
|
||||||
|
var tiResults = compiler.typeInference(file);
|
||||||
|
|
||||||
|
Map<JavaClassName, byte[]> bytecode = compiler.generateBytecode(parsedSource, tiResults);
|
||||||
|
Files.createDirectories(path.getParent().resolve("out"));
|
||||||
|
compiler.writeClassFile(bytecode, path.getParent().resolve("out").toFile(), false);
|
||||||
|
|
||||||
|
return new LanguageServerTransferObject(tiResults, parsedSource, "", compiler.getGeneratedGenerics());
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the AST without calculating the result
|
||||||
|
* You have to give the input as well as the path because of potential locks when the File is currently opened in an IDE.
|
||||||
|
* Example: file:///c:/test/main.jav -> file:///c:/test/out/main.class
|
||||||
|
*
|
||||||
|
* @param path the URI of the File. See Example.
|
||||||
|
* @throws IOException
|
||||||
|
* @throws ClassNotFoundException
|
||||||
|
* @throws URISyntaxException
|
||||||
|
*/
|
||||||
|
public SourceFile getAST(String path) throws IOException, ClassNotFoundException, URISyntaxException {
|
||||||
|
|
||||||
|
|
||||||
|
System.setOut(new PrintStream(OutputStream.nullOutputStream()));
|
||||||
|
|
||||||
|
|
||||||
|
URI uri = new URI(path);
|
||||||
|
ArrayList<String> pathWithoutName = new ArrayList<>(List.of(uri.getPath().split("/")));
|
||||||
|
pathWithoutName.remove(List.of(uri.getPath().split("/")).size() - 1);
|
||||||
|
String stringPathWithoutName = "";
|
||||||
|
|
||||||
|
for (String i : pathWithoutName) {
|
||||||
|
stringPathWithoutName += "/" + i;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
FileUtils.cleanDirectory(new File(stringPathWithoutName + "/out"));
|
||||||
|
} catch (Exception e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
(new File(stringPathWithoutName + "/out")).mkdirs();
|
||||||
|
} catch (Exception e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
var test = getAST(uri.getPath().split("/")[uri.getPath().split("/").length - 1], new File(stringPathWithoutName).getPath());
|
||||||
|
System.setOut(System.out);
|
||||||
|
return test;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SourceFile getAST(String filename, String filePath) throws IOException, ClassNotFoundException {
|
||||||
|
var file = Path.of(filePath, filename).toFile();
|
||||||
|
var compiler = new JavaTXCompiler(List.of(file), List.of(file.getParentFile()), Path.of(filePath + "/out").toFile(), false);
|
||||||
|
return compiler.sourceFiles.get(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package de.dhbwstuttgart.languageServerInterface;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.languageServerInterface.model.CustomParserErrorHandler;
|
||||||
|
import de.dhbwstuttgart.languageServerInterface.model.ParserError;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Lexer;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17Parser;
|
||||||
|
import de.dhbwstuttgart.parser.antlr.Java17ParserBaseListener;
|
||||||
|
import org.antlr.v4.runtime.CharStream;
|
||||||
|
import org.antlr.v4.runtime.CharStreams;
|
||||||
|
import org.antlr.v4.runtime.CommonTokenStream;
|
||||||
|
import org.antlr.v4.runtime.tree.ParseTree;
|
||||||
|
import org.antlr.v4.runtime.tree.ParseTreeWalker;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ParserInterface {
|
||||||
|
|
||||||
|
public List<ParserError> getParseErrors(String input){
|
||||||
|
|
||||||
|
CustomParserErrorHandler errorListener = new CustomParserErrorHandler();
|
||||||
|
CharStream charStream = CharStreams.fromString(input);
|
||||||
|
|
||||||
|
Java17Lexer lexer = new Java17Lexer(charStream);
|
||||||
|
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
||||||
|
|
||||||
|
Java17Parser parser = new Java17Parser(tokens);
|
||||||
|
parser.removeErrorListeners();
|
||||||
|
parser.addErrorListener(errorListener);
|
||||||
|
|
||||||
|
|
||||||
|
ParseTree tree = parser.sourceFile();
|
||||||
|
ParseTreeWalker walker = new ParseTreeWalker();
|
||||||
|
Java17ParserBaseListener listener = new Java17ParserBaseListener();
|
||||||
|
walker.walk(listener, tree);
|
||||||
|
|
||||||
|
return errorListener.getErrorMessages();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package de.dhbwstuttgart.languageServerInterface.model;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import org.antlr.v4.runtime.*;
|
||||||
|
import org.antlr.v4.runtime.atn.ATNConfigSet;
|
||||||
|
import org.antlr.v4.runtime.dfa.DFA;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.BitSet;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class CustomParserErrorHandler implements ANTLRErrorListener {
|
||||||
|
private final List<ParserError> errorMessages = new ArrayList<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
|
||||||
|
int endCharPosition = charPositionInLine;
|
||||||
|
if (offendingSymbol instanceof Token) {
|
||||||
|
Token offendingToken = (Token) offendingSymbol;
|
||||||
|
endCharPosition = charPositionInLine + offendingToken.getText().length();
|
||||||
|
}
|
||||||
|
|
||||||
|
ParserError parserError = new ParserError(line, charPositionInLine, endCharPosition, msg);
|
||||||
|
errorMessages.add(parserError);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reportAmbiguity(Parser parser, DFA dfa, int i, int i1, boolean b, BitSet bitSet, ATNConfigSet atnConfigSet) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reportAttemptingFullContext(Parser parser, DFA dfa, int i, int i1, BitSet bitSet, ATNConfigSet atnConfigSet) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reportContextSensitivity(Parser parser, DFA dfa, int i, int i1, int i2, ATNConfigSet atnConfigSet) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ParserError> getErrorMessages() {
|
||||||
|
return errorMessages;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package de.dhbwstuttgart.languageServerInterface.model;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.syntaxtree.SourceFile;
|
||||||
|
import de.dhbwstuttgart.target.generate.GenericsResult;
|
||||||
|
import de.dhbwstuttgart.typeinference.result.ResultSet;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class LanguageServerTransferObject {
|
||||||
|
List<ResultSet> resultSets;
|
||||||
|
SourceFile Ast;
|
||||||
|
String printedAst;
|
||||||
|
Map<SourceFile, List<GenericsResult>> generatedGenerics = new HashMap<>();
|
||||||
|
|
||||||
|
|
||||||
|
public LanguageServerTransferObject(List<ResultSet> resultSets, SourceFile Ast, String printedAst, Map<SourceFile, List<GenericsResult>> generatedGenerics) {
|
||||||
|
this.resultSets = resultSets;
|
||||||
|
this.Ast = Ast;
|
||||||
|
this.printedAst = printedAst;
|
||||||
|
this.generatedGenerics = generatedGenerics;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ResultSet> getResultSets() {return resultSets;}
|
||||||
|
public SourceFile getAst() {return Ast;}
|
||||||
|
public String getPrintedAst() {return printedAst;}
|
||||||
|
public Map<SourceFile, List<GenericsResult>> getGeneratedGenerics() {return generatedGenerics;}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package de.dhbwstuttgart.languageServerInterface.model;
|
||||||
|
|
||||||
|
public class ParserError {
|
||||||
|
|
||||||
|
private int line;
|
||||||
|
private int charPositionInLine;
|
||||||
|
private int endCharPosition;
|
||||||
|
String msg;
|
||||||
|
|
||||||
|
public ParserError(int line, int charPositionInLine, int endCharPosition, String msg) {
|
||||||
|
this.line = line;
|
||||||
|
this.charPositionInLine = charPositionInLine;
|
||||||
|
this. endCharPosition = endCharPosition;
|
||||||
|
this.msg = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getEndCharPosition() {
|
||||||
|
return endCharPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEndCharPosition(int endCharPosition) {
|
||||||
|
this.endCharPosition = endCharPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCharPositionInLine(int charPositionInLine) {
|
||||||
|
this.charPositionInLine = charPositionInLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLine(int line) {
|
||||||
|
this.line = line;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMsg(String msg) {
|
||||||
|
this.msg = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCharPositionInLine() {
|
||||||
|
return charPositionInLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLine() {
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMsg() {
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package de.dhbwstuttgart.languageServerInterface.model;
|
||||||
|
|
||||||
|
|
||||||
|
import com.google.common.reflect.TypeResolver;
|
||||||
|
import de.dhbwstuttgart.typeinference.unify.UnifyResultEvent;
|
||||||
|
import de.dhbwstuttgart.typeinference.unify.UnifyResultListener;
|
||||||
|
|
||||||
|
public class ResultSetListener implements UnifyResultListener {
|
||||||
|
|
||||||
|
TypeResolver typeResolver;
|
||||||
|
|
||||||
|
public ResultSetListener(TypeResolver typeResolver){
|
||||||
|
this.typeResolver = typeResolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNewTypeResultFound(UnifyResultEvent evt) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -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)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -150,7 +151,7 @@ public class StatementGenerator {
|
|||||||
} else {
|
} else {
|
||||||
type = methodparameters?
|
type = methodparameters?
|
||||||
TypePlaceholder.fresh(fp.getStart(), 1, false)
|
TypePlaceholder.fresh(fp.getStart(), 1, false)
|
||||||
: TypePlaceholder.fresh(fp.getStart());
|
: TypePlaceholder.fresh(fp.getStart(), 1, false);
|
||||||
}
|
}
|
||||||
ret.add(new FormalParameter(paramName, type, fp.getStart()));
|
ret.add(new FormalParameter(paramName, type, fp.getStart()));
|
||||||
localVars.put(paramName, type);
|
localVars.put(paramName, type);
|
||||||
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1065,7 +1066,7 @@ public class StatementGenerator {
|
|||||||
List<Pattern> parameterList = new ArrayList<>();
|
List<Pattern> parameterList = new ArrayList<>();
|
||||||
for (IdentifierContext identifier : lambdaParams.identifier()) {
|
for (IdentifierContext identifier : lambdaParams.identifier()) {
|
||||||
Token offset = identifier.getStart();
|
Token offset = identifier.getStart();
|
||||||
parameterList.add(new FormalParameter(identifier.getText(), TypePlaceholder.fresh(offset), offset));
|
parameterList.add(new FormalParameter(identifier.getText(), TypePlaceholder.fresh(offset, 1, false), offset));
|
||||||
}
|
}
|
||||||
params = new ParameterList(parameterList, lambdaParams.getStart());
|
params = new ParameterList(parameterList, lambdaParams.getStart());
|
||||||
} else if (lambdaParams.formalParameterList() != null) {
|
} else if (lambdaParams.formalParameterList() != null) {
|
||||||
@@ -1075,7 +1076,7 @@ public class StatementGenerator {
|
|||||||
List<Pattern> parameterList = new ArrayList<>();
|
List<Pattern> parameterList = new ArrayList<>();
|
||||||
for (LambdaLVTIParameterContext param : lambdaParams.lambdaLVTIList().lambdaLVTIParameter()) {
|
for (LambdaLVTIParameterContext param : lambdaParams.lambdaLVTIList().lambdaLVTIParameter()) {
|
||||||
Token offset = param.getStart();
|
Token offset = param.getStart();
|
||||||
parameterList.add(new FormalParameter(param.identifier().getText(), TypePlaceholder.fresh(offset), offset));
|
parameterList.add(new FormalParameter(param.identifier().getText(), TypePlaceholder.fresh(offset, 1, false), offset));
|
||||||
}
|
}
|
||||||
params = new ParameterList(parameterList, lambdaParams.getStart());
|
params = new ParameterList(parameterList, lambdaParams.getStart());
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ public class SyntaxTreeGenerator {
|
|||||||
this.allmodifiers.put(Modifier.toString(Modifier.INTERFACE), Modifier.INTERFACE);
|
this.allmodifiers.put(Modifier.toString(Modifier.INTERFACE), Modifier.INTERFACE);
|
||||||
this.allmodifiers.put("sealed", 4096);
|
this.allmodifiers.put("sealed", 4096);
|
||||||
this.allmodifiers.put("non-sealed", 8192);
|
this.allmodifiers.put("non-sealed", 8192);
|
||||||
this.allmodifiers.put("default", 16384);
|
this.allmodifiers.put("default", 0); // Doesn't exist
|
||||||
this.allmodifiers.put("strictfp", 32768);
|
this.allmodifiers.put("strictfp", 32768);
|
||||||
|
|
||||||
this.compiler = compiler;
|
this.compiler = compiler;
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@@ -168,7 +168,7 @@ public class TypeGenerator {
|
|||||||
if (generics.contains(name)) {
|
if (generics.contains(name)) {
|
||||||
return new GenericRefType(name, offset);
|
return new GenericRefType(name, offset);
|
||||||
} else {
|
} else {
|
||||||
Pattern p = Pattern.compile("Fun(\\d+)[$][$]");
|
Pattern p = Pattern.compile("Fun(Void|VoidImpl|Wrapper)?(\\d+)[$][$]"); // TODO Regex shenanigans
|
||||||
Matcher m = p.matcher(name);
|
Matcher m = p.matcher(name);
|
||||||
if (m.matches()) {// es ist FunN$$-Type
|
if (m.matches()) {// es ist FunN$$-Type
|
||||||
return new RefType(new JavaClassName(name), convert(typeArguments, reg, generics), offset);
|
return new RefType(new JavaClassName(name), convert(typeArguments, reg, generics), offset);
|
||||||
|
|||||||
@@ -140,8 +140,7 @@ public class GatherNames {
|
|||||||
if (importDeclCtx.MUL() == null) {
|
if (importDeclCtx.MUL() == null) {
|
||||||
var name = importDeclCtx.qualifiedName().getText();
|
var name = importDeclCtx.qualifiedName().getText();
|
||||||
var className = new JavaClassName(name);
|
var className = new JavaClassName(name);
|
||||||
var clazz = compiler.loadJavaTXClass(className);
|
if (compiler.input.contains(className)) {
|
||||||
if (clazz != null) {
|
|
||||||
ret.put(name, compiler.classRegistry.getNumberOfGenerics(name));
|
ret.put(name, compiler.classRegistry.getNumberOfGenerics(name));
|
||||||
} else {
|
} else {
|
||||||
Class<?> cl = compiler.getClassLoader().loadClass(name);
|
Class<?> cl = compiler.getClassLoader().loadClass(name);
|
||||||
|
|||||||
@@ -64,6 +64,6 @@ public class JavaClassRegistry{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int getNumberOfGenerics(String name) {
|
public int getNumberOfGenerics(String name) {
|
||||||
return existingClasses.get(new JavaClassName(name));
|
return existingClasses.getOrDefault(new JavaClassName(name), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
41
src/main/java/de/dhbwstuttgart/server/ServerTaskLogger.java
Normal file
41
src/main/java/de/dhbwstuttgart/server/ServerTaskLogger.java
Normal 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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
202
src/main/java/de/dhbwstuttgart/server/SocketClient.java
Normal file
202
src/main/java/de/dhbwstuttgart/server/SocketClient.java
Normal 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
48
src/main/java/de/dhbwstuttgart/server/SocketFuture.java
Normal file
48
src/main/java/de/dhbwstuttgart/server/SocketFuture.java
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
235
src/main/java/de/dhbwstuttgart/server/SocketServer.java
Normal file
235
src/main/java/de/dhbwstuttgart/server/SocketServer.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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> {}
|
||||||
|
}
|
||||||
|
|
||||||
12
src/main/java/de/dhbwstuttgart/server/packet/IPacket.java
Normal file
12
src/main/java/de/dhbwstuttgart/server/packet/IPacket.java
Normal 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 {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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 org.jspecify.annotations.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package de.dhbwstuttgart.syntaxtree;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.util.Logger;
|
||||||
|
|
||||||
|
public class SyntaxTree {
|
||||||
|
|
||||||
|
public static Logger logger = new Logger("SyntaxTree");
|
||||||
|
}
|
||||||
@@ -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";
|
||||||
@@ -13,6 +16,10 @@ public class NameGenerator {
|
|||||||
public static void reset() {
|
public static void reset() {
|
||||||
strNextName = "A";
|
strNextName = "A";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void resetTo(String name) {
|
||||||
|
strNextName = name;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Berechnet einen neuen, eindeutigen Namen f�r eine neue
|
* Berechnet einen neuen, eindeutigen Namen f�r eine neue
|
||||||
@@ -26,7 +33,11 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,57 +1,77 @@
|
|||||||
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void accept(ASTVisitor visitor) {
|
public void accept(ASTVisitor visitor) {
|
||||||
visitor.visit(this);
|
visitor.visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <A> A acceptTV(TypeVisitor<A> visitor) {
|
public <A> A acceptTV(TypeVisitor<A> visitor) {
|
||||||
return visitor.visit(this);
|
return visitor.visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void accept(ResultSetVisitor visitor) {
|
public void accept(ResultSetVisitor visitor) {
|
||||||
visitor.visit(this);
|
visitor.visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
GenericRefType that = (GenericRefType) o;
|
GenericRefType that = (GenericRefType) o;
|
||||||
return name.equals(that.name);
|
return name.equals(that.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(name);
|
return Objects.hash(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@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()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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,122 +18,137 @@ 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);
|
}
|
||||||
|
|
||||||
|
public boolean isPrimitive() {
|
||||||
|
return primitiveFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
String params = "";
|
||||||
|
if (parameter.size() > 0) {
|
||||||
|
params += "<";
|
||||||
|
Iterator<RefTypeOrTPHOrWildcardOrGeneric> it = parameter.iterator();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
RefTypeOrTPHOrWildcardOrGeneric param = it.next();
|
||||||
|
params += param.toString();
|
||||||
|
if (it.hasNext()) params += ", ";
|
||||||
|
}
|
||||||
|
params += ">";
|
||||||
|
}
|
||||||
|
return this.name.toString() + params;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return this.name.hashCode();//Nur den Name hashen. Sorgt für langsame, aber funktionierende HashMaps
|
||||||
|
}
|
||||||
|
|
||||||
|
public RefType(JavaClassName fullyQualifiedName, List<RefTypeOrTPHOrWildcardOrGeneric> parameter, Token offset) {
|
||||||
|
this(fullyQualifiedName, parameter, offset, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RefType(JavaClassName fullyQualifiedName, List<RefTypeOrTPHOrWildcardOrGeneric> parameter, Token offset, boolean primitiveFlag) {
|
||||||
|
super(offset);
|
||||||
|
this.name = (fullyQualifiedName);
|
||||||
|
this.parameter = parameter;
|
||||||
|
this.primitiveFlag = primitiveFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JavaClassName getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<RefTypeOrTPHOrWildcardOrGeneric> getParaList() {
|
||||||
|
if (this.parameter == null) return new ArrayList<>();
|
||||||
|
return this.parameter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Author: Jrg Buerle<br/>
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (!(obj instanceof RefType refObj)) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPrimitive() {
|
if (!Objects.equals(this.name, refObj.name)) return false;
|
||||||
return primitiveFlag;
|
boolean ret = true;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
//if(!(super.equals(obj))) PL 2020-03-12 muss vll. einkommentiert werden
|
||||||
public String toString(){
|
// return false;
|
||||||
String params = "";
|
|
||||||
if(parameter.size()>0){
|
if (parameter == null || parameter.size() == 0) {
|
||||||
params += "<";
|
ret &= (refObj.getParaList() == null || refObj.getParaList().isEmpty());
|
||||||
Iterator<RefTypeOrTPHOrWildcardOrGeneric> it = parameter.iterator();
|
} else {
|
||||||
while(it.hasNext()){
|
if (refObj.getParaList() == null) {
|
||||||
RefTypeOrTPHOrWildcardOrGeneric param = it.next();
|
ret = false;
|
||||||
params += param.toString();
|
} else if (parameter.size() != refObj.getParaList().size()) {
|
||||||
if(it.hasNext())params += ", ";
|
ret = false;
|
||||||
}
|
} else {
|
||||||
params += ">";
|
for (int i = 0; i < parameter.size(); i++) {
|
||||||
|
ret &= parameter.get(i).equals(refObj.getParaList().get(i));
|
||||||
}
|
}
|
||||||
return this.name.toString() + params;
|
}
|
||||||
}
|
}
|
||||||
|
return ret;
|
||||||
|
|
||||||
@Override
|
}
|
||||||
public int hashCode() {
|
|
||||||
return this.name.hashCode();//Nur den Name hashen. Sorgt für langsame, aber funktionierende HashMaps
|
|
||||||
}
|
|
||||||
|
|
||||||
public RefType(JavaClassName fullyQualifiedName, List<RefTypeOrTPHOrWildcardOrGeneric> parameter, Token offset) {
|
|
||||||
this(fullyQualifiedName, parameter, offset, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public RefType(JavaClassName fullyQualifiedName, List<RefTypeOrTPHOrWildcardOrGeneric> parameter, Token offset, boolean primitiveFlag) {
|
@Override
|
||||||
super(offset);
|
public void accept(ASTVisitor visitor) {
|
||||||
this.name = (fullyQualifiedName);
|
visitor.visit(this);
|
||||||
this.parameter = parameter;
|
}
|
||||||
this.primitiveFlag = primitiveFlag;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JavaClassName getName()
|
@Override
|
||||||
{
|
public <A> A acceptTV(TypeVisitor<A> visitor) {
|
||||||
return name;
|
return visitor.visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<RefTypeOrTPHOrWildcardOrGeneric> getParaList(){
|
@Override
|
||||||
if(this.parameter==null)return new ArrayList<>();
|
public void accept(ResultSetVisitor visitor) {
|
||||||
return this.parameter;
|
visitor.visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Author: Jrg Buerle<br/>
|
public ISerialNode toSerial(KeyStorage keyStorage) {
|
||||||
* @return
|
SerialMap serialized = new SerialMap();
|
||||||
*/
|
serialized.put("isPrimitive", this.primitiveFlag);
|
||||||
public boolean equals(Object obj)
|
serialized.put("name", this.name.toString());
|
||||||
{
|
serialized.put("parameters", SerialList.fromMapped(this.parameter, param -> param.toSerial(keyStorage)));
|
||||||
if(obj instanceof RefType){
|
|
||||||
if (!Objects.equals(this.name, ((RefType) obj).name)) return false;
|
|
||||||
boolean ret = true;
|
|
||||||
|
|
||||||
//if(!(super.equals(obj))) PL 2020-03-12 muss vll. einkommentiert werden
|
|
||||||
// return false;
|
|
||||||
|
|
||||||
if(parameter==null || parameter.size()==0){
|
|
||||||
ret &= (((RefType)obj).getParaList()==null || ((RefType)obj).getParaList().size()==0);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
if(((RefType)obj).getParaList()==null){
|
|
||||||
ret = false;
|
|
||||||
}
|
|
||||||
else if(parameter.size() != ((RefType)obj).getParaList().size())
|
|
||||||
{
|
|
||||||
ret = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for(int i = 0; i<parameter.size(); i++)
|
|
||||||
{
|
|
||||||
ret &= parameter.get(i).equals(((RefType)obj).getParaList().get(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
// create the wrapper and put this as the object
|
||||||
public void accept(ASTVisitor visitor) {
|
var serializedWrapper = super.toSerial(keyStorage).assertType(SerialMap.class);
|
||||||
visitor.visit(this);
|
serializedWrapper.put("object", serialized);
|
||||||
}
|
return serializedWrapper;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
public static RefType fromSerial(SerialMap data, UnifyContext context) {
|
||||||
public <A> A acceptTV(TypeVisitor<A> visitor) {
|
return new RefType(
|
||||||
return visitor.visit(this);
|
new JavaClassName(data.getValue("name").getOf(String.class)),
|
||||||
}
|
data.getList("parameters").assertListOfMaps().stream()
|
||||||
|
.map(param -> RefTypeOrTPHOrWildcardOrGeneric.fromSerial(param, context))
|
||||||
@Override
|
.toList(),
|
||||||
public void accept(ResultSetVisitor visitor) {
|
new NullToken(),
|
||||||
visitor.visit(this);
|
data.getValue("isPrimitive").getOf(Boolean.class)
|
||||||
}
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
@@ -18,5 +24,26 @@ 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
@@ -65,7 +68,12 @@ public class TypePlaceholder extends RefTypeOrTPHOrWildcardOrGeneric
|
|||||||
public static TypePlaceholder fresh(Token position){
|
public static TypePlaceholder fresh(Token position){
|
||||||
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)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
8
src/main/java/de/dhbwstuttgart/target/Target.java
Normal file
8
src/main/java/de/dhbwstuttgart/target/Target.java
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package de.dhbwstuttgart.target;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.util.Logger;
|
||||||
|
|
||||||
|
public class Target {
|
||||||
|
public static Logger logger = new Logger("Target");
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
package de.dhbwstuttgart.target.generate;
|
package de.dhbwstuttgart.target.generate;
|
||||||
|
|
||||||
import de.dhbwstuttgart.bytecode.FunNGenerator;
|
import de.dhbwstuttgart.bytecode.FunNGenerator;
|
||||||
@@ -13,6 +14,7 @@ import de.dhbwstuttgart.syntaxtree.statement.*;
|
|||||||
import de.dhbwstuttgart.syntaxtree.type.*;
|
import de.dhbwstuttgart.syntaxtree.type.*;
|
||||||
import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter;
|
import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter;
|
||||||
import de.dhbwstuttgart.syntaxtree.visual.OutputGenerator;
|
import de.dhbwstuttgart.syntaxtree.visual.OutputGenerator;
|
||||||
|
import de.dhbwstuttgart.target.Target;
|
||||||
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.*;
|
||||||
@@ -343,10 +345,10 @@ 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.name() + " " + m.getSignature());
|
for (var m : l) Target.logger.info(m.name() + " " + m.getSignature());
|
||||||
System.out.println();
|
Target.logger.info("");
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -845,13 +847,6 @@ public class ASTToTargetAST {
|
|||||||
compiler.usedFunNSuperTypes.add(params.size());
|
compiler.usedFunNSuperTypes.add(params.size());
|
||||||
var code = FunNGenerator.generateSuperBytecode(params.size() - 1, returnType != null ? 1 : 0);
|
var code = FunNGenerator.generateSuperBytecode(params.size() - 1, returnType != null ? 1 : 0);
|
||||||
var superClassName = FunNGenerator.getSuperClassName(params.size() - 1, returnType != null ? 1 : 0);
|
var superClassName = FunNGenerator.getSuperClassName(params.size() - 1, returnType != null ? 1 : 0);
|
||||||
try {
|
|
||||||
compiler.classLoader.findClass(superClassName);
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
try {
|
|
||||||
compiler.classLoader.loadClass(superClassName, code);
|
|
||||||
} catch (LinkageError ignored) {}
|
|
||||||
}
|
|
||||||
compiler.auxiliaries.put(superClassName, code);
|
compiler.auxiliaries.put(superClassName, code);
|
||||||
}
|
}
|
||||||
FunNGenerator.GenericParameters gep = null;
|
FunNGenerator.GenericParameters gep = null;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ 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;
|
||||||
@@ -140,17 +141,17 @@ public abstract class GenerateGenerics {
|
|||||||
this.compiler = compiler;
|
this.compiler = compiler;
|
||||||
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 record GenericsState(Map<TPH, RefTypeOrTPHOrWildcardOrGeneric> concreteTypes, Map<TypePlaceholder, TypePlaceholder> equality) {}
|
||||||
@@ -250,7 +251,7 @@ public abstract class GenerateGenerics {
|
|||||||
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));
|
||||||
@@ -319,7 +320,7 @@ public abstract class GenerateGenerics {
|
|||||||
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;
|
||||||
@@ -334,7 +335,7 @@ public abstract class GenerateGenerics {
|
|||||||
var optMethod = ASTToTargetAST.findMethod(owner, methodCall.name, methodCall.signatureArguments().stream().map(x -> getTargetType(x)).toList(), GenerateGenerics.this, compiler);
|
var optMethod = ASTToTargetAST.findMethod(owner, methodCall.name, methodCall.signatureArguments().stream().map(x -> getTargetType(x)).toList(), GenerateGenerics.this, compiler);
|
||||||
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
|
||||||
@@ -367,7 +368,7 @@ public abstract class GenerateGenerics {
|
|||||||
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))
|
||||||
@@ -569,7 +570,7 @@ public abstract class GenerateGenerics {
|
|||||||
Set<Pair> generics(ClassOrInterface owner, Method method) {
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -598,7 +599,7 @@ public abstract class GenerateGenerics {
|
|||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -677,7 +678,7 @@ public abstract class GenerateGenerics {
|
|||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -728,7 +729,7 @@ public abstract class GenerateGenerics {
|
|||||||
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;
|
||||||
@@ -923,7 +924,7 @@ public abstract class GenerateGenerics {
|
|||||||
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)
|
||||||
@@ -961,8 +962,8 @@ public abstract class GenerateGenerics {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
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)));
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ 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.*;
|
||||||
@@ -161,7 +162,6 @@ public class StatementToTargetExpression implements ASTVisitor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(FieldVar fieldVar) {
|
public void visit(FieldVar fieldVar) {
|
||||||
var isStatic = false;
|
|
||||||
var type = converter.convert(fieldVar.receiver.getType());
|
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();
|
||||||
@@ -255,7 +255,7 @@ public class StatementToTargetExpression implements ASTVisitor {
|
|||||||
isInterface = receiverClass.isInterface();
|
isInterface = receiverClass.isInterface();
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.println(argList);
|
Target.logger.info(argList);
|
||||||
result = new TargetMethodCall(converter.convert(methodCall.getType()), returnType, argList, converter.convert(methodCall.receiver), methodCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), receiverType, methodCall.name, isStatic, isInterface, isPrivate);
|
result = new TargetMethodCall(converter.convert(methodCall.getType()), returnType, argList, converter.convert(methodCall.receiver), methodCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), receiverType, methodCall.name, isStatic, isInterface, isPrivate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,30 +36,30 @@ public record TargetMethod(int access, String name, TargetBlock block, Signature
|
|||||||
public static String getDescriptor(TargetType returnType, TargetType... parameters) {
|
public static String getDescriptor(TargetType returnType, TargetType... parameters) {
|
||||||
String ret = "(";
|
String ret = "(";
|
||||||
for (var parameterType : parameters) {
|
for (var parameterType : parameters) {
|
||||||
ret += parameterType.toSignature();
|
ret += parameterType.toDescriptor();
|
||||||
}
|
}
|
||||||
ret += ")";
|
ret += ")";
|
||||||
if (returnType == null) ret += "V";
|
if (returnType == null) ret += "V";
|
||||||
else ret += returnType.toSignature();
|
else ret += returnType.toDescriptor();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getSignature(Set<TargetGeneric> generics, List<MethodParameter> parameters, TargetType returnType) {
|
public static String getSignature(Set<TargetGeneric> generics, List<MethodParameter> parameters, TargetType returnType) {
|
||||||
String ret = "";
|
String ret = "";
|
||||||
if (generics.size() > 0) {
|
if (!generics.isEmpty()) {
|
||||||
ret += "<";
|
ret += "<";
|
||||||
for (var generic : generics) {
|
for (var generic : generics) {
|
||||||
ret += generic.name() + ":" + generic.bound().toDescriptor();
|
ret += generic.name() + ":" + generic.bound().toSignature();
|
||||||
}
|
}
|
||||||
ret += ">";
|
ret += ">";
|
||||||
}
|
}
|
||||||
ret += "(";
|
ret += "(";
|
||||||
for (var param : parameters) {
|
for (var param : parameters) {
|
||||||
ret += param.pattern().type().toDescriptor();
|
ret += param.pattern().type().toSignature();
|
||||||
}
|
}
|
||||||
ret += ")";
|
ret += ")";
|
||||||
if (returnType == null) ret += "V";
|
if (returnType == null) ret += "V";
|
||||||
else ret += returnType.toDescriptor();
|
else ret += returnType.toSignature();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,42 +8,42 @@ public sealed interface TargetLiteral extends TargetExpression {
|
|||||||
record BooleanLiteral(Boolean value) implements TargetLiteral {
|
record BooleanLiteral(Boolean value) implements TargetLiteral {
|
||||||
@Override
|
@Override
|
||||||
public TargetType type() {
|
public TargetType type() {
|
||||||
return TargetType.Boolean;
|
return TargetType.boolean_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
record CharLiteral(Character value) implements TargetLiteral {
|
record CharLiteral(Character value) implements TargetLiteral {
|
||||||
@Override
|
@Override
|
||||||
public TargetType type() {
|
public TargetType type() {
|
||||||
return TargetType.Char;
|
return TargetType.char_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
record IntLiteral(Integer value) implements TargetLiteral {
|
record IntLiteral(Integer value) implements TargetLiteral {
|
||||||
@Override
|
@Override
|
||||||
public TargetType type() {
|
public TargetType type() {
|
||||||
return TargetType.Integer;
|
return TargetType.int_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
record LongLiteral(Long value) implements TargetLiteral {
|
record LongLiteral(Long value) implements TargetLiteral {
|
||||||
@Override
|
@Override
|
||||||
public TargetType type() {
|
public TargetType type() {
|
||||||
return TargetType.Long;
|
return TargetType.long_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
record FloatLiteral(Float value) implements TargetLiteral {
|
record FloatLiteral(Float value) implements TargetLiteral {
|
||||||
@Override
|
@Override
|
||||||
public TargetType type() {
|
public TargetType type() {
|
||||||
return TargetType.Float;
|
return TargetType.float_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
record DoubleLiteral(Double value) implements TargetLiteral {
|
record DoubleLiteral(Double value) implements TargetLiteral {
|
||||||
@Override
|
@Override
|
||||||
public TargetType type() {
|
public TargetType type() {
|
||||||
return TargetType.Double;
|
return TargetType.double_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,12 +3,12 @@ package de.dhbwstuttgart.target.tree.type;
|
|||||||
public record TargetExtendsWildcard(TargetType innerType) implements TargetType {
|
public record TargetExtendsWildcard(TargetType innerType) implements TargetType {
|
||||||
@Override
|
@Override
|
||||||
public String toSignature() {
|
public String toSignature() {
|
||||||
return innerType.toSignature();
|
return "+" + innerType.toSignature();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toDescriptor() {
|
public String toDescriptor() {
|
||||||
return "+" + innerType.toDescriptor();
|
return innerType.toDescriptor();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ public record TargetFunNType(String name, List<TargetType> funNParams, List<Targ
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toSignature() {
|
public String toSignature() {
|
||||||
return "L" + getInternalName() + ";";
|
var args = FunNGenerator.getArguments(funNParams);
|
||||||
|
return "LFun" + args.size() + "$$" + TargetSpecializedType.signatureParameters(funNParams) + ";";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ package de.dhbwstuttgart.target.tree.type;
|
|||||||
|
|
||||||
public record TargetGenericType(String name) implements TargetType {
|
public record TargetGenericType(String name) implements TargetType {
|
||||||
@Override
|
@Override
|
||||||
public String toSignature() {
|
public String toDescriptor() {
|
||||||
return "Ljava/lang/Object;"; // TODO Use bounds for this?
|
return "Ljava/lang/Object;"; // TODO Use bounds for this?
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toDescriptor() {
|
public String toSignature() {
|
||||||
return "T" + getInternalName() + ";";
|
return "T" + getInternalName() + ";";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,11 +12,6 @@ public record TargetRefType(String name, List<TargetType> params) implements Tar
|
|||||||
return this.name.replaceAll("\\.", "/");
|
return this.name.replaceAll("\\.", "/");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toSignature() {
|
|
||||||
return "L" + getInternalName() + ";";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Type erasure means we need to override hashCode and equals to only consider the name
|
// Type erasure means we need to override hashCode and equals to only consider the name
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
|
|||||||
@@ -6,16 +6,27 @@ public sealed interface TargetSpecializedType extends TargetType permits TargetF
|
|||||||
List<TargetType> params();
|
List<TargetType> params();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default String toDescriptor() {
|
default String toSignature() {
|
||||||
String ret = "L" + getInternalName();
|
String ret = "L" + getInternalName();
|
||||||
if (params().size() > 0) {
|
ret += signatureParameters(params());
|
||||||
ret += "<";
|
|
||||||
for (var param : params()) {
|
|
||||||
ret += param.toDescriptor();
|
|
||||||
}
|
|
||||||
ret += ">";
|
|
||||||
}
|
|
||||||
ret += ";";
|
ret += ";";
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static String signatureParameters(List<TargetType> params) {
|
||||||
|
var ret = "";
|
||||||
|
if (!params.isEmpty()) {
|
||||||
|
ret += "<";
|
||||||
|
for (var param : params) {
|
||||||
|
ret += param.toSignature();
|
||||||
|
}
|
||||||
|
ret += ">";
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default String toDescriptor() {
|
||||||
|
return "L" + getInternalName() + ";";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,12 +3,12 @@ package de.dhbwstuttgart.target.tree.type;
|
|||||||
public record TargetSuperWildcard(TargetType innerType) implements TargetType {
|
public record TargetSuperWildcard(TargetType innerType) implements TargetType {
|
||||||
@Override
|
@Override
|
||||||
public String toSignature() {
|
public String toSignature() {
|
||||||
return innerType.toSignature();
|
return "-" + innerType.toSignature();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toDescriptor() {
|
public String toDescriptor() {
|
||||||
return "-" + innerType.toDescriptor();
|
return innerType.toDescriptor();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,24 @@
|
|||||||
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.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class Constraint<A> extends HashSet<A> implements Comparable<Constraint<A>> {
|
public class Constraint<A extends IConstraintElement> extends HashSet<A> implements Comparable<Constraint<A>>, 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
|
||||||
@@ -22,28 +31,32 @@ public class Constraint<A> extends HashSet<A> implements Comparable<Constraint<A
|
|||||||
public Constraint() {
|
public Constraint() {
|
||||||
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 +76,96 @@ 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
|
||||||
//" + extendsContraint: " + (extendConstraint != null ? extendConstraint.toStringBase() : "null" )
|
+ " msc[" + methodSignatureConstraint.size() + "] = " + methodSignatureConstraint
|
||||||
+ "\n" ;
|
//" + extendsContraint: " + (extendConstraint != null ? extendConstraint.toStringBase() : "null" )
|
||||||
|
+ "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toStringBase() {
|
public String toStringBase() {
|
||||||
return super.toString();
|
return super.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(Constraint<A> o) {
|
@Override
|
||||||
return this.toString().compareTo(o.toString());
|
public int compareTo(Constraint<A> o) {
|
||||||
}
|
return this.toString().compareTo(o.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private String serialUUID = null;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SerialUUID toSerial(KeyStorage keyStorage) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,63 +1,80 @@
|
|||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addOderConstraint(Set<Constraint<A>> methodConstraints) {
|
public void addOderConstraint(Set<Constraint<A>> methodConstraints) {
|
||||||
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){
|
|
||||||
this.oderConstraints.addAll(allOderConstraints);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addAll(ConstraintSet constraints) {
|
|
||||||
this.addAllUndConstraint(constraints.undConstraints);
|
|
||||||
this.addAllOderConstraint(constraints.oderConstraints);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
public void addAllOderConstraint(List<Set<Constraint<A>>> allOderConstraints) {
|
||||||
public String toString(){
|
this.oderConstraints.addAll(allOderConstraints);
|
||||||
BinaryOperator<String> b = (x,y) -> x+y;
|
}
|
||||||
return "\nUND:" + this.undConstraints.toString() + "\n" +
|
|
||||||
"ODER:" + this.oderConstraints.stream().reduce("", (x,y) -> x.toString()+ "\n" +y, b);
|
|
||||||
//cartesianProduct().toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<List<Constraint<A>>> cartesianProduct(){
|
public void addAll(ConstraintSet constraints) {
|
||||||
Set<Constraint<A>> toAdd = new HashSet<>();
|
this.addAllUndConstraint(constraints.undConstraints);
|
||||||
toAdd.add(undConstraints);
|
this.addAllOderConstraint(constraints.oderConstraints);
|
||||||
List<Set<Constraint<A>>> allConstraints = new ArrayList<>();
|
}
|
||||||
allConstraints.add(toAdd);
|
|
||||||
allConstraints.addAll(oderConstraints);
|
|
||||||
return new GuavaSetOperations().cartesianProduct(allConstraints);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <B> ConstraintSet<B> map(Function<? super A, ? extends B> o) {
|
@Override
|
||||||
Hashtable<Constraint<A>,Constraint<B>> CSA2CSB = new Hashtable<>();
|
public String toString() {
|
||||||
ConstraintSet<B> ret = new ConstraintSet<>();
|
BinaryOperator<String> b = (x, y) -> x + y;
|
||||||
ret.undConstraints = undConstraints.stream().map(o).collect(Collectors.toCollection(Constraint<B>::new));
|
return "\nUND:\n" + this.undConstraints.toString() +
|
||||||
List<Set<Constraint<B>>> newOder = new ArrayList<>();
|
"ODER:" + this.oderConstraints.stream().reduce("", (x, y) -> x + "\n\t" + y, b) +
|
||||||
|
"\n";
|
||||||
|
//cartesianProduct().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@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<>();
|
||||||
|
toAdd.add(undConstraints);
|
||||||
|
List<Set<Constraint<A>>> allConstraints = new ArrayList<>();
|
||||||
|
allConstraints.add(toAdd);
|
||||||
|
allConstraints.addAll(oderConstraints);
|
||||||
|
return new GuavaSetOperations().cartesianProduct(allConstraints);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <B extends IConstraintElement> ConstraintSet<B> map(Function<? super A, ? extends B> o) {
|
||||||
|
Hashtable<Constraint<A>, Constraint<B>> CSA2CSB = new Hashtable<>();
|
||||||
|
ConstraintSet<B> ret = new ConstraintSet<>();
|
||||||
|
ret.undConstraints = undConstraints.stream().map(o).collect(Collectors.toCollection(Constraint<B>::new));
|
||||||
|
List<Set<Constraint<B>>> newOder = new ArrayList<>();
|
||||||
/*
|
/*
|
||||||
for(Set<Constraint<A>> oderConstraint : oderConstraints){
|
for(Set<Constraint<A>> oderConstraint : oderConstraints){
|
||||||
oderConstraint.forEach(as -> {
|
oderConstraint.forEach(as -> {
|
||||||
@@ -68,25 +85,25 @@ public class ConstraintSet<A> {
|
|||||||
CSA2CSB.put(as, newConst);} );
|
CSA2CSB.put(as, newConst);} );
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
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))
|
||||||
: null,
|
: null,
|
||||||
as.getmethodSignatureConstraint().stream().map(o).collect(Collectors.toCollection(HashSet::new))))
|
as.getmethodSignatureConstraint().stream().map(o).collect(Collectors.toCollection(HashSet::new))))
|
||||||
));
|
));
|
||||||
|
|
||||||
//CSA2CSB.put(as, newConst);
|
//CSA2CSB.put(as, newConst);
|
||||||
|
|
||||||
return newConst;
|
return newConst;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Constraint<B> bs = CSA2CSB.get(as);
|
Constraint<B> bs = CSA2CSB.get(as);
|
||||||
@@ -95,36 +112,60 @@ public class ConstraintSet<A> {
|
|||||||
}
|
}
|
||||||
return bs;
|
return bs;
|
||||||
*/
|
*/
|
||||||
}).collect(Collectors.toSet())
|
}).collect(Collectors.toSet())
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
ret.oderConstraints = newOder;
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void forEach (Consumer<? super A> c) {
|
ret.oderConstraints = newOder;
|
||||||
undConstraints.stream().forEach(c);
|
return ret;
|
||||||
for(Set<Constraint<A>> oderConstraint : oderConstraints){
|
}
|
||||||
oderConstraint.parallelStream().forEach((Constraint<A> as) ->
|
|
||||||
as.stream().forEach(c));
|
public void forEach(Consumer<? super A> c) {
|
||||||
}
|
undConstraints.stream().forEach(c);
|
||||||
|
for (Set<Constraint<A>> oderConstraint : oderConstraints) {
|
||||||
|
oderConstraint.parallelStream().forEach((Constraint<A> as) ->
|
||||||
|
as.stream().forEach(c));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public Set<A> getAll () {
|
|
||||||
Set<A> ret = new HashSet<>();
|
public Set<A> getAll() {
|
||||||
ret.addAll(undConstraints);
|
Set<A> ret = new HashSet<>(undConstraints);
|
||||||
for(Set<Constraint<A>> oderConstraint : oderConstraints){
|
for (Set<Constraint<A>> oderConstraint : oderConstraints) {
|
||||||
oderConstraint.parallelStream().forEach((Constraint<A> as) -> ret.addAll(as));
|
oderConstraint.parallelStream().forEach(ret::addAll);
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Set<Constraint<A>>> getOderConstraints() {
|
|
||||||
return oderConstraints;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<A> getUndConstraints() {
|
|
||||||
return undConstraints;
|
|
||||||
}
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Set<Constraint<A>>> getOderConstraints() {
|
||||||
|
return oderConstraints;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<A> getUndConstraints() {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
package de.dhbwstuttgart.typeinference.constraints;
|
||||||
|
|
||||||
|
public interface IConstraintElement {
|
||||||
|
}
|
||||||
@@ -1,72 +1,70 @@
|
|||||||
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 )
|
|
||||||
{
|
|
||||||
this.TA1 = TA1;
|
|
||||||
this.TA2 = TA2;
|
|
||||||
if(TA1 == null || TA2 == null)
|
|
||||||
throw new NullPointerException();
|
|
||||||
eOperator = PairOperator.SMALLER;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Pair(RefTypeOrTPHOrWildcardOrGeneric TA1, RefTypeOrTPHOrWildcardOrGeneric TA2, PairOperator eOp)
|
private Pair(RefTypeOrTPHOrWildcardOrGeneric TA1, RefTypeOrTPHOrWildcardOrGeneric TA2) {
|
||||||
{
|
this.TA1 = TA1;
|
||||||
// Konstruktor
|
this.TA2 = TA2;
|
||||||
this(TA1,TA2);
|
if (TA1 == null || TA2 == null)
|
||||||
this.eOperator = eOp;
|
throw new NullPointerException();
|
||||||
}
|
eOperator = PairOperator.SMALLER;
|
||||||
|
}
|
||||||
|
|
||||||
public Pair(RefTypeOrTPHOrWildcardOrGeneric TA1, RefTypeOrTPHOrWildcardOrGeneric TA2, PairOperator e0p, SourceLoc location) {
|
public Pair(RefTypeOrTPHOrWildcardOrGeneric TA1, RefTypeOrTPHOrWildcardOrGeneric TA2, PairOperator eOp) {
|
||||||
this(TA1, TA2, e0p);
|
// Konstruktor
|
||||||
this.location = location;
|
this(TA1, TA2);
|
||||||
}
|
this.eOperator = eOp;
|
||||||
|
}
|
||||||
public Pair(RefTypeOrTPHOrWildcardOrGeneric TA1, RefTypeOrTPHOrWildcardOrGeneric TA2, PairOperator eOp, Boolean noUnification)
|
|
||||||
{
|
|
||||||
// Konstruktor
|
|
||||||
this(TA1,TA2);
|
|
||||||
this.eOperator = eOp;
|
|
||||||
this.noUnification = noUnification;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SourceLoc getLocation() {
|
public Pair(RefTypeOrTPHOrWildcardOrGeneric TA1, RefTypeOrTPHOrWildcardOrGeneric TA2, PairOperator e0p, SourceLoc location) {
|
||||||
return this.location;
|
this(TA1, TA2, e0p);
|
||||||
}
|
this.location = location;
|
||||||
|
}
|
||||||
public String toString()
|
|
||||||
{
|
public Pair(RefTypeOrTPHOrWildcardOrGeneric TA1, RefTypeOrTPHOrWildcardOrGeneric TA2, PairOperator eOp, boolean noUnification) {
|
||||||
// otth: Gibt ein Paar als String aus --> zum Debuggen und Vergleichen
|
// Konstruktor
|
||||||
String strElement1 = "NULL";
|
this(TA1, TA2);
|
||||||
String strElement2 = "NULL";
|
this.eOperator = eOp;
|
||||||
String Operator = "<.";
|
this.noUnification = noUnification;
|
||||||
|
}
|
||||||
if( TA1 != null )
|
|
||||||
strElement1 = TA1.toString();
|
public SourceLoc getLocation() {
|
||||||
|
return this.location;
|
||||||
if( TA2 != null )
|
}
|
||||||
strElement2 = TA2.toString();
|
|
||||||
|
public String toString() {
|
||||||
|
// otth: Gibt ein Paar als String aus --> zum Debuggen und Vergleichen
|
||||||
|
String strElement1 = "NULL";
|
||||||
|
String strElement2 = "NULL";
|
||||||
|
String Operator = "<.";
|
||||||
|
|
||||||
|
if (TA1 != null)
|
||||||
|
strElement1 = TA1.toString();
|
||||||
|
|
||||||
|
if (TA2 != null)
|
||||||
|
strElement2 = TA2.toString();
|
||||||
|
|
||||||
/* PL ausskommentiert 2018-05-24
|
/* PL ausskommentiert 2018-05-24
|
||||||
if(OperatorEqual())
|
if(OperatorEqual())
|
||||||
@@ -76,80 +74,104 @@ public class Pair implements Serializable
|
|||||||
if(OperatorSmallerExtends())
|
if(OperatorSmallerExtends())
|
||||||
Operator = "<?";
|
Operator = "<?";
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return "\n(" + strElement1 + " " + eOperator.toString() + " " + strElement2 + ")";
|
|
||||||
|
|
||||||
/*- Equals: " + bEqual*/
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
return "\n(P: " + strElement1 + " " + eOperator.toString() + " " + strElement2 + ")";
|
||||||
* <br/>Author: J�rg B�uerle
|
|
||||||
* @param obj
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public boolean equals(Object obj)
|
|
||||||
{
|
|
||||||
boolean ret = true;
|
|
||||||
ret &= (obj instanceof Pair);
|
|
||||||
if(!ret)return ret;
|
|
||||||
ret &= ((Pair)obj).TA1.equals(this.TA1);
|
|
||||||
ret &= ((Pair)obj).TA2.equals(this.TA2);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/*- Equals: " + bEqual*/
|
||||||
* Author: Arne Lüdtke<br/>
|
}
|
||||||
* Abfrage, ob Operator vom Typ Equal ist.
|
|
||||||
*/
|
|
||||||
public boolean OperatorEqual()
|
|
||||||
{
|
|
||||||
return eOperator == PairOperator.EQUALSDOT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Author: Arne Lüdtke<br/>
|
|
||||||
* Abfrage, ob Operator vom Typ Smaller ist.
|
|
||||||
*/
|
|
||||||
public boolean OperatorSmaller()
|
|
||||||
{
|
|
||||||
return eOperator == PairOperator.SMALLER;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Author: Arne Lüdtke<br/>
|
|
||||||
* Abfrage, ob Operator vom Typ SmallerExtends ist.
|
|
||||||
*/
|
|
||||||
public boolean OperatorSmallerExtends()
|
|
||||||
{
|
|
||||||
return eOperator == PairOperator.SMALLERDOTWC;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Author: Arne Lüdtke<br/>
|
|
||||||
* Gibt den Operator zurück.
|
|
||||||
*/
|
|
||||||
public PairOperator GetOperator()
|
|
||||||
{
|
|
||||||
return eOperator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean OperatorSmallerDot() {
|
/**
|
||||||
return eOperator == PairOperator.SMALLERDOT;
|
* <br/>Author: J�rg B�uerle
|
||||||
}
|
*
|
||||||
|
* @param obj
|
||||||
|
* @return
|
||||||
static public Map<String, TypePlaceholder> generateTPHMap(ConstraintSet<Pair> constraints) {
|
*/
|
||||||
HashMap<String, TypePlaceholder> ret = new HashMap<>();
|
public boolean equals(Object obj) {
|
||||||
constraints.map((Pair p) -> {
|
return (
|
||||||
if (p.TA1 instanceof TypePlaceholder) {
|
(obj instanceof Pair pairObj) &&
|
||||||
ret.put(((TypePlaceholder) p.TA1).getName(), (TypePlaceholder) p.TA1);
|
pairObj.TA1.equals(this.TA1) &&
|
||||||
}
|
pairObj.TA2.equals(this.TA2)
|
||||||
if (p.TA2 instanceof TypePlaceholder) {
|
);
|
||||||
ret.put(((TypePlaceholder) p.TA2).getName(), (TypePlaceholder) p.TA2);
|
}
|
||||||
}
|
|
||||||
return null;
|
/**
|
||||||
});
|
* Author: Arne Lüdtke<br/>
|
||||||
return ret;
|
* Abfrage, ob Operator vom Typ Equal ist.
|
||||||
}
|
*/
|
||||||
|
public boolean OperatorEqual() {
|
||||||
|
return eOperator == PairOperator.EQUALSDOT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Author: Arne Lüdtke<br/>
|
||||||
|
* Abfrage, ob Operator vom Typ Smaller ist.
|
||||||
|
*/
|
||||||
|
public boolean OperatorSmaller() {
|
||||||
|
return eOperator == PairOperator.SMALLER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Author: Arne Lüdtke<br/>
|
||||||
|
* Abfrage, ob Operator vom Typ SmallerExtends ist.
|
||||||
|
*/
|
||||||
|
public boolean OperatorSmallerExtends() {
|
||||||
|
return eOperator == PairOperator.SMALLERDOTWC;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Author: Arne Lüdtke<br/>
|
||||||
|
* Gibt den Operator zurück.
|
||||||
|
*/
|
||||||
|
public PairOperator GetOperator() {
|
||||||
|
return eOperator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean OperatorSmallerDot() {
|
||||||
|
return eOperator == PairOperator.SMALLERDOT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static public Map<String, TypePlaceholder> generateTPHMap(ConstraintSet<Pair> constraints) {
|
||||||
|
HashMap<String, TypePlaceholder> ret = new HashMap<>();
|
||||||
|
constraints.map((Pair p) -> {
|
||||||
|
if (p.TA1 instanceof TypePlaceholder) {
|
||||||
|
ret.put(((TypePlaceholder) p.TA1).getName(), (TypePlaceholder) p.TA1);
|
||||||
|
}
|
||||||
|
if (p.TA2 instanceof TypePlaceholder) {
|
||||||
|
ret.put(((TypePlaceholder) p.TA2).getName(), (TypePlaceholder) p.TA2);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 Comparable<ResultPair<A,B>>, ISerializableData {
|
||||||
private final A left;
|
private final A left;
|
||||||
private final B right;
|
private final B right;
|
||||||
|
|
||||||
@@ -67,5 +73,36 @@ public abstract class ResultPair<A extends RefTypeOrTPHOrWildcardOrGeneric, B ex
|
|||||||
|
|
||||||
return o.left.toString().compareTo(this.left.toString());
|
return o.left.toString().compareTo(this.left.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SerialMap toSerial(KeyStorage keyStorage) {
|
||||||
|
SerialMap serialized = new SerialMap();
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,15 @@
|
|||||||
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.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -12,23 +21,28 @@ 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 Comparable<ResultSet>, 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() {
|
public List<ResultPair> getSortedResults() {
|
||||||
return results.stream().sorted().toList();
|
return results.stream().sorted().toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean contains(ResultPair toCheck) {
|
public boolean contains(ResultPair toCheck) {
|
||||||
return this.results.contains(toCheck);
|
return this.results.contains(toCheck);
|
||||||
}
|
}
|
||||||
@@ -37,142 +51,168 @@ public class ResultSet implements Comparable<ResultSet>{
|
|||||||
results.remove(toCheck);
|
results.remove(toCheck);
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
} else {
|
} else {
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
//return new ResolvedType(type,new HashSet<>());
|
//return new ResolvedType(type,new HashSet<>());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return results.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();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (o instanceof ResultSet other) {
|
||||||
|
// sort both result lists
|
||||||
|
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 {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (o instanceof ResultSet) {
|
|
||||||
ResultSet other = (ResultSet)o;
|
|
||||||
return this.results.equals(other.results);
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return results.hashCode();
|
return results.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(ResultSet o) {
|
public int compareTo(ResultSet o) {
|
||||||
List<ResultPair> thisSorted = this.getSortedResults();
|
List<ResultPair> thisSorted = this.getSortedResults();
|
||||||
List<ResultPair> otherSorted = o.getSortedResults();
|
List<ResultPair> otherSorted = o.getSortedResults();
|
||||||
int sizeCompare = Integer.compare(thisSorted.size(), otherSorted.size());
|
int sizeCompare = Integer.compare(thisSorted.size(), otherSorted.size());
|
||||||
if (sizeCompare != 0) return sizeCompare;
|
if (sizeCompare != 0) return sizeCompare;
|
||||||
|
|
||||||
for (int i = 0; i < thisSorted.size(); i++) {
|
for (int i = 0; i < thisSorted.size(); i++) {
|
||||||
int cmp = thisSorted.get(i).compareTo(otherSorted.get(i));
|
int cmp = thisSorted.get(i).compareTo(otherSorted.get(i));
|
||||||
if (cmp != 0) return cmp;
|
if (cmp != 0) return cmp;
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SerialMap toSerial(KeyStorage keyStorage) {
|
||||||
|
SerialMap serialized = new SerialMap();;
|
||||||
|
serialized.put("results", SerialList.fromMapped(results, result -> result.toSerial(keyStorage)));
|
||||||
|
return serialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
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()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Resolver implements ResultSetVisitor {
|
class Resolver implements ResultSetVisitor {
|
||||||
private final ResultSet result;
|
private final ResultSet result;
|
||||||
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");
|
||||||
this.result = resultPairs;
|
|
||||||
|
public Resolver(ResultSet resultPairs) {
|
||||||
|
this.result = resultPairs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResolvedType resolve(TypePlaceholder tph) {
|
||||||
|
toResolve = tph;
|
||||||
|
resolved = null;
|
||||||
|
logger.info(tph.toString());
|
||||||
|
for (ResultPair<?, ?> resultPair : result.results) {
|
||||||
|
if (resultPair instanceof PairTPHEqualTPH && ((PairTPHEqualTPH) resultPair).getLeft().equals(toResolve)) {
|
||||||
|
currentPair = resultPair;
|
||||||
|
return resolve(((PairTPHEqualTPH) resultPair).getRight());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (ResultPair<?, ?> resultPair : result.results) {
|
||||||
|
currentPair = resultPair;
|
||||||
|
resultPair.accept(this);
|
||||||
|
}
|
||||||
|
if (resolved == null) {//TPH kommt nicht im Result vor:
|
||||||
|
resolved = tph;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResolvedType resolve(TypePlaceholder tph){
|
ResolvedType result = new ResolvedType(resolved, additionalTPHs);//resolved;
|
||||||
toResolve = tph;
|
result.setResultPair(currentPair);
|
||||||
resolved = null;
|
return result;
|
||||||
System.out.println(tph.toString());
|
}
|
||||||
for(ResultPair<?,?> resultPair : result.results) {
|
|
||||||
if(resultPair instanceof PairTPHEqualTPH && ((PairTPHEqualTPH) resultPair).getLeft().equals(toResolve)){
|
|
||||||
currentPair = resultPair;
|
|
||||||
return resolve(((PairTPHEqualTPH) resultPair).getRight());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(ResultPair<?,?> resultPair : result.results){
|
|
||||||
currentPair = resultPair;
|
|
||||||
resultPair.accept(this);
|
|
||||||
}
|
|
||||||
if(resolved==null){//TPH kommt nicht im Result vor:
|
|
||||||
resolved = tph;
|
|
||||||
}
|
|
||||||
|
|
||||||
ResolvedType result = new ResolvedType(resolved, additionalTPHs);//resolved;
|
@Override
|
||||||
result.setResultPair(currentPair);
|
public void visit(PairTPHsmallerTPH p) {
|
||||||
return result;
|
currentPair = p;
|
||||||
|
if (p.left.equals(toResolve)) {
|
||||||
|
additionalTPHs.add(new GenericInsertPair(p.left, p.right));
|
||||||
|
additionalTPHs.addAll(new RelatedTypeWalker(p.right, result).relatedTPHs);
|
||||||
}
|
}
|
||||||
|
if (p.right.equals(toResolve))
|
||||||
|
additionalTPHs.addAll(new RelatedTypeWalker(p.left, result).relatedTPHs);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(PairTPHsmallerTPH p) {
|
public void visit(PairTPHequalRefTypeOrWildcardType p) {
|
||||||
currentPair = p;
|
currentPair = p;
|
||||||
if(p.left.equals(toResolve)){
|
if (p.left.equals(toResolve)) {
|
||||||
additionalTPHs.add(new GenericInsertPair(p.left, p.right));
|
resolved = p.right;
|
||||||
additionalTPHs.addAll(new RelatedTypeWalker(p.right, result).relatedTPHs);
|
RelatedTypeWalker related = new RelatedTypeWalker(null, result);
|
||||||
}
|
p.right.accept(related);
|
||||||
if(p.right.equals(toResolve))
|
additionalTPHs.addAll(related.relatedTPHs);
|
||||||
additionalTPHs.addAll(new RelatedTypeWalker(p.left, result).relatedTPHs);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(PairTPHequalRefTypeOrWildcardType p) {
|
public void visit(PairTPHEqualTPH p) {
|
||||||
currentPair = p;
|
//Do nothing. Dieser Fall wird in der resolve-Methode abgefangen
|
||||||
if(p.left.equals(toResolve)){
|
}
|
||||||
resolved = p.right;
|
|
||||||
RelatedTypeWalker related = new RelatedTypeWalker(null, result);
|
|
||||||
p.right.accept(related);
|
|
||||||
additionalTPHs.addAll(related.relatedTPHs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(PairTPHEqualTPH p) {
|
public void visit(RefType refType) {
|
||||||
//Do nothing. Dieser Fall wird in der resolve-Methode abgefangen
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
}
|
||||||
public void visit(RefType refType) {
|
|
||||||
|
|
||||||
}
|
@Override
|
||||||
|
public void visit(GenericRefType genericRefType) {
|
||||||
|
|
||||||
@Override
|
}
|
||||||
public void visit(GenericRefType genericRefType) {
|
|
||||||
|
|
||||||
}
|
@Override
|
||||||
|
public void visit(SuperWildcardType superWildcardType) {
|
||||||
|
|
||||||
@Override
|
}
|
||||||
public void visit(SuperWildcardType superWildcardType) {
|
|
||||||
|
|
||||||
}
|
@Override
|
||||||
|
public void visit(TypePlaceholder typePlaceholder) {
|
||||||
|
|
||||||
@Override
|
}
|
||||||
public void visit(TypePlaceholder typePlaceholder) {
|
|
||||||
|
|
||||||
}
|
@Override
|
||||||
|
public void visit(ExtendsWildcardType extendsWildcardType) {
|
||||||
|
|
||||||
@Override
|
}
|
||||||
public void visit(ExtendsWildcardType extendsWildcardType) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,149 +222,150 @@ class Resolver implements ResultSetVisitor {
|
|||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
class TPHResolver implements ResultSetVisitor {
|
class TPHResolver implements ResultSetVisitor {
|
||||||
|
|
||||||
private final TypePlaceholder tph;
|
private final TypePlaceholder tph;
|
||||||
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){
|
|
||||||
resolved.add(new GenericInsertPair(tph, null));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (resolved.size() == 0) {
|
||||||
@Override
|
resolved.add(new GenericInsertPair(tph, null));
|
||||||
public void visit(PairTPHsmallerTPH p) {
|
|
||||||
if(p.left.equals(tph) || p.right.equals(tph)){
|
|
||||||
resolved.add(new GenericInsertPair(p.left, p.right));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(PairTPHequalRefTypeOrWildcardType p) {
|
public void visit(PairTPHsmallerTPH p) {
|
||||||
TypePlaceholder otherSide = null;
|
if (p.left.equals(tph) || p.right.equals(tph)) {
|
||||||
if(p.right.equals(tph)){
|
resolved.add(new GenericInsertPair(p.left, p.right));
|
||||||
otherSide = p.left;
|
|
||||||
}
|
|
||||||
if(otherSide != null){
|
|
||||||
Set<ResultPair> newResultSet = new HashSet<>(this.resultSet.results);
|
|
||||||
newResultSet.remove(p);
|
|
||||||
resolved.addAll(new TPHResolver(otherSide, new ResultSet(newResultSet)).resolved);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(PairTPHEqualTPH p) {
|
public void visit(PairTPHequalRefTypeOrWildcardType p) {
|
||||||
//ignorieren. Wird vom Resolver behandelt
|
TypePlaceholder otherSide = null;
|
||||||
|
if (p.right.equals(tph)) {
|
||||||
|
otherSide = p.left;
|
||||||
}
|
}
|
||||||
|
if (otherSide != null) {
|
||||||
@Override
|
Set<ResultPair> newResultSet = new HashSet<>(this.resultSet.results);
|
||||||
public void visit(RefType refType) {
|
newResultSet.remove(p);
|
||||||
|
resolved.addAll(new TPHResolver(otherSide, new ResultSet(newResultSet)).resolved);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(GenericRefType genericRefType) {
|
public void visit(PairTPHEqualTPH p) {
|
||||||
|
//ignorieren. Wird vom Resolver behandelt
|
||||||
|
}
|
||||||
|
|
||||||
}
|
@Override
|
||||||
|
public void visit(RefType refType) {
|
||||||
|
|
||||||
@Override
|
}
|
||||||
public void visit(SuperWildcardType superWildcardType) {
|
|
||||||
|
|
||||||
}
|
@Override
|
||||||
|
public void visit(GenericRefType genericRefType) {
|
||||||
|
|
||||||
@Override
|
}
|
||||||
public void visit(TypePlaceholder typePlaceholder) {
|
|
||||||
|
|
||||||
}
|
@Override
|
||||||
|
public void visit(SuperWildcardType superWildcardType) {
|
||||||
|
|
||||||
@Override
|
}
|
||||||
public void visit(ExtendsWildcardType extendsWildcardType) {
|
|
||||||
|
|
||||||
}
|
@Override
|
||||||
|
public void visit(TypePlaceholder typePlaceholder) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ExtendsWildcardType extendsWildcardType) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
class RelatedTypeWalker implements ResultSetVisitor {
|
class RelatedTypeWalker implements ResultSetVisitor {
|
||||||
|
|
||||||
final Set<GenericInsertPair> relatedTPHs = new HashSet<>();
|
final Set<GenericInsertPair> relatedTPHs = new HashSet<>();
|
||||||
private final TypePlaceholder toResolve;
|
private final TypePlaceholder toResolve;
|
||||||
private final ResultSet resultSet;
|
private final ResultSet resultSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 resultSet
|
* @param start - kann null sein, wenn der Walker für einen RefType benutzt wird
|
||||||
*/
|
* @param resultSet
|
||||||
RelatedTypeWalker(TypePlaceholder start, ResultSet resultSet){
|
*/
|
||||||
this.toResolve = start;
|
RelatedTypeWalker(TypePlaceholder start, ResultSet resultSet) {
|
||||||
this.resultSet = resultSet;
|
this.toResolve = start;
|
||||||
int resolved = 0;
|
this.resultSet = resultSet;
|
||||||
do{
|
int resolved = 0;
|
||||||
resolved = relatedTPHs.size();
|
do {
|
||||||
for(ResultPair p : resultSet.results){
|
resolved = relatedTPHs.size();
|
||||||
p.accept(this);
|
for (ResultPair p : resultSet.results) {
|
||||||
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)){
|
|
||||||
relatedTPHs.addAll(new TPHResolver(p.left, resultSet).resolved);
|
|
||||||
//relatedTPHs.addAll(new RelatedTypeWalker(p.left, resultSet).relatedTPHs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (p.getLeft().equals(toResolve)) {
|
||||||
|
relatedTPHs.addAll(new TPHResolver(p.left, resultSet).resolved);
|
||||||
|
//relatedTPHs.addAll(new RelatedTypeWalker(p.left, resultSet).relatedTPHs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@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);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(PairTPHEqualTPH p) {
|
public void visit(PairTPHEqualTPH p) {
|
||||||
//Kann ignoriert werden. Diese Fälle werden vom Resolver behandelt
|
//Kann ignoriert werden. Diese Fälle werden vom Resolver behandelt
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Die folgenden Funktionen fügen alle TPHs an die relatedTPHs an, denen sie begegnen:
|
Die folgenden Funktionen fügen alle TPHs an die relatedTPHs an, denen sie begegnen:
|
||||||
Das wird verwendet, wenn alle relatedTPHs aus den Parametern eines RefTypes angefügt werden sollen
|
Das wird verwendet, wenn alle relatedTPHs aus den Parametern eines RefTypes angefügt werden sollen
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@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);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(SuperWildcardType superWildcardType) {
|
public void visit(SuperWildcardType superWildcardType) {
|
||||||
superWildcardType.getInnerType().accept(this);
|
superWildcardType.getInnerType().accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(TypePlaceholder typePlaceholder) {
|
public void visit(TypePlaceholder typePlaceholder) {
|
||||||
relatedTPHs.addAll(new TPHResolver(typePlaceholder, resultSet).resolved);
|
relatedTPHs.addAll(new TPHResolver(typePlaceholder, resultSet).resolved);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ExtendsWildcardType extendsWildcardType) {
|
public void visit(ExtendsWildcardType extendsWildcardType) {
|
||||||
extendsWildcardType.getInnerType().accept(this);
|
extendsWildcardType.getInnerType().accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(GenericRefType genericRefType) {
|
public void visit(GenericRefType genericRefType) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -17,6 +17,7 @@ import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation;
|
|||||||
import de.dhbwstuttgart.typeinference.constraints.Constraint;
|
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;
|
||||||
@@ -26,20 +27,19 @@ import java.util.*;
|
|||||||
|
|
||||||
public class TYPE {
|
public class TYPE {
|
||||||
|
|
||||||
private final SourceFile sf;
|
|
||||||
private final Set<ClassOrInterface> allAvailableClasses;
|
private final Set<ClassOrInterface> allAvailableClasses;
|
||||||
|
private final Set<ClassOrInterface> definedClasses;
|
||||||
public TYPE(SourceFile sf, Set<ClassOrInterface> allAvailableClasses){
|
|
||||||
this.sf = sf;
|
public TYPE(Set<ClassOrInterface> definedClasses, Set<ClassOrInterface> allAvailableClasses){
|
||||||
this.allAvailableClasses = allAvailableClasses;
|
this.allAvailableClasses = allAvailableClasses;
|
||||||
|
this.definedClasses = definedClasses;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConstraintSet getConstraints() {
|
public ConstraintSet getConstraints() {
|
||||||
ConstraintSet ret = new ConstraintSet();
|
ConstraintSet ret = new ConstraintSet();
|
||||||
for (ClassOrInterface cl : sf.KlassenVektor) {
|
for (ClassOrInterface cl : definedClasses) {
|
||||||
var allClasses = new HashSet<ClassOrInterface>();
|
Set<ClassOrInterface> allClasses = TypeUnifyTaskHelper.getPresizedHashSet(allAvailableClasses.size());
|
||||||
allClasses.addAll(allAvailableClasses);
|
allClasses.addAll(allAvailableClasses);
|
||||||
allClasses.addAll(sf.availableClasses);
|
|
||||||
ret.addAll(getConstraintsClass(cl, new TypeInferenceInformation(allClasses)));
|
ret.addAll(getConstraintsClass(cl, new TypeInferenceInformation(allClasses)));
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
@@ -72,7 +72,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) {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
@@ -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);
|
||||||
@@ -694,8 +702,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 +741,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 +754,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 +850,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 +891,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) {
|
||||||
|
recursivelyAddRecordConstraints(pattern);
|
||||||
if (el.getPattern() instanceof RecordPattern) {
|
}
|
||||||
var pattern = (RecordPattern) recType.getPattern();
|
|
||||||
recursivelyAddRecordConstraints(pattern);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -905,13 +909,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);
|
||||||
@@ -935,7 +939,7 @@ public class TYPEStmt implements StatementVisitor {
|
|||||||
@Override
|
@Override
|
||||||
public void visit(Yield aYield) {
|
public void visit(Yield aYield) {
|
||||||
aYield.retexpr.accept(this);
|
aYield.retexpr.accept(this);
|
||||||
constraintsSet.addUndConstraint(new Pair(aYield.getType(), switchStack.peek().getType(), PairOperator.EQUALSDOT, loc(aYield.getOffset())));
|
constraintsSet.addUndConstraint(new Pair(aYield.getType(), switchStack.peek().getType(), PairOperator.SMALLERDOT, loc(aYield.getOffset())));
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -94,8 +94,8 @@ public class MartelliMontanariUnify implements IUnify {
|
|||||||
// SUBST - Rule
|
// SUBST - Rule
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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,15 +649,17 @@ 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());
|
||||||
occuringTypes.push(pair.getRhsType());
|
occuringTypes.push(pair.getRhsType());
|
||||||
}
|
}
|
||||||
|
|
||||||
while(!occuringTypes.isEmpty()) {
|
while(!occuringTypes.isEmpty()) {
|
||||||
UnifyType t1 = occuringTypes.pop();
|
UnifyType t1 = occuringTypes.pop();
|
||||||
if(!typeMap.containsKey(t1))
|
if(!typeMap.containsKey(t1))
|
||||||
@@ -672,12 +671,12 @@ 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;
|
||||||
|
|
||||||
while(!result1.isEmpty()) {
|
while(!result1.isEmpty()) {
|
||||||
UnifyPair pair = result1.poll();
|
UnifyPair pair = result1.poll();
|
||||||
PlaceholderType lhsType = null;
|
PlaceholderType lhsType = null;
|
||||||
@@ -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()));
|
||||||
|
|
||||||
@@ -953,18 +960,14 @@ public class RuleSet implements IRuleSet{
|
|||||||
result.add(new UnifyPair(rhsType, funNLhsType.setTypeParams(new TypeParams(freshPlaceholders)), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair()));
|
result.add(new UnifyPair(rhsType, funNLhsType.setTypeParams(new TypeParams(freshPlaceholders)), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair()));
|
||||||
|
|
||||||
result.stream().forEach(x -> { UnifyType l = x.getLhsType();
|
result.stream().forEach(x -> { UnifyType l = x.getLhsType();
|
||||||
if (l instanceof PlaceholderType) { ((PlaceholderType)l).disableWildcardtable(); }
|
if (l instanceof PlaceholderType) { ((PlaceholderType)l).disableWildcardtable(); }
|
||||||
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()));
|
||||||
@@ -1003,18 +1006,15 @@ public class RuleSet implements IRuleSet{
|
|||||||
result.add(new UnifyPair(lhsType, funNRhsType.setTypeParams(new TypeParams(freshPlaceholders)), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair()));
|
result.add(new UnifyPair(lhsType, funNRhsType.setTypeParams(new TypeParams(freshPlaceholders)), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair()));
|
||||||
|
|
||||||
result.stream().forEach(x -> { UnifyType l = x.getLhsType();
|
result.stream().forEach(x -> { UnifyType l = x.getLhsType();
|
||||||
if (l instanceof PlaceholderType) { ((PlaceholderType)l).disableWildcardtable(); }
|
if (l instanceof PlaceholderType) { ((PlaceholderType)l).disableWildcardtable(); }
|
||||||
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);
|
||||||
|
|||||||
@@ -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
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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<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) {
|
Set<Set<UnifyPair>> setToFlatten;
|
||||||
super(eq, oderConstraints, fc, parallel, logFile, log, rekTiefe, urm, usedTasks);
|
Set<UnifyPair> methodSignatureConstraintUebergabe;
|
||||||
this.setToFlatten = setToFlatten;
|
|
||||||
this.nextSetElement = nextSetElement;
|
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) {
|
||||||
this.methodSignatureConstraintUebergabe = methodSignatureConstraintUebergabe;
|
super(eq, oderConstraints, fc, context, rekTiefe);
|
||||||
}
|
this.setToFlatten = setToFlatten;
|
||||||
|
this.nextSetElement = nextSetElement;
|
||||||
Set<UnifyPair> getNextSetElement() {
|
this.methodSignatureConstraintUebergabe = methodSignatureConstraintUebergabe;
|
||||||
return nextSetElement;
|
}
|
||||||
}
|
|
||||||
|
public Set<UnifyPair> getNextSetElement() {
|
||||||
@Override
|
return nextSetElement;
|
||||||
protected Set<Set<UnifyPair>> compute() {
|
}
|
||||||
if (one) {
|
|
||||||
System.out.println("two");
|
@Override
|
||||||
}
|
public CompletableFuture<Set<Set<UnifyPair>>> compute() {
|
||||||
one = true;
|
if (one) {
|
||||||
Set<Set<UnifyPair>> res = unify2(setToFlatten, eq, oderConstraintsField, fc, parallel, rekTiefeField, methodSignatureConstraintUebergabe);
|
context.logger().info("two");
|
||||||
|
}
|
||||||
|
one = true;
|
||||||
|
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 {
|
||||||
}
|
return res;
|
||||||
else {
|
}
|
||||||
return res;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void closeLogFile() {
|
|
||||||
|
|
||||||
try {
|
public void closeLogFile() {
|
||||||
logFile.close();
|
context.logger().close();
|
||||||
}
|
}
|
||||||
catch (IOException ioE) {
|
|
||||||
System.err.println("no log-File" + thNo);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user