Compare commits

..

11 Commits

Author SHA1 Message Date
Fabian Holzwarth
c5c31bc372 Merge branch 'feat/unify-server' into feat/unify-server-0variance 2025-07-07 11:12:39 +02:00
Fabian Holzwarth
03042fab97 feat: apply result for all parallel results on variance 0 2025-07-05 14:17:59 +02:00
Fabian Holzwarth
8d5b4ff54f Merge branch 'feat/unify-server' into feat/unify-server-0variance 2025-07-02 17:14:05 +02:00
Fabian Holzwarth
e8335715fb Merge branch 'feat/unify-server-0variance' of ssh://gitea.hb.dhbw-stuttgart.de:2222/f.holzwarth/JavaCompilerCore into feat/unify-server-0variance 2025-07-01 23:11:43 +02:00
Fabian Holzwarth
e574174962 feat: undo some changes for testing 2025-07-01 23:09:33 +02:00
Fabian Holzwarth
6df99fcacb feat: prevent concurrent list access on cancellable task 2025-07-01 23:08:41 +02:00
Fabian Holzwarth
d3fbaea8c7 feat: introduce task cancelling 2025-07-01 23:08:41 +02:00
Fabian Holzwarth
3415c250a3 feat: select multiple elements for variance 0 2025-07-01 23:08:39 +02:00
Fabian Holzwarth
9ec32970ee feat: prevent concurrent list access on cancellable task 2025-06-30 22:53:25 +02:00
Fabian Holzwarth
c54e012426 feat: introduce task cancelling 2025-06-30 22:20:52 +02:00
Fabian Holzwarth
52f6ebcf3c feat: select multiple elements for variance 0 2025-06-30 16:43:39 +02:00
122 changed files with 2364 additions and 3644 deletions

View File

@@ -1,8 +1,5 @@
name: Build and Test with Maven
on:
push:
branches-ignore:
- master
on: [push]
jobs:
Build-and-test-with-Maven:
@@ -18,11 +15,11 @@ jobs:
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '25'
java-version: '23'
cache: 'maven'
- name: Compile project
run: |
mvn compile
- name: Run tests
run: |
mvn test
mvn test

View File

@@ -1,45 +0,0 @@
on:
push:
branches:
- master
pull_request:
types: [opened, synchronize, reopened]
name: SonarQube Scan
jobs:
sonarqube:
name: SonarQube Trigger
runs-on: ubuntu-latest
steps:
- name: Checking out
uses: actions/checkout@v4
with:
# Disabling shallow clone is recommended for improving relevancy of reporting
fetch-depth: 0
- name: Install maven
run: |
apt update
apt install -y maven
- name: Install java
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '25'
cache: 'maven'
- name: Compile project
run: |
mvn clean dependency:copy-dependencies verify
- name: SonarQube Scan
uses: SonarSource/sonarqube-scan-action@v5.3.0
env:
SONAR_HOST_URL: ${{ secrets.SONARQUBE_HOST }}
SONAR_TOKEN: ${{ secrets.SONARQUBE_TOKEN }}
with:
args: >
-Dsonar.projectKey=Java-TX
-Dsonar.sources=src/main/java
-Dsonar.tests=src/test/java
-Dsonar.junit.reportPaths=target/test-reports
-Dsonar.java.binaries=target/classes
-Dsonar.java.libraries=target/dependency/*.jar
-Dsonar.coverage.jacoco.xmlReportPaths=target/site/jacoco/jacoco.xml

View File

@@ -1,7 +0,0 @@
## Java-TX Compiler
[![Lines of Code](https://gitea.hb.dhbw-stuttgart.de/sonarqube/api/project_badges/measure?project=Java-TX&metric=ncloc&token=sqb_d4a372fca7a6b86441243728a6ea5f88183db5eb)](https://gitea.hb.dhbw-stuttgart.de/sonarqube/dashboard?id=Java-TX)
[![Coverage](https://gitea.hb.dhbw-stuttgart.de/sonarqube/api/project_badges/measure?project=Java-TX&metric=coverage&token=sqb_d4a372fca7a6b86441243728a6ea5f88183db5eb)](https://gitea.hb.dhbw-stuttgart.de/sonarqube/dashboard?id=Java-TX)
[![Quality Gate Status](https://gitea.hb.dhbw-stuttgart.de/sonarqube/api/project_badges/measure?project=Java-TX&metric=alert_status&token=sqb_d4a372fca7a6b86441243728a6ea5f88183db5eb)](https://gitea.hb.dhbw-stuttgart.de/sonarqube/dashboard?id=Java-TX)
Work in Progress Java-TX Compiler repository!

View File

@@ -9,8 +9,7 @@ mkdir $TDIR
cd $TDIR
git clone $REPO .
git checkout feat/unify-server
# git checkout 93e1a8787cd94c73f4538f6a348f58613893a584
git checkout feat/unify-server-0variance
# git checkout dad468368b86bdd5a3d3b2754b17617cee0a9107 # 1:55
# git checkout a0c11b60e8c9d7addcbe0d3a09c9ce2924e9d5c0 # 2:25
# git checkout 4cddf73e6d6c9116d3e1705c4b27a8e7f18d80c3 # 2:27
@@ -20,14 +19,14 @@ git checkout feat/unify-server
# 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
mkdir testOut
#mvn clean compile -DskipTests package
#time java -jar target/JavaTXcompiler-0.1-jar-with-dependencies.jar resources/bytecode/javFiles/Merge.jav -vv -d testOut;
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
mvn clean compile test
echo -e "\nCleanup... "

60
pom.xml
View File

@@ -12,48 +12,43 @@ http://maven.apache.org/maven-v4_0_0.xsd">
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.13.2</version>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.antlr/antlr4 -->
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4</artifactId>
<version>4.13.2</version>
<version>4.11.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.19.0</version>
<version>2.16.1</version>
</dependency>
<dependency>
<groupId>io.github.classgraph</groupId>
<artifactId>classgraph</artifactId>
<version>4.8.180</version>
<version>4.8.172</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>33.4.8-jre</version>
<version>33.2.0-jre</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.ow2.asm/asm -->
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>9.8</version>
<version>9.5</version>
</dependency>
<dependency>
<groupId>org.java-websocket</groupId>
<artifactId>Java-WebSocket</artifactId>
<version>1.5.2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
@@ -64,51 +59,28 @@ http://maven.apache.org/maven-v4_0_0.xsd">
<artifactId>JColor</artifactId>
<version>5.5.1</version>
</dependency>
<dependency>
<groupId>org.jcommander</groupId>
<artifactId>jcommander</artifactId>
<version>3.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.13</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.14.0</version>
<version>3.11.0</version>
<configuration>
<source>25</source>
<target>25</target>
<compilerArgs>--enable-preview</compilerArgs>
<source>23</source>
<target>23</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.5.3</version>
<version>3.1.0</version>
<configuration>
<redirectTestOutputToFile>true</redirectTestOutputToFile>
<reportsDirectory>${project.build.directory}/test-reports</reportsDirectory>
<argLine>${argLine} --enable-preview</argLine>
<argLine>--enable-preview</argLine>
<trimStackTrace>false</trimStackTrace>
<excludes>
<exclude>**/JavaTXCompilerTest.java</exclude>
@@ -120,7 +92,7 @@ http://maven.apache.org/maven-v4_0_0.xsd">
<plugin>
<groupId>org.antlr</groupId>
<artifactId>antlr4-maven-plugin</artifactId>
<version>4.13.2</version>
<version>4.11.1</version>
<executions>
<execution>
<id>antlr</id>
@@ -133,7 +105,7 @@ http://maven.apache.org/maven-v4_0_0.xsd">
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.4.2</version>
<version>3.3.0</version>
<configuration>
<archive>
<manifest>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,3 +0,0 @@
class Bug378Id {
id2 = x -> x;
}

View File

@@ -1,8 +0,0 @@
import Bug378Id;
import java.lang.Integer;
public class Bug378Main {
public static main(args) {
var hallo = (new Bug378Id<Integer>().id2).apply(1);
}
}

View File

@@ -1,24 +0,0 @@
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);
}
}

View File

@@ -1,12 +0,0 @@
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
};
}
}

View File

@@ -1,13 +0,0 @@
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();
}
}

View File

@@ -1,10 +0,0 @@
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();
}
}

View File

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

View File

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

View File

@@ -4,7 +4,7 @@ import java.lang.Integer;
import java.lang.Boolean;
public class MatrixOP extends Vector<Vector<Integer>> {
MatrixOP () {
}
@@ -36,8 +36,8 @@ public class MatrixOP extends Vector<Vector<Integer>> {
v2.addElement(erg);
j++; }
ret.addElement(v2);
i++;
i++;
}
return ret;
};
}
}

View File

@@ -1,18 +1,17 @@
import java.lang.Integer;
import java.lang.Double;
import java.lang.Number;
import java.lang.String;
public record R(String n) {}
public record R(Number n) {}
public class SwitchOverload {
f() { return 10; }
g() { return 20; }
public f(){}
public m(r) {
return switch(r) {
case R("test") -> f();
case R("foo") -> g();
case R r -> 0;
};
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -39,10 +39,6 @@ public class FunNGenerator {
public final List<TargetType> inParams;
public final List<TargetType> realParams;
public GenericParameters(TargetFunNType funNType) {
this(funNType.funNParams(), funNType.returnArguments());
}
public GenericParameters(List<TargetType> params, int numReturns) {
this.realParams = params;
this.inParams = flattenTypeParams(params);
@@ -75,7 +71,7 @@ public class FunNGenerator {
if (type == null) return VOID;
var res = "L" + type.getInternalName();
if (type instanceof TargetSpecializedType a) {
if (!a.params().isEmpty() && !(a.params().size() == 1 && a.params().getFirst() == null)) {
if (a.params().size() > 0) {
res += "<";
for (var param : a.params()) {
if (param instanceof TargetGenericType gp) {
@@ -98,7 +94,7 @@ public class FunNGenerator {
}
private static String applySignature(TargetType a) { return a.toSignature(); }
private static String applyNameDescriptor(TargetType a){ return a instanceof TargetGenericType ? "LTPH;" : String.format("%s", a.toDescriptor()); }
private static String applyNameDescriptor(TargetType a){ return a instanceof TargetGenericType ? "LTPH;" : String.format("%s", applySignature(a)); }
public static String encodeType(TargetType type) {
if (type == null) return VOID;
@@ -115,12 +111,11 @@ public class FunNGenerator {
superFunNMethodSignature.append(String.format("T%s;", argumentGenericBase + currentParameter));
superFunNMethodDescriptor.append(objectSignature);
}
superFunNClassSignature.append(String.format("%s:%s>%s", returnGeneric, objectSignature, objectSignature));
if (numReturnTypes > 0) {
superFunNClassSignature.append(String.format("%s:%s>%s", returnGeneric, objectSignature, objectSignature));
superFunNMethodSignature.append(String.format(")T%s;", returnGeneric));
superFunNMethodDescriptor.append(String.format(")%s", objectSignature));
} else {
superFunNClassSignature = new StringBuilder(objectSignature);
superFunNMethodSignature.append(")V");
superFunNMethodDescriptor.append(")V");
}

View File

@@ -1,83 +1,77 @@
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.IOException;
import java.util.*;
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);
public static Logger.LogLevel logLevel = Logger.LogLevel.ERROR;
public static boolean writeLogFiles = false;
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();
Optional<Integer> serverPort = Optional.empty();
Optional<String> unifyServer = Optional.empty();
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\n" +
"\t[--server-mode <port>]\n" +
"\t[--unify-server <url>]\n" +
"\t[--write-logs]\n" +
"\t[-v|-vv-|-vvv]");
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 if (arg.equals("--server-mode")) {
serverPort = Optional.of(Integer.parseInt(it.next()));
} else if (arg.equals("--unify-server")) {
unifyServer = Optional.of(it.next());
} else if (arg.equals("--write-logs")) {
ConsoleInterface.writeLogFiles = true;
} else if (arg.startsWith("-v")) {
logLevel = switch (arg) {
case "-v" -> Logger.LogLevel.WARNING;
case "-vv" -> Logger.LogLevel.INFO;
case "-vvv" -> Logger.LogLevel.DEBUG;
default -> throw new IllegalArgumentException("Argument " + arg + " is not a valid verbosity level");
};
} else {
input.add(new File(arg));
}
}
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 (serverPort.isPresent()) {
if (unifyServer.isPresent()) throw new RuntimeException("Cannot use unifyServer when in server mode!");
JavaTXServer server = new JavaTXServer(serverPort.get());
server.listen();
}
else {
JavaTXCompiler compiler = new JavaTXCompiler(input, classpath, outputPath != null ? new File(outputPath) : null, unifyServer);
//compiler.typeInference();
compiler.generateBytecode();
}
}
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);
compiler.generateBytecode();
SocketClient.closeIfOpen();
}
}
}

View File

@@ -2,11 +2,9 @@
package de.dhbwstuttgart.core;
import de.dhbwstuttgart.bytecode.Codegen;
import de.dhbwstuttgart.bytecode.FunNGenerator;
import de.dhbwstuttgart.environment.CompilationEnvironment;
import de.dhbwstuttgart.environment.DirectoryClassLoader;
import de.dhbwstuttgart.exceptions.DebugException;
import de.dhbwstuttgart.languageServerInterface.model.LanguageServerTransferObject;
import de.dhbwstuttgart.parser.JavaTXParser;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.parser.scope.GenericsRegistry;
@@ -15,10 +13,6 @@ import de.dhbwstuttgart.parser.antlr.Java17Parser.SourceFileContext;
import de.dhbwstuttgart.parser.scope.JavaClassName;
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.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.Method;
@@ -63,7 +57,6 @@ import de.dhbwstuttgart.util.Logger;
import java.io.*;
import java.lang.reflect.Modifier;
import java.nio.file.Path;
import java.sql.Array;
import java.util.*;
import java.util.Map.Entry;
import java.util.function.Function;
@@ -81,7 +74,6 @@ public class JavaTXCompiler {
final CompilationEnvironment environment;
Boolean resultmodel = true;
public final Map<File, SourceFile> sourceFiles = new HashMap<>();
public final List<File> input;
public volatile UnifyTaskModel usedTasks = new UnifyTaskModel();
public final DirectoryClassLoader classLoader;
@@ -89,27 +81,29 @@ public class JavaTXCompiler {
public final List<File> classPath;
private final File outputPath;
public final Map<String, FunNGenerator.GenericParameters> usedFunN = new HashMap<>();
public final Set<Integer> usedFunNSuperTypes = new HashSet<>();
public Map<String, byte[]> auxiliaries = new HashMap<>();
private final Optional<String> unifyServer;
public DirectoryClassLoader getClassLoader() {
return classLoader;
}
public JavaTXCompiler(File sourceFile) throws IOException, ClassNotFoundException {
this(Collections.singletonList(sourceFile), List.of(), new File("."));
this(Arrays.asList(sourceFile), List.of(), new File("."), Optional.empty());
}
public JavaTXCompiler(List<File> sourceFiles) throws IOException, ClassNotFoundException {
this(sourceFiles, List.of(), new File("."));
this(sourceFiles, List.of(), new File("."), Optional.empty());
}
public JavaTXCompiler(List<File> sources, List<File> contextPath, File outputPath) throws IOException, ClassNotFoundException {
this(sources, contextPath, outputPath, Optional.empty());
}
public JavaTXCompiler(List<File> sources, List<File> contextPath, File outputPath, Optional<String> unifyServer) throws IOException, ClassNotFoundException {
// ensure new default placeholder registry for tests
defaultClientPlaceholderRegistry = new PlaceholderRegistry();
this.unifyServer = unifyServer;
var path = new ArrayList<>(contextPath);
if (contextPath.isEmpty()) {
// When no contextPaths are given, the working directory is the sources root
@@ -120,7 +114,6 @@ public class JavaTXCompiler {
environment = new CompilationEnvironment(sources, classLoader);
classPath = path;
this.outputPath = outputPath;
this.input = sources.stream().map(File::getAbsoluteFile).toList();
for (File s : sources) {
parse(s);
@@ -147,7 +140,7 @@ public class JavaTXCompiler {
return null;
}
public Set<ClassOrInterface> getAvailableClasses(File sourceFile) throws ClassNotFoundException, IOException {
public ConstraintSet<Pair> getConstraints(File sourceFile) throws ClassNotFoundException, IOException {
Set<ClassOrInterface> allClasses = new HashSet<>();// environment.getAllAvailableClasses();
ClassOrInterface objectClass = ASTFactory.createClass(Object.class);
var recordClass = ASTFactory.createClass(Record.class);
@@ -186,13 +179,7 @@ public class JavaTXCompiler {
allClasses.addAll(sf.KlassenVektor);
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);
TYPE ty = new TYPE(sf, allClasses);
var constraints = ty.getConstraints();
return constraints;
}
@@ -242,12 +229,12 @@ public class JavaTXCompiler {
private Set<ClassOrInterface> getAvailableClasses(JavaClassName name) throws ClassNotFoundException {
Set<ClassOrInterface> allClasses = new HashSet<>();
var cle = loadJavaTXClass(name);
if (cle == null) {
var clazz = loadJavaTXClass(name);
if (clazz == null) {
ClassOrInterface importedClass = ASTFactory.createClass(classLoader.loadClass(name.toString()));
allClasses.add(importedClass);
} else if (cle.cif != null) {
allClasses.add(cle.cif);
} else {
allClasses.add(clazz);
}
return allClasses;
}
@@ -375,30 +362,25 @@ public class JavaTXCompiler {
}
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);
var sf = sourceFiles.get(file);
Set<ClassOrInterface> allClasses = new HashSet<>();// environment.getAllAvailableClasses();
allClasses.addAll(getAvailableClasses(sf));
allClasses.addAll(sf.getClasses());
var newClasses = CompilationEnvironment.loadDefaultPackageClasses(sf.getPkgName(), file, this).stream().map(ASTFactory::createClass).collect(Collectors.toSet());
for (var clazz : newClasses) {
// Don't load classes that get recompiled
if (sf.getClasses().stream().anyMatch(nf -> nf.getClassName().equals(clazz.getClassName())))
continue;
if (allClasses.stream().noneMatch(old -> old.getClassName().equals(clazz.getClassName())))
allClasses.add(clazz);
}
TYPE ty = new TYPE(definedClasses, allClasses);
var cons = ty.getConstraints();
final ConstraintSet<Pair> cons = getConstraints(file);
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);
if (ConsoleInterface.writeLogFiles && !logFolder.mkdirs()) throw new RuntimeException("Could not creat directoy 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");
@@ -416,175 +398,86 @@ public class JavaTXCompiler {
};
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);
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");
logger.debug(ASTTypePrinter.print(sf));
logger.info(ASTTypePrinter.print(sf));
// logFile.flush();
logger.info("Unify nach Oder-Constraints-Anpassung:" + unifyCons.toString());
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);
// 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))
*/;
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();
if (unifyServer.isPresent()) {
UnifyResultModel urm = new UnifyResultModel(cons, finiteClosure);
UnifyContext context = new UnifyContext(logger, true, urm, usedTasks, placeholderRegistry);
SocketClient socketClient = new SocketClient(unifyServer.get());
return socketClient.execute(finiteClosure, cons, unifyCons, 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);
logger.info("RESULT Final: " + li.getResults());
logger.info("Constraints for Generated Generics: " + " ???");
logFile.write("RES_FINAL: " + li.getResults().toString() + "\n");
// logFile.flush();
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);
logFile.write("RES: " + result.toString() + "\n");
// logFile.flush();
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);
if(sf == null){
sf = sourceFiles.values().stream().findFirst().get();
}
Set<ClassOrInterface> allClasses = new HashSet<>();
allClasses.addAll(getAvailableClasses(sf));
allClasses.addAll(sf.getClasses());
var newClasses = CompilationEnvironment.loadDefaultPackageClasses(sf.getPkgName(), file, this).stream().map(ASTFactory::createClass).collect(Collectors.toSet());
for (var clazz : newClasses) {
// Don't load classes that get recompiled
if (sf.getClasses().stream().anyMatch(nf -> nf.getClassName().equals(clazz.getClassName())))
continue;
if (allClasses.stream().noneMatch(old -> old.getClassName().equals(clazz.getClassName())))
allClasses.add(clazz);
}
final ConstraintSet<Pair> cons = getConstraints(file);
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 {
IFiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses.stream().toList(), logger, classLoader, this, context.placeholderRegistry());
ConstraintSet<UnifyPair> unifyCons = UnifyTypeFactory.convert(this, cons, context.placeholderRegistry());
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;
};
unifyCons = unifyCons.map(distributeInnerVars);
Set<PlaceholderType> varianceTPHold;
Set<PlaceholderType> varianceTPH = new HashSet<>();
varianceTPH = varianceInheritanceConstraintSet(unifyCons);
List<Set<Constraint<UnifyPair>>> oderConstraints = unifyCons.getOderConstraints();
if (resultmodel) {
/* UnifyResultModel Anfang */
UnifyResultModel urm = new UnifyResultModel(cons, finiteClosure);
UnifyResultListenerImpl li = new UnifyResultListenerImpl();
urm.addUnifyResultListener(li);
TypeUnify.unifyParallel(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, context);
generateBytecode(sf, li.getResults());
return new LanguageServerTransferObject(li.getResults(), sf, ASTTypePrinter.print(sf), generatedGenerics);
}
/* UnifyResultModel End */
else {
Set<Set<UnifyPair>> result = TypeUnify.unifyOderConstraints(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, context);
results.addAll(result);
results = results.stream().map(x -> {
Optional<Set<UnifyPair>> res = new RuleSet(context.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));
}
} catch (ClassNotFoundException e) {
}
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.
*
@@ -665,12 +558,10 @@ public class JavaTXCompiler {
* if it doesn't exist it's going to compile it and add it to the source files list
* @param name
*/
public ClassEntry loadJavaTXClass(JavaClassName name) {
public ClassOrInterface loadJavaTXClass(JavaClassName name) {
var file = findFileForClass(name);
var classEntry = new ClassEntry(new File(outputPath, name.getClassName() + ".class"), null);
if (input.contains(file)) return classEntry;
if (file != null) {
if (loadedClasses.containsKey(name)) return loadedClasses.get(name);
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?
@@ -687,9 +578,8 @@ public class JavaTXCompiler {
writeClassFile(classFiles, outputPath != null ? outputPath : new File("."), false);
var clazz = classLoader.loadClass(name.toString());
var classOrInterface = ASTFactory.createClass(clazz);
classEntry = new ClassEntry(new File(outputPath, clazz.getName() + ".class"), classOrInterface);
loadedClasses.put(name, classEntry);
return classEntry;
loadedClasses.put(name, new ClassEntry(new File(outputPath, clazz.getName() + ".class"), classOrInterface));
return classOrInterface;
} catch (Exception e) {
throw new RuntimeException(e);
}
@@ -708,24 +598,12 @@ public class JavaTXCompiler {
}
public void generateBytecode() throws ClassNotFoundException, IOException {
if (ConsoleInterface.inferTogether) {
var files = sourceFiles.keySet().stream().toList();
var typeinferenceResult = this.typeInference(files);
for (var file : files) {
var sf = sourceFiles.get(file);
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);
}
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);
}
}
@@ -770,12 +648,12 @@ public class JavaTXCompiler {
var codegen = new Codegen(converter.convert(clazz), this, converter);
var code = codegen.generate();
generatedClasses.put(clazz.getClassName(), code);
converter.auxiliaries.forEach((name, source) -> {
generatedClasses.put(new JavaClassName(name), source);
});
}
generatedGenerics.put(sf, converter.javaGenerics());
converter.generateFunNTypes();
auxiliaries.forEach((name, source) -> {
generatedClasses.put(new JavaClassName(name), source);
});
return generatedClasses;
}
@@ -791,7 +669,7 @@ public class JavaTXCompiler {
output = new FileOutputStream(outputFile);
output.write(bytecode);
output.close();
defaultLogger.success(name + ".class file generated");
defaultLogger.info(name + ".class file generated");
}
}

View File

@@ -10,10 +10,10 @@ public class JavaTXServer {
public JavaTXServer(int port) {
this.socketServer = new SocketServer(port);
isRunning = true;
}
public void listen() {
isRunning = true;
socketServer.start();
}

View File

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

View File

@@ -30,7 +30,7 @@ public class CompilationEnvironment {
public final PackageCrawler packageCrawler;
/**
* Imitiert die Environment beim Aufruf des JavaCompilers auf einer Menge von java-Dateien Die Environment enthält automatisch die Java Standard Library
* Imitiert die Environment beim Aufruf des JavaCompilers auf einer Menge von java-Dateien Die Environment enth<EFBFBD>lt automatisch die Java Standard Library
*
* @param sourceFiles die zu kompilierenden Dateien
*/
@@ -86,10 +86,6 @@ public class CompilationEnvironment {
File[] files = dir.listFiles((dir1, name) -> name.endsWith(".class"));
if (files != null)
for (File classFile : files) {
var javFile = new File(classFile.getParentFile(), classFile.getName().substring(0, classFile.getName().lastIndexOf('.')) + ".jav").getAbsoluteFile();
// Ignore class file if the corresponding jav file already exists in the input
// FIXME this can't work because we don't know the corresponding file that created a class
if (compiler.input.contains(javFile)) continue;
String className = classFile.getName().substring(0, classFile.getName().length() - 6);
if (className.matches("Fun\\d+\\$\\$.*"))
continue;

View File

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

View File

@@ -1,120 +0,0 @@
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());
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());
return compiler.sourceFiles.get(file);
}
}

View File

@@ -1,40 +0,0 @@
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();
}
}

View File

@@ -1,47 +0,0 @@
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;
}
}

View File

@@ -1,31 +0,0 @@
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;}
}

View File

@@ -1,48 +0,0 @@
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;
}
}

View File

@@ -1,20 +0,0 @@
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) {
}
}

View File

@@ -151,7 +151,7 @@ public class StatementGenerator {
} else {
type = methodparameters?
TypePlaceholder.fresh(fp.getStart(), 1, false)
: TypePlaceholder.fresh(fp.getStart(), 1, false);
: TypePlaceholder.fresh(fp.getStart());
}
ret.add(new FormalParameter(paramName, type, fp.getStart()));
localVars.put(paramName, type);
@@ -1066,7 +1066,7 @@ public class StatementGenerator {
List<Pattern> parameterList = new ArrayList<>();
for (IdentifierContext identifier : lambdaParams.identifier()) {
Token offset = identifier.getStart();
parameterList.add(new FormalParameter(identifier.getText(), TypePlaceholder.fresh(offset, 1, false), offset));
parameterList.add(new FormalParameter(identifier.getText(), TypePlaceholder.fresh(offset), offset));
}
params = new ParameterList(parameterList, lambdaParams.getStart());
} else if (lambdaParams.formalParameterList() != null) {
@@ -1076,7 +1076,7 @@ public class StatementGenerator {
List<Pattern> parameterList = new ArrayList<>();
for (LambdaLVTIParameterContext param : lambdaParams.lambdaLVTIList().lambdaLVTIParameter()) {
Token offset = param.getStart();
parameterList.add(new FormalParameter(param.identifier().getText(), TypePlaceholder.fresh(offset, 1, false), offset));
parameterList.add(new FormalParameter(param.identifier().getText(), TypePlaceholder.fresh(offset), offset));
}
params = new ParameterList(parameterList, lambdaParams.getStart());
} else {
@@ -1100,9 +1100,9 @@ public class StatementGenerator {
block = lambdaGenerator.convert(expression.lambdaBody().block(), true);
}
List<RefTypeOrTPHOrWildcardOrGeneric> funNParams = new ArrayList<>();
funNParams.add(TypePlaceholder.fresh(expression.getStart(), -1, false));// ret-Type
funNParams.add(TypePlaceholder.fresh(expression.getStart()));// ret-Type
params.getFormalparalist().forEach(formalParameter -> // Für jeden Parameter einen TPH anfügen:
funNParams.add(TypePlaceholder.fresh(expression.getStart(), 1, false)));
funNParams.add(TypePlaceholder.fresh(expression.getStart())));
RefTypeOrTPHOrWildcardOrGeneric lambdaType = TypePlaceholder.fresh(expression.getStart());
// RefType lambdaType = new
// RefType(reg.getName("Fun"+params.getFormalparalist().size()),

View File

@@ -111,7 +111,7 @@ public class SyntaxTreeGenerator {
this.allmodifiers.put(Modifier.toString(Modifier.INTERFACE), Modifier.INTERFACE);
this.allmodifiers.put("sealed", 4096);
this.allmodifiers.put("non-sealed", 8192);
this.allmodifiers.put("default", 0); // Doesn't exist
this.allmodifiers.put("default", 16384);
this.allmodifiers.put("strictfp", 32768);
this.compiler = compiler;

View File

@@ -168,7 +168,7 @@ public class TypeGenerator {
if (generics.contains(name)) {
return new GenericRefType(name, offset);
} else {
Pattern p = Pattern.compile("Fun(Void|VoidImpl|Wrapper)?(\\d+)[$][$]"); // TODO Regex shenanigans
Pattern p = Pattern.compile("Fun(\\d+)[$][$]");
Matcher m = p.matcher(name);
if (m.matches()) {// es ist FunN$$-Type
return new RefType(new JavaClassName(name), convert(typeArguments, reg, generics), offset);

View File

@@ -41,7 +41,7 @@ public class JavaClassName {
}
/**
* Gibt von einem Klassennamen nur den Namen der Klasse zurück
* Gibt von einem Klassennamen nur den Namen der Klasse zur<EFBFBD>ck
* Beispiel:
* java.lang.Object wird zu: Object
*/

View File

@@ -5,9 +5,9 @@ import de.dhbwstuttgart.exceptions.NotImplementedException;
import java.util.*;
/**
* Speichert die Klassen für einen bestimmten Projektscope
* Speichert die Klassen f<EFBFBD>r einen bestimmten Projektscope
*/
public class JavaClassRegistry{
public class JavaClassRegistry {
final Map<JavaClassName, Integer> existingClasses = new HashMap<>();
public JavaClassRegistry(Map<String, Integer> initialNames) {
@@ -22,10 +22,6 @@ public class JavaClassRegistry{
}
}
public Set<JavaClassName> getAllClassNames(){
return existingClasses.keySet();
}
public void addName(String className, int numberOfGenerics) {
existingClasses.put(new JavaClassName(className), numberOfGenerics);
}
@@ -64,6 +60,6 @@ public class JavaClassRegistry{
}
public int getNumberOfGenerics(String name) {
return existingClasses.getOrDefault(new JavaClassName(name), 0);
return existingClasses.get(new JavaClassName(name));
}
}

View File

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

View File

@@ -1,8 +1,6 @@
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;
@@ -16,10 +14,8 @@ 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;
@@ -35,31 +31,43 @@ public class SocketClient extends WebSocketClient {
public static Logger logger = new Logger("SocketClient");
/**
* The singleton object
*/
private static SocketClient socketClient = null;
// use a latch to wait until the connection is closed by the remote host
private final CountDownLatch closeLatch = new CountDownLatch(1);
// temporarily: The received unify result
// TODO: replace with uuid and future system, such that responses can be mapped by a uuid to fulfill a Future
private UnifyResultPacket unifyResultPacket;
/**
* List of futures that are still waiting to be fulfilled
*/
private final Map<String, SocketFuture<?>> responseFutures = new HashMap<>();
private SocketClient(String url) {
public SocketClient(String url) {
super(
URI.create(url), // target url
//SocketServer.perMessageDeflateDraft, // enable compression
SocketServer.perMessageDeflateDraft, // enable compression
Map.of( // headers
"packetProtocolVersion", SocketServer.packetProtocolVersion
)
);
// make sure the url is in a valid format
// 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>");
}
}
public SocketClient(String host, int port, boolean secure) {
this(String.format("%s://%s:%d/", secure ? "wss" : "ws", host, port));
}
/**
* The main method for connecting, requesting and waiting for the server to unify.
* This is synchronized to prevent multiple webSockets connections at the moment, but it is not called from any
* thread except the main thread right now and is not necessary at all, probably. Maybe remove it later
*/
synchronized public List<ResultSet> execute(
FiniteClosure finiteClosure,
ConstraintSet<Pair> constraintSet,
ConstraintSet<UnifyPair> unifyConstraintSet,
UnifyContext context
) throws JsonProcessingException {
try {
// wait for the connection to be set up
@@ -68,108 +76,60 @@ public class SocketClient extends WebSocketClient {
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 {
// send the unify task request
UnifyRequestPacket packet = new UnifyRequestPacket(finiteClosure, constraintSet, unifyConstraintSet, context.placeholderRegistry());
String json = PacketContainer.serialize(packet);
client.send(json);
this.send(json);
// block the thread, until the connection is closed by the remote host (usually after sending the results)
this.waitUntilClosed();
// wait for the connection to fully close
this.closeBlocking();
} catch (InterruptedException exception) {
System.err.println("Server connection interrupted: " + exception);
this.notifyAll();
throw new RuntimeException("Aborted server connection", exception);
} catch (Exception exception) {
logger.exception(exception);
throw new RuntimeException("Exception occurred in server connection: ", exception);
}
return future;
}
// detect error cases, in which no error was thrown, but also no result was sent back from the server
if (this.unifyResultPacket == null) {
throw new RuntimeException("Did not receive server response but closed connection already");
}
/**
* 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();
return unifyResultPacket.getResultSet(context);
}
/**
* 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();
if (packet instanceof IServerToClientPacket serverToClientPacket) {
try {
serverToClientPacket.onHandle(this.getConnection(), this);
} catch (Exception exception) {
this.closeLatch.countDown();
this.close();
throw exception;
}
return;
}
serverToClientPacket.onHandle(this.getConnection(), this);
System.err.println("Received package of invalid type + " + packet.getClass().getName());
this.close();
}
/**
* 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();
}
public void setUnifyResultSets(UnifyResultPacket unifyResultPacket) {
this.unifyResultPacket = unifyResultPacket;
}
@Override
public void onOpen(ServerHandshake handshakedata) {
logger.success("Connected to server with status " + handshakedata.getHttpStatus());
logger.info("Connected to server with status " + handshakedata.getHttpStatus());
}
@Override
@@ -187,16 +147,16 @@ public class SocketClient extends WebSocketClient {
(reason.isEmpty() ? "" : "and reason " + reason + " ") +
"(closed by remote: " + remote + ")"
);
if (!this.responseFutures.isEmpty()) {
throw new RuntimeException("Server closed before all required tasks were answered");
}
this.closeLatch.countDown();
}
@Override
public void onError(Exception e) {
logger.exception(e);
throw new RuntimeException(e);
logger.error("Error: " + e.getMessage());
e.printStackTrace();
}
public void waitUntilClosed() throws InterruptedException {
closeLatch.await();
}
}

View File

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

View File

@@ -1,6 +1,7 @@
package de.dhbwstuttgart.server;
import com.fasterxml.jackson.core.JsonProcessingException;
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.server.packet.ErrorPacket;
import de.dhbwstuttgart.server.packet.IClientToServerPacket;
import de.dhbwstuttgart.server.packet.IPacket;
@@ -9,13 +10,11 @@ import de.dhbwstuttgart.server.packet.PacketContainer;
import de.dhbwstuttgart.util.Logger;
import java.net.InetSocketAddress;
import java.util.Collections;
import java.util.Objects;
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;
@@ -23,83 +22,67 @@ 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.DefaultWebSocketServerFactory;
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.
* This will prevent errors when 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();
/**
* Draft object for enabling the perMessageDeflate extension for more packet compression
*/
public static final Draft perMessageDeflateDraft = new Draft_6455(new PerMessageDeflateExtension());
public SocketServer(int port) {
super(new InetSocketAddress(port));
super(new InetSocketAddress(port), Collections.singletonList(perMessageDeflateDraft));
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
);
try {
ErrorPacket errorPacket = ErrorPacket.create(
"Mismatch in packet protocol version! Client (you): " + ppv + " and Server (me): " + packetProtocolVersion,
true
);
webSocket.send(PacketContainer.serialize(errorPacket));
}
catch (JsonProcessingException exception) {
System.err.println("Failed to serialize json: " + exception);
}
webSocket.close(1);
return;
}
SocketData socketData = new SocketData(webSocket);
SocketData socketData = new SocketData(UUID.randomUUID().toString());
webSocket.setAttachment(socketData);
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()) {
try (ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor()) {
Runnable task = () -> {
if (webSocket.<SocketData>getAttachment().unhandledTasks.get() == 0 || !webSocket.isOpen()) {
return;
}
sendMessage(webSocket, "No task received after " + secondsUntilTimeout + " seconds. Closing connection...");
sendMessage(webSocket, "No task received after 10 seconds. Closing connection...");
webSocket.close();
},
secondsUntilTimeout,
TimeUnit.SECONDS
);
};
executor.schedule(task, 10, TimeUnit.SECONDS);
executor.shutdown();
}
// and finally, when your program wants to exit
} catch (Exception e) {
@@ -129,22 +112,20 @@ public class SocketServer extends WebSocketServer {
this.onPacketReceived(webSocket, reconstructedPacket);
} catch (JsonProcessingException e) {
logger.exception(e);
this.log(webSocket, "Error on processing incoming package: " + e.getMessage());
this.log("Error on processing incoming package: " + e.getMessage(), webSocket);
}
}
@Override
public void onError(WebSocket webSocket, Exception e) {
if (webSocket != null) {
log(webSocket, e.getMessage());
webSocket.close();
}
logger.exception(e);
log(e.getMessage(), webSocket);
webSocket.close();
}
@Override
public void onStart() {
logger.success("Websocket server started on port " + this.getPort());
logger.info("Websocket server started on port " + this.getPort());
}
/**
@@ -152,7 +133,8 @@ public class SocketServer extends WebSocketServer {
*/
public void sendMessage(WebSocket webSocket, String text) {
try {
MessagePacket message = MessagePacket.create(text);
MessagePacket message = new MessagePacket();
message.message = text;
webSocket.send(PacketContainer.serialize(message));
} catch (Exception e) {
System.err.println("Failed to send message: " + text);
@@ -163,31 +145,33 @@ public class SocketServer extends WebSocketServer {
/**
* A shorthand method for sending error messages to the client
*/
public void sendError(WebSocket webSocket, String text, boolean isFatal) {
public void sendError(WebSocket webSocket, String text) {
try {
ErrorPacket error = ErrorPacket.create(text, isFatal);
ErrorPacket error = new ErrorPacket();
error.error = text;
webSocket.send(PacketContainer.serialize(error));
} catch (Exception e) {
logger.exception(e);
log(webSocket, "Failed to send error: " + text);
log("Failed to send error: " + text, webSocket);
}
}
/**
* The server-side implementation on how to handle certain packets when received
* 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);
// limit the amount of tasks per connection
final int maxTasks = 100;
if (socketData.totalTasks.get() >= maxTasks) {
sendError(webSocket, "Exceeded the maximum amount of " + maxTasks + " tasks per session");
webSocket.close();
return;
}
// only allow packets that are meant to be handled by the server
if (!(packet instanceof IClientToServerPacket<?> clientToServerPacket)) {
// 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;
}
@@ -196,24 +180,22 @@ public class SocketServer extends WebSocketServer {
socketData.unhandledTasks.incrementAndGet();
socketData.totalTasks.incrementAndGet();
// add the packet to the queue so it can be started by the worker
// 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();
}
// if the websocket has 0 unhandled Tasks, close the connection
int remainingUnhandledTasks = socketData.unhandledTasks.decrementAndGet();
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);
public void log(String msg, WebSocket webSocket) {
SocketData socketData = webSocket == null ? new SocketData("???") : webSocket.getAttachment();
logger.info("["+socketData.id+"] " + msg);
}
/**
@@ -225,11 +207,9 @@ public class SocketServer extends WebSocketServer {
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);
public SocketData(String id) {
this.id = id;
}
}
}

View File

@@ -2,7 +2,6 @@ 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;
@@ -11,7 +10,7 @@ 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 class DebugPacket implements IClientToServerPacket, IServerToClientPacket {
public SerialUUID a1;
public SerialUUID a2;
@@ -23,13 +22,9 @@ public class DebugPacket implements IClientToServerPacket.Void, IServerToClientP
public SerialValue<?> d2;
@JsonIgnore
public void onHandle(WebSocket webSocket, SocketClient socketClient) {}
public void onHandle(WebSocket webSocket, SocketClient socketServer) {}
@JsonIgnore
public void onHandle(WebSocket webSocket, SocketServer socketServer) {}
@JsonIgnore
public SocketFuture<IServerToClientPacket> getFuture() {
return SocketFuture.completedFuture();
}
}

View File

@@ -2,17 +2,16 @@ 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 {
public class ErrorPacket implements IClientToServerPacket, IServerToClientPacket {
/**
* The error endpoint for messages from the server that should be logged out as errors and possibly abort the process
* The error endpoint for messages from the server, that should be logged out outputted
*/
public String error;
public boolean isFatal;
@@ -28,9 +27,15 @@ public class ErrorPacket implements IServerToClientPacket {
@JsonIgnore
public void onHandle(WebSocket webSocket, SocketClient socketClient) {
SocketClient.logger.exception(new RuntimeException(this.error));
SocketClient.logger.error("SocketError: " + this.error);
if (this.isFatal) {
socketClient.close(1, "Received fatal error from server");
throw new RuntimeException("Received fatal error from server: " + this.error);
}
}
@JsonIgnore
public void onHandle(WebSocket webSocket, SocketServer socketServer) {
socketServer.log("SocketError: " + this.error, webSocket);
}
}

View File

@@ -1,26 +1,12 @@
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 {
public interface IClientToServerPacket extends IPacket {
@JsonIgnore
void onHandle(WebSocket webSocket, SocketServer socketServer);
@JsonIgnore
SocketFuture<T> getFuture();
/**
* Special case, where the packet will remain unanswered by the server
*/
interface Void extends IClientToServerPacket<IServerToClientPacket> {}
}

View File

@@ -2,14 +2,13 @@ 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
* 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 {
public class InvalidPacket implements IClientToServerPacket, IServerToClientPacket {
/**
* If available, the error that caused this package to appear
@@ -19,17 +18,12 @@ public class InvalidPacket implements IClientToServerPacket.Void, IServerToClien
@JsonIgnore
public void onHandle(WebSocket webSocket, SocketClient socketClient) {
SocketClient.logger.error("InvalidPacket: " + this.error);
System.err.println("[socket] " + "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();
socketServer.log("InvalidPacket: " + this.error, webSocket);
}
}

View File

@@ -2,17 +2,16 @@ 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 {
public class MessagePacket implements IClientToServerPacket, IServerToClientPacket {
/**
* The informational message from the server that should be logged out outputted
* The informational message from the server, that should be logged out outputted
*/
public String message;
@@ -30,11 +29,7 @@ public class MessagePacket implements IClientToServerPacket.Void, IServerToClien
@JsonIgnore
public void onHandle(WebSocket webSocket, SocketServer socketServer) {
socketServer.log(webSocket, this.message);
socketServer.log(this.message, webSocket);
}
@JsonIgnore
public SocketFuture<IServerToClientPacket> getFuture() {
return SocketFuture.completedFuture();
}
}

View File

@@ -25,14 +25,13 @@ public class PacketContainer {
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
* @return The json representation of the packet
*/
public static String serialize(IPacket packet) throws JsonProcessingException {
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
@@ -48,11 +47,7 @@ public class PacketContainer {
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);
}
@@ -81,8 +76,6 @@ public class PacketContainer {
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");

View File

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

View File

@@ -1,9 +1,6 @@
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;
@@ -23,16 +20,18 @@ 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.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
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 class UnifyRequestPacket implements IClientToServerPacket {
public SerialMap finiteClosure;
public SerialMap constraintSet;
@@ -40,33 +39,30 @@ public class UnifyRequestPacket implements IClientToServerPacket<UnifyResultPack
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(
public UnifyRequestPacket() {}
public UnifyRequestPacket(
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 contraint and finite closure
this.finiteClosure = finiteClosure.toSerial(keyStorage);
this.constraintSet = constraintSet.toSerial(keyStorage);
this.unifyConstraintSet = unifyConstraintSet.toSerial(keyStorage);
// store placeholder registry
var serialRegistry = placeholderRegistry.toSerial(packet.keyStorage);
packet.placeholders = serialRegistry.getValue("ph");
packet.factoryplaceholders = serialRegistry.getList("factoryPh").assertListOfMaps();
var serialRegistry = placeholderRegistry.toSerial(keyStorage);
this.placeholders = serialRegistry.getValue("ph");
this.factoryplaceholders = serialRegistry.getList("factoryPh").assertListOfMaps();
// store referenced objects separately
packet.serialKeyStorage = packet.keyStorage.toSerial(packet.keyStorage);
packet.logLevel = ConsoleInterface.logLevel.getValue();
return packet;
this.serialKeyStorage = keyStorage.toSerial(keyStorage);
}
@@ -99,22 +95,15 @@ public class UnifyRequestPacket implements IClientToServerPacket<UnifyResultPack
@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...");
SocketServer.logger.info("Client " + webSocket.<SocketServer.SocketData>getAttachment().id + " 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)),
var unifyContext = new UnifyContext(Logger.NULL_LOGGER, true,
new UnifyResultModel(new ConstraintSet<>(), new FiniteClosure(new HashSet<>(), Logger.NULL_LOGGER, placeholderRegistry)),
new UnifyTaskModel(), ForkJoinPool.commonPool(), placeholderRegistry
);
@@ -141,24 +130,17 @@ public class UnifyRequestPacket implements IClientToServerPacket<UnifyResultPack
var resultSets = resultListener.getResults();
socketServer.log(webSocket, "Finished unification");
SocketServer.logger.info("Finished unification for client " + webSocket.<SocketServer.SocketData>getAttachment().id);
socketServer.sendMessage(webSocket, "Unification finished. Found " + resultSets.size() + " result sets");
if (webSocket.isOpen()) {
UnifyResultPacket resultPacket = UnifyResultPacket.create(resultSets, futureId);
UnifyResultPacket resultPacket = UnifyResultPacket.create(resultSets);
webSocket.send(PacketContainer.serialize(resultPacket));
}
} catch (Exception e) {
SocketServer.logger.exception(e);
socketServer.log(webSocket, e.getMessage());
socketServer.log(e.getMessage(), webSocket);
}
}
@JsonIgnore
public SocketFuture<UnifyResultPacket> getFuture() {
var future = new SocketFuture<>(List.of(UnifyResultPacket.class));
futureId = future.futureId;
return future;
}
}

View File

@@ -18,14 +18,12 @@ public class UnifyResultPacket implements IServerToClientPacket {
public SerialList<ISerialNode> results;
public SerialMap keyStorage;
public String futureId;
public static UnifyResultPacket create(List<ResultSet> resultSets, String futureId) {
public static UnifyResultPacket create(List<ResultSet> resultSets) {
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;
}
@@ -37,8 +35,8 @@ public class UnifyResultPacket implements IServerToClientPacket {
@JsonIgnore
public void onHandle(WebSocket webSocket, SocketClient socketClient) {
SocketClient.logger.info("Received unify result");
socketClient.completeResponseFuture(futureId, this);
SocketClient.logger.info("[socket] Received unify result");
socketClient.setUnifyResultSets(this);
}

View File

@@ -3,7 +3,7 @@ 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;
import javax.annotation.Nullable;
public class SerialMap extends HashMap<String, ISerialNode> implements ISerialNode {

View File

@@ -6,12 +6,10 @@ import de.dhbwstuttgart.syntaxtree.type.GenericRefType;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.target.tree.TargetGeneric;
import org.antlr.v4.runtime.Token;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.stream.Collectors;
/**
* Stellt jede Art von Klasse dar. Auch abstrakte Klassen und Interfaces
@@ -33,7 +31,6 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope {
private List<RefType> implementedInterfaces;
private List<RefType> permittedSubtypes;
private List<Constructor> constructors;
private Set<GenericTypeVar> userDefinedGenerics;
public ClassOrInterface(int modifiers, JavaClassName name, List<Field> fielddecl, Optional<Constructor> fieldInitializations, Optional<Method> staticInitializer, List<Method> methods, List<Constructor> constructors, GenericDeclarationList genericClassParameters, RefType superClass, Boolean isInterface, Boolean isFunctionalInterface, List<RefType> implementedInterfaces, List<RefType> permittedSubtypes, Token offset, String fileName) {
super(offset);
@@ -202,22 +199,4 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope {
public int hashCode() {
return Objects.hash(name);
}
public Set<GenericTypeVar> getUserDefinedGenerics() {
if (this.userDefinedGenerics != null) return this.userDefinedGenerics;
var genericsIter = getGenerics().iterator();
if (genericsIter.hasNext()) {
// Add empty set of generics to cache so that it doesn't try to calculate it later
this.userDefinedGenerics = new HashSet<>();
while (genericsIter.hasNext()) {
var next = genericsIter.next();
userDefinedGenerics.add(next);
}
} else {
this.userDefinedGenerics = new HashSet<>();
}
return this.userDefinedGenerics;
}
}

View File

@@ -5,10 +5,8 @@ import java.util.*;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.target.generate.ASTToTargetAST;
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation;
import de.dhbwstuttgart.typeinference.result.ResultSet;
//import sun.security.x509.X509CertInfo;
public class SourceFile extends SyntaxTreeNode {
@@ -20,7 +18,6 @@ public class SourceFile extends SyntaxTreeNode {
private boolean isGenerated;
public List<ClassOrInterface> availableClasses = new ArrayList<>();
public List<ASTToTargetAST.Generics> generics = new ArrayList<>();
/**
* Die SourceFile repräsntiert eine zu einem Syntaxbaum eingelesene Java-Datei.
@@ -43,10 +40,6 @@ public class SourceFile extends SyntaxTreeNode {
this.imports = new HashSet<>(sf.imports);
}
public void addResultSet(ResultSet rs) {
}
public void setPackageName(String packageName) {
this.pkgName = packageName;
}

View File

@@ -16,10 +16,6 @@ public class NameGenerator {
public static void reset() {
strNextName = "A";
}
public static void resetTo(String name) {
strNextName = name;
}
/**
* Berechnet einen neuen, eindeutigen Namen f�r eine neue

View File

@@ -1,8 +1,8 @@
package de.dhbwstuttgart.target.generate;
import de.dhbwstuttgart.bytecode.FunNGenerator;
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.environment.ByteArrayClassLoader;
import de.dhbwstuttgart.environment.IByteArrayClassLoader;
import de.dhbwstuttgart.exceptions.DebugException;
import de.dhbwstuttgart.parser.NullToken;
@@ -12,8 +12,6 @@ import de.dhbwstuttgart.syntaxtree.Record;
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
import de.dhbwstuttgart.syntaxtree.statement.*;
import de.dhbwstuttgart.syntaxtree.type.*;
import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter;
import de.dhbwstuttgart.syntaxtree.visual.OutputGenerator;
import de.dhbwstuttgart.target.Target;
import de.dhbwstuttgart.target.tree.*;
import de.dhbwstuttgart.target.tree.expression.*;
@@ -38,6 +36,7 @@ public class ASTToTargetAST {
public Generics generics;
public List<Generics> currentMethodOverloads;
final Map<ClassOrInterface, Set<GenericTypeVar>> userDefinedGenerics = new HashMap<>();
final Map<Method, Set<SignaturePair>> tphsInMethods = new HashMap<>();
private Method currentMethod;
@@ -62,19 +61,17 @@ public class ASTToTargetAST {
}
public record Generics(JavaGenerics javaGenerics, TxGenerics txGenerics) {
public Generics(JavaTXCompiler compiler, ResultSet set) {
this(new JavaGenerics(compiler, set), new TxGenerics(compiler, set));
}
}
public IByteArrayClassLoader classLoader;
protected SourceFile sourceFile;
public ASTToTargetAST(List<ResultSet> resultSets, IByteArrayClassLoader classLoader) {
this(null, resultSets, classLoader);
public ASTToTargetAST(List<ResultSet> resultSets) {
this(null, resultSets);
}
public ASTToTargetAST(JavaTXCompiler compiler, List<ResultSet> resultSets, IByteArrayClassLoader classLoader) {
this(compiler, resultSets, null, classLoader);
public ASTToTargetAST(JavaTXCompiler compiler, List<ResultSet> resultSets) {
this(compiler, resultSets, null, new ByteArrayClassLoader());
}
public ASTToTargetAST(JavaTXCompiler compiler, List<ResultSet> resultSets, SourceFile sourceFile, IByteArrayClassLoader classLoader) {
@@ -84,9 +81,9 @@ public class ASTToTargetAST {
all = new ArrayList<>();
for (var set : resultSets) {
all.add(new Generics(compiler, set));
all.add(new Generics(new JavaGenerics(this, set), new TxGenerics(this, set)));
}
this.generics = all.getFirst();
this.generics = all.get(0);
}
public void addSignaturePair(TypePlaceholder signature, RefTypeOrTPHOrWildcardOrGeneric parameter) {
@@ -96,13 +93,9 @@ public class ASTToTargetAST {
}
Optional<Method> findMethod(ClassOrInterface owner, String name, List<TargetType> argumentList) {
return findMethod(owner, name, argumentList, this.generics.javaGenerics, this.compiler);
}
public static Optional<Method> findMethod(ClassOrInterface owner, String name, List<TargetType> argumentList, GenerateGenerics generics, JavaTXCompiler compiler) {
Optional<Method> method = Optional.empty();
while (method.isEmpty()) {
method = owner.getMethods().stream().filter(m -> m.name.equals(name) && parameterEquals(m.getParameterList(), argumentList, generics)).findFirst();
method = owner.getMethods().stream().filter(m -> m.name.equals(name) && parameterEquals(m.getParameterList(), argumentList)).findFirst();
if (owner.getClassName().toString().equals("java.lang.Object")) break;
owner = compiler.getClass(owner.getSuperClass().getName());
}
@@ -110,16 +103,16 @@ public class ASTToTargetAST {
}
Optional<Constructor> findConstructor(ClassOrInterface owner, List<TargetType> argumentList) {
return owner.getConstructors().stream().filter(c -> parameterEquals(c.getParameterList(), argumentList, generics.javaGenerics)).findFirst();
return owner.getConstructors().stream().filter(c -> parameterEquals(c.getParameterList(), argumentList)).findFirst();
}
static boolean parameterEquals(ParameterList parameterList, List<TargetType> arguments, GenerateGenerics generics) {
boolean parameterEquals(ParameterList parameterList, List<TargetType> arguments) {
var pars = parameterList.getFormalparalist();
if (pars.size() != arguments.size())
return false;
for (var i = 0; i < pars.size(); i++) {
var type1 = generics.getTargetType(pars.get(i).getType());
var type1 = convert(pars.get(i).getType(), generics.javaGenerics);
var type2 = arguments.get(i);
if (type1 instanceof TargetGenericType)
return true;
@@ -357,14 +350,19 @@ public class ASTToTargetAST {
Set<TargetGeneric> javaGenerics = new HashSet<>();
Set<TargetGeneric> txGenerics = new HashSet<>();
var userDefinedGenerics = input.getUserDefinedGenerics();
if (!userDefinedGenerics.isEmpty()) {
var genericsIter = input.getGenerics().iterator();
if (genericsIter.hasNext()) {
// Add empty set of generics to cache so that it doesn't try to calculate it later
for (var generic : userDefinedGenerics) {
// TODO Support multiple bouds
javaGenerics.add(new TargetGeneric(generic.getName(), convert(generic.getBounds().getFirst())));
var userDefinedGenerics = new HashSet<GenericTypeVar>();
this.userDefinedGenerics.put(input, userDefinedGenerics);
while (genericsIter.hasNext()) {
var next = genericsIter.next();
userDefinedGenerics.add(next);
// TODO Support multiple bounds
javaGenerics.add(new TargetGeneric(next.getName(), convert(next.getBounds().get(0))));
}
} else {
this.userDefinedGenerics.put(input, new HashSet<>());
// Generate generics only if there are no user defined ones
javaGenerics = convert(generics.javaGenerics.generics(input), generics.javaGenerics);
txGenerics = convert(generics.txGenerics.generics(input), generics.txGenerics);
@@ -426,7 +424,7 @@ public class ASTToTargetAST {
}
private List<TargetConstructor> convert(ClassOrInterface currentClass, Constructor input, TargetBlock fieldInitializer) {
generics = all.getFirst();
generics = all.get(0);
List<TargetConstructor> result = new ArrayList<>();
Set<List<MethodParameter>> parameterSet = new HashSet<>();
this.currentMethod = input;
@@ -470,6 +468,13 @@ public class ASTToTargetAST {
}
}
private TargetType unwrap(TargetType type) {
if (type instanceof TargetRefType ref) {
if (!ref.params().isEmpty()) return new TargetRefType(ref.name());
}
return type;
}
private TargetExpression generatePatternOverloadsRec(int offset, TargetExpression switchExpr, List<TargetLocalVar> params, List<TargetPattern> patterns, List<TargetMethod> methods, TargetType classType) {
if (methods.isEmpty()) throw new DebugException("Couldn't find a candidate for switch overloading");
if (methods.size() == 1) {
@@ -740,6 +745,11 @@ public class ASTToTargetAST {
return new TargetField(input.modifier, convert(input.getType(), generics.javaGenerics), input.getName());
}
private final Map<String, FunNGenerator.GenericParameters> usedFunN = new HashMap<>();
private final Set<Integer> usedFunNSuperTypes = new HashSet<>();
public Map<String, byte[]> auxiliaries = new HashMap<>();
public TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input) {
return convert(input, generics.javaGenerics);
}
@@ -772,15 +782,7 @@ public class ASTToTargetAST {
return TargetFunNType.fromParams(params, filteredParams, gep.getReturnType() != null ? 1 : 0);
}
private FunNGenerator.GenericParameters convertToParameters(TargetFunNType input) {
return null;
}
private boolean isSubtype(TargetType test, TargetType other) {
if (other.equals(TargetType.Object)) return true;
if (test instanceof TargetFunNType tfun && other instanceof TargetFunNType ofun)
return isSubtype(new FunNGenerator.GenericParameters(tfun), new FunNGenerator.GenericParameters(ofun));
var testClass = compiler.getClass(new JavaClassName(test.name()));
var otherClass = compiler.getClass(new JavaClassName(other.name()));
if (testClass == null) return false;
@@ -808,24 +810,28 @@ public class ASTToTargetAST {
}
public void generateFunNTypes() {
for (var entry : compiler.usedFunN.entrySet()) {
for (var entry : usedFunN.entrySet()) {
var gep = entry.getValue();
var superInterfaces = compiler.usedFunN.values().stream()
var superInterfaces = usedFunN.values().stream()
.filter(g -> !g.equals(gep))
.filter(genericParameters -> isSubtype(gep, genericParameters))
.map(FunNGenerator::getSpecializedClassName)
.toList();
var code = FunNGenerator.generateSpecializedBytecode(gep, superInterfaces);
compiler.auxiliaries.put(entry.getKey(), code);
try {
classLoader.findClass(entry.getKey());
} catch (ClassNotFoundException e) {
try {
classLoader.loadClass(code);
} catch (LinkageError ignored) {}
}
auxiliaries.put(entry.getKey(), code);
}
}
public TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input, GenerateGenerics generics) {
return convert(input, generics, compiler);
}
public static TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input, GenerateGenerics generics, JavaTXCompiler compiler) {
protected TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input, GenerateGenerics generics) {
return input.acceptTV(new TypeVisitor<>() {
@Override
public TargetType visit(RefType refType) {
@@ -837,24 +843,31 @@ public class ASTToTargetAST {
}
var params = refType.getParaList().stream().map(type -> {
return convert(type, generics, compiler);
return convert(type, generics);
}).toList();
if (name.matches("Fun\\d+\\$\\$")) { // TODO This seems like a bad idea
var returnType = FunNGenerator.getReturnType(params);
var className = FunNGenerator.getSpecializedClassName(FunNGenerator.getArguments(params), returnType);
if (!compiler.usedFunNSuperTypes.contains(params.size())) {
compiler.usedFunNSuperTypes.add(params.size());
if (!usedFunNSuperTypes.contains(params.size())) {
usedFunNSuperTypes.add(params.size());
var code = FunNGenerator.generateSuperBytecode(params.size() - 1, returnType != null ? 1 : 0);
var superClassName = FunNGenerator.getSuperClassName(params.size() - 1, returnType != null ? 1 : 0);
compiler.auxiliaries.put(superClassName, code);
try {
classLoader.findClass(superClassName);
} catch (ClassNotFoundException e) {
try {
classLoader.loadClass(code);
} catch (LinkageError ignored) {}
}
auxiliaries.put(superClassName, code);
}
FunNGenerator.GenericParameters gep = null;
if (!compiler.usedFunN.containsKey(className)) {
if (!usedFunN.containsKey(className)) {
gep = new FunNGenerator.GenericParameters(params, returnType != null ? 1 : 0);
compiler.usedFunN.put(className, gep);
usedFunN.put(className, gep);
} else {
gep = compiler.usedFunN.get(className);
gep = usedFunN.get(className);
}
return flattenFunNType(params, gep);
}
@@ -863,7 +876,7 @@ public class ASTToTargetAST {
@Override
public TargetType visit(SuperWildcardType superWildcardType) {
return new TargetSuperWildcard(convert(superWildcardType.getInnerType(), generics, compiler));
return new TargetSuperWildcard(convert(superWildcardType.getInnerType(), generics));
}
@Override
@@ -873,7 +886,7 @@ public class ASTToTargetAST {
@Override
public TargetType visit(ExtendsWildcardType extendsWildcardType) {
return new TargetExtendsWildcard(convert(extendsWildcardType.getInnerType(), generics, compiler));
return new TargetExtendsWildcard(convert(extendsWildcardType.getInnerType(), generics));
}
@Override

View File

@@ -1,7 +1,6 @@
package de.dhbwstuttgart.target.generate;
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.parser.JavaTXParser;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.syntaxtree.*;
import de.dhbwstuttgart.syntaxtree.statement.*;
@@ -21,7 +20,7 @@ import java.util.stream.Stream;
public abstract class GenerateGenerics {
private final JavaTXCompiler compiler;
private final ASTToTargetAST astToTargetAST;
public class TPH {
private final TypePlaceholder wrap;
@@ -137,8 +136,8 @@ public abstract class GenerateGenerics {
Map<TPH, RefTypeOrTPHOrWildcardOrGeneric> concreteTypes = new HashMap<>();
Map<TypePlaceholder, TypePlaceholder> equality = new HashMap<>();
GenerateGenerics(JavaTXCompiler compiler, ResultSet constraints) {
this.compiler = compiler;
GenerateGenerics(ASTToTargetAST astToTargetAST, ResultSet constraints) {
this.astToTargetAST = astToTargetAST;
for (var constraint : constraints.results) {
if (constraint instanceof PairTPHsmallerTPH p) {
Target.logger.info(p.left + " " + p.left.getVariance());
@@ -284,7 +283,7 @@ public abstract class GenerateGenerics {
Set<TPH> typeVariablesOfClass,
Set<Pair> result
) {
var userDefinedGenericsOfClass = owner.getUserDefinedGenerics();
var userDefinedGenericsOfClass = astToTargetAST.userDefinedGenerics.get(owner);
// Type variables with bounds that are also type variables of the method
for (var typeVariable : new HashSet<>(typeVariables)) {
@@ -332,7 +331,7 @@ public abstract class GenerateGenerics {
if (methodCall.receiver instanceof ExpressionReceiver expressionReceiver) {
if (expressionReceiver.expr instanceof This) {
var optMethod = ASTToTargetAST.findMethod(owner, methodCall.name, methodCall.signatureArguments().stream().map(x -> getTargetType(x)).toList(), GenerateGenerics.this, compiler);
var optMethod = astToTargetAST.findMethod(owner, methodCall.name, methodCall.signatureArguments().stream().map(astToTargetAST::convert).toList());
if (optMethod.isEmpty()) return;
var method2 = optMethod.get();
Target.logger.info("In: " + method.getName() + " Method: " + method2.getName());
@@ -767,7 +766,7 @@ public abstract class GenerateGenerics {
}
for (var pair : elementsToAddToEquality) {
System.out.println(pair);
Target.logger.info(pair);
addToEquality(pair.left, pair.right, referenced);
}
}
@@ -920,7 +919,7 @@ public abstract class GenerateGenerics {
}
}
if (infima.size() > 1) {
System.out.println(infima);
Target.logger.info(infima);
for (var pair : infima) {
var returnTypes = findTypeVariables(method.getReturnType());
var chain = findConnectionToReturnType(returnTypes, input, new HashSet<>(), pair.left);
@@ -1008,8 +1007,8 @@ public abstract class GenerateGenerics {
}
var type = concreteTypes.get(new TPH(tph));
if (type == null) return new TargetGenericType(tph.getName());
return ASTToTargetAST.convert(type, this, compiler);
return astToTargetAST.convert(type, this);
}
return ASTToTargetAST.convert(in, this, compiler);
return astToTargetAST.convert(in, this);
}
}

View File

@@ -69,4 +69,8 @@ public class GenericsResult {
return this.generics.getType(tph);
return type;
}
public TargetType resolveTarget(RefTypeOrTPHOrWildcardOrGeneric type) {
return this.generics.getTargetType(type);
}
}

View File

@@ -1,6 +1,5 @@
package de.dhbwstuttgart.target.generate;
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.typeinference.result.ResultSet;
@@ -8,8 +7,8 @@ import de.dhbwstuttgart.typeinference.result.ResultSet;
import java.util.Set;
final class JavaGenerics extends GenerateGenerics {
JavaGenerics(JavaTXCompiler compiler, ResultSet constraints) {
super(compiler, constraints);
JavaGenerics(ASTToTargetAST astToTargetAST, ResultSet constraints) {
super(astToTargetAST, constraints);
}
@Override

View File

@@ -15,7 +15,6 @@ import de.dhbwstuttgart.target.tree.expression.*;
import de.dhbwstuttgart.target.tree.type.*;
import java.lang.reflect.Modifier;
import java.sql.Array;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
@@ -34,71 +33,54 @@ public class StatementToTargetExpression implements ASTVisitor {
throw new NotImplementedException();
}
private class LambdaCaptureFinder extends TracingStatementVisitor {
// TODO The same mechanism is implemented in Codegen, maybe use it from there?
final Stack<Set<String>> localVariables = new Stack<>();
private final List<MethodParameter> parameters;
private final List<MethodParameter> captures;
LambdaCaptureFinder(List<MethodParameter> parameters, List<MethodParameter> captures) {
localVariables.push(new HashSet<>());
this.parameters = parameters;
this.captures = captures;
}
boolean hasLocalVar(String name) {
for (var localVariables : this.localVariables) {
if (localVariables.contains(name))
return true;
}
return false;
}
@Override
public void visit(Block block) {
localVariables.push(new HashSet<>());
super.visit(block);
localVariables.pop();
}
@Override
public void visit(LocalVar localVar) {
super.visit(localVar);
var capture = new MethodParameter(new TargetTypePattern(converter.convert(localVar.getType()), localVar.name));
if (!hasLocalVar(localVar.name) && !parameters.contains(capture) && !captures.contains(capture))
captures.add(capture);
}
@Override
public void visit(LocalVarDecl varDecl) {
var localVariables = this.localVariables.peek();
localVariables.add(varDecl.getName());
}
@Override
public void visit(LambdaExpression lambda) {
var newCaptures = new ArrayList<MethodParameter>();
var captureFinder = new LambdaCaptureFinder(createParameters(lambda), newCaptures);
lambda.methodBody.accept(captureFinder);
newCaptures.removeAll(parameters);
captures.addAll(newCaptures);
}
}
private List<MethodParameter> createParameters(LambdaExpression lambda) {
return StreamSupport.stream(lambda.params.spliterator(), false)
.map(p -> (FormalParameter) p)
.map(p -> new MethodParameter(new TargetTypePattern(converter.convert(p.getType()), p.getName())))
.toList();
}
@Override
public void visit(LambdaExpression lambdaExpression) {
var parameters = createParameters(lambdaExpression);
var parameters = StreamSupport.stream(lambdaExpression.params.spliterator(), false)
.map(p -> (FormalParameter) p)
.map(p -> new MethodParameter(new TargetTypePattern(converter.convert(p.getType()), p.getName())))
.toList();
List<MethodParameter> captures = new ArrayList<>();
var visitor = new LambdaCaptureFinder(parameters, captures);
lambdaExpression.methodBody.accept(visitor);
lambdaExpression.methodBody.accept(new TracingStatementVisitor() {
// TODO The same mechanism is implemented in Codegen, maybe use it from there?
final Stack<Set<String>> localVariables = new Stack<>();
{
localVariables.push(new HashSet<>());
}
boolean hasLocalVar(String name) {
for (var localVariables : this.localVariables) {
if (localVariables.contains(name))
return true;
}
return false;
}
@Override
public void visit(Block block) {
localVariables.push(new HashSet<>());
super.visit(block);
localVariables.pop();
}
@Override
public void visit(LocalVar localVar) {
super.visit(localVar);
var capture = new MethodParameter(new TargetTypePattern(converter.convert(localVar.getType()), localVar.name));
if (!hasLocalVar(localVar.name) && !parameters.contains(capture) && !captures.contains(capture))
captures.add(capture);
}
@Override
public void visit(LocalVarDecl varDecl) {
var localVariables = this.localVariables.peek();
localVariables.add(varDecl.getName());
}
@Override
public void visit(LambdaExpression lambda) {
} // Don't look at lambda expressions
});
TargetMethod.Signature signature = new TargetMethod.Signature(Set.of(), parameters, converter.convert(lambdaExpression.getReturnType()));;
var tpe = converter.convert(lambdaExpression.getType());
@@ -139,10 +121,7 @@ public class StatementToTargetExpression implements ASTVisitor {
@Override
public void visit(BoolExpression bool) {
result = switch(bool.operation) {
case OR -> new TargetBinaryOp.Or(converter.convert(bool.getType()), converter.convert(bool.lexpr), converter.convert(bool.rexpr));
case AND -> new TargetBinaryOp.And(converter.convert(bool.getType()), converter.convert(bool.lexpr), converter.convert(bool.rexpr));
};
Target.logger.info("BoolExpression");
}
@Override
@@ -162,6 +141,7 @@ public class StatementToTargetExpression implements ASTVisitor {
@Override
public void visit(FieldVar fieldVar) {
var isStatic = false;
var type = converter.convert(fieldVar.receiver.getType());
var clazz = converter.compiler.getClass(new JavaClassName(type.name()));
var field = clazz.getField(fieldVar.fieldVarName).orElseThrow();

View File

@@ -1,6 +1,5 @@
package de.dhbwstuttgart.target.generate;
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.typeinference.result.ResultSet;
@@ -8,8 +7,8 @@ import de.dhbwstuttgart.typeinference.result.ResultSet;
import java.util.Set;
final class TxGenerics extends GenerateGenerics {
TxGenerics(JavaTXCompiler compiler, ResultSet constraints) {
super(compiler, constraints);
TxGenerics(ASTToTargetAST astToTargetAST, ResultSet constraints) {
super(astToTargetAST, constraints);
}
@Override

View File

@@ -36,30 +36,30 @@ public record TargetMethod(int access, String name, TargetBlock block, Signature
public static String getDescriptor(TargetType returnType, TargetType... parameters) {
String ret = "(";
for (var parameterType : parameters) {
ret += parameterType.toDescriptor();
ret += parameterType.toSignature();
}
ret += ")";
if (returnType == null) ret += "V";
else ret += returnType.toDescriptor();
else ret += returnType.toSignature();
return ret;
}
public static String getSignature(Set<TargetGeneric> generics, List<MethodParameter> parameters, TargetType returnType) {
String ret = "";
if (!generics.isEmpty()) {
if (generics.size() > 0) {
ret += "<";
for (var generic : generics) {
ret += generic.name() + ":" + generic.bound().toSignature();
ret += generic.name() + ":" + generic.bound().toDescriptor();
}
ret += ">";
}
ret += "(";
for (var param : parameters) {
ret += param.pattern().type().toSignature();
ret += param.pattern().type().toDescriptor();
}
ret += ")";
if (returnType == null) ret += "V";
else ret += returnType.toSignature();
else ret += returnType.toDescriptor();
return ret;
}

View File

@@ -8,42 +8,42 @@ public sealed interface TargetLiteral extends TargetExpression {
record BooleanLiteral(Boolean value) implements TargetLiteral {
@Override
public TargetType type() {
return TargetType.boolean_;
return TargetType.Boolean;
}
}
record CharLiteral(Character value) implements TargetLiteral {
@Override
public TargetType type() {
return TargetType.char_;
return TargetType.Char;
}
}
record IntLiteral(Integer value) implements TargetLiteral {
@Override
public TargetType type() {
return TargetType.int_;
return TargetType.Integer;
}
}
record LongLiteral(Long value) implements TargetLiteral {
@Override
public TargetType type() {
return TargetType.long_;
return TargetType.Long;
}
}
record FloatLiteral(Float value) implements TargetLiteral {
@Override
public TargetType type() {
return TargetType.float_;
return TargetType.Float;
}
}
record DoubleLiteral(Double value) implements TargetLiteral {
@Override
public TargetType type() {
return TargetType.double_;
return TargetType.Double;
}
}

View File

@@ -3,12 +3,12 @@ package de.dhbwstuttgart.target.tree.type;
public record TargetExtendsWildcard(TargetType innerType) implements TargetType {
@Override
public String toSignature() {
return "+" + innerType.toSignature();
return innerType.toSignature();
}
@Override
public String toDescriptor() {
return innerType.toDescriptor();
return "+" + innerType.toDescriptor();
}
@Override

View File

@@ -36,7 +36,6 @@ public record TargetFunNType(String name, List<TargetType> funNParams, List<Targ
@Override
public String toSignature() {
var args = FunNGenerator.getArguments(funNParams);
return "LFun" + args.size() + "$$" + TargetSpecializedType.signatureParameters(funNParams) + ";";
return "L" + getInternalName() + ";";
}
}

View File

@@ -2,12 +2,12 @@ package de.dhbwstuttgart.target.tree.type;
public record TargetGenericType(String name) implements TargetType {
@Override
public String toDescriptor() {
public String toSignature() {
return "Ljava/lang/Object;"; // TODO Use bounds for this?
}
@Override
public String toSignature() {
public String toDescriptor() {
return "T" + getInternalName() + ";";
}

View File

@@ -12,6 +12,11 @@ public record TargetRefType(String name, List<TargetType> params) implements Tar
return this.name.replaceAll("\\.", "/");
}
@Override
public String toSignature() {
return "L" + getInternalName() + ";";
}
// Type erasure means we need to override hashCode and equals to only consider the name
@Override
public int hashCode() {

View File

@@ -6,27 +6,16 @@ public sealed interface TargetSpecializedType extends TargetType permits TargetF
List<TargetType> params();
@Override
default String toSignature() {
default String toDescriptor() {
String ret = "L" + getInternalName();
ret += signatureParameters(params());
ret += ";";
return ret;
}
static String signatureParameters(List<TargetType> params) {
var ret = "";
if (!params.isEmpty()) {
if (params().size() > 0) {
ret += "<";
for (var param : params) {
ret += param.toSignature();
for (var param : params()) {
ret += param.toDescriptor();
}
ret += ">";
}
ret += ";";
return ret;
}
@Override
default String toDescriptor() {
return "L" + getInternalName() + ";";
}
}

View File

@@ -3,12 +3,12 @@ package de.dhbwstuttgart.target.tree.type;
public record TargetSuperWildcard(TargetType innerType) implements TargetType {
@Override
public String toSignature() {
return "-" + innerType.toSignature();
return innerType.toSignature();
}
@Override
public String toDescriptor() {
return innerType.toDescriptor();
return "-" + innerType.toDescriptor();
}
@Override

View File

@@ -9,97 +9,84 @@ import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialUUID;
import de.dhbwstuttgart.typeinference.unify.UnifyContext;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
public class Constraint<A extends IConstraintElement> extends HashSet<A> implements Comparable<Constraint<A>>, ISerializableData {
private static final long serialVersionUID = 1L;
private boolean isInherited = false;//wird beides nur für die Method-Constraints benoetigt
private boolean isImplemented = false;
/*
* wird verwendet um bei der Codegenerierung die richtige Methoden - Signatur
* auszuwaehlen
*/
/*private*/ Set<A> methodSignatureConstraint = new HashSet<>();
private Constraint<A> extendConstraint = null;
public Constraint() {
super();
}
public class Constraint<A extends IConstraintElement> extends HashSet<A> implements ISerializableData {
private static final long serialVersionUID = 1L;
private boolean isInherited = false;//wird beides nur für die Method-Constraints benoetigt
private boolean isImplemented = false;
public Constraint(int initialCapacity) {
super(initialCapacity);
/*
* wird verwendet um bei der Codegenerierung die richtige Methoden - Signatur
* auszuwaehlen
*/
/*private*/ Set<A> methodSignatureConstraint = new HashSet<>();
private Constraint<A> extendConstraint = null;
public Constraint() {
super();
}
public Constraint(boolean isInherited, boolean isImplemented) {
this.isInherited = isInherited;
this.isImplemented = isImplemented;
}
public Constraint(boolean isInherited, boolean isImplemented, Constraint<A> extendConstraint, Set<A> methodSignatureConstraint) {
this.isInherited = isInherited;
this.isImplemented = isImplemented;
this.extendConstraint = extendConstraint;
this.methodSignatureConstraint = methodSignatureConstraint;
}
public void setIsInherited(boolean isInherited) {
this.isInherited = isInherited;
}
public boolean isInherited() {
return isInherited;
}
public boolean isImplemented() {
return isImplemented;
}
public Constraint<A> getExtendConstraint() {
return extendConstraint;
}
public void setExtendConstraint(Constraint<A> c) {
extendConstraint = c;
}
public Set<A> getmethodSignatureConstraint() {
return methodSignatureConstraint;
}
public void setmethodSignatureConstraint(Set<A> 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 Constraint(boolean isInherited, boolean isImplemented) {
this.isInherited = isInherited;
this.isImplemented = isImplemented;
}
public String toString() {
public Constraint(boolean isInherited, boolean isImplemented, Constraint<A> extendConstraint, Set<A> methodSignatureConstraint) {
this.isInherited = isInherited;
this.isImplemented = isImplemented;
this.extendConstraint = extendConstraint;
this.methodSignatureConstraint = methodSignatureConstraint;
}
public void setIsInherited(boolean isInherited) {
this.isInherited = isInherited;
}
public boolean isInherited() {
return isInherited;
}
public boolean isImplemented() {
return isImplemented;
}
public Constraint<A> getExtendConstraint() {
return extendConstraint;
}
public void setExtendConstraint(Constraint<A> c) {
extendConstraint = c;
}
public Set<A> getmethodSignatureConstraint() {
return methodSignatureConstraint;
}
public void setmethodSignatureConstraint(Set<A> c) {
methodSignatureConstraint = c;
}
public String toString() {
return super.toString() + "\nisInherited = " + isInherited
+ " isOveridden = " + isImplemented
+ " msc[" + methodSignatureConstraint.size() + "] = " + methodSignatureConstraint
//" + extendsContraint: " + (extendConstraint != null ? extendConstraint.toStringBase() : "null" )
+ "\n";
}
public String toStringBase() {
return super.toString();
}
}
@Override
public int compareTo(Constraint<A> o) {
return this.toString().compareTo(o.toString());
public String toStringBase() {
return super.toString();
}
private String serialUUID = null;
@@ -168,4 +155,5 @@ public class Constraint<A extends IConstraintElement> extends HashSet<A> impleme
return keyStorage.getUnserialized(uuid, Constraint.class);
}
}

View File

@@ -11,7 +11,7 @@ import de.dhbwstuttgart.typeinference.unify.UnifyContext;
* Paare, welche das Unifikationsergebnis darstellen
*/
public abstract class ResultPair<A extends RefTypeOrTPHOrWildcardOrGeneric,B extends RefTypeOrTPHOrWildcardOrGeneric>
implements Comparable<ResultPair<A,B>>, ISerializableData {
implements ISerializableData {
private final A left;
private final B right;
@@ -65,16 +65,6 @@ public abstract class ResultPair<A extends RefTypeOrTPHOrWildcardOrGeneric,B ext
return true;
}
@Override
public int compareTo(ResultPair<A, B> o) {
if (o == null) {
return 1; // this is greater than null
}
return o.left.toString().compareTo(this.left.toString());
}
@Override
public SerialMap toSerial(KeyStorage keyStorage) {

View File

@@ -5,13 +5,11 @@ 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.List;
import java.util.Set;
import de.dhbwstuttgart.exceptions.NotImplementedException;
@@ -24,32 +22,28 @@ import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import java.util.stream.Collectors;
@SuppressWarnings("rawtypes")
public class ResultSet implements Comparable<ResultSet>, ISerializableData {
public class ResultSet implements ISerializableData {
public final Set<ResultPair> results;
public Set<ResultPair<TypePlaceholder, TypePlaceholder>> genIns;
public ResultSet(Set<ResultPair> set){
this.results = set;
this.genIns = TypeUnifyTaskHelper.getPresizedHashSet(results.size());
results.forEach(x -> {
if (x instanceof PairTPHsmallerTPH) {
this.genIns.add(x);
}
});
}
public ResultSet(Set<ResultPair> set) {
this.results = set;
this.genIns = new HashSet<>();
results.forEach(x -> {
if (x instanceof PairTPHsmallerTPH) {
this.genIns.add(x);
}
});
}
public List<ResultPair> getSortedResults() {
return results.stream().sorted().toList();
}
public boolean contains(ResultPair toCheck) {
return this.results.contains(toCheck);
}
public boolean contains(ResultPair toCheck) {
return this.results.contains(toCheck);
}
public void remove(ResultPair toCheck) {
results.remove(toCheck);
}
public void remove(ResultPair toCheck) {
results.remove(toCheck);
}
public ResolvedType resolveType(RefTypeOrTPHOrWildcardOrGeneric type) {
if (type instanceof TypePlaceholder)
@@ -92,24 +86,9 @@ public class ResultSet implements Comparable<ResultSet>, ISerializableData {
}
}
@Override
public int hashCode() {
return results.hashCode();
}
@Override
public int compareTo(ResultSet o) {
List<ResultPair> thisSorted = this.getSortedResults();
List<ResultPair> otherSorted = o.getSortedResults();
int sizeCompare = Integer.compare(thisSorted.size(), otherSorted.size());
if (sizeCompare != 0) return sizeCompare;
for (int i = 0; i < thisSorted.size(); i++) {
int cmp = thisSorted.get(i).compareTo(otherSorted.get(i));
if (cmp != 0) return cmp;
}
return 0;
public int hashCode() {
return results.hashCode();
}
@Override

View File

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

View File

@@ -2,7 +2,6 @@
package de.dhbwstuttgart.typeinference.typeAlgo;
import de.dhbwstuttgart.typeinference.unify.PlaceholderRegistry;
import de.dhbwstuttgart.typeinference.unify.TypeUnifyTaskHelper;
import java.util.*;
import java.util.stream.Collectors;
@@ -75,7 +74,7 @@ public class TYPEStmt implements StatementVisitor {
@Override
public void visit(LambdaExpression lambdaExpression) {
TypePlaceholder tphRetType = TypePlaceholder.fresh(new NullToken(), -1, false);
TypePlaceholder tphRetType = TypePlaceholder.fresh(new NullToken());
List<RefTypeOrTPHOrWildcardOrGeneric> lambdaParams = lambdaExpression.params.getFormalparalist().stream().map((formalParameter -> formalParameter.getType())).collect(Collectors.toList());
lambdaParams.add(tphRetType);
// lambdaParams.add(0,tphRetType);
@@ -118,18 +117,17 @@ public class TYPEStmt implements StatementVisitor {
@Override
public void visit(FieldVar fieldVar) {
fieldVar.receiver.accept(this);
List<FieldAssumption> fieldAssumptions = info.getFields(fieldVar.fieldVarName);
Set<Constraint> oderConstraints = TypeUnifyTaskHelper.getPresizedHashSet(fieldAssumptions.size());
Set<Constraint> oderConstraints = new HashSet<>();
for (FieldAssumption fieldAssumption : fieldAssumptions) {
for (FieldAssumption fieldAssumption : info.getFields(fieldVar.fieldVarName)) {
Constraint constraint = new Constraint();
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.getType(), fieldAssumption.getType(resolver), PairOperator.EQUALSDOT, loc(fieldVar.getOffset())));
oderConstraints.add(constraint);
}
if (oderConstraints.isEmpty())
if (oderConstraints.size() == 0)
throw new TypeinferenceException("Kein Feld " + fieldVar.fieldVarName + " gefunden", fieldVar.getOffset());
constraintsSet.addOderConstraint(oderConstraints);
}
@@ -144,7 +142,7 @@ public class TYPEStmt implements StatementVisitor {
@Override
public void visit(ForEachStmt forEachStmt) {
var iterableType = new RefType(ASTFactory.createClass(java.lang.Iterable.class).getClassName(), List.of(new ExtendsWildcardType(forEachStmt.statement.getType(), new NullToken())), new NullToken());
var iterableType = new RefType(ASTFactory.createClass(java.lang.Iterable.class).getClassName(), Arrays.asList(new ExtendsWildcardType(forEachStmt.statement.getType(), new NullToken())), new NullToken());
constraintsSet.addUndConstraint(new Pair(forEachStmt.expression.getType(), iterableType, PairOperator.SMALLERDOT, loc(forEachStmt.getOffset())));
forEachStmt.statement.accept(this);
forEachStmt.expression.accept(this);
@@ -192,7 +190,7 @@ public class TYPEStmt implements StatementVisitor {
methodCall.receiver.accept(this);
// Overloading:
Set<Constraint<Pair>> methodConstraints = new HashSet<>();
for (MethodAssumption m : TYPEStmt.getMethods(methodCall.name, methodCall.arglist, info)) {
for (MethodAssumption m : this.getMethods(methodCall.name, methodCall.arglist, info)) {
GenericsResolver resolver = getResolverInstance();
Set<Constraint<Pair>> oneMethodConstraints = generateConstraint(methodCall, m, info, resolver);
methodConstraints.addAll(oneMethodConstraints);
@@ -202,7 +200,7 @@ public class TYPEStmt implements StatementVisitor {
* oneMethodConstraint.setExtendConstraint(extendsOneMethodConstraint); extendsOneMethodConstraint.setExtendConstraint(oneMethodConstraint); methodConstraints.add(extendsOneMethodConstraint);
*/
}
if (methodConstraints.isEmpty()) {
if (methodConstraints.size() < 1) {
throw new TypeinferenceException("Methode " + methodCall.name + " ist nicht vorhanden!", methodCall.getOffset());
}
constraintsSet.addOderConstraint(methodConstraints);
@@ -215,7 +213,7 @@ public class TYPEStmt implements StatementVisitor {
for (MethodAssumption m : this.getConstructors(info, (RefType) methodCall.getType(), methodCall.getArgumentList())) {
methodConstraints.add(generateConstructorConstraint(methodCall, m, info, getResolverInstance()));
}
if (methodConstraints.isEmpty()) {
if (methodConstraints.size() < 1) {
throw new TypeinferenceException("Konstruktor in Klasse " + methodCall.getType().toString() + " ist nicht vorhanden!", methodCall.getOffset());
}
constraintsSet.addOderConstraint(methodConstraints);
@@ -285,13 +283,8 @@ public class TYPEStmt implements StatementVisitor {
// 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
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
if (classNames.contains(bytee.getName())) {
if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(bytee.getName())) {
numeric = new Constraint<>();
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())));
@@ -299,7 +292,7 @@ public class TYPEStmt implements StatementVisitor {
numericAdditionOrStringConcatenation.add(numeric);
}
// PL eingefuegt 2018-07-17
if (classNames.contains(shortt.getName())) {
if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(shortt.getName())) {
numeric = new Constraint<>();
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())));
@@ -307,7 +300,7 @@ public class TYPEStmt implements StatementVisitor {
numericAdditionOrStringConcatenation.add(numeric);
}
// PL eingefuegt 2018-07-17
if (classNames.contains(integer.getName())) {
if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(integer.getName())) {
numeric = new Constraint<>();
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())));
@@ -315,7 +308,7 @@ public class TYPEStmt implements StatementVisitor {
numericAdditionOrStringConcatenation.add(numeric);
}
// PL eingefuegt 2018-07-17
if (classNames.contains(longg.getName())) {
if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(longg.getName())) {
numeric = new Constraint<>();
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())));
@@ -323,7 +316,7 @@ public class TYPEStmt implements StatementVisitor {
numericAdditionOrStringConcatenation.add(numeric);
}
// PL eingefuegt 2018-07-17
if (classNames.contains(floatt.getName())) {
if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(floatt.getName())) {
numeric = new Constraint<>();
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())));
@@ -331,7 +324,7 @@ public class TYPEStmt implements StatementVisitor {
numericAdditionOrStringConcatenation.add(numeric);
}
// PL eingefuegt 2018-07-17
if (classNames.contains(doublee.getName())) {
if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(doublee.getName())) {
numeric = new Constraint<>();
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())));
@@ -346,7 +339,7 @@ public class TYPEStmt implements StatementVisitor {
if (binary.operation.equals(BinaryExpr.Operator.ADD)) {
// Dann kann der Ausdruck auch das aneinanderfügen zweier Strings sein: ("a" + "b") oder (1 + 2)
if (classNames.contains(string.getName())) {
if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(string.getName())) {
Constraint<Pair> stringConcat = new Constraint<>();
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())));
@@ -354,7 +347,7 @@ public class TYPEStmt implements StatementVisitor {
numericAdditionOrStringConcatenation.add(stringConcat);
}
}
if (numericAdditionOrStringConcatenation.isEmpty()) {
if (numericAdditionOrStringConcatenation.size() < 1) {
throw new TypeinferenceException("Kein Typ für " + binary.operation.toString() + " vorhanden", binary.getOffset());
}
constraintsSet.addOderConstraint(numericAdditionOrStringConcatenation);
@@ -643,7 +636,6 @@ public class TYPEStmt implements StatementVisitor {
params.add(resolver.resolve(new GenericRefType(gtv.getName(), new NullToken())));
}
RefTypeOrTPHOrWildcardOrGeneric receiverType;
if (receiver instanceof FunNClass) {
receiverType = new RefType(new JavaClassName(receiver.getClassName().toString() + "$$"), params, new NullToken()); // new FunN(params);
} else {
@@ -741,7 +733,7 @@ public class TYPEStmt implements StatementVisitor {
}
// Zuordnung von MethodCall.signature(ReturnType) zu dem ReturnType der ausgewaehlten Methode (assumption.returnType)
ret.add(new Pair(foMethod.signature.getLast(), assumption.getReturnType(), PairOperator.EQUALSDOT));
ret.add(new Pair(foMethod.signature.get(foMethod.signature.size() - 1), assumption.getReturnType(), PairOperator.EQUALSDOT));
return ret;
}
@@ -754,8 +746,8 @@ public class TYPEStmt implements StatementVisitor {
// funNParams.add(TypePlaceholder.fresh(new NullToken()));
funNParams.add(new GenericRefType(NameGenerator.makeNewName(), new NullToken()));
}
funNParams.getLast();
ret.add(new MethodAssumption(new FunNClass(funNParams), funNParams.getLast(), funNParams.subList(0, funNParams.size() - 1), new TypeScope() {
funNParams.get(funNParams.size() - 1);
ret.add(new MethodAssumption(new FunNClass(funNParams), funNParams.get(funNParams.size() - 1), funNParams.subList(0, funNParams.size() - 1), new TypeScope() {
@Override
public Iterable<? extends GenericTypeVar> getGenerics() {
throw new NotImplementedException();
@@ -891,9 +883,13 @@ public class TYPEStmt implements StatementVisitor {
child.getLabels().forEach(el -> {
if (el.getType() instanceof RefType) {
if (el.getPattern() instanceof RecordPattern pattern) {
recursivelyAddRecordConstraints(pattern);
}
var recType = el;
if (el.getPattern() instanceof RecordPattern) {
var pattern = (RecordPattern) recType.getPattern();
recursivelyAddRecordConstraints(pattern);
}
}
});
@@ -909,7 +905,7 @@ public class TYPEStmt implements StatementVisitor {
var allClasses = info.getAvailableClasses();
var interestingClasses = allClasses.stream().filter(as -> as.getClassName().equals(((RefType) pattern.getType()).getName())).toList();
var constructors = interestingClasses.getFirst().getConstructors();
var constructors = interestingClasses.get(0).getConstructors();
int counter = 0;
@@ -939,7 +935,7 @@ public class TYPEStmt implements StatementVisitor {
@Override
public void visit(Yield aYield) {
aYield.retexpr.accept(this);
constraintsSet.addUndConstraint(new Pair(aYield.getType(), switchStack.peek().getType(), PairOperator.SMALLERDOT, loc(aYield.getOffset())));
constraintsSet.addUndConstraint(new Pair(aYield.getType(), switchStack.peek().getType(), PairOperator.EQUALSDOT, loc(aYield.getOffset())));
// TODO Auto-generated method stub
}
}

View File

@@ -1,7 +1,6 @@
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;
@@ -9,7 +8,7 @@ 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
* This allows to cancel 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>
@@ -17,19 +16,20 @@ import java.util.concurrent.atomic.AtomicBoolean;
public abstract class CancellableTask<T> extends RecursiveTask<T> {
private final AtomicBoolean executionCancelled = new AtomicBoolean(false);
private final List<CancellableTask<?>> childTasks = new LinkedList<>();
private final List<CancellableTask<?>> childTasks = new ArrayList<>();
private CancellableTask<?> parentTask = null;
/**
* Set the execution for this task and all its (recursive) children to be canceled
* Set the execution for this task and all its (recursive) children to be cancelled
*/
protected void cancelExecution() {
// is this branch already canceled? Then do nothing
if (this.executionCancelled.getAndSet(true)) return;
// is this branch already cancelled? Then do nothing
if (this.executionCancelled.get()) return;
executionCancelled.set(true);
this.cancelChildExecution();
}
private void cancelChildExecution() {
public void cancelChildExecution() {
synchronized (this.childTasks) {
for (var childTask : childTasks) {
// no need to cancel a branch that is already finished
@@ -40,24 +40,6 @@ public abstract class CancellableTask<T> extends RecursiveTask<T> {
}
}
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();
@@ -66,12 +48,6 @@ public abstract class CancellableTask<T> extends RecursiveTask<T> {
}
}
public void cancelYoungerSiblingTasks() {
if (this.parentTask != null) {
this.parentTask.cancelChildExecutionAfter(this);
}
}
public Boolean isExecutionCancelled() {
return executionCancelled.get();
}
@@ -79,9 +55,6 @@ public abstract class CancellableTask<T> extends RecursiveTask<T> {
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) {

View File

@@ -94,8 +94,8 @@ public class MartelliMontanariUnify implements IUnify {
// SUBST - Rule
if(lhsType instanceof PlaceholderType) {
mgu.add((PlaceholderType) lhsType, rhsType);
//PL 2018-04-01 nach checken, ob es richtig ist, dass keine Substitutionen uebergeben werden muessen.
termsList.replaceAll(mgu::apply);
//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));
idx = idx+1 == termsList.size() ? 0 : idx+1;
continue;
}

View File

@@ -6,7 +6,6 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Optional;
import java.util.Queue;
import java.util.Set;
@@ -649,17 +648,15 @@ public class RuleSet implements IRuleSet{
@Override
public Optional<Set<UnifyPair>> subst(Set<UnifyPair> pairs, List<Set<Constraint<UnifyPair>>> oderConstraints) {
// 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);
HashMap<UnifyType, Integer> typeMap = new HashMap<>();
Stack<UnifyType> occuringTypes = new Stack<>();
occuringTypes.ensureCapacity(pairs.size() * 3);
for(UnifyPair pair : pairs) {
occuringTypes.push(pair.getLhsType());
occuringTypes.push(pair.getRhsType());
}
while(!occuringTypes.isEmpty()) {
UnifyType t1 = occuringTypes.pop();
if(!typeMap.containsKey(t1))
@@ -671,12 +668,12 @@ public class RuleSet implements IRuleSet{
if(t1 instanceof SuperType)
occuringTypes.push(((SuperType) t1).getSuperedType());
else
t1.getTypeParams().forEach(occuringTypes::push);
t1.getTypeParams().forEach(x -> occuringTypes.push(x));
}
LinkedList<UnifyPair> result1 = new LinkedList<UnifyPair>(pairs);
Queue<UnifyPair> result1 = new LinkedList<UnifyPair>(pairs);
ArrayList<UnifyPair> result = new ArrayList<UnifyPair>();
boolean applied = false;
while(!result1.isEmpty()) {
UnifyPair pair = result1.poll();
PlaceholderType lhsType = null;
@@ -694,30 +691,19 @@ public class RuleSet implements IRuleSet{
&& !((rhsType instanceof WildcardType) && ((WildcardType)rhsType).getWildcardedType().equals(lhsType))) //PL eigefuegt 2018-02-18
{
Unifier uni = new Unifier(lhsType, rhsType);
// apply unifier to result and result1 in place
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));
}
result = result.stream().map(x -> uni.apply(pair,x)).collect(Collectors.toCollection(ArrayList::new));
result1 = result1.stream().map(x -> uni.apply(pair,x)).collect(Collectors.toCollection(LinkedList::new));
Function<? super Constraint<UnifyPair>,? extends Constraint<UnifyPair>> applyUni = b -> b.stream().map(
x -> uni.apply(pair,x)).collect(Collectors.toCollection((b.getExtendConstraint() != null)
? () -> new Constraint<UnifyPair>(
b.isInherited(),
b.isImplemented(),
b.getExtendConstraint().createdMapped(x -> uni.apply(pair,x)),
b.getExtendConstraint().stream().map(x -> uni.apply(pair,x)).collect(Collectors.toCollection(Constraint::new)),
b.getmethodSignatureConstraint().stream().map(x -> uni.apply(pair,x)).collect(Collectors.toCollection(HashSet::new)))
: () -> new Constraint<UnifyPair>(b.isInherited(), b.isImplemented())
));
oderConstraints.replaceAll(oc -> {
HashSet<Constraint<UnifyPair>> mapped = new HashSet<>(oc.size());
for (var element : oc) {
mapped.add(applyUni.apply(element));
}
return mapped;
});
oderConstraints.replaceAll(oc -> oc.stream().map(applyUni).collect(Collectors.toCollection(HashSet::new)));
/*
oderConstraints = oderConstraints.stream().map(
a -> a.stream().map(applyUni

View File

@@ -45,7 +45,7 @@ public class TypeUnify2Task extends TypeUnifyTask {
*/
//writeLog("xxx");
//noOfThread--;
if (this.isExecutionCancelled()) {
if (this.myIsCancelled()) {
return CompletableFuture.completedFuture(new HashSet<>());
} else {
return res;

View File

@@ -1,10 +1,8 @@
//PL 2018-12-19: Merge checken
package de.dhbwstuttgart.typeinference.unify;
import de.dhbwstuttgart.core.ConsoleInterface;
import de.dhbwstuttgart.exceptions.TypeinferenceException;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.server.ServerTaskLogger;
import de.dhbwstuttgart.typeinference.constraints.Constraint;
import de.dhbwstuttgart.typeinference.unify.cartesianproduct.VarianceCase;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
@@ -28,7 +26,11 @@ import de.dhbwstuttgart.typeinference.unify.model.WildcardType;
import de.dhbwstuttgart.util.Logger;
import de.dhbwstuttgart.util.Pair;
import de.dhbwstuttgart.util.Tuple;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Serial;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -47,6 +49,7 @@ import java.util.concurrent.RecursiveTask;
import java.util.function.BiFunction;
import java.util.function.BinaryOperator;
import java.util.stream.Collectors;
import org.apache.commons.io.output.NullOutputStream;
/**
@@ -114,6 +117,8 @@ public class TypeUnifyTask extends CancellableTask<CompletableFuture<Set<Set<Uni
public static int noShortendElements;
public static int noou = 0;
boolean myIsCanceled = false;
public TypeUnifyTask(UnifyContext context) {
this.context = context.newWithLogger(Logger.NULL_LOGGER);
rules = new RuleSet(context.placeholderRegistry());
@@ -150,7 +155,7 @@ public class TypeUnifyTask extends CancellableTask<CompletableFuture<Set<Set<Uni
this.fc = fc;
this.oup = new OrderingUnifyPair(fc, context);
this.context = (!ConsoleInterface.writeLogFiles || context.logger() instanceof ServerTaskLogger) ? context : context.newWithLogger(
this.context = context.newWithLogger(
Logger.forFile(
System.getProperty("user.dir") + "/logFiles/" + "Thread",
"Unify"
@@ -208,6 +213,13 @@ public class TypeUnifyTask extends CancellableTask<CompletableFuture<Set<Set<Uni
}
}
*/
void myCancel(boolean b) {
myIsCanceled = true;
}
public boolean myIsCancelled() {
return myIsCanceled;
}
public CompletableFuture<Set<Set<UnifyPair>>> compute() {
if (one) {
@@ -237,7 +249,7 @@ public class TypeUnifyTask extends CancellableTask<CompletableFuture<Set<Set<Uni
throw new TypeinferenceException("Unresolved constraints: " + res, new NullToken()); //return new HashSet<>();
}
if (this.isExecutionCancelled()) {
if (this.myIsCancelled()) {
return new HashSet<>();
}
@@ -274,7 +286,7 @@ public class TypeUnifyTask extends CancellableTask<CompletableFuture<Set<Set<Uni
//.collect(Collectors.toCollection(HashSet::new)));
if (this.isExecutionCancelled()) {
if (this.myIsCancelled()) {
return CompletableFuture.completedFuture(new HashSet<>());
}
@@ -303,7 +315,14 @@ public class TypeUnifyTask extends CancellableTask<CompletableFuture<Set<Set<Uni
/*
* Occurs-Check durchfuehren
*/
Set<UnifyPair> ocurrPairs = TypeUnifyTaskHelper.occursCheck(eq);
Set<UnifyPair> ocurrPairs = eq.stream().filter(x -> {
UnifyType lhs, rhs;
return (lhs = x.getLhsType()) instanceof PlaceholderType
&& !((rhs = x.getRhsType()) instanceof PlaceholderType)
&& rhs.getTypeParams().occurs((PlaceholderType) lhs);
})
.peek(UnifyPair::setUndefinedPair)
.collect(Collectors.toCollection(HashSet::new));
Set<UnifyPair> finalOcurrPairs = ocurrPairs;
context.logger().debug(() -> "ocurrPairs: " + finalOcurrPairs);
@@ -327,7 +346,14 @@ public class TypeUnifyTask extends CancellableTask<CompletableFuture<Set<Set<Uni
/* In commit dfd91b5f8b7fca1cb5f302eec4b0ba3330271c9b eingefuegt ANFANG */
Set<UnifyPair> occurcheck = new HashSet<>(eq0);
occurcheck.removeAll(eq0Prime);
ocurrPairs = TypeUnifyTaskHelper.occursCheck(occurcheck);
ocurrPairs = occurcheck.stream().filter(x -> {
UnifyType lhs, rhs;
return (lhs = x.getLhsType()) instanceof PlaceholderType
&& !((rhs = x.getRhsType()) instanceof PlaceholderType)
&& rhs.getTypeParams().occurs((PlaceholderType) lhs);
})
.peek(UnifyPair::setUndefinedPair)
.collect(Collectors.toCollection(HashSet::new));
Set<UnifyPair> finalOcurrPairs1 = ocurrPairs;
context.logger().debug(() -> "ocurrPairs: " + finalOcurrPairs1);
if (!ocurrPairs.isEmpty()) {
@@ -464,7 +490,7 @@ public class TypeUnifyTask extends CancellableTask<CompletableFuture<Set<Set<Uni
// .collect(Collectors.toCollection(HashSet::new));
//Muss auskommentiert werden, wenn computeCartesianRecursive ENDE
if (this.isExecutionCancelled()) {
if (this.myIsCancelled()) {
return CompletableFuture.completedFuture(new HashSet<>());
}
@@ -741,8 +767,7 @@ public class TypeUnifyTask extends CancellableTask<CompletableFuture<Set<Set<Uni
// Ergebnisvariable für die parallele Verabeitung: Tupel aus
// - forkOrig result : currentThreadResult (frueher "res")
// - fork results : forkResults (frueher "add_res")
CompletableFuture<VarianceCase.ComputationResults> parallelResultDataFuture;
CompletableFuture<Tuple<Set<Set<UnifyPair>>, Set<Set<Set<UnifyPair>>>>> parallelResultDataFuture;
if (parallel) {
parallelResultDataFuture = varianceCase.computeParallel(
@@ -753,16 +778,13 @@ public class TypeUnifyTask extends CancellableTask<CompletableFuture<Set<Set<Uni
// same as variance = 0
elems.add(varianceCase.a); //PL 2019-01-16 muss das wirklich hin steht schon in Zeile 859 ja braucht man siehe Zeile 859
parallelResultDataFuture = this.unify2(elems, eq, oderConstraints, fc, false, rekTiefe, new HashSet<>(methodSignatureConstraint))
.thenApply(VarianceCase.ComputationResults::new);
.thenApply(currentThreadResult -> new Tuple<>(currentThreadResult, new HashSet<>()));
}
if (this.isExecutionCancelled()) {
return CompletableFuture.completedFuture(new HashSet<>());
}
return parallelResultDataFuture.thenCompose(parallelResultData -> {
Set<Set<UnifyPair>> currentThreadResult = parallelResultData.mainResult;
Set<Set<Set<UnifyPair>>> forkResults = parallelResultData.forkResults;
Set<Set<UnifyPair>> currentThreadResult = parallelResultData.getFirst();
Set<Set<Set<UnifyPair>>> forkResults = parallelResultData.getSecond();
Set<Set<UnifyPair>> result = prevResult;
List<Set<UnifyPair>> nextSetAsList = prevNextSetAsList;
@@ -826,6 +848,17 @@ public class TypeUnifyTask extends CancellableTask<CompletableFuture<Set<Set<Uni
if (parallel) {
for (Set<Set<UnifyPair>> par_res : forkResults) {
if (variance == 0) {
if (!result.isEmpty() && !isUndefinedPairSetSet(currentThreadResult)) {
return CompletableFuture.completedFuture(result);
}
else {
result.addAll(par_res);
continue;
}
}
if (!isUndefinedPairSetSet(par_res) && isUndefinedPairSetSet(result)) {
//wenn korrektes Ergebnis gefunden alle Fehlerfaelle loeschen
result = par_res;
@@ -859,7 +892,7 @@ public class TypeUnifyTask extends CancellableTask<CompletableFuture<Set<Set<Uni
// Iterator<Set<UnifyPair>> nextSetasListIt = new ArrayList<>(nextSetAsList).iterator();
boolean shouldBreak = varianceCase.eraseInvalidSets(rekTiefe, aParDef, nextSetAsList);
if (shouldBreak) {
// this.cancelYoungerSiblingTasks();
//this.cancelChildExecution();
return CompletableFuture.completedFuture(result);
}
@@ -1712,9 +1745,8 @@ public class TypeUnifyTask extends CancellableTask<CompletableFuture<Set<Set<Uni
aa.putAll(b);
return aa;
};
var involvedPlaceholderTypes = x.getInvolvedPlaceholderTypes();
HashMap<PlaceholderType, PlaceholderType> hm = involvedPlaceholderTypes.stream()
.reduce(TypeUnifyTaskHelper.getPresizedHashMap(involvedPlaceholderTypes.size()),
HashMap<PlaceholderType, PlaceholderType> hm = x.getInvolvedPlaceholderTypes().stream()
.reduce(new HashMap<PlaceholderType, PlaceholderType>(),
(aa, b) -> {
aa.put(b, PlaceholderType.freshPlaceholder(context.placeholderRegistry()));
return aa;

View File

@@ -5,7 +5,6 @@ import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
import de.dhbwstuttgart.typeinference.unify.model.UnifyType;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
@@ -186,36 +185,4 @@ public class TypeUnifyTaskHelper {
.collect(Collectors.toCollection(ArrayList::new));
}
public static Set<UnifyPair> occursCheck(final Set<UnifyPair> eq) {
Set<UnifyPair> ocurrPairs = new HashSet<>(eq.size());
for (UnifyPair x : eq) {
UnifyType lhs = x.getLhsType();
UnifyType rhs = x.getRhsType();
if (lhs instanceof PlaceholderType lhsPlaceholder &&
!(rhs instanceof PlaceholderType) &&
rhs.getTypeParams().occurs(lhsPlaceholder))
{
x.setUndefinedPair();
ocurrPairs.add(x);
}
}
return ocurrPairs;
}
public static <T> HashSet<T> getPresizedHashSet(int minElements) {
if (minElements < 16) return new HashSet<>();
// HashSet and HashMap will resize at 75% load, so we account for that by multiplying with 1.5
int n = (int)(minElements * 1.5);
return new HashSet<>(n);
}
public static <S,T> HashMap<S,T> getPresizedHashMap(int minElements) {
if (minElements < 16) return new HashMap<>();
// HashSet and HashMap will resize at 75% load, so we account for that by multiplying with 1.5
int n = (int)(minElements * 1.5);
return new HashMap<>(n);
}
}

View File

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

View File

@@ -1,110 +0,0 @@
package de.dhbwstuttgart.typeinference.unify.cartesianproduct;
import de.dhbwstuttgart.typeinference.constraints.Constraint;
import de.dhbwstuttgart.typeinference.unify.TypeUnifyTask;
import de.dhbwstuttgart.typeinference.unify.UnifyContext;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
import de.dhbwstuttgart.util.Tuple;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
public class UnknownVarianceCase extends VarianceCase {
protected final int variance = 0;
protected UnknownVarianceCase(boolean isOderConstraint, TypeUnifyTask typeUnifyTask, UnifyContext context) {
super(isOderConstraint, typeUnifyTask, context);
}
@Override
public void selectNextData(
TypeUnifyTask typeUnifyTask,
List<Set<UnifyPair>> nextSetAsList,
Optional<UnifyPair> optOrigPair
) {
//wenn a <. theta dann ist ein maximales Element sehr wahrscheinlich
//wenn theta <. a dann ist ein minimales Element sehr wahrscheinlich
if (!this.isOderConstraint && optOrigPair != null && optOrigPair.isPresent()) {
if (optOrigPair.get().getBasePair().getLhsType() instanceof PlaceholderType) {
a = typeUnifyTask.oup.max(nextSetAsList.iterator());
} else {
a = typeUnifyTask.oup.min(nextSetAsList.iterator());
}
nextSetAsList.remove(a);
} else if (this.isOderConstraint) {
a = typeUnifyTask.oup.max(nextSetAsList.iterator());
nextSetAsList.remove(a);
nextSetasListOderConstraints.add(((Constraint<UnifyPair>) a).getExtendConstraint());
} else {
a = nextSetAsList.removeFirst();
}
}
@Override
public CompletableFuture<ComputationResults> computeParallel(
Set<Set<UnifyPair>> elems,
Set<UnifyPair> eq,
List<Set<Constraint<UnifyPair>>> oderConstraints,
IFiniteClosure fc,
int rekTiefe,
Set<UnifyPair> methodSignatureConstraint,
List<Set<UnifyPair>> nextSetAsList,
Set<UnifyPair> sameEqSet,
Set<Set<UnifyPair>> result,
Set<Set<UnifyPair>> aParDef
) {
elems.add(a);
return typeUnifyTask.unify2(elems, eq, oderConstraints, fc, context.parallel(), rekTiefe, new HashSet<>(methodSignatureConstraint))
.thenApply(ComputationResults::new);
}
@Override
public void applyComputedResults(
Set<Set<UnifyPair>> result,
Set<Set<UnifyPair>> currentThreadResult,
Set<UnifyPair> compResult,
Set<UnifyPair> compRes
) {
context.logger().debug("RES var=0 ADD:" + result.toString() + " " + currentThreadResult.toString());
result.addAll(currentThreadResult);
}
@Override
public boolean eraseInvalidSets(
int rekTiefe,
Set<Set<UnifyPair>> aParDef,
List<Set<UnifyPair>> nextSetAsList
) {
if (!this.isOderConstraint) {
return true;
} else {
nextSetAsList.removeAll(nextSetasListOderConstraints);
nextSetasListOderConstraints = new ArrayList<>();
context.logger().debug("Removed: " + nextSetasListOderConstraints);
List<Set<UnifyPair>> smallerSetasList = typeUnifyTask.oup.smallerThan(a, nextSetAsList);
List<Set<UnifyPair>> notInherited = smallerSetasList.stream()
.filter(x -> !((Constraint<UnifyPair>) x).isInherited())
.collect(Collectors.toCollection(ArrayList::new));
List<Set<UnifyPair>> notErased = new ArrayList<>();
notInherited.forEach(x -> notErased.addAll(typeUnifyTask.oup.smallerEqThan(x, smallerSetasList)));
List<Set<UnifyPair>> erased = new ArrayList<>(smallerSetasList);
erased.removeAll(notErased);
nextSetAsList.removeAll(erased);
context.logger().debug("Removed: " + erased);
context.logger().debug("Not Removed: " + nextSetAsList);
}
return false;
}
}

View File

@@ -0,0 +1,229 @@
package de.dhbwstuttgart.typeinference.unify.cartesianproduct;
import de.dhbwstuttgart.exceptions.UnifyCancelException;
import de.dhbwstuttgart.typeinference.constraints.Constraint;
import de.dhbwstuttgart.typeinference.unify.TypeUnify2Task;
import de.dhbwstuttgart.typeinference.unify.TypeUnifyTask;
import de.dhbwstuttgart.typeinference.unify.UnifyContext;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
import de.dhbwstuttgart.util.Tuple;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
public class Variance0Case extends VarianceCase {
protected final int variance = 0;
protected Variance0Case(boolean isOderConstraint, TypeUnifyTask typeUnifyTask, UnifyContext context) {
super(isOderConstraint, typeUnifyTask, context);
}
@Override
public void selectNextData(
TypeUnifyTask typeUnifyTask,
List<Set<UnifyPair>> nextSetAsList,
Optional<UnifyPair> optOrigPair
) {
//wenn a <. theta dann ist ein maximales Element sehr wahrscheinlich
//wenn theta <. a dann ist ein minimales Element sehr wahrscheinlich
if (!this.isOderConstraint && optOrigPair != null && optOrigPair.isPresent()) {
if (optOrigPair.get().getBasePair().getLhsType() instanceof PlaceholderType) {
a = typeUnifyTask.oup.max(nextSetAsList.iterator());
} else {
a = typeUnifyTask.oup.min(nextSetAsList.iterator());
}
nextSetAsList.remove(a);
} else if (this.isOderConstraint) {
a = typeUnifyTask.oup.max(nextSetAsList.iterator());
nextSetAsList.remove(a);
nextSetasListOderConstraints.add(((Constraint<UnifyPair>) a).getExtendConstraint());
} else {
a = nextSetAsList.removeFirst();
}
Set<UnifyPair> finalA = a;
if (!this.isOderConstraint && optOrigPair != null && optOrigPair.isPresent()) {
if (optOrigPair.get().getBasePair().getLhsType() instanceof PlaceholderType) {
nextSetasListRest = typeUnifyTask.oup.maxElements(
nextSetAsList.stream().filter(a_next -> typeUnifyTask.oup.compare(finalA, a_next) != 1).toList()
);
} else {
nextSetasListRest = typeUnifyTask.oup.minElements(
nextSetAsList.stream().filter(a_next -> typeUnifyTask.oup.compare(finalA, a_next) != -1).toList()
);
}
nextSetAsList.remove(a);
} else if (this.isOderConstraint) {
nextSetasListRest = typeUnifyTask.oup.maxElements(
nextSetAsList.stream().filter(a_next -> typeUnifyTask.oup.compare(finalA, a_next) != 1).toList()
);
} else {
for (int i = 0; i < Math.min(nextSetAsList.size(), 5); i++) {
nextSetasListRest.add(nextSetAsList.removeFirst());
}
}
}
@Override
public CompletableFuture<Tuple<Set<Set<UnifyPair>>, Set<Set<Set<UnifyPair>>>>> computeParallel(
Set<Set<UnifyPair>> elems,
Set<UnifyPair> eq,
List<Set<Constraint<UnifyPair>>> oderConstraints,
IFiniteClosure fc,
int rekTiefe,
Set<UnifyPair> methodSignatureConstraint,
List<Set<UnifyPair>> nextSetAsList,
Set<UnifyPair> sameEqSet,
Set<Set<UnifyPair>> result,
Set<Set<UnifyPair>> aParDef
) {
CompletableFuture<Tuple<Set<Set<UnifyPair>>, Set<Set<Set<UnifyPair>>>>> resultValues = CompletableFuture.completedFuture(new Tuple<>(
new HashSet<>(), new HashSet<>()
));
Set<UnifyPair> newEqOrig = new HashSet<>(eq);
Set<Set<UnifyPair>> newElemsOrig = new HashSet<>(elems);
List<Set<Constraint<UnifyPair>>> newOderConstraintsOrig = new ArrayList<>(oderConstraints);
newElemsOrig.add(a);
/* FORK ANFANG */
TypeUnify2Task forkOrig = new TypeUnify2Task(newElemsOrig, newEqOrig, newOderConstraintsOrig, a, fc, context, rekTiefe, new HashSet<>(methodSignatureConstraint));
typeUnifyTask.addChildTask(forkOrig);
// schedule compute() on another thread
CompletableFuture<Set<Set<UnifyPair>>> forkOrigFuture = CompletableFuture.supplyAsync(forkOrig::compute, context.executor()).thenCompose(f -> f);
resultValues = resultValues.thenCombine(forkOrigFuture,
(prevResults, currentThreadResult) -> {
forkOrig.context.logger().debug("final Orig 0");
forkOrig.closeLogFile();
return new Tuple<>(currentThreadResult, prevResults.getSecond());
});
//forks.add(forkOrig);
if (typeUnifyTask.myIsCancelled()) {
throw new UnifyCancelException();
}
/* FORK ENDE */
context.logger().debug("a in " + variance + " " + a);
context.logger().debug("nextSetasListRest: " + nextSetasListRest.toString());
while (!nextSetasListRest.isEmpty()) {
Set<UnifyPair> nSaL = nextSetasListRest.removeFirst();
nextSetAsList.remove(nSaL);
context.logger().debug("0 RM" + nSaL.toString());
if (!this.isOderConstraint) {
//ueberpruefung ob zu a =. ty \in nSaL in sameEqSet ein Widerspruch besteht
if (!sameEqSet.isEmpty() && !typeUnifyTask.checkNoContradiction(nSaL, sameEqSet, result)) {
TypeUnifyTask.noShortendElements++;
continue;
}
} else {
Constraint<UnifyPair> extendConstraint = ((Constraint<UnifyPair>) nSaL).getExtendConstraint();
nextSetasListOderConstraints.add(extendConstraint);
}
Set<UnifyPair> newEq = new HashSet<>(eq);
Set<Set<UnifyPair>> newElems = new HashSet<>(elems);
List<Set<Constraint<UnifyPair>>> newOderConstraints = new ArrayList<>(oderConstraints);
newElems.add(nSaL);
TypeUnify2Task fork = new TypeUnify2Task(newElems, newEq, newOderConstraints, nSaL, fc, context, rekTiefe, new HashSet<>(methodSignatureConstraint));
typeUnifyTask.addChildTask(fork);
// schedule compute() on another thread
CompletableFuture<Set<Set<UnifyPair>>> forkFuture = CompletableFuture.supplyAsync(fork::compute, context.executor()).thenCompose(f -> f);
resultValues = resultValues.thenCombine(forkFuture,
(prevResults, fork_res) -> {
if (typeUnifyTask.myIsCancelled()) {
throw new UnifyCancelException();
}
context.logger().debug("fork_res: " + fork_res.toString());
context.logger().debug(Boolean.valueOf((typeUnifyTask.isUndefinedPairSetSet(fork_res))).toString());
prevResults.getSecond().add(fork_res);
if (!typeUnifyTask.isUndefinedPairSetSet(fork_res)) {
aParDef.add(fork.getNextSetElement());
}
fork.context.logger().debug("final 0");
fork.closeLogFile();
return prevResults;
}
);
if (typeUnifyTask.myIsCancelled()) {
throw new UnifyCancelException();
}
}
return resultValues;
}
@Override
public void applyComputedResults(
Set<Set<UnifyPair>> result,
Set<Set<UnifyPair>> currentThreadResult,
Set<UnifyPair> compResult,
Set<UnifyPair> compRes
) {
context.logger().debug("RES var=0 ADD:" + result.toString() + " " + currentThreadResult.toString());
result.addAll(currentThreadResult);
}
@Override
public boolean eraseInvalidSets(
int rekTiefe,
Set<Set<UnifyPair>> aParDef,
List<Set<UnifyPair>> nextSetAsList
) {
if (!this.isOderConstraint) {
return true;
} else {
nextSetAsList.removeAll(nextSetasListOderConstraints);
nextSetasListOderConstraints = new ArrayList<>();
context.logger().debug("Removed: " + nextSetasListOderConstraints);
List<Set<UnifyPair>> smallerSetasList = typeUnifyTask.oup.smallerThan(a, nextSetAsList);
List<Set<UnifyPair>> notInherited = smallerSetasList.stream()
.filter(x -> !((Constraint<UnifyPair>) x).isInherited())
.collect(Collectors.toCollection(ArrayList::new));
final List<Set<UnifyPair>> notErased = new ArrayList<>();
notInherited.forEach(x -> notErased.addAll(typeUnifyTask.oup.smallerEqThan(x, smallerSetasList)));
List<Set<UnifyPair>> erased = new ArrayList<>(smallerSetasList);
erased.removeAll(notErased);
nextSetAsList.removeAll(erased);
context.logger().debug("Removed: " + erased);
context.logger().debug("Not Removed: " + nextSetAsList);
for (Set<UnifyPair> aPar : aParDef) {
nextSetAsList.removeAll(nextSetasListOderConstraints);
nextSetasListOderConstraints = new ArrayList<>();
context.logger().debug("Removed: " + nextSetasListOderConstraints);
smallerSetasList.clear();
smallerSetasList.addAll(typeUnifyTask.oup.smallerThan(aPar, nextSetAsList));
notInherited = smallerSetasList.stream()
.filter(x -> !((Constraint<UnifyPair>) x).isInherited())
.collect(Collectors.toCollection(ArrayList::new));
notErased.clear();
notInherited.forEach(x -> notErased.addAll(typeUnifyTask.oup.smallerEqThan(x, smallerSetasList)));
erased = new ArrayList<>(smallerSetasList);
erased.removeAll(notErased);
nextSetAsList.removeAll(erased);
context.logger().debug("Removed: " + erased);
context.logger().debug("Not Removed: " + nextSetAsList);
}
}
return false;
}
}

View File

@@ -1,5 +1,6 @@
package de.dhbwstuttgart.typeinference.unify.cartesianproduct;
import de.dhbwstuttgart.exceptions.UnifyCancelException;
import de.dhbwstuttgart.typeinference.constraints.Constraint;
import de.dhbwstuttgart.typeinference.unify.TypeUnify2Task;
import de.dhbwstuttgart.typeinference.unify.TypeUnifyTask;
@@ -16,11 +17,11 @@ import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
public class ContravarianceCase extends VarianceCase {
public class Variance1Case extends VarianceCase {
protected final int variance = 1;
protected ContravarianceCase(boolean isOderConstraint, TypeUnifyTask typeUnifyTask, UnifyContext context) {
protected Variance1Case(boolean isOderConstraint, TypeUnifyTask typeUnifyTask, UnifyContext context) {
super(isOderConstraint, typeUnifyTask, context);
}
@@ -36,7 +37,7 @@ public class ContravarianceCase extends VarianceCase {
if (this.isOderConstraint) {
nextSetasListOderConstraints.add(((Constraint<UnifyPair>) a).getExtendConstraint());
}
context.logger().debug(() -> "nextSetasListOderConstraints 1: " + nextSetasListOderConstraints);
context.logger().debug("nextSetasListOderConstraints 1: " + nextSetasListOderConstraints);
//Alle maximale Elemente in nextSetasListRest bestimmen
//nur für diese wird parallele Berechnung angestossen.
@@ -48,7 +49,7 @@ public class ContravarianceCase extends VarianceCase {
@Override
public CompletableFuture<ComputationResults> computeParallel(
public CompletableFuture<Tuple<Set<Set<UnifyPair>>, Set<Set<Set<UnifyPair>>>>> computeParallel(
Set<Set<UnifyPair>> elems,
Set<UnifyPair> eq,
List<Set<Constraint<UnifyPair>>> oderConstraints,
@@ -60,6 +61,10 @@ public class ContravarianceCase extends VarianceCase {
Set<Set<UnifyPair>> result,
Set<Set<UnifyPair>> aParDef
) {
CompletableFuture<Tuple<Set<Set<UnifyPair>>, Set<Set<Set<UnifyPair>>>>> resultValues = CompletableFuture.completedFuture(new Tuple<>(
new HashSet<>(), new HashSet<>()
));
Set<UnifyPair> newEqOrig = new HashSet<>(eq);
Set<Set<UnifyPair>> newElemsOrig = new HashSet<>(elems);
List<Set<Constraint<UnifyPair>>> newOderConstraintsOrig = new ArrayList<>(oderConstraints);
@@ -70,16 +75,16 @@ public class ContravarianceCase extends VarianceCase {
typeUnifyTask.addChildTask(forkOrig);
// schedule compute() on another thread
CompletableFuture<Set<Set<UnifyPair>>> forkOrigFuture = CompletableFuture.supplyAsync(forkOrig::compute, context.executor()).thenCompose(f -> f);
CompletableFuture<ComputationResults> resultValues = forkOrigFuture.thenApply(
(currentThreadResult) -> {
resultValues = resultValues.thenCombine(forkOrigFuture,
(prevResults, currentThreadResult) -> {
forkOrig.context.logger().debug("final Orig 1");
forkOrig.closeLogFile();
return new ComputationResults(currentThreadResult);
return new Tuple<>(currentThreadResult, prevResults.getSecond());
});
//forks.add(forkOrig);
if (typeUnifyTask.isExecutionCancelled()) {
return CompletableFuture.completedFuture(new ComputationResults());
if (typeUnifyTask.myIsCancelled()) {
throw new UnifyCancelException();
}
/* FORK ENDE */
@@ -109,12 +114,12 @@ public class ContravarianceCase extends VarianceCase {
CompletableFuture<Set<Set<UnifyPair>>> forkFuture = CompletableFuture.supplyAsync(fork::compute, context.executor()).thenCompose(f -> f);
resultValues = resultValues.thenCombine(forkFuture,
(prevResults, fork_res) -> {
if (typeUnifyTask.isExecutionCancelled()) {
return new ComputationResults();
if (typeUnifyTask.myIsCancelled()) {
throw new UnifyCancelException();
}
context.logger().debug("fork_res: " + fork_res.toString());
context.logger().debug(Boolean.valueOf((typeUnifyTask.isUndefinedPairSetSet(fork_res))).toString());
prevResults.addForkResult(fork_res);
prevResults.getSecond().add(fork_res);
if (!typeUnifyTask.isUndefinedPairSetSet(fork_res)) {
aParDef.add(fork.getNextSetElement());
}
@@ -124,8 +129,8 @@ public class ContravarianceCase extends VarianceCase {
}
);
if (typeUnifyTask.isExecutionCancelled()) {
return CompletableFuture.completedFuture(new ComputationResults());
if (typeUnifyTask.myIsCancelled()) {
throw new UnifyCancelException();
}
}

View File

@@ -1,5 +1,6 @@
package de.dhbwstuttgart.typeinference.unify.cartesianproduct;
import de.dhbwstuttgart.exceptions.UnifyCancelException;
import de.dhbwstuttgart.typeinference.constraints.Constraint;
import de.dhbwstuttgart.typeinference.unify.TypeUnify2Task;
import de.dhbwstuttgart.typeinference.unify.TypeUnifyTask;
@@ -14,12 +15,11 @@ import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
public class InvarianceOrConstraintCase extends VarianceCase {
public class Variance2Case extends VarianceCase {
// either for invariance or for oderConstraints
protected final int variance = 2;
protected InvarianceOrConstraintCase(boolean isOderConstraint, TypeUnifyTask typeUnifyTask, UnifyContext context) {
protected Variance2Case(boolean isOderConstraint, TypeUnifyTask typeUnifyTask, UnifyContext context) {
super(isOderConstraint, typeUnifyTask, context);
}
@@ -37,7 +37,7 @@ public class InvarianceOrConstraintCase extends VarianceCase {
@Override
public CompletableFuture<ComputationResults> computeParallel(
public CompletableFuture<Tuple<Set<Set<UnifyPair>>, Set<Set<Set<UnifyPair>>>>> computeParallel(
Set<Set<UnifyPair>> elems,
Set<UnifyPair> eq,
List<Set<Constraint<UnifyPair>>> oderConstraints,
@@ -49,6 +49,8 @@ public class InvarianceOrConstraintCase extends VarianceCase {
Set<Set<UnifyPair>> result,
Set<Set<UnifyPair>> aParDef
) {
CompletableFuture<Tuple<Set<Set<UnifyPair>>, Set<Set<Set<UnifyPair>>>>> resultValuesFuture;
context.logger().debug("var2einstieg");
Set<TypeUnify2Task> forks = new HashSet<>();
Set<UnifyPair> newEqOrig = new HashSet<>(eq);
@@ -60,14 +62,13 @@ public class InvarianceOrConstraintCase extends VarianceCase {
TypeUnify2Task forkOrig = new TypeUnify2Task(newElemsOrig, newEqOrig, newOderConstraintsOrig, a, fc, context, rekTiefe, new HashSet<>(methodSignatureConstraint));
typeUnifyTask.addChildTask(forkOrig);
CompletableFuture<Set<Set<UnifyPair>>> forkOrigFuture = CompletableFuture.supplyAsync(forkOrig::compute, context.executor()).thenCompose(f -> f);
CompletableFuture<ComputationResults> resultValues = forkOrigFuture.thenApply((currentThreadResult) -> {
resultValuesFuture = forkOrigFuture.thenApply((currentThreadResult) -> {
forkOrig.context.logger().debug("final Orig 2");
forkOrig.closeLogFile();
return new ComputationResults(currentThreadResult);
return new Tuple<>(currentThreadResult, new HashSet<>());
});
if (typeUnifyTask.isExecutionCancelled()) {
return resultValues;
if (typeUnifyTask.myIsCancelled()) {
throw new UnifyCancelException();
}
/* FORK ENDE */
@@ -91,22 +92,26 @@ public class InvarianceOrConstraintCase extends VarianceCase {
TypeUnify2Task fork = new TypeUnify2Task(newElems, newEq, newOderConstraints, nSaL, fc, context, rekTiefe, new HashSet<>(methodSignatureConstraintForParallel));
typeUnifyTask.addChildTask(fork);
CompletableFuture<Set<Set<UnifyPair>>> forkFuture = CompletableFuture.supplyAsync(fork::compute, context.executor()).thenCompose(f -> f);
resultValues = resultValues.thenCombine(forkFuture, (prevResults, fork_res) -> {
if (typeUnifyTask.isExecutionCancelled()) {
return prevResults;
resultValuesFuture = resultValuesFuture.thenCombine(forkFuture, (resultValues, fork_res) -> {
if (typeUnifyTask.myIsCancelled()) {
throw new UnifyCancelException();
}
prevResults.addForkResult(fork_res);
resultValues.getSecond().add(fork_res);
fork.context.logger().debug("final 2");
fork.closeLogFile();
return prevResults;
return resultValues;
});
if (typeUnifyTask.isExecutionCancelled()) {
return resultValues;
if (typeUnifyTask.myIsCancelled()) {
throw new UnifyCancelException();
}
}
return resultValues;
if (typeUnifyTask.myIsCancelled()) {
throw new UnifyCancelException();
}
return resultValuesFuture;
}
@Override

View File

@@ -5,9 +5,9 @@ import de.dhbwstuttgart.typeinference.unify.TypeUnifyTask;
import de.dhbwstuttgart.typeinference.unify.UnifyContext;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
import de.dhbwstuttgart.util.Logger;
import de.dhbwstuttgart.util.Tuple;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
@@ -17,11 +17,11 @@ public abstract class VarianceCase {
public static VarianceCase createFromVariance(int variance, boolean isOderConstraint, TypeUnifyTask typeUnifyTask, UnifyContext context) {
return switch (variance) {
case 0 -> new UnknownVarianceCase(isOderConstraint, typeUnifyTask, context);
case 1 -> new ContravarianceCase(isOderConstraint, typeUnifyTask, context);
case -1 -> new CovarianceCase(isOderConstraint, typeUnifyTask, context);
case 2 -> new InvarianceOrConstraintCase(isOderConstraint, typeUnifyTask, context);
default -> throw new RuntimeException("Invalid variance: " + variance);
case 0 -> new Variance0Case(isOderConstraint, typeUnifyTask, context);
case 1 -> new Variance1Case(isOderConstraint, typeUnifyTask, context);
case -1 -> new VarianceM1Case(isOderConstraint, typeUnifyTask, context);
case 2 -> new Variance2Case(isOderConstraint, typeUnifyTask, context);
default -> throw new RuntimeException("Invalid variance: " + variance);
};
}
@@ -72,7 +72,7 @@ public abstract class VarianceCase {
/**
*
*/
public abstract CompletableFuture<ComputationResults> computeParallel(
public abstract CompletableFuture<Tuple<Set<Set<UnifyPair>>, Set<Set<Set<UnifyPair>>>>> computeParallel(
Set<Set<UnifyPair>> elems,
Set<UnifyPair> eq,
List<Set<Constraint<UnifyPair>>> oderConstraints,
@@ -104,29 +104,4 @@ public abstract class VarianceCase {
Set<Set<UnifyPair>> aParDef,
List<Set<UnifyPair>> nextSetAsList
);
/**
* Wrapper class for the parallel computation results
*/
public static class ComputationResults {
public Set<Set<UnifyPair>> mainResult;
public Set<Set<Set<UnifyPair>>> forkResults;
public ComputationResults() {
this(new HashSet<>(), new HashSet<>());
}
public ComputationResults(Set<Set<UnifyPair>> mainResult) {
this(mainResult, new HashSet<>());
}
public ComputationResults(Set<Set<UnifyPair>> mainResult, Set<Set<Set<UnifyPair>>> forkResults) {
this.mainResult = mainResult;
this.forkResults = forkResults;
}
void addForkResult(Set<Set<UnifyPair>> forkResult) {
forkResults.add(forkResult);
}
}
}

View File

@@ -1,5 +1,6 @@
package de.dhbwstuttgart.typeinference.unify.cartesianproduct;
import de.dhbwstuttgart.exceptions.UnifyCancelException;
import de.dhbwstuttgart.typeinference.constraints.Constraint;
import de.dhbwstuttgart.typeinference.unify.TypeUnify2Task;
import de.dhbwstuttgart.typeinference.unify.TypeUnifyTask;
@@ -16,11 +17,11 @@ import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
public class CovarianceCase extends VarianceCase {
public class VarianceM1Case extends VarianceCase {
protected final int variance = -1;
protected CovarianceCase(boolean isOderConstraint, TypeUnifyTask typeUnifyTask, UnifyContext context) {
protected VarianceM1Case(boolean isOderConstraint, TypeUnifyTask typeUnifyTask, UnifyContext context) {
super(isOderConstraint, typeUnifyTask, context);
}
@@ -48,7 +49,7 @@ public class CovarianceCase extends VarianceCase {
@Override
public CompletableFuture<ComputationResults> computeParallel(
public CompletableFuture<Tuple<Set<Set<UnifyPair>>, Set<Set<Set<UnifyPair>>>>> computeParallel(
Set<Set<UnifyPair>> elems,
Set<UnifyPair> eq,
List<Set<Constraint<UnifyPair>>> oderConstraints,
@@ -60,6 +61,10 @@ public class CovarianceCase extends VarianceCase {
Set<Set<UnifyPair>> result,
Set<Set<UnifyPair>> aParDef
) {
CompletableFuture<Tuple<Set<Set<UnifyPair>>, Set<Set<Set<UnifyPair>>>>> resultValues = CompletableFuture.completedFuture(new Tuple<>(
new HashSet<>(), new HashSet<>()
));
Set<UnifyPair> newEqOrig = new HashSet<>(eq);
Set<Set<UnifyPair>> newElemsOrig = new HashSet<>(elems);
List<Set<Constraint<UnifyPair>>> newOderConstraintsOrig = new ArrayList<>(oderConstraints);
@@ -70,16 +75,16 @@ public class CovarianceCase extends VarianceCase {
typeUnifyTask.addChildTask(forkOrig);
// schedule compute() on another thread
CompletableFuture<Set<Set<UnifyPair>>> forkOrigFuture = CompletableFuture.supplyAsync(forkOrig::compute, context.executor()).thenCompose(f -> f);
CompletableFuture<ComputationResults> resultValues = forkOrigFuture.thenApply(
(currentThreadResult) -> {
resultValues = resultValues.thenCombine(forkOrigFuture,
(prevResults, currentThreadResult) -> {
forkOrig.context.logger().debug("final Orig -1");
forkOrig.closeLogFile();
return new ComputationResults(currentThreadResult);
return new Tuple<>(currentThreadResult, prevResults.getSecond());
});
//forks.add(forkOrig);
if (typeUnifyTask.isExecutionCancelled()) {
return resultValues;
if (typeUnifyTask.myIsCancelled()) {
throw new UnifyCancelException();
}
/* FORK ENDE */
@@ -110,12 +115,12 @@ public class CovarianceCase extends VarianceCase {
CompletableFuture<Set<Set<UnifyPair>>> forkFuture = CompletableFuture.supplyAsync(fork::compute, context.executor()).thenCompose(f -> f);
resultValues = resultValues.thenCombine(forkFuture,
(prevResults, fork_res) -> {
if (typeUnifyTask.isExecutionCancelled()) {
return prevResults;
if (typeUnifyTask.myIsCancelled()) {
throw new UnifyCancelException();
}
context.logger().debug(() -> "fork_res: " + fork_res.toString());
context.logger().debug(() -> Boolean.valueOf((typeUnifyTask.isUndefinedPairSetSet(fork_res))).toString());
prevResults.addForkResult(fork_res);
prevResults.getSecond().add(fork_res);
if (!typeUnifyTask.isUndefinedPairSetSet(fork_res)) {
aParDef.add(fork.getNextSetElement());
}
@@ -125,8 +130,8 @@ public class CovarianceCase extends VarianceCase {
}
);
if (typeUnifyTask.isExecutionCancelled()) {
return resultValues;
if (typeUnifyTask.myIsCancelled()) {
throw new UnifyCancelException();
}
}

View File

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

View File

@@ -170,66 +170,30 @@ public class OrderingUnifyPair extends OrderingExtend<Set<UnifyPair>> {
left.add(p2);
left.add(p4);
*/
Set<UnifyPair> lefteq = new HashSet<>();
Set<UnifyPair> leftle = new HashSet<>();
Set<UnifyPair> leftlewc = new HashSet<>();
Set<UnifyPair> lefteqOder = new HashSet<>();
Set<UnifyPair> lefteqRet = new HashSet<>();
Set<UnifyPair> leftleOder = new HashSet<>();
for (var x : left) {
boolean isLeftPlaceholder = x.getLhsType() instanceof PlaceholderType;
boolean isRightPlaceholder = x.getRhsType() instanceof PlaceholderType;
boolean hasPlaceholder = isLeftPlaceholder || isRightPlaceholder;
if (isLeftPlaceholder && x.getPairOp() == PairOperator.EQUALSDOT) lefteq.add(x);
if (hasPlaceholder && x.getPairOp() == PairOperator.SMALLERDOT) leftle.add(x);
if (hasPlaceholder && x.getPairOp() == PairOperator.SMALLERDOTWC) leftlewc.add(x);
UnifyPair y = x.getGroundBasePair();
boolean isBasePairLeftPlaceholder = y.getLhsType() instanceof PlaceholderType;
boolean isBasePairRightPlaceholder = y.getRhsType() instanceof PlaceholderType;
if (isBasePairLeftPlaceholder && !isBasePairRightPlaceholder && x.getPairOp() == PairOperator.EQUALSDOT) {
lefteqOder.add(x);
}
else if (isBasePairRightPlaceholder && ((PlaceholderType)y.getRhsType()).getOrCons() == (byte)-1) {
lefteqRet.add(x);
}
else if (x.getPairOp() == PairOperator.SMALLERDOT) {
leftleOder.add(x);
}
}
Set<UnifyPair> righteq = new HashSet<>();
Set<UnifyPair> rightle = new HashSet<>();
Set<UnifyPair> rightlewc = new HashSet<>();
Set<UnifyPair> righteqOder = new HashSet<>();
Set<UnifyPair> righteqRet = new HashSet<>();
Set<UnifyPair> rightleOder = new HashSet<>();
for (var x : right) {
boolean isLeftPlaceholder = x.getLhsType() instanceof PlaceholderType;
boolean isRightPlaceholder = x.getRhsType() instanceof PlaceholderType;
boolean hasPlaceholder = isLeftPlaceholder || isRightPlaceholder;
if (isLeftPlaceholder && x.getPairOp() == PairOperator.EQUALSDOT) righteq.add(x);
if (hasPlaceholder && x.getPairOp() == PairOperator.SMALLERDOT) rightle.add(x);
if (hasPlaceholder && x.getPairOp() == PairOperator.SMALLERDOTWC) rightlewc.add(x);
UnifyPair y = x.getGroundBasePair();
boolean isBasePairLeftPlaceholder = y.getLhsType() instanceof PlaceholderType;
boolean isBasePairRightPlaceholder = y.getRhsType() instanceof PlaceholderType;
if (isBasePairLeftPlaceholder && !isBasePairRightPlaceholder && x.getPairOp() == PairOperator.EQUALSDOT) {
righteqOder.add(x);
}
else if (isBasePairRightPlaceholder && ((PlaceholderType)y.getRhsType()).getOrCons() == (byte)-1) {
righteqRet.add(x);
}
else if (x.getPairOp() == PairOperator.SMALLERDOT) {
rightleOder.add(x);
}
}
Set<UnifyPair> lefteq = left.stream()
.filter(x -> (x.getLhsType() instanceof PlaceholderType && x.getPairOp() == PairOperator.EQUALSDOT))
.collect(Collectors.toCollection(HashSet::new));
Set<UnifyPair> righteq = right.stream()
.filter(x -> (x.getLhsType() instanceof PlaceholderType && x.getPairOp() == PairOperator.EQUALSDOT))
.collect(Collectors.toCollection(HashSet::new));
Set<UnifyPair> leftle = left.stream()
.filter(x -> ((x.getLhsType() instanceof PlaceholderType || x.getRhsType() instanceof PlaceholderType)
&& x.getPairOp() == PairOperator.SMALLERDOT))
.collect(Collectors.toCollection(HashSet::new));
Set<UnifyPair> rightle = right.stream()
.filter(x -> ((x.getLhsType() instanceof PlaceholderType || x.getRhsType() instanceof PlaceholderType)
&& x.getPairOp() == PairOperator.SMALLERDOT))
.collect(Collectors.toCollection(HashSet::new));
Set<UnifyPair> leftlewc = left.stream()
.filter(x -> ((x.getLhsType() instanceof PlaceholderType || x.getRhsType() instanceof PlaceholderType)
&& x.getPairOp() == PairOperator.SMALLERDOTWC))
.collect(Collectors.toCollection(HashSet::new));
Set<UnifyPair> rightlewc = right.stream()
.filter(x -> ((x.getLhsType() instanceof PlaceholderType || x.getRhsType() instanceof PlaceholderType)
&& x.getPairOp() == PairOperator.SMALLERDOTWC))
.collect(Collectors.toCollection(HashSet::new));
//context.logger().info(left.toString());
//Fall 2
//if (lefteq.iterator().next().getLhsType().getName().equals("AJO")) {
@@ -237,14 +201,54 @@ public class OrderingUnifyPair extends OrderingExtend<Set<UnifyPair>> {
//}
//ODER-CONSTRAINT
// Set<UnifyPair> leftBase = left.stream().map(x -> x.getGroundBasePair()).collect(Collectors.toCollection(HashSet::new));
// Set<UnifyPair> rightBase = right.stream().map(x -> x.getGroundBasePair()).collect(Collectors.toCollection(HashSet::new));
Set<UnifyPair> leftBase = left.stream().map(x -> x.getGroundBasePair()).collect(Collectors.toCollection(HashSet::new));
Set<UnifyPair> rightBase = right.stream().map(x -> x.getGroundBasePair()).collect(Collectors.toCollection(HashSet::new));
Set<UnifyPair> lefteqOder = left.stream()
.filter(x -> { UnifyPair y = x.getGroundBasePair();
/*try {
((FiniteClosure)fc).logFile.write("leftBase: " + leftBase.toString() +"\n");
((FiniteClosure)fc).logFile.write("rightBase: " + rightBase.toString() +"\n\n");
((FiniteClosure)fc).logFile.write("left: " + left.toString() +"\n");
((FiniteClosure)fc).logFile.write("right: " + right.toString() +"\n\n");
((FiniteClosure)fc).logFile.write("y: " + y.toString() +"\n");
((FiniteClosure)fc).logFile.write("y.getLhsType() : " + y.getLhsType() .toString() +"\n\n");
((FiniteClosure)fc).logFile.write("y.getRhsType(): " + y.getRhsType().toString() +"\n");
((FiniteClosure)fc).logFile.write("x.getPairOp(): " + x.getPairOp().toString() +"\n\n");
}
catch (IOException ie) {
} */
return (y.getLhsType() instanceof PlaceholderType &&
!(y.getRhsType() instanceof PlaceholderType) &&
x.getPairOp() == PairOperator.EQUALSDOT);})
.collect(Collectors.toCollection(HashSet::new));
left.removeAll(lefteqOder);
left.removeAll(lefteqRet);
Set<UnifyPair> righteqOder = right.stream()
.filter(x -> { UnifyPair y = x.getGroundBasePair();
return (y.getLhsType() instanceof PlaceholderType &&
!(y.getRhsType() instanceof PlaceholderType) &&
x.getPairOp() == PairOperator.EQUALSDOT);})
.collect(Collectors.toCollection(HashSet::new));
right.removeAll(righteqOder);
Set<UnifyPair> lefteqRet = left.stream()
.filter(x -> { UnifyPair y = x.getGroundBasePair();
return (y.getRhsType() instanceof PlaceholderType &&
((PlaceholderType)y.getRhsType()).getOrCons() == (byte)-1);})
.collect(Collectors.toCollection(HashSet::new));
left.removeAll(lefteqRet);
Set<UnifyPair> righteqRet = right.stream()
.filter(x -> { UnifyPair y = x.getGroundBasePair();
return (y.getRhsType() instanceof PlaceholderType &&
((PlaceholderType)y.getRhsType()).getOrCons() == (byte)-1);})
.collect(Collectors.toCollection(HashSet::new));
right.removeAll(righteqRet);
Set<UnifyPair> leftleOder = left.stream()
.filter(x -> (x.getPairOp() == PairOperator.SMALLERDOT))
.collect(Collectors.toCollection(HashSet::new));
Set<UnifyPair> rightleOder = right.stream()
.filter(x -> (x.getPairOp() == PairOperator.SMALLERDOT))
.collect(Collectors.toCollection(HashSet::new));
/*
synchronized(this) {
try {
@@ -269,43 +273,59 @@ public class OrderingUnifyPair extends OrderingExtend<Set<UnifyPair>> {
int compareEq;
if (lefteqOder.size() == 1 && righteqOder.size() == 1 && lefteqRet.size() == 1 && righteqRet.size() == 1) {
Match m = new Match();
compareEq = compareEq(lefteqOder.iterator().next().getGroundBasePair(), righteqOder.iterator().next().getGroundBasePair());
if (compareEq == -1) {
ArrayList<UnifyPair> matchList =
rightleOder.stream().map(x -> {
UnifyPair leftElem = leftleOder.stream()
if ((compareEq = compareEq(lefteqOder.iterator().next().getGroundBasePair(), righteqOder.iterator().next().getGroundBasePair())) == -1) {
ArrayList<UnifyPair> matchList =
rightleOder.stream().map(x -> {
UnifyPair leftElem = leftleOder.stream()
.filter(y -> y.getGroundBasePair().getLhsType().equals(x.getGroundBasePair().getLhsType()))
.findAny().orElseThrow();
return new UnifyPair(x.getRhsType(), leftElem.getRhsType(), PairOperator.EQUALSDOT);}
)
.collect(Collectors.toCollection(ArrayList::new));
return (m.match(matchList).isPresent()) ? -1 : 0;
.findAny().get();
return new UnifyPair(x.getRhsType(), leftElem.getRhsType(), PairOperator.EQUALSDOT);})
.collect(Collectors.toCollection(ArrayList::new));
if (m.match(matchList).isPresent()) {
//try { ((FiniteClosure)fc).logFile.write("result1: -1 \n\n"); } catch (IOException ie) {}
return -1;
}
else {
//try { ((FiniteClosure)fc).logFile.write("result1: 0 \n\n"); } catch (IOException ie) {}
return 0;
}
} else if (compareEq == 1) {
ArrayList<UnifyPair> matchList =
leftleOder.stream().map(x -> {
ArrayList<UnifyPair> matchList =
leftleOder.stream().map(x -> {
UnifyPair rightElem = rightleOder.stream()
.filter(y -> y.getGroundBasePair().getLhsType().equals(x.getGroundBasePair().getLhsType()))
.findAny().orElseThrow();
return new UnifyPair(x.getRhsType(), rightElem.getRhsType(), PairOperator.EQUALSDOT);}
)
.collect(Collectors.toCollection(ArrayList::new));
return (m.match(matchList).isPresent()) ? 1 : 0;
.filter(y ->
y.getGroundBasePair().getLhsType().equals(x.getGroundBasePair().getLhsType()))
.findAny().get();
return new UnifyPair(x.getRhsType(), rightElem.getRhsType(), PairOperator.EQUALSDOT);})
.collect(Collectors.toCollection(ArrayList::new));
if (m.match(matchList).isPresent()) {
//try { ((FiniteClosure)fc).logFile.write("result2: 1 \n\n"); } catch (IOException ie) {}
return 1;
}
else {
//try { ((FiniteClosure)fc).logFile.write("result2: 0 \n\n"); } catch (IOException ie) {}
return 0;
}
} else {
/*
((FiniteClosure)fc).logFile.write("leftBase: " + leftBase.toString() +"\n");
((FiniteClosure)fc).logFile.write("rightBase: " + rightBase.toString() +"\n\n");
((FiniteClosure)fc).logFile.write("left: " + left.toString() +"\n");
((FiniteClosure)fc).logFile.write("right: " + right.toString() +"\n\n");
((FiniteClosure)fc).logFile.write("lefteqOder: " + lefteqOder.toString() +"\n");
((FiniteClosure)fc).logFile.write("righteqOder: " + righteqOder.toString() +"\n\n");
((FiniteClosure)fc).logFile.write("lefteqRet: " + lefteqRet.toString() +"\n");
((FiniteClosure)fc).logFile.write("righteqRet: " + righteqRet.toString() +"\n\n");
((FiniteClosure)fc).logFile.write("leftleOder: " + leftleOder.toString() +"\n");
((FiniteClosure)fc).logFile.write("rightleOder: " + rightleOder.toString() +"\n\n");
((FiniteClosure)fc).logFile.write("result3: 0 \n\n");
((FiniteClosure)fc).logFile.flush();
synchronized(this) {
try {
((FiniteClosure)fc).logFile.write("leftBase: " + leftBase.toString() +"\n");
((FiniteClosure)fc).logFile.write("rightBase: " + rightBase.toString() +"\n\n");
((FiniteClosure)fc).logFile.write("left: " + left.toString() +"\n");
((FiniteClosure)fc).logFile.write("right: " + right.toString() +"\n\n");
((FiniteClosure)fc).logFile.write("lefteqOder: " + lefteqOder.toString() +"\n");
((FiniteClosure)fc).logFile.write("righteqOder: " + righteqOder.toString() +"\n\n");
((FiniteClosure)fc).logFile.write("lefteqRet: " + lefteqRet.toString() +"\n");
((FiniteClosure)fc).logFile.write("righteqRet: " + righteqRet.toString() +"\n\n");
((FiniteClosure)fc).logFile.write("leftleOder: " + leftleOder.toString() +"\n");
((FiniteClosure)fc).logFile.write("rightleOder: " + rightleOder.toString() +"\n\n");
((FiniteClosure)fc).logFile.write("result3: 0 \n\n");
((FiniteClosure)fc).logFile.flush();
}
catch (IOException ie) {
}
}
*/
return 0;
}
@@ -372,12 +392,12 @@ public class OrderingUnifyPair extends OrderingExtend<Set<UnifyPair>> {
//TODO: Hier wird bei Wildcards nicht das richtige compare aufgerufen PL 18-04-20
Pair<Integer, Set<UnifyPair>> int_Unifier = compare(lseq.getRhsType(), rseq.getRhsType());
Unifier uni = new Unifier();
int_Unifier.getValue().orElseThrow().forEach(x -> uni.add((PlaceholderType) x.getLhsType(), x.getRhsType()));
if (!lseq.getRhsType().getName().equals(rseq.getRhsType().getName())
int_Unifier.getValue().get().forEach(x -> uni.add((PlaceholderType) x.getLhsType(), x.getRhsType()));
if (!lseq.getRhsType().getName().equals(rseq.getRhsType().getName())
|| leftlewc.isEmpty() || rightlewc.isEmpty()) return int_Unifier.getKey();
else {
Set <UnifyPair> lsleuni = leftlewc.stream().map(uni::apply).collect(Collectors.toCollection(HashSet::new));
Set <UnifyPair> rsleuni = rightlewc.stream().map(uni::apply).collect(Collectors.toCollection(HashSet::new));
Set <UnifyPair> lsleuni = leftlewc.stream().map(x -> uni.apply(x)).collect(Collectors.toCollection(HashSet::new));
Set <UnifyPair> rsleuni = rightlewc.stream().map(x -> uni.apply(x)).collect(Collectors.toCollection(HashSet::new));
BinaryOperator<HashMap<UnifyType,UnifyPair>> combiner = (x,y) -> { x.putAll(y); return x;};
HashMap<UnifyType,UnifyPair> hm;
@@ -398,7 +418,6 @@ public class OrderingUnifyPair extends OrderingExtend<Set<UnifyPair>> {
}
} else {
if (!leftlewc.isEmpty()) {
/*
Set<UnifyPair> subst;
subst = leftlewc.stream().map(x -> {
if (x.getLhsType() instanceof PlaceholderType) {
@@ -407,7 +426,6 @@ public class OrderingUnifyPair extends OrderingExtend<Set<UnifyPair>> {
else {
return new UnifyPair(x.getRhsType(), x.getLhsType(), PairOperator.EQUALSDOT);
}}).collect(Collectors.toCollection(HashSet::new));
*/
Unifier uni = new Unifier();
lseq = uni.apply(lseq);
}

View File

@@ -2,14 +2,11 @@ package de.dhbwstuttgart.util;
import com.diogonunes.jcolor.Attribute;
import de.dhbwstuttgart.core.ConsoleInterface;
import de.dhbwstuttgart.server.SocketServer;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.nio.file.Path;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Objects;
import java.util.function.Supplier;
@@ -19,12 +16,11 @@ import static com.diogonunes.jcolor.Ansi.colorize;
public class Logger {
public static final Logger NULL_LOGGER = new NullLogger();
private static final DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
protected final Writer writer;
protected final String prefix;
public static Logger NULL_LOGGER = new NullLogger();
public Logger() {
this(null, "");
}
@@ -58,7 +54,7 @@ public class Logger {
/**
* Create a new logger object that inherits the writer of the given logger object
*
* @param logger The old logger object that will provide the writer
* @param logger The old logger object, that will provide the writer
* @return The new prefix for the new logger object
*/
public static Logger inherit(Logger logger, String newPrefix) {
@@ -73,11 +69,10 @@ public class Logger {
protected String getPrefix(LogLevel logLevel) {
String fullPrefix = prefix + "[" + logLevel + "] ";
return switch (logLevel) {
case DEBUG -> colorize(fullPrefix, Attribute.BRIGHT_MAGENTA_TEXT());
case INFO -> colorize(fullPrefix, Attribute.BLUE_TEXT());
case WARNING -> colorize(fullPrefix, Attribute.YELLOW_TEXT());
case ERROR -> colorize(fullPrefix, Attribute.RED_TEXT());
case SUCCESS -> colorize(fullPrefix, Attribute.GREEN_TEXT());
case DEBUG -> colorize(fullPrefix, Attribute.BRIGHT_MAGENTA_TEXT());
case INFO -> colorize(fullPrefix, Attribute.BLUE_TEXT());
case WARNING -> colorize(fullPrefix, Attribute.YELLOW_TEXT());
case ERROR -> colorize(fullPrefix, Attribute.RED_TEXT());
};
}
@@ -88,15 +83,7 @@ public class Logger {
*/
protected void print(String s, LogLevel logLevel) {
String coloredPrefix = this.getPrefix(logLevel);
// if we are running the server, prepend the timestamp
if(SocketServer.isServerRunning()) {
String timestamp = LocalDateTime.now().format(timeFormatter);
coloredPrefix = "[" + timestamp + "] " + coloredPrefix;
}
// output to the correct output-stream
if (logLevel.getValue() == LogLevel.ERROR.getValue()) {
if (logLevel.value > LogLevel.WARNING.value) {
System.out.println(coloredPrefix + s);
}
else {
@@ -105,11 +92,11 @@ public class Logger {
}
public boolean isLogLevelActive(LogLevel logLevel) {
return logLevel.isHigherOrEqualTo(ConsoleInterface.logLevel);
return logLevel.value >= ConsoleInterface.logLevel.value;
}
/**
* Write text to the attached writer if there is any
* Write text to the attached writer, if there is any
* @param s The string to print
*/
protected void write(String s) {
@@ -153,7 +140,7 @@ public class Logger {
/**
* Output a debug message
* Replaces the old FileWriter.write() call
* @param s The string to log
*/
public void debug(String s) {
@@ -167,7 +154,7 @@ public class Logger {
}
/**
* Output an info message
* Replaces the old System.out.println() call
* @param s The string to log
*/
public void info(String s) {
@@ -208,21 +195,6 @@ public class Logger {
this.log(supp, LogLevel.ERROR);
}
/**
* Output a success message
* @param s The string to log
*/
public void success(String s) {
this.log(s, LogLevel.SUCCESS);
}
public void success(Object o) {
this.log(o, LogLevel.SUCCESS);
}
public void success(Supplier<String> supp) {
this.log(supp, LogLevel.SUCCESS);
}
/**
* Special logging function that prints a throwable object and all of its recursive causes (including stacktrace)
* as an error
@@ -236,7 +208,7 @@ public class Logger {
" | " + stackTraceElement.toString()
).collect(Collectors.joining("\n"));
// if there is a cause printed afterward, announce it with the print of the exception
// if there will be a cause printed afterward, announce it with the print of the exception
if (throwable.getCause() != null) {
s += "\n\nCaused by: ";
}
@@ -263,50 +235,22 @@ public class Logger {
/**
* An enum representing the different log levels as integers:
* <ul>
* <li>DEBUG: highly specific output only for debugging</li>
* <li>INFO: informational output about the current state of the program</li>
* <li>WARNING: warnings about potential issues or an unexpected state</li>
* <li>ERROR: invalid states, errors and exceptions</li>
* <li>SUCCESS: successfully executed key steps of the program</li>
* </ul>
* An enum representing the different log levels as integers
*/
public enum LogLevel {
/** Highly specific output only for debugging */
// all the output
DEBUG(0),
/** Informational output about the current state of the program */
// a lot of info about the process
INFO(1),
/** Warnings about potential issues or an unexpected state **/
// warnings and up
WARNING(2),
/** Invalid states, errors and exceptions */
ERROR(3),
/** Successfully executed key steps of the program */
SUCCESS(4);
// only errors and exceptions
ERROR(3);
private final int value;
LogLevel(final int newValue) {
value = newValue;
}
public boolean isHigherOrEqualTo(LogLevel other) {
return this.value >= other.value;
}
public int getValue() {
return value;
}
public static LogLevel fromValue(int value) {
return switch (value) {
case 0 -> LogLevel.DEBUG;
case 1 -> LogLevel.INFO;
case 2 -> LogLevel.WARNING;
case 3 -> LogLevel.ERROR;
case 4 -> LogLevel.SUCCESS;
default -> throw new RuntimeException("Invalid log level value: " + value);
};
}
}
@@ -316,7 +260,7 @@ public class Logger {
private static class NullLogger extends Logger {
@Override
public void log(String s, LogLevel logLevel) {
// Do nothing. Yay
// do nothing. Yay
}
}
}

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

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