forked from i21017/JavaCompilerCore
Compare commits
16 Commits
c5c31bc372
...
1af31e4513
Author | SHA1 | Date | |
---|---|---|---|
|
1af31e4513 | ||
|
5b06f0a249 | ||
|
3d99f282f5 | ||
|
512b10542e | ||
|
3b1185d9d0 | ||
|
303c91dc87 | ||
|
603a8b176a | ||
|
f396189a4b | ||
|
e7f4a94908 | ||
|
ce49a4b9a5 | ||
|
03b3692724 | ||
|
f0022d2b6f | ||
|
b1015cfa82 | ||
|
b63a27a0a0 | ||
|
3b0a53d3c4 | ||
|
50dbbf5f86 |
@@ -9,7 +9,8 @@ mkdir $TDIR
|
||||
|
||||
cd $TDIR
|
||||
git clone $REPO .
|
||||
git checkout feat/unify-server-0variance
|
||||
git checkout feat/unify-server
|
||||
# git checkout 93e1a8787cd94c73f4538f6a348f58613893a584
|
||||
# git checkout dad468368b86bdd5a3d3b2754b17617cee0a9107 # 1:55
|
||||
# git checkout a0c11b60e8c9d7addcbe0d3a09c9ce2924e9d5c0 # 2:25
|
||||
# git checkout 4cddf73e6d6c9116d3e1705c4b27a8e7f18d80c3 # 2:27
|
||||
@@ -19,14 +20,14 @@ git checkout feat/unify-server-0variance
|
||||
# git checkout 1391206dfe59263cdb22f93371cfd1dd5465d97f # 1:29
|
||||
|
||||
date "+%Y.%m.%d %H:%M:%S"
|
||||
|
||||
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;
|
||||
# sed -i -e 's/source>21/source>23/g' pom.xml
|
||||
# sed -i -e 's/target>21/target>23/g' pom.xml
|
||||
|
||||
|
||||
mvn clean compile test
|
||||
mvn clean compile -DskipTests package
|
||||
time java -jar target/JavaTXcompiler-0.1-jar-with-dependencies.jar resources/bytecode/javFiles/Matrix.jav;
|
||||
|
||||
# mvn clean compile test
|
||||
|
||||
|
||||
echo -e "\nCleanup... "
|
||||
|
5
pom.xml
5
pom.xml
@@ -49,6 +49,11 @@ http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<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>
|
||||
|
51
resources/LaufzeitTests/DeeplyNested.jav
Normal file
51
resources/LaufzeitTests/DeeplyNested.jav
Normal file
@@ -0,0 +1,51 @@
|
||||
class C1 {
|
||||
C1 self() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
class C2 {
|
||||
C2 self() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
class Example {
|
||||
untypedMethod(var) {
|
||||
return var.self().self().self().self()
|
||||
.self().self().self().self()
|
||||
.self().self().self().self()
|
||||
.self().self().self().self()
|
||||
.self().self().self().self()
|
||||
.self().self().self().self()
|
||||
.self().self().self().self()
|
||||
.self().self().self().self()
|
||||
.self().self().self().self()
|
||||
.self().self().self().self()
|
||||
.self().self().self().self()
|
||||
.self().self().self().self()
|
||||
.self().self().self().self()
|
||||
.self().self().self().self()
|
||||
.self().self().self().self()
|
||||
.self().self().self().self()
|
||||
.self().self().self().self()
|
||||
.self().self().self().self()
|
||||
.self().self().self().self()
|
||||
.self().self().self().self()
|
||||
.self().self().self().self()
|
||||
.self().self().self().self()
|
||||
.self().self().self().self()
|
||||
.self().self().self().self()
|
||||
.self().self().self().self()
|
||||
.self().self().self().self()
|
||||
.self().self().self().self()
|
||||
.self().self().self().self()
|
||||
.self().self().self().self()
|
||||
.self().self().self().self()
|
||||
.self().self().self().self()
|
||||
.self().self().self().self()
|
||||
.self().self().self().self()
|
||||
.self().self().self().self()
|
||||
.self().self().self().self();
|
||||
}
|
||||
}
|
43
resources/LaufzeitTests/GridSearch.jav
Normal file
43
resources/LaufzeitTests/GridSearch.jav
Normal file
@@ -0,0 +1,43 @@
|
||||
import java.lang.Integer;
|
||||
import java.lang.Boolean;
|
||||
import java.util.Queue;
|
||||
import java.util.Vector;
|
||||
import java.util.List;
|
||||
import java.util.ArrayDeque;
|
||||
|
||||
class Pos {
|
||||
public Integer x;
|
||||
public Integer y;
|
||||
public Pos(Integer x, Integer y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
}
|
||||
|
||||
class GridSearch {
|
||||
|
||||
Pos search(Vector<Vector<Boolean>> grid) {
|
||||
var w = grid.size();
|
||||
var h = grid.getFirst().size();
|
||||
|
||||
// keep a queue on which cells to check
|
||||
var cellQueue = new ArrayDeque<Pos>();
|
||||
cellQueue.add(new Pos(0,0));
|
||||
|
||||
while (!cellQueue.isEmpty()) {
|
||||
var pos = cellQueue.poll();
|
||||
// if the target was found: return the position
|
||||
var value = grid.get(pos.x).get(pos.y);
|
||||
if (value) {
|
||||
return pos;
|
||||
}
|
||||
|
||||
// keep searching on neighboring tiles
|
||||
if (pos.x < w-1) cellQueue.add(new Pos(pos.x + 1, pos.y));
|
||||
if (pos.y < h-1) cellQueue.add(new Pos(pos.x, pos.y + 1));
|
||||
}
|
||||
|
||||
return (Pos)null;
|
||||
}
|
||||
|
||||
}
|
42
resources/LaufzeitTests/Mask.jav
Normal file
42
resources/LaufzeitTests/Mask.jav
Normal file
@@ -0,0 +1,42 @@
|
||||
import java.util.List;
|
||||
import java.util.AbstractList;
|
||||
import java.util.Vector;
|
||||
import java.lang.Integer;
|
||||
|
||||
class Pixel {
|
||||
public color;
|
||||
}
|
||||
|
||||
class Mask {
|
||||
|
||||
mask;
|
||||
|
||||
Mask(mask) {
|
||||
this.mask = mask;
|
||||
}
|
||||
|
||||
apply(pixels) {
|
||||
var w = mask.size();
|
||||
var h = mask.get(0).size();
|
||||
var imgW = pixels.size();
|
||||
var imgH = pixels.get(0).size();
|
||||
|
||||
for (var x = 0; x < imgW - w; x++) {
|
||||
for (var y = 0; y < imgH - h; y++) {
|
||||
|
||||
var total = 0;
|
||||
for (var xd = 0; xd < w; xd++) {
|
||||
for (var yd = 0; yd < h; yd++) {
|
||||
var p = pixels.get(x + xd).get(y + yd);
|
||||
var m = mask.get(xd).get(yd);
|
||||
total = total + (p.color * m);
|
||||
}
|
||||
}
|
||||
|
||||
pixels.get(x).get(y).color = total;
|
||||
}
|
||||
}
|
||||
|
||||
return pixels;
|
||||
}
|
||||
}
|
39
resources/LaufzeitTests/PascalsTriangle.jav
Normal file
39
resources/LaufzeitTests/PascalsTriangle.jav
Normal file
@@ -0,0 +1,39 @@
|
||||
import java.lang.Integer;
|
||||
import java.lang.Boolean;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class PascalsTriangle {
|
||||
|
||||
create(n) {
|
||||
var rows = new ArrayList<ArrayList<Integer>>();
|
||||
var evens = new ArrayList<ArrayList<Boolean>>();
|
||||
|
||||
if (n <= 0) return rows;
|
||||
// first row
|
||||
rows.add(new ArrayList<Integer>(1));
|
||||
evens.add(new ArrayList<Boolean>(false));
|
||||
|
||||
for (int y = 1; y < n; y++) {
|
||||
var row = new ArrayList<Integer>();
|
||||
var evensRow = new ArrayList<Boolean>();
|
||||
row.add(1);
|
||||
evensRow.add(false);
|
||||
|
||||
for (int x = 1; x < y-1; x++) {
|
||||
int tl = rows.getLast().get(x-1);
|
||||
int tr = rows.getLast().get(x);
|
||||
row.add(tl + tr);
|
||||
evensRow.add(((tl + tr) % 2) == 1);
|
||||
}
|
||||
|
||||
row.add(1);
|
||||
rows.add(row);
|
||||
evensRow.add(false);
|
||||
evens.add(evensRow);
|
||||
}
|
||||
|
||||
return rows;
|
||||
}
|
||||
|
||||
}
|
17
resources/bytecode/javFiles/Merge2.jav
Normal file
17
resources/bytecode/javFiles/Merge2.jav
Normal file
@@ -0,0 +1,17 @@
|
||||
import java.util.List;
|
||||
import java.lang.Integer;
|
||||
//import java.util.Collection;
|
||||
|
||||
public class Merge2 {
|
||||
|
||||
public merge(a, b) {
|
||||
a.addAll(b);
|
||||
return a;
|
||||
}
|
||||
|
||||
public sort(in){
|
||||
var firstHalf = in.subList(1,2);
|
||||
return merge(sort(firstHalf), sort(in));
|
||||
}
|
||||
|
||||
}
|
@@ -1,5 +1,6 @@
|
||||
package de.dhbwstuttgart.core;
|
||||
|
||||
import de.dhbwstuttgart.server.SocketClient;
|
||||
import de.dhbwstuttgart.util.Logger;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -7,8 +8,12 @@ import java.util.*;
|
||||
|
||||
public class ConsoleInterface {
|
||||
|
||||
/**
|
||||
* Leave the argument configurations here for the rest of the code to read
|
||||
*/
|
||||
public static Logger.LogLevel logLevel = Logger.LogLevel.ERROR;
|
||||
public static boolean writeLogFiles = false;
|
||||
public static Optional<String> unifyServerUrl = Optional.empty();
|
||||
|
||||
public static void main(String[] args) throws IOException, ClassNotFoundException {
|
||||
List<File> input = new ArrayList<>();
|
||||
@@ -16,7 +21,6 @@ public class ConsoleInterface {
|
||||
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");
|
||||
@@ -45,7 +49,7 @@ public class ConsoleInterface {
|
||||
} else if (arg.equals("--server-mode")) {
|
||||
serverPort = Optional.of(Integer.parseInt(it.next()));
|
||||
} else if (arg.equals("--unify-server")) {
|
||||
unifyServer = Optional.of(it.next());
|
||||
unifyServerUrl = Optional.of(it.next());
|
||||
} else if (arg.equals("--write-logs")) {
|
||||
ConsoleInterface.writeLogFiles = true;
|
||||
} else if (arg.startsWith("-v")) {
|
||||
@@ -61,15 +65,15 @@ public class ConsoleInterface {
|
||||
}
|
||||
|
||||
if (serverPort.isPresent()) {
|
||||
if (unifyServer.isPresent()) throw new RuntimeException("Cannot use unifyServer when in server mode!");
|
||||
|
||||
if (unifyServerUrl.isPresent()) throw new RuntimeException("Cannot use unifyServer when in server mode!");
|
||||
JavaTXServer server = new JavaTXServer(serverPort.get());
|
||||
server.listen();
|
||||
}
|
||||
else {
|
||||
JavaTXCompiler compiler = new JavaTXCompiler(input, classpath, outputPath != null ? new File(outputPath) : null, unifyServer);
|
||||
JavaTXCompiler compiler = new JavaTXCompiler(input, classpath, outputPath != null ? new File(outputPath) : null);
|
||||
//compiler.typeInference();
|
||||
compiler.generateBytecode();
|
||||
SocketClient.closeIfOpen();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -13,6 +13,10 @@ 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;
|
||||
@@ -20,6 +24,7 @@ import de.dhbwstuttgart.syntaxtree.ParameterList;
|
||||
import de.dhbwstuttgart.syntaxtree.SourceFile;
|
||||
import de.dhbwstuttgart.syntaxtree.GenericDeclarationList;
|
||||
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
|
||||
import de.dhbwstuttgart.syntaxtree.factory.NameGenerator;
|
||||
import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory;
|
||||
import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType;
|
||||
import de.dhbwstuttgart.syntaxtree.type.GenericRefType;
|
||||
@@ -81,29 +86,24 @@ public class JavaTXCompiler {
|
||||
public final List<File> classPath;
|
||||
private final File outputPath;
|
||||
|
||||
private final Optional<String> unifyServer;
|
||||
|
||||
public DirectoryClassLoader getClassLoader() {
|
||||
return classLoader;
|
||||
}
|
||||
|
||||
public JavaTXCompiler(File sourceFile) throws IOException, ClassNotFoundException {
|
||||
this(Arrays.asList(sourceFile), List.of(), new File("."), Optional.empty());
|
||||
this(Collections.singletonList(sourceFile), List.of(), new File("."));
|
||||
}
|
||||
|
||||
public JavaTXCompiler(List<File> sourceFiles) throws IOException, ClassNotFoundException {
|
||||
this(sourceFiles, List.of(), new File("."), Optional.empty());
|
||||
this(sourceFiles, List.of(), new File("."));
|
||||
}
|
||||
|
||||
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();
|
||||
NameGenerator.reset();
|
||||
ASTToTargetAST.OBJECT = ASTFactory.createObjectType();
|
||||
|
||||
this.unifyServer = unifyServer;
|
||||
var path = new ArrayList<>(contextPath);
|
||||
if (contextPath.isEmpty()) {
|
||||
// When no contextPaths are given, the working directory is the sources root
|
||||
@@ -425,11 +425,14 @@ public class JavaTXCompiler {
|
||||
* Set<Set<UnifyPair>> ret = new HashSet<>(); for (Constraint<UnifyPair> y : x) { ret.add(new HashSet<>(y)); } return ret; }).collect(Collectors.toCollection(ArrayList::new))
|
||||
*/;
|
||||
|
||||
if (unifyServer.isPresent()) {
|
||||
if (ConsoleInterface.unifyServerUrl.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);
|
||||
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 */
|
||||
@@ -669,7 +672,7 @@ public class JavaTXCompiler {
|
||||
output = new FileOutputStream(outputFile);
|
||||
output.write(bytecode);
|
||||
output.close();
|
||||
defaultLogger.info(name + ".class file generated");
|
||||
defaultLogger.success(name + ".class file generated");
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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();
|
||||
}
|
||||
|
||||
|
41
src/main/java/de/dhbwstuttgart/server/ServerTaskLogger.java
Normal file
41
src/main/java/de/dhbwstuttgart/server/ServerTaskLogger.java
Normal file
@@ -0,0 +1,41 @@
|
||||
package de.dhbwstuttgart.server;
|
||||
|
||||
import de.dhbwstuttgart.util.Logger;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import org.java_websocket.WebSocket;
|
||||
|
||||
public class ServerTaskLogger extends Logger {
|
||||
|
||||
private final WebSocket webSocket;
|
||||
private final SocketServer socketServer;
|
||||
private final LogLevel customLogLevel;
|
||||
|
||||
public ServerTaskLogger(WebSocket webSocket, SocketServer socketServer, LogLevel customLogLevel) {
|
||||
this.webSocket = webSocket;
|
||||
this.socketServer = socketServer;
|
||||
this.customLogLevel = customLogLevel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLogLevelActive(LogLevel logLevel) {
|
||||
return logLevel.isHigherOrEqualTo(customLogLevel);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void print(String s, LogLevel logLevel) {
|
||||
String coloredPrefix = this.getPrefix(logLevel);
|
||||
if (logLevel.isHigherOrEqualTo(LogLevel.ERROR)) {
|
||||
socketServer.sendError(webSocket, coloredPrefix + s, false);
|
||||
}
|
||||
else {
|
||||
socketServer.sendMessage(webSocket, coloredPrefix + s);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void write(String s) {
|
||||
// under no circumstances write anything to a file
|
||||
}
|
||||
|
||||
}
|
@@ -1,6 +1,8 @@
|
||||
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;
|
||||
@@ -14,8 +16,10 @@ 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;
|
||||
@@ -31,43 +35,31 @@ public class SocketClient extends WebSocketClient {
|
||||
|
||||
public static Logger logger = new Logger("SocketClient");
|
||||
|
||||
// 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;
|
||||
/**
|
||||
* The singleton object
|
||||
*/
|
||||
private static SocketClient socketClient = null;
|
||||
|
||||
public SocketClient(String url) {
|
||||
/**
|
||||
* List of futures that are still waiting to be fulfilled
|
||||
*/
|
||||
private final Map<String, SocketFuture<?>> responseFutures = new HashMap<>();
|
||||
|
||||
private SocketClient(String url) {
|
||||
super(
|
||||
URI.create(url), // target url
|
||||
SocketServer.perMessageDeflateDraft, // enable compression
|
||||
//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
|
||||
@@ -76,60 +68,108 @@ public class SocketClient extends WebSocketClient {
|
||||
if (this.getReadyState() != ReadyState.OPEN) {
|
||||
throw new RuntimeException("WebSocket Client could not connect to remote host at " + this.uri);
|
||||
}
|
||||
|
||||
// send the unify task request
|
||||
UnifyRequestPacket packet = new UnifyRequestPacket(finiteClosure, constraintSet, unifyConstraintSet, context.placeholderRegistry());
|
||||
String json = PacketContainer.serialize(packet);
|
||||
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);
|
||||
throw new RuntimeException(exception);
|
||||
}
|
||||
|
||||
// add a shutdown hook to close the connection when the process ends or is stopped by a SIGINT signal
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(this::close));
|
||||
}
|
||||
|
||||
private SocketClient(String host, int port, boolean secure) throws InterruptedException {
|
||||
this(String.format("%s://%s:%d/", secure ? "wss" : "ws", host, port));
|
||||
}
|
||||
|
||||
/**
|
||||
* Singleton access method, creates one if none is available
|
||||
*
|
||||
* @return The one and only socketClient
|
||||
*/
|
||||
private static SocketClient initializeClient() {
|
||||
if (socketClient == null) {
|
||||
socketClient = new SocketClient(ConsoleInterface.unifyServerUrl.get());
|
||||
}
|
||||
return socketClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a packet to the server (connection will be created, if none is found) and return a future
|
||||
* for the response packet
|
||||
*/
|
||||
synchronized public static <T extends IServerToClientPacket> SocketFuture<T> execute(IClientToServerPacket<T> packet) {
|
||||
SocketClient client = initializeClient();
|
||||
|
||||
/*
|
||||
* Create a future that will be associated with the packet and eventually completed
|
||||
*/
|
||||
SocketFuture<T> future = packet.getFuture();
|
||||
if (!future.isDone()) {
|
||||
client.responseFutures.put(future.futureId, future);
|
||||
}
|
||||
|
||||
/*
|
||||
* Establish connection, if not already done.
|
||||
* Serialize the packet and send it to the server.
|
||||
* Return the future to be handled by the caller.
|
||||
*/
|
||||
try {
|
||||
String json = PacketContainer.serialize(packet);
|
||||
client.send(json);
|
||||
} catch (Exception exception) {
|
||||
logger.exception(exception);
|
||||
throw new RuntimeException("Exception occurred in server connection: ", exception);
|
||||
}
|
||||
|
||||
// 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");
|
||||
}
|
||||
return future;
|
||||
}
|
||||
|
||||
return unifyResultPacket.getResultSet(context);
|
||||
/**
|
||||
* Shortcut for waiting and retrieving the response immediately
|
||||
*
|
||||
* @param packet The packet to send
|
||||
* @param <T> The type of response packet to await
|
||||
* @return The response packet, once it is received
|
||||
*/
|
||||
public static <T extends IServerToClientPacket> T executeAndGet(IClientToServerPacket<T> packet) {
|
||||
return SocketClient.execute(packet).get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Specific client-side implementations to handle incoming packets
|
||||
*/
|
||||
protected void handleReceivedPacket(IPacket packet) {
|
||||
if (packet instanceof IServerToClientPacket serverToClientPacket) {
|
||||
|
||||
try {
|
||||
serverToClientPacket.onHandle(this.getConnection(), this);
|
||||
} catch (Exception exception) {
|
||||
this.closeLatch.countDown();
|
||||
this.close();
|
||||
throw exception;
|
||||
}
|
||||
|
||||
if (!(packet instanceof IServerToClientPacket serverToClientPacket)) {
|
||||
System.err.println("Received package of invalid type + " + packet.getClass().getName());
|
||||
this.close();
|
||||
return;
|
||||
}
|
||||
|
||||
System.err.println("Received package of invalid type + " + packet.getClass().getName());
|
||||
this.close();
|
||||
serverToClientPacket.onHandle(this.getConnection(), this);
|
||||
}
|
||||
|
||||
public void setUnifyResultSets(UnifyResultPacket unifyResultPacket) {
|
||||
this.unifyResultPacket = unifyResultPacket;
|
||||
/**
|
||||
* Complete a registered future, so it can be handled by whoever executed the creator task
|
||||
*
|
||||
* @param id The associated id for this future
|
||||
* @param trigger The object triggering the completion
|
||||
*/
|
||||
public void completeResponseFuture(String id, IServerToClientPacket trigger) {
|
||||
SocketFuture<?> future = this.responseFutures.remove(id);
|
||||
if (future == null) return;
|
||||
if (!future.accept(trigger)) {
|
||||
throw new RuntimeException("Packet " + trigger.getClass().getName() + " tried to complete future, but was not allowed to");
|
||||
}
|
||||
}
|
||||
|
||||
public static void closeIfOpen() {
|
||||
if (socketClient != null && socketClient.isOpen()) {
|
||||
socketClient.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOpen(ServerHandshake handshakedata) {
|
||||
logger.info("Connected to server with status " + handshakedata.getHttpStatus());
|
||||
logger.success("Connected to server with status " + handshakedata.getHttpStatus());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -147,16 +187,16 @@ public class SocketClient extends WebSocketClient {
|
||||
(reason.isEmpty() ? "" : "and reason " + reason + " ") +
|
||||
"(closed by remote: " + remote + ")"
|
||||
);
|
||||
this.closeLatch.countDown();
|
||||
|
||||
if (!this.responseFutures.isEmpty()) {
|
||||
throw new RuntimeException("Server closed before all required tasks were answered");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Exception e) {
|
||||
logger.error("Error: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
logger.exception(e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
public void waitUntilClosed() throws InterruptedException {
|
||||
closeLatch.await();
|
||||
}
|
||||
}
|
||||
|
48
src/main/java/de/dhbwstuttgart/server/SocketFuture.java
Normal file
48
src/main/java/de/dhbwstuttgart/server/SocketFuture.java
Normal file
@@ -0,0 +1,48 @@
|
||||
package de.dhbwstuttgart.server;
|
||||
|
||||
import de.dhbwstuttgart.server.packet.IServerToClientPacket;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
public class SocketFuture<T extends IServerToClientPacket> extends CompletableFuture<T> {
|
||||
|
||||
public final String futureId = UUID.randomUUID().toString();
|
||||
|
||||
public final List<Class<T>> allowedTriggers;
|
||||
|
||||
public SocketFuture(List<Class<T>> allowedTriggers) {
|
||||
this.allowedTriggers = allowedTriggers;
|
||||
}
|
||||
|
||||
public boolean accept(IServerToClientPacket trigger) {
|
||||
if (this.allowedTriggers.contains(trigger.getClass())) {
|
||||
this.complete((T)trigger);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get() {
|
||||
try {
|
||||
return super.get();
|
||||
}
|
||||
catch (InterruptedException | ExecutionException exception) {
|
||||
throw new RuntimeException(exception);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Special case where the future is immediately fulfilled without a response package similar to
|
||||
* <code>CompletableFuture.completedFuture()</code> but without a value
|
||||
*/
|
||||
public static <R extends IServerToClientPacket> SocketFuture<R> completedFuture() {
|
||||
SocketFuture<R> dummyFuture = new SocketFuture<>(new ArrayList<>(0));
|
||||
dummyFuture.complete(null);
|
||||
return dummyFuture;
|
||||
}
|
||||
|
||||
}
|
@@ -1,7 +1,6 @@
|
||||
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;
|
||||
@@ -10,11 +9,13 @@ 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;
|
||||
@@ -22,67 +23,83 @@ 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 server version and client version do not match.
|
||||
* This will prevent errors when the server version and client version do not match.
|
||||
*/
|
||||
public static final String packetProtocolVersion = "1";
|
||||
|
||||
/**
|
||||
* Draft object for enabling the perMessageDeflate extension for more packet compression
|
||||
*/
|
||||
public static final Draft perMessageDeflateDraft = new Draft_6455(new PerMessageDeflateExtension());
|
||||
// create an executor for tasks that will always keep at least one task around
|
||||
private final ThreadPoolExecutor taskExecutor = new ThreadPoolExecutor(1, Integer.MAX_VALUE,60L, TimeUnit.SECONDS, new SynchronousQueue<>());
|
||||
// create an executor for scheduling timeouts
|
||||
private final ScheduledExecutorService timeoutExecutor = Executors.newSingleThreadScheduledExecutor();
|
||||
|
||||
public SocketServer(int port) {
|
||||
super(new InetSocketAddress(port), Collections.singletonList(perMessageDeflateDraft));
|
||||
super(new InetSocketAddress(port));
|
||||
this.setConnectionLostTimeout(30);
|
||||
|
||||
serverRunning = true;
|
||||
// add a shutdown hook to close all connections when the process ends or is stopped by a SIGINT signal
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(this::onShutdown));
|
||||
}
|
||||
|
||||
public static boolean isServerRunning() {
|
||||
return serverRunning;
|
||||
}
|
||||
|
||||
private void onShutdown() {
|
||||
serverRunning = false;
|
||||
try {
|
||||
for (var webSocket : this.getConnections()) {
|
||||
this.sendError(webSocket, "Sorry, i am shutting down. You are now on your own, good Luck!", true);
|
||||
webSocket.close();
|
||||
}
|
||||
this.stop();
|
||||
taskExecutor.shutdown();
|
||||
timeoutExecutor.shutdown();
|
||||
} catch (InterruptedException exception) {
|
||||
// we are shutting down anyway
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOpen(WebSocket webSocket, ClientHandshake clientHandshake) {
|
||||
String ppv = clientHandshake.getFieldValue("packetProtocolVersion");
|
||||
if (!ppv.equals(packetProtocolVersion)) {
|
||||
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);
|
||||
}
|
||||
this.sendError(webSocket,
|
||||
"Mismatch in packet protocol version! Client (you): \"" + ppv + "\" and Server (me): \"" + packetProtocolVersion + "\"",
|
||||
true
|
||||
);
|
||||
webSocket.close(1);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SocketData socketData = new SocketData(UUID.randomUUID().toString());
|
||||
webSocket.setAttachment(socketData);
|
||||
SocketData socketData = new SocketData(webSocket);
|
||||
logger.info("New connection: " + socketData.id + " (with ppv " + ppv + ")");
|
||||
|
||||
try {
|
||||
sendMessage(webSocket, "Welcome to the server!");
|
||||
|
||||
// wait 10 seconds for the client to send a task and close the connection if nothing has been received until then
|
||||
try (ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor()) {
|
||||
Runnable task = () -> {
|
||||
if (webSocket.<SocketData>getAttachment().unhandledTasks.get() == 0 || !webSocket.isOpen()) {
|
||||
final int secondsUntilTimeout = 10;
|
||||
timeoutExecutor.schedule(() -> {
|
||||
if (webSocket.<SocketData>getAttachment().totalTasks.get() > 0 || !webSocket.isOpen()) {
|
||||
return;
|
||||
}
|
||||
sendMessage(webSocket, "No task received after 10 seconds. Closing connection...");
|
||||
sendMessage(webSocket, "No task received after " + secondsUntilTimeout + " seconds. Closing connection...");
|
||||
webSocket.close();
|
||||
};
|
||||
executor.schedule(task, 10, TimeUnit.SECONDS);
|
||||
executor.shutdown();
|
||||
}
|
||||
},
|
||||
secondsUntilTimeout,
|
||||
TimeUnit.SECONDS
|
||||
);
|
||||
|
||||
// and finally, when your program wants to exit
|
||||
} catch (Exception e) {
|
||||
@@ -112,20 +129,22 @@ public class SocketServer extends WebSocketServer {
|
||||
this.onPacketReceived(webSocket, reconstructedPacket);
|
||||
} catch (JsonProcessingException e) {
|
||||
logger.exception(e);
|
||||
this.log("Error on processing incoming package: " + e.getMessage(), webSocket);
|
||||
this.log(webSocket, "Error on processing incoming package: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(WebSocket webSocket, Exception e) {
|
||||
if (webSocket != null) {
|
||||
log(webSocket, e.getMessage());
|
||||
webSocket.close();
|
||||
}
|
||||
logger.exception(e);
|
||||
log(e.getMessage(), webSocket);
|
||||
webSocket.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
logger.info("Websocket server started on port " + this.getPort());
|
||||
logger.success("Websocket server started on port " + this.getPort());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -133,8 +152,7 @@ public class SocketServer extends WebSocketServer {
|
||||
*/
|
||||
public void sendMessage(WebSocket webSocket, String text) {
|
||||
try {
|
||||
MessagePacket message = new MessagePacket();
|
||||
message.message = text;
|
||||
MessagePacket message = MessagePacket.create(text);
|
||||
webSocket.send(PacketContainer.serialize(message));
|
||||
} catch (Exception e) {
|
||||
System.err.println("Failed to send message: " + text);
|
||||
@@ -145,33 +163,31 @@ public class SocketServer extends WebSocketServer {
|
||||
/**
|
||||
* A shorthand method for sending error messages to the client
|
||||
*/
|
||||
public void sendError(WebSocket webSocket, String text) {
|
||||
public void sendError(WebSocket webSocket, String text, boolean isFatal) {
|
||||
try {
|
||||
ErrorPacket error = new ErrorPacket();
|
||||
error.error = text;
|
||||
ErrorPacket error = ErrorPacket.create(text, isFatal);
|
||||
webSocket.send(PacketContainer.serialize(error));
|
||||
} catch (Exception e) {
|
||||
logger.exception(e);
|
||||
log("Failed to send error: " + text, webSocket);
|
||||
log(webSocket, "Failed to send error: " + text);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 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");
|
||||
// limit the number of tasks per connection
|
||||
if (socketData.totalTasks.get() >= maxTasksPerSession) {
|
||||
sendError(webSocket, "Exceeded the maximum amount of " + maxTasksPerSession + " tasks per session", true);
|
||||
webSocket.close();
|
||||
return;
|
||||
}
|
||||
|
||||
// only allow packets, that are meant to be handled by the server
|
||||
if (!(packet instanceof IClientToServerPacket clientToServerPacket)) {
|
||||
// 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;
|
||||
}
|
||||
@@ -180,22 +196,24 @@ 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);
|
||||
|
||||
// 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();
|
||||
|
||||
if (socketData.closeIfNoTasksLeft) {
|
||||
// if the websocket has 0 unhandled Tasks, close the connection
|
||||
if (remainingUnhandledTasks <= 0) {
|
||||
sendMessage(webSocket, "All requested tasks finished! Closing connection...");
|
||||
webSocket.close();
|
||||
}
|
||||
}
|
||||
});
|
||||
}, taskExecutor);
|
||||
}
|
||||
|
||||
public void log(String msg, WebSocket webSocket) {
|
||||
SocketData socketData = webSocket == null ? new SocketData("???") : webSocket.getAttachment();
|
||||
logger.info("["+socketData.id+"] " + msg);
|
||||
public void log(WebSocket webSocket, String msg) {
|
||||
String socketId = (webSocket == null) ? "???" : webSocket.<SocketData>getAttachment().id;
|
||||
logger.info("[" + socketId + "] " + msg);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -207,9 +225,11 @@ 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(String id) {
|
||||
this.id = id;
|
||||
public SocketData(WebSocket webSocket) {
|
||||
this.id = UUID.randomUUID().toString();
|
||||
webSocket.setAttachment(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -2,6 +2,7 @@ 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;
|
||||
@@ -10,7 +11,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, IServerToClientPacket {
|
||||
public class DebugPacket implements IClientToServerPacket.Void, IServerToClientPacket {
|
||||
|
||||
public SerialUUID a1;
|
||||
public SerialUUID a2;
|
||||
@@ -22,9 +23,13 @@ public class DebugPacket implements IClientToServerPacket, IServerToClientPacket
|
||||
public SerialValue<?> d2;
|
||||
|
||||
@JsonIgnore
|
||||
public void onHandle(WebSocket webSocket, SocketClient socketServer) {}
|
||||
public void onHandle(WebSocket webSocket, SocketClient socketClient) {}
|
||||
|
||||
@JsonIgnore
|
||||
public void onHandle(WebSocket webSocket, SocketServer socketServer) {}
|
||||
|
||||
@JsonIgnore
|
||||
public SocketFuture<IServerToClientPacket> getFuture() {
|
||||
return SocketFuture.completedFuture();
|
||||
}
|
||||
}
|
||||
|
@@ -2,16 +2,17 @@ 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 IClientToServerPacket, IServerToClientPacket {
|
||||
public class ErrorPacket implements IServerToClientPacket {
|
||||
|
||||
/**
|
||||
* The error endpoint for messages from the server, that should be logged out outputted
|
||||
* The error endpoint for messages from the server that should be logged out as errors and possibly abort the process
|
||||
*/
|
||||
public String error;
|
||||
public boolean isFatal;
|
||||
@@ -27,15 +28,9 @@ public class ErrorPacket implements IClientToServerPacket, IServerToClientPacket
|
||||
|
||||
@JsonIgnore
|
||||
public void onHandle(WebSocket webSocket, SocketClient socketClient) {
|
||||
SocketClient.logger.error("SocketError: " + this.error);
|
||||
SocketClient.logger.exception(new RuntimeException(this.error));
|
||||
if (this.isFatal) {
|
||||
throw new RuntimeException("Received fatal error from server: " + this.error);
|
||||
socketClient.close(1, "Received fatal error from server");
|
||||
}
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public void onHandle(WebSocket webSocket, SocketServer socketServer) {
|
||||
socketServer.log("SocketError: " + this.error, webSocket);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,12 +1,26 @@
|
||||
package de.dhbwstuttgart.server.packet;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import de.dhbwstuttgart.server.SocketFuture;
|
||||
import de.dhbwstuttgart.server.SocketServer;
|
||||
import org.java_websocket.WebSocket;
|
||||
|
||||
public interface IClientToServerPacket extends IPacket {
|
||||
/**
|
||||
* A packet that will be sent to the server. Use <code>Void</code> Sub-Interface for packets without response
|
||||
*
|
||||
* @param <T> The response packet that will fulfill the future.
|
||||
*/
|
||||
public interface IClientToServerPacket<T extends IServerToClientPacket> extends IPacket {
|
||||
|
||||
@JsonIgnore
|
||||
void onHandle(WebSocket webSocket, SocketServer socketServer);
|
||||
|
||||
@JsonIgnore
|
||||
SocketFuture<T> getFuture();
|
||||
|
||||
/**
|
||||
* Special case, where the packet will remain unanswered by the server
|
||||
*/
|
||||
interface Void extends IClientToServerPacket<IServerToClientPacket> {}
|
||||
}
|
||||
|
||||
|
@@ -2,13 +2,14 @@ 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, IServerToClientPacket {
|
||||
public class InvalidPacket implements IClientToServerPacket.Void, IServerToClientPacket {
|
||||
|
||||
/**
|
||||
* If available, the error that caused this package to appear
|
||||
@@ -18,12 +19,17 @@ public class InvalidPacket implements IClientToServerPacket, IServerToClientPack
|
||||
|
||||
@JsonIgnore
|
||||
public void onHandle(WebSocket webSocket, SocketClient socketClient) {
|
||||
System.err.println("[socket] " + "InvalidPacket: " + this.error);
|
||||
SocketClient.logger.error("InvalidPacket: " + this.error);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public void onHandle(WebSocket webSocket, SocketServer socketServer) {
|
||||
socketServer.log("InvalidPacket: " + this.error, webSocket);
|
||||
socketServer.log(webSocket, "InvalidPacket: " + this.error);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public SocketFuture<IServerToClientPacket> getFuture() {
|
||||
return SocketFuture.completedFuture();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -2,16 +2,17 @@ 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, IServerToClientPacket {
|
||||
public class MessagePacket implements IClientToServerPacket.Void, 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;
|
||||
|
||||
@@ -29,7 +30,11 @@ public class MessagePacket implements IClientToServerPacket, IServerToClientPack
|
||||
|
||||
@JsonIgnore
|
||||
public void onHandle(WebSocket webSocket, SocketServer socketServer) {
|
||||
socketServer.log(this.message, webSocket);
|
||||
socketServer.log(webSocket, this.message);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public SocketFuture<IServerToClientPacket> getFuture() {
|
||||
return SocketFuture.completedFuture();
|
||||
}
|
||||
}
|
||||
|
@@ -25,13 +25,14 @@ 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);
|
||||
@@ -47,7 +48,11 @@ 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);
|
||||
}
|
||||
@@ -76,6 +81,8 @@ 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");
|
||||
|
@@ -0,0 +1,32 @@
|
||||
package de.dhbwstuttgart.server.packet;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import de.dhbwstuttgart.server.SocketClient;
|
||||
import de.dhbwstuttgart.server.SocketFuture;
|
||||
import de.dhbwstuttgart.server.SocketServer;
|
||||
import org.java_websocket.WebSocket;
|
||||
|
||||
/**
|
||||
* Normally, a connection stays open until either the client or the server process ends.
|
||||
* Send this packet to inform the server that the connection can be closed once all tasks are done
|
||||
*/
|
||||
public class SetAutoclosePacket implements IClientToServerPacket.Void {
|
||||
|
||||
public int dummyProperty = 1;
|
||||
|
||||
@JsonIgnore
|
||||
public static SetAutoclosePacket create() {
|
||||
return new SetAutoclosePacket();
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public void onHandle(WebSocket webSocket, SocketServer socketServer) {
|
||||
webSocket.<SocketServer.SocketData>getAttachment().closeIfNoTasksLeft = true;
|
||||
socketServer.log(webSocket, "Marked connection as autoclose");
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public SocketFuture<IServerToClientPacket> getFuture() {
|
||||
return SocketFuture.completedFuture();
|
||||
}
|
||||
}
|
@@ -1,6 +1,9 @@
|
||||
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;
|
||||
@@ -20,18 +23,16 @@ 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 {
|
||||
public class UnifyRequestPacket implements IClientToServerPacket<UnifyResultPacket> {
|
||||
|
||||
public SerialMap finiteClosure;
|
||||
public SerialMap constraintSet;
|
||||
@@ -39,30 +40,33 @@ public class UnifyRequestPacket implements IClientToServerPacket {
|
||||
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 UnifyRequestPacket() {}
|
||||
|
||||
public UnifyRequestPacket(
|
||||
public static UnifyRequestPacket create(
|
||||
FiniteClosure finiteClosure,
|
||||
ConstraintSet<Pair> constraintSet,
|
||||
ConstraintSet<UnifyPair> unifyConstraintSet,
|
||||
PlaceholderRegistry placeholderRegistry
|
||||
) {
|
||||
// store contraint and finite closure
|
||||
this.finiteClosure = finiteClosure.toSerial(keyStorage);
|
||||
this.constraintSet = constraintSet.toSerial(keyStorage);
|
||||
this.unifyConstraintSet = unifyConstraintSet.toSerial(keyStorage);
|
||||
UnifyRequestPacket packet = new UnifyRequestPacket();
|
||||
// store constraint and finite closure
|
||||
packet.finiteClosure = finiteClosure.toSerial(packet.keyStorage);
|
||||
packet.constraintSet = constraintSet.toSerial(packet.keyStorage);
|
||||
packet.unifyConstraintSet = unifyConstraintSet.toSerial(packet.keyStorage);
|
||||
// store placeholder registry
|
||||
var serialRegistry = placeholderRegistry.toSerial(keyStorage);
|
||||
this.placeholders = serialRegistry.getValue("ph");
|
||||
this.factoryplaceholders = serialRegistry.getList("factoryPh").assertListOfMaps();
|
||||
var serialRegistry = placeholderRegistry.toSerial(packet.keyStorage);
|
||||
packet.placeholders = serialRegistry.getValue("ph");
|
||||
packet.factoryplaceholders = serialRegistry.getList("factoryPh").assertListOfMaps();
|
||||
// store referenced objects separately
|
||||
this.serialKeyStorage = keyStorage.toSerial(keyStorage);
|
||||
packet.serialKeyStorage = packet.keyStorage.toSerial(packet.keyStorage);
|
||||
packet.logLevel = ConsoleInterface.logLevel.getValue();
|
||||
return packet;
|
||||
}
|
||||
|
||||
|
||||
@@ -95,15 +99,22 @@ public class UnifyRequestPacket implements IClientToServerPacket {
|
||||
@JsonIgnore
|
||||
public void onHandle(WebSocket webSocket, SocketServer socketServer) {
|
||||
socketServer.sendMessage(webSocket, "You requested a unify! Please wait until I calculated everything...");
|
||||
SocketServer.logger.info("Client " + webSocket.<SocketServer.SocketData>getAttachment().id + " requested a unification. Starting now...");
|
||||
socketServer.log(webSocket, "Client requested a unification. Starting now...");
|
||||
|
||||
try {
|
||||
var placeholderRegistry = new PlaceholderRegistry();
|
||||
ArrayList<String> existingPlaceholders = (ArrayList) this.placeholders.getOf(ArrayList.class);
|
||||
existingPlaceholders.forEach(placeholderRegistry::addPlaceholder);
|
||||
|
||||
var unifyContext = new UnifyContext(Logger.NULL_LOGGER, true,
|
||||
new UnifyResultModel(new ConstraintSet<>(), new FiniteClosure(new HashSet<>(), Logger.NULL_LOGGER, placeholderRegistry)),
|
||||
Logger logger = new ServerTaskLogger(
|
||||
webSocket,
|
||||
socketServer,
|
||||
Logger.LogLevel.fromValue(
|
||||
Math.max(this.logLevel, Logger.LogLevel.INFO.getValue())
|
||||
)
|
||||
);
|
||||
var unifyContext = new UnifyContext(logger, true,
|
||||
new UnifyResultModel(new ConstraintSet<>(), new FiniteClosure(new HashSet<>(), logger, placeholderRegistry)),
|
||||
new UnifyTaskModel(), ForkJoinPool.commonPool(), placeholderRegistry
|
||||
);
|
||||
|
||||
@@ -130,17 +141,24 @@ public class UnifyRequestPacket implements IClientToServerPacket {
|
||||
|
||||
var resultSets = resultListener.getResults();
|
||||
|
||||
SocketServer.logger.info("Finished unification for client " + webSocket.<SocketServer.SocketData>getAttachment().id);
|
||||
socketServer.log(webSocket, "Finished unification");
|
||||
socketServer.sendMessage(webSocket, "Unification finished. Found " + resultSets.size() + " result sets");
|
||||
|
||||
if (webSocket.isOpen()) {
|
||||
UnifyResultPacket resultPacket = UnifyResultPacket.create(resultSets);
|
||||
UnifyResultPacket resultPacket = UnifyResultPacket.create(resultSets, futureId);
|
||||
webSocket.send(PacketContainer.serialize(resultPacket));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
SocketServer.logger.exception(e);
|
||||
socketServer.log(e.getMessage(), webSocket);
|
||||
socketServer.log(webSocket, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public SocketFuture<UnifyResultPacket> getFuture() {
|
||||
var future = new SocketFuture<>(List.of(UnifyResultPacket.class));
|
||||
futureId = future.futureId;
|
||||
return future;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -18,12 +18,14 @@ public class UnifyResultPacket implements IServerToClientPacket {
|
||||
|
||||
public SerialList<ISerialNode> results;
|
||||
public SerialMap keyStorage;
|
||||
public String futureId;
|
||||
|
||||
public static UnifyResultPacket create(List<ResultSet> resultSets) {
|
||||
public static UnifyResultPacket create(List<ResultSet> resultSets, String futureId) {
|
||||
UnifyResultPacket serialized = new UnifyResultPacket();
|
||||
KeyStorage keyStorage = new KeyStorage();
|
||||
serialized.results = SerialList.fromMapped(resultSets, resultSet -> resultSet.toSerial(keyStorage));
|
||||
serialized.keyStorage = keyStorage.toSerial(keyStorage);
|
||||
serialized.futureId = futureId;
|
||||
return serialized;
|
||||
}
|
||||
|
||||
@@ -35,8 +37,8 @@ public class UnifyResultPacket implements IServerToClientPacket {
|
||||
|
||||
@JsonIgnore
|
||||
public void onHandle(WebSocket webSocket, SocketClient socketClient) {
|
||||
SocketClient.logger.info("[socket] Received unify result");
|
||||
socketClient.setUnifyResultSets(this);
|
||||
SocketClient.logger.info("Received unify result");
|
||||
socketClient.completeResponseFuture(futureId, this);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -1,6 +1,5 @@
|
||||
package de.dhbwstuttgart.target.generate;
|
||||
|
||||
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||
import de.dhbwstuttgart.exceptions.DebugException;
|
||||
import de.dhbwstuttgart.exceptions.NotImplementedException;
|
||||
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal;
|
||||
@@ -16,6 +15,7 @@ import de.dhbwstuttgart.target.tree.type.*;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
@@ -219,6 +219,22 @@ public class StatementToTargetExpression implements ASTVisitor {
|
||||
if (methodCall.receiver instanceof ExpressionReceiver expressionReceiver && expressionReceiver.expr instanceof This) {
|
||||
if (receiverClass == null) throw new DebugException("Class " + receiverName + " does not exist!");
|
||||
var thisMethod = converter.findMethod(receiverClass, methodCall.name, signature);
|
||||
if (thisMethod.isEmpty()) {
|
||||
Target.logger.error("Expected: " + receiverClass.getClassName() + "." + methodCall.name + "(" +
|
||||
signature.stream().map(TargetType::toSignature).collect(Collectors.joining())+ ")" );
|
||||
|
||||
AtomicBoolean hasM = new AtomicBoolean(false);
|
||||
receiverClass.getMethods().forEach(m -> {
|
||||
if (Objects.equals(m.getName(), methodCall.name)) {
|
||||
hasM.set(true);
|
||||
Target.logger.error("But only has: " + m.name + "(" +
|
||||
m.getParameterList().getFormalparalist().stream().map(t -> t.getType().toString()).collect(Collectors.joining())+ ")" );
|
||||
}
|
||||
});
|
||||
if (!hasM.get())
|
||||
Target.logger.error("But does not contain method at all");
|
||||
}
|
||||
|
||||
ClassOrInterface finalReceiverClass = receiverClass;
|
||||
foundMethod = thisMethod.orElseGet(() -> findMethod(finalReceiverClass.getSuperClass().getName(), methodCall.name, signature).orElseThrow());
|
||||
} else if (!isFunNType) {
|
||||
|
@@ -37,6 +37,10 @@ public class Constraint<A extends IConstraintElement> extends HashSet<A> impleme
|
||||
super();
|
||||
}
|
||||
|
||||
public Constraint(int initialCapacity) {
|
||||
super(initialCapacity);
|
||||
}
|
||||
|
||||
public Constraint(boolean isInherited, boolean isImplemented) {
|
||||
this.isInherited = isInherited;
|
||||
this.isImplemented = isImplemented;
|
||||
@@ -77,6 +81,14 @@ public class Constraint<A extends IConstraintElement> extends HashSet<A> impleme
|
||||
methodSignatureConstraint = c;
|
||||
}
|
||||
|
||||
public <B extends IConstraintElement> Constraint<B> createdMapped(Function<A,B> mapper) {
|
||||
Constraint<B> result = new Constraint<>(this.size());
|
||||
for (A element : this) {
|
||||
result.add(mapper.apply(element));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return super.toString() + "\nisInherited = " + isInherited
|
||||
+ " isOveridden = " + isImplemented
|
||||
|
@@ -5,6 +5,7 @@ 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;
|
||||
@@ -29,7 +30,7 @@ public class ResultSet implements ISerializableData {
|
||||
|
||||
public ResultSet(Set<ResultPair> set) {
|
||||
this.results = set;
|
||||
this.genIns = new HashSet<>();
|
||||
this.genIns = TypeUnifyTaskHelper.getPresizedHashSet(results.size());
|
||||
results.forEach(x -> {
|
||||
if (x instanceof PairTPHsmallerTPH) {
|
||||
this.genIns.add(x);
|
||||
|
@@ -14,6 +14,7 @@ import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation;
|
||||
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation;
|
||||
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;
|
||||
@@ -33,7 +34,7 @@ public class TYPE {
|
||||
public ConstraintSet getConstraints() {
|
||||
ConstraintSet ret = new ConstraintSet();
|
||||
for (ClassOrInterface cl : sf.KlassenVektor) {
|
||||
var allClasses = new HashSet<ClassOrInterface>();
|
||||
Set<ClassOrInterface> allClasses = TypeUnifyTaskHelper.getPresizedHashSet(allAvailableClasses.size() + sf.availableClasses.size());
|
||||
allClasses.addAll(allAvailableClasses);
|
||||
allClasses.addAll(sf.availableClasses);
|
||||
ret.addAll(getConstraintsClass(cl, new TypeInferenceInformation(allClasses)));
|
||||
|
@@ -2,6 +2,7 @@
|
||||
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;
|
||||
|
||||
@@ -117,17 +118,18 @@ public class TYPEStmt implements StatementVisitor {
|
||||
@Override
|
||||
public void visit(FieldVar fieldVar) {
|
||||
fieldVar.receiver.accept(this);
|
||||
Set<Constraint> oderConstraints = new HashSet<>();
|
||||
List<FieldAssumption> fieldAssumptions = info.getFields(fieldVar.fieldVarName);
|
||||
Set<Constraint> oderConstraints = TypeUnifyTaskHelper.getPresizedHashSet(fieldAssumptions.size());
|
||||
|
||||
|
||||
for (FieldAssumption fieldAssumption : info.getFields(fieldVar.fieldVarName)) {
|
||||
for (FieldAssumption fieldAssumption : fieldAssumptions) {
|
||||
Constraint constraint = new Constraint();
|
||||
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.size() == 0)
|
||||
if (oderConstraints.isEmpty())
|
||||
throw new TypeinferenceException("Kein Feld " + fieldVar.fieldVarName + " gefunden", fieldVar.getOffset());
|
||||
constraintsSet.addOderConstraint(oderConstraints);
|
||||
}
|
||||
@@ -142,7 +144,7 @@ public class TYPEStmt implements StatementVisitor {
|
||||
|
||||
@Override
|
||||
public void visit(ForEachStmt forEachStmt) {
|
||||
var iterableType = new RefType(ASTFactory.createClass(java.lang.Iterable.class).getClassName(), Arrays.asList(new ExtendsWildcardType(forEachStmt.statement.getType(), new NullToken())), new NullToken());
|
||||
var iterableType = new RefType(ASTFactory.createClass(java.lang.Iterable.class).getClassName(), List.of(new ExtendsWildcardType(forEachStmt.statement.getType(), new NullToken())), new NullToken());
|
||||
constraintsSet.addUndConstraint(new Pair(forEachStmt.expression.getType(), iterableType, PairOperator.SMALLERDOT, loc(forEachStmt.getOffset())));
|
||||
forEachStmt.statement.accept(this);
|
||||
forEachStmt.expression.accept(this);
|
||||
@@ -190,7 +192,7 @@ public class TYPEStmt implements StatementVisitor {
|
||||
methodCall.receiver.accept(this);
|
||||
// Overloading:
|
||||
Set<Constraint<Pair>> methodConstraints = new HashSet<>();
|
||||
for (MethodAssumption m : this.getMethods(methodCall.name, methodCall.arglist, info)) {
|
||||
for (MethodAssumption m : TYPEStmt.getMethods(methodCall.name, methodCall.arglist, info)) {
|
||||
GenericsResolver resolver = getResolverInstance();
|
||||
Set<Constraint<Pair>> oneMethodConstraints = generateConstraint(methodCall, m, info, resolver);
|
||||
methodConstraints.addAll(oneMethodConstraints);
|
||||
@@ -200,7 +202,7 @@ public class TYPEStmt implements StatementVisitor {
|
||||
* oneMethodConstraint.setExtendConstraint(extendsOneMethodConstraint); extendsOneMethodConstraint.setExtendConstraint(oneMethodConstraint); methodConstraints.add(extendsOneMethodConstraint);
|
||||
*/
|
||||
}
|
||||
if (methodConstraints.size() < 1) {
|
||||
if (methodConstraints.isEmpty()) {
|
||||
throw new TypeinferenceException("Methode " + methodCall.name + " ist nicht vorhanden!", methodCall.getOffset());
|
||||
}
|
||||
constraintsSet.addOderConstraint(methodConstraints);
|
||||
@@ -213,7 +215,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.size() < 1) {
|
||||
if (methodConstraints.isEmpty()) {
|
||||
throw new TypeinferenceException("Konstruktor in Klasse " + methodCall.getType().toString() + " ist nicht vorhanden!", methodCall.getOffset());
|
||||
}
|
||||
constraintsSet.addOderConstraint(methodConstraints);
|
||||
@@ -283,8 +285,13 @@ 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 (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(bytee.getName())) {
|
||||
if (classNames.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())));
|
||||
@@ -292,7 +299,7 @@ public class TYPEStmt implements StatementVisitor {
|
||||
numericAdditionOrStringConcatenation.add(numeric);
|
||||
}
|
||||
// PL eingefuegt 2018-07-17
|
||||
if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(shortt.getName())) {
|
||||
if (classNames.contains(shortt.getName())) {
|
||||
numeric = new Constraint<>();
|
||||
numeric.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())));
|
||||
@@ -300,7 +307,7 @@ public class TYPEStmt implements StatementVisitor {
|
||||
numericAdditionOrStringConcatenation.add(numeric);
|
||||
}
|
||||
// PL eingefuegt 2018-07-17
|
||||
if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(integer.getName())) {
|
||||
if (classNames.contains(integer.getName())) {
|
||||
numeric = new Constraint<>();
|
||||
numeric.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())));
|
||||
@@ -308,7 +315,7 @@ public class TYPEStmt implements StatementVisitor {
|
||||
numericAdditionOrStringConcatenation.add(numeric);
|
||||
}
|
||||
// PL eingefuegt 2018-07-17
|
||||
if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(longg.getName())) {
|
||||
if (classNames.contains(longg.getName())) {
|
||||
numeric = new Constraint<>();
|
||||
numeric.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())));
|
||||
@@ -316,7 +323,7 @@ public class TYPEStmt implements StatementVisitor {
|
||||
numericAdditionOrStringConcatenation.add(numeric);
|
||||
}
|
||||
// PL eingefuegt 2018-07-17
|
||||
if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(floatt.getName())) {
|
||||
if (classNames.contains(floatt.getName())) {
|
||||
numeric = new Constraint<>();
|
||||
numeric.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())));
|
||||
@@ -324,7 +331,7 @@ public class TYPEStmt implements StatementVisitor {
|
||||
numericAdditionOrStringConcatenation.add(numeric);
|
||||
}
|
||||
// PL eingefuegt 2018-07-17
|
||||
if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(doublee.getName())) {
|
||||
if (classNames.contains(doublee.getName())) {
|
||||
numeric = new Constraint<>();
|
||||
numeric.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())));
|
||||
@@ -339,7 +346,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 (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(string.getName())) {
|
||||
if (classNames.contains(string.getName())) {
|
||||
Constraint<Pair> stringConcat = new Constraint<>();
|
||||
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())));
|
||||
@@ -347,7 +354,7 @@ public class TYPEStmt implements StatementVisitor {
|
||||
numericAdditionOrStringConcatenation.add(stringConcat);
|
||||
}
|
||||
}
|
||||
if (numericAdditionOrStringConcatenation.size() < 1) {
|
||||
if (numericAdditionOrStringConcatenation.isEmpty()) {
|
||||
throw new TypeinferenceException("Kein Typ für " + binary.operation.toString() + " vorhanden", binary.getOffset());
|
||||
}
|
||||
constraintsSet.addOderConstraint(numericAdditionOrStringConcatenation);
|
||||
@@ -733,7 +740,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.get(foMethod.signature.size() - 1), assumption.getReturnType(), PairOperator.EQUALSDOT));
|
||||
ret.add(new Pair(foMethod.signature.getLast(), assumption.getReturnType(), PairOperator.EQUALSDOT));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -746,8 +753,8 @@ public class TYPEStmt implements StatementVisitor {
|
||||
// funNParams.add(TypePlaceholder.fresh(new NullToken()));
|
||||
funNParams.add(new GenericRefType(NameGenerator.makeNewName(), new NullToken()));
|
||||
}
|
||||
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() {
|
||||
funNParams.getLast();
|
||||
ret.add(new MethodAssumption(new FunNClass(funNParams), funNParams.getLast(), funNParams.subList(0, funNParams.size() - 1), new TypeScope() {
|
||||
@Override
|
||||
public Iterable<? extends GenericTypeVar> getGenerics() {
|
||||
throw new NotImplementedException();
|
||||
@@ -883,13 +890,9 @@ public class TYPEStmt implements StatementVisitor {
|
||||
|
||||
child.getLabels().forEach(el -> {
|
||||
if (el.getType() instanceof RefType) {
|
||||
var recType = el;
|
||||
|
||||
if (el.getPattern() instanceof RecordPattern) {
|
||||
var pattern = (RecordPattern) recType.getPattern();
|
||||
recursivelyAddRecordConstraints(pattern);
|
||||
}
|
||||
|
||||
if (el.getPattern() instanceof RecordPattern pattern) {
|
||||
recursivelyAddRecordConstraints(pattern);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -905,7 +908,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.get(0).getConstructors();
|
||||
var constructors = interestingClasses.getFirst().getConstructors();
|
||||
|
||||
int counter = 0;
|
||||
|
||||
|
@@ -1,6 +1,7 @@
|
||||
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;
|
||||
@@ -8,7 +9,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* An intermediate class for the recursive steps of the TypeUnifyTask:
|
||||
* This allows to cancel parts of the recursion tree, instead of only the whole execution as before. But in
|
||||
* This allows canceling parts of the recursion tree, instead of only the whole execution as before. But in
|
||||
* order for that to work, all cancellable child tasks must be added when they are created
|
||||
*
|
||||
* @param <T>
|
||||
@@ -16,20 +17,19 @@ 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 ArrayList<>();
|
||||
private final List<CancellableTask<?>> childTasks = new LinkedList<>();
|
||||
private CancellableTask<?> parentTask = null;
|
||||
|
||||
/**
|
||||
* Set the execution for this task and all its (recursive) children to be cancelled
|
||||
* Set the execution for this task and all its (recursive) children to be canceled
|
||||
*/
|
||||
protected void cancelExecution() {
|
||||
// is this branch already cancelled? Then do nothing
|
||||
if (this.executionCancelled.get()) return;
|
||||
executionCancelled.set(true);
|
||||
// is this branch already canceled? Then do nothing
|
||||
if (this.executionCancelled.getAndSet(true)) return;
|
||||
this.cancelChildExecution();
|
||||
}
|
||||
|
||||
public void cancelChildExecution() {
|
||||
private void cancelChildExecution() {
|
||||
synchronized (this.childTasks) {
|
||||
for (var childTask : childTasks) {
|
||||
// no need to cancel a branch that is already finished
|
||||
@@ -40,6 +40,24 @@ 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();
|
||||
@@ -48,6 +66,12 @@ 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();
|
||||
}
|
||||
@@ -55,6 +79,9 @@ 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) {
|
||||
|
@@ -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 = termsList.stream().map(x -> mgu.apply(x)).collect(Collectors.toCollection(ArrayList::new));
|
||||
//PL 2018-04-01 nach checken, ob es richtig ist, dass keine Substitutionen uebergeben werden muessen.
|
||||
termsList.replaceAll(mgu::apply);
|
||||
idx = idx+1 == termsList.size() ? 0 : idx+1;
|
||||
continue;
|
||||
}
|
||||
|
@@ -6,6 +6,7 @@ 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;
|
||||
@@ -648,15 +649,17 @@ public class RuleSet implements IRuleSet{
|
||||
|
||||
@Override
|
||||
public Optional<Set<UnifyPair>> subst(Set<UnifyPair> pairs, List<Set<Constraint<UnifyPair>>> oderConstraints) {
|
||||
HashMap<UnifyType, Integer> typeMap = new HashMap<>();
|
||||
// Statistically, typeMap will fill up quickly and resize multiple times. To reduce this, we start with a higher capacity
|
||||
HashMap<UnifyType, Integer> typeMap = new HashMap<>(200);
|
||||
|
||||
Stack<UnifyType> occuringTypes = new Stack<>();
|
||||
|
||||
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))
|
||||
@@ -668,12 +671,12 @@ public class RuleSet implements IRuleSet{
|
||||
if(t1 instanceof SuperType)
|
||||
occuringTypes.push(((SuperType) t1).getSuperedType());
|
||||
else
|
||||
t1.getTypeParams().forEach(x -> occuringTypes.push(x));
|
||||
t1.getTypeParams().forEach(occuringTypes::push);
|
||||
}
|
||||
Queue<UnifyPair> result1 = new LinkedList<UnifyPair>(pairs);
|
||||
LinkedList<UnifyPair> result1 = new LinkedList<UnifyPair>(pairs);
|
||||
ArrayList<UnifyPair> result = new ArrayList<UnifyPair>();
|
||||
boolean applied = false;
|
||||
|
||||
|
||||
while(!result1.isEmpty()) {
|
||||
UnifyPair pair = result1.poll();
|
||||
PlaceholderType lhsType = null;
|
||||
@@ -691,19 +694,30 @@ public class RuleSet implements IRuleSet{
|
||||
&& !((rhsType instanceof WildcardType) && ((WildcardType)rhsType).getWildcardedType().equals(lhsType))) //PL eigefuegt 2018-02-18
|
||||
{
|
||||
Unifier uni = new Unifier(lhsType, rhsType);
|
||||
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));
|
||||
|
||||
// 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));
|
||||
}
|
||||
|
||||
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().stream().map(x -> uni.apply(pair,x)).collect(Collectors.toCollection(Constraint::new)),
|
||||
b.getExtendConstraint().createdMapped(x -> uni.apply(pair,x)),
|
||||
b.getmethodSignatureConstraint().stream().map(x -> uni.apply(pair,x)).collect(Collectors.toCollection(HashSet::new)))
|
||||
: () -> new Constraint<UnifyPair>(b.isInherited(), b.isImplemented())
|
||||
));
|
||||
oderConstraints.replaceAll(oc -> oc.stream().map(applyUni).collect(Collectors.toCollection(HashSet::new)));
|
||||
oderConstraints.replaceAll(oc -> {
|
||||
HashSet<Constraint<UnifyPair>> mapped = new HashSet<>(oc.size());
|
||||
for (var element : oc) {
|
||||
mapped.add(applyUni.apply(element));
|
||||
}
|
||||
return mapped;
|
||||
});
|
||||
/*
|
||||
oderConstraints = oderConstraints.stream().map(
|
||||
a -> a.stream().map(applyUni
|
||||
|
@@ -45,7 +45,7 @@ public class TypeUnify2Task extends TypeUnifyTask {
|
||||
*/
|
||||
//writeLog("xxx");
|
||||
//noOfThread--;
|
||||
if (this.myIsCancelled()) {
|
||||
if (this.isExecutionCancelled()) {
|
||||
return CompletableFuture.completedFuture(new HashSet<>());
|
||||
} else {
|
||||
return res;
|
||||
|
@@ -3,6 +3,7 @@ package de.dhbwstuttgart.typeinference.unify;
|
||||
|
||||
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;
|
||||
@@ -26,11 +27,7 @@ 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;
|
||||
@@ -49,7 +46,6 @@ 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;
|
||||
|
||||
|
||||
/**
|
||||
@@ -117,8 +113,6 @@ 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());
|
||||
@@ -155,7 +149,7 @@ public class TypeUnifyTask extends CancellableTask<CompletableFuture<Set<Set<Uni
|
||||
this.fc = fc;
|
||||
this.oup = new OrderingUnifyPair(fc, context);
|
||||
|
||||
this.context = context.newWithLogger(
|
||||
this.context = (context.logger() instanceof ServerTaskLogger) ? context : context.newWithLogger(
|
||||
Logger.forFile(
|
||||
System.getProperty("user.dir") + "/logFiles/" + "Thread",
|
||||
"Unify"
|
||||
@@ -213,13 +207,6 @@ 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) {
|
||||
@@ -249,7 +236,7 @@ public class TypeUnifyTask extends CancellableTask<CompletableFuture<Set<Set<Uni
|
||||
throw new TypeinferenceException("Unresolved constraints: " + res, new NullToken()); //return new HashSet<>();
|
||||
}
|
||||
|
||||
if (this.myIsCancelled()) {
|
||||
if (this.isExecutionCancelled()) {
|
||||
return new HashSet<>();
|
||||
}
|
||||
|
||||
@@ -286,7 +273,7 @@ public class TypeUnifyTask extends CancellableTask<CompletableFuture<Set<Set<Uni
|
||||
|
||||
//.collect(Collectors.toCollection(HashSet::new)));
|
||||
|
||||
if (this.myIsCancelled()) {
|
||||
if (this.isExecutionCancelled()) {
|
||||
return CompletableFuture.completedFuture(new HashSet<>());
|
||||
}
|
||||
|
||||
@@ -315,14 +302,7 @@ public class TypeUnifyTask extends CancellableTask<CompletableFuture<Set<Set<Uni
|
||||
/*
|
||||
* Occurs-Check durchfuehren
|
||||
*/
|
||||
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> ocurrPairs = TypeUnifyTaskHelper.occursCheck(eq);
|
||||
|
||||
Set<UnifyPair> finalOcurrPairs = ocurrPairs;
|
||||
context.logger().debug(() -> "ocurrPairs: " + finalOcurrPairs);
|
||||
@@ -346,14 +326,7 @@ public class TypeUnifyTask extends CancellableTask<CompletableFuture<Set<Set<Uni
|
||||
/* In commit dfd91b5f8b7fca1cb5f302eec4b0ba3330271c9b eingefuegt ANFANG */
|
||||
Set<UnifyPair> occurcheck = new HashSet<>(eq0);
|
||||
occurcheck.removeAll(eq0Prime);
|
||||
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));
|
||||
ocurrPairs = TypeUnifyTaskHelper.occursCheck(occurcheck);
|
||||
Set<UnifyPair> finalOcurrPairs1 = ocurrPairs;
|
||||
context.logger().debug(() -> "ocurrPairs: " + finalOcurrPairs1);
|
||||
if (!ocurrPairs.isEmpty()) {
|
||||
@@ -490,7 +463,7 @@ public class TypeUnifyTask extends CancellableTask<CompletableFuture<Set<Set<Uni
|
||||
// .collect(Collectors.toCollection(HashSet::new));
|
||||
//Muss auskommentiert werden, wenn computeCartesianRecursive ENDE
|
||||
|
||||
if (this.myIsCancelled()) {
|
||||
if (this.isExecutionCancelled()) {
|
||||
return CompletableFuture.completedFuture(new HashSet<>());
|
||||
}
|
||||
|
||||
@@ -767,7 +740,8 @@ 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<Tuple<Set<Set<UnifyPair>>, Set<Set<Set<UnifyPair>>>>> parallelResultDataFuture;
|
||||
CompletableFuture<VarianceCase.ComputationResults> parallelResultDataFuture;
|
||||
|
||||
|
||||
if (parallel) {
|
||||
parallelResultDataFuture = varianceCase.computeParallel(
|
||||
@@ -778,13 +752,16 @@ 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(currentThreadResult -> new Tuple<>(currentThreadResult, new HashSet<>()));
|
||||
.thenApply(VarianceCase.ComputationResults::new);
|
||||
}
|
||||
|
||||
if (this.isExecutionCancelled()) {
|
||||
return CompletableFuture.completedFuture(new HashSet<>());
|
||||
}
|
||||
|
||||
return parallelResultDataFuture.thenCompose(parallelResultData -> {
|
||||
Set<Set<UnifyPair>> currentThreadResult = parallelResultData.getFirst();
|
||||
Set<Set<Set<UnifyPair>>> forkResults = parallelResultData.getSecond();
|
||||
Set<Set<UnifyPair>> currentThreadResult = parallelResultData.mainResult;
|
||||
Set<Set<Set<UnifyPair>>> forkResults = parallelResultData.forkResults;
|
||||
|
||||
Set<Set<UnifyPair>> result = prevResult;
|
||||
List<Set<UnifyPair>> nextSetAsList = prevNextSetAsList;
|
||||
@@ -848,17 +825,6 @@ 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;
|
||||
@@ -892,7 +858,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.cancelChildExecution();
|
||||
// this.cancelYoungerSiblingTasks();
|
||||
return CompletableFuture.completedFuture(result);
|
||||
}
|
||||
|
||||
@@ -1745,8 +1711,9 @@ public class TypeUnifyTask extends CancellableTask<CompletableFuture<Set<Set<Uni
|
||||
aa.putAll(b);
|
||||
return aa;
|
||||
};
|
||||
HashMap<PlaceholderType, PlaceholderType> hm = x.getInvolvedPlaceholderTypes().stream()
|
||||
.reduce(new HashMap<PlaceholderType, PlaceholderType>(),
|
||||
var involvedPlaceholderTypes = x.getInvolvedPlaceholderTypes();
|
||||
HashMap<PlaceholderType, PlaceholderType> hm = involvedPlaceholderTypes.stream()
|
||||
.reduce(TypeUnifyTaskHelper.getPresizedHashMap(involvedPlaceholderTypes.size()),
|
||||
(aa, b) -> {
|
||||
aa.put(b, PlaceholderType.freshPlaceholder(context.placeholderRegistry()));
|
||||
return aa;
|
||||
|
@@ -5,6 +5,7 @@ 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;
|
||||
@@ -185,4 +186,36 @@ 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -12,7 +12,7 @@ public class UnifyTaskModel {
|
||||
|
||||
public synchronized void cancel() {
|
||||
for(TypeUnifyTask t : usedTasks) {
|
||||
t.myCancel(true);
|
||||
t.cancelExecution();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,5 @@
|
||||
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;
|
||||
@@ -17,11 +16,11 @@ import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Variance1Case extends VarianceCase {
|
||||
public class ContravarianceCase extends VarianceCase {
|
||||
|
||||
protected final int variance = 1;
|
||||
|
||||
protected Variance1Case(boolean isOderConstraint, TypeUnifyTask typeUnifyTask, UnifyContext context) {
|
||||
protected ContravarianceCase(boolean isOderConstraint, TypeUnifyTask typeUnifyTask, UnifyContext context) {
|
||||
super(isOderConstraint, typeUnifyTask, context);
|
||||
}
|
||||
|
||||
@@ -37,7 +36,7 @@ public class Variance1Case 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.
|
||||
@@ -49,7 +48,7 @@ public class Variance1Case extends VarianceCase {
|
||||
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Tuple<Set<Set<UnifyPair>>, Set<Set<Set<UnifyPair>>>>> computeParallel(
|
||||
public CompletableFuture<ComputationResults> computeParallel(
|
||||
Set<Set<UnifyPair>> elems,
|
||||
Set<UnifyPair> eq,
|
||||
List<Set<Constraint<UnifyPair>>> oderConstraints,
|
||||
@@ -61,10 +60,6 @@ public class Variance1Case 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);
|
||||
@@ -75,16 +70,16 @@ public class Variance1Case extends VarianceCase {
|
||||
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) -> {
|
||||
CompletableFuture<ComputationResults> resultValues = forkOrigFuture.thenApply(
|
||||
(currentThreadResult) -> {
|
||||
forkOrig.context.logger().debug("final Orig 1");
|
||||
forkOrig.closeLogFile();
|
||||
return new Tuple<>(currentThreadResult, prevResults.getSecond());
|
||||
return new ComputationResults(currentThreadResult);
|
||||
});
|
||||
|
||||
//forks.add(forkOrig);
|
||||
if (typeUnifyTask.myIsCancelled()) {
|
||||
throw new UnifyCancelException();
|
||||
if (typeUnifyTask.isExecutionCancelled()) {
|
||||
return CompletableFuture.completedFuture(new ComputationResults());
|
||||
}
|
||||
/* FORK ENDE */
|
||||
|
||||
@@ -114,12 +109,12 @@ public class Variance1Case 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.myIsCancelled()) {
|
||||
throw new UnifyCancelException();
|
||||
if (typeUnifyTask.isExecutionCancelled()) {
|
||||
return new ComputationResults();
|
||||
}
|
||||
context.logger().debug("fork_res: " + fork_res.toString());
|
||||
context.logger().debug(Boolean.valueOf((typeUnifyTask.isUndefinedPairSetSet(fork_res))).toString());
|
||||
prevResults.getSecond().add(fork_res);
|
||||
prevResults.addForkResult(fork_res);
|
||||
if (!typeUnifyTask.isUndefinedPairSetSet(fork_res)) {
|
||||
aParDef.add(fork.getNextSetElement());
|
||||
}
|
||||
@@ -129,8 +124,8 @@ public class Variance1Case extends VarianceCase {
|
||||
}
|
||||
);
|
||||
|
||||
if (typeUnifyTask.myIsCancelled()) {
|
||||
throw new UnifyCancelException();
|
||||
if (typeUnifyTask.isExecutionCancelled()) {
|
||||
return CompletableFuture.completedFuture(new ComputationResults());
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,5 @@
|
||||
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;
|
||||
@@ -17,11 +16,11 @@ import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class VarianceM1Case extends VarianceCase {
|
||||
public class CovarianceCase extends VarianceCase {
|
||||
|
||||
protected final int variance = -1;
|
||||
|
||||
protected VarianceM1Case(boolean isOderConstraint, TypeUnifyTask typeUnifyTask, UnifyContext context) {
|
||||
protected CovarianceCase(boolean isOderConstraint, TypeUnifyTask typeUnifyTask, UnifyContext context) {
|
||||
super(isOderConstraint, typeUnifyTask, context);
|
||||
}
|
||||
|
||||
@@ -49,7 +48,7 @@ public class VarianceM1Case extends VarianceCase {
|
||||
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Tuple<Set<Set<UnifyPair>>, Set<Set<Set<UnifyPair>>>>> computeParallel(
|
||||
public CompletableFuture<ComputationResults> computeParallel(
|
||||
Set<Set<UnifyPair>> elems,
|
||||
Set<UnifyPair> eq,
|
||||
List<Set<Constraint<UnifyPair>>> oderConstraints,
|
||||
@@ -61,10 +60,6 @@ public class VarianceM1Case 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);
|
||||
@@ -75,16 +70,16 @@ public class VarianceM1Case extends VarianceCase {
|
||||
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) -> {
|
||||
CompletableFuture<ComputationResults> resultValues = forkOrigFuture.thenApply(
|
||||
(currentThreadResult) -> {
|
||||
forkOrig.context.logger().debug("final Orig -1");
|
||||
forkOrig.closeLogFile();
|
||||
return new Tuple<>(currentThreadResult, prevResults.getSecond());
|
||||
return new ComputationResults(currentThreadResult);
|
||||
});
|
||||
|
||||
//forks.add(forkOrig);
|
||||
if (typeUnifyTask.myIsCancelled()) {
|
||||
throw new UnifyCancelException();
|
||||
if (typeUnifyTask.isExecutionCancelled()) {
|
||||
return resultValues;
|
||||
}
|
||||
/* FORK ENDE */
|
||||
|
||||
@@ -115,12 +110,12 @@ public class VarianceM1Case 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.myIsCancelled()) {
|
||||
throw new UnifyCancelException();
|
||||
if (typeUnifyTask.isExecutionCancelled()) {
|
||||
return prevResults;
|
||||
}
|
||||
context.logger().debug(() -> "fork_res: " + fork_res.toString());
|
||||
context.logger().debug(() -> Boolean.valueOf((typeUnifyTask.isUndefinedPairSetSet(fork_res))).toString());
|
||||
prevResults.getSecond().add(fork_res);
|
||||
prevResults.addForkResult(fork_res);
|
||||
if (!typeUnifyTask.isUndefinedPairSetSet(fork_res)) {
|
||||
aParDef.add(fork.getNextSetElement());
|
||||
}
|
||||
@@ -130,8 +125,8 @@ public class VarianceM1Case extends VarianceCase {
|
||||
}
|
||||
);
|
||||
|
||||
if (typeUnifyTask.myIsCancelled()) {
|
||||
throw new UnifyCancelException();
|
||||
if (typeUnifyTask.isExecutionCancelled()) {
|
||||
return resultValues;
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,5 @@
|
||||
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;
|
||||
@@ -15,11 +14,12 @@ import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class Variance2Case extends VarianceCase {
|
||||
public class InvarianceOrConstraintCase extends VarianceCase {
|
||||
|
||||
// either for invariance or for oderConstraints
|
||||
protected final int variance = 2;
|
||||
|
||||
protected Variance2Case(boolean isOderConstraint, TypeUnifyTask typeUnifyTask, UnifyContext context) {
|
||||
protected InvarianceOrConstraintCase(boolean isOderConstraint, TypeUnifyTask typeUnifyTask, UnifyContext context) {
|
||||
super(isOderConstraint, typeUnifyTask, context);
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ public class Variance2Case extends VarianceCase {
|
||||
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Tuple<Set<Set<UnifyPair>>, Set<Set<Set<UnifyPair>>>>> computeParallel(
|
||||
public CompletableFuture<ComputationResults> computeParallel(
|
||||
Set<Set<UnifyPair>> elems,
|
||||
Set<UnifyPair> eq,
|
||||
List<Set<Constraint<UnifyPair>>> oderConstraints,
|
||||
@@ -49,8 +49,6 @@ public class Variance2Case 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);
|
||||
@@ -62,13 +60,14 @@ public class Variance2Case 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);
|
||||
resultValuesFuture = forkOrigFuture.thenApply((currentThreadResult) -> {
|
||||
CompletableFuture<ComputationResults> resultValues = forkOrigFuture.thenApply((currentThreadResult) -> {
|
||||
forkOrig.context.logger().debug("final Orig 2");
|
||||
forkOrig.closeLogFile();
|
||||
return new Tuple<>(currentThreadResult, new HashSet<>());
|
||||
return new ComputationResults(currentThreadResult);
|
||||
});
|
||||
if (typeUnifyTask.myIsCancelled()) {
|
||||
throw new UnifyCancelException();
|
||||
|
||||
if (typeUnifyTask.isExecutionCancelled()) {
|
||||
return resultValues;
|
||||
}
|
||||
/* FORK ENDE */
|
||||
|
||||
@@ -92,26 +91,22 @@ public class Variance2Case 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);
|
||||
resultValuesFuture = resultValuesFuture.thenCombine(forkFuture, (resultValues, fork_res) -> {
|
||||
if (typeUnifyTask.myIsCancelled()) {
|
||||
throw new UnifyCancelException();
|
||||
resultValues = resultValues.thenCombine(forkFuture, (prevResults, fork_res) -> {
|
||||
if (typeUnifyTask.isExecutionCancelled()) {
|
||||
return prevResults;
|
||||
}
|
||||
resultValues.getSecond().add(fork_res);
|
||||
prevResults.addForkResult(fork_res);
|
||||
fork.context.logger().debug("final 2");
|
||||
fork.closeLogFile();
|
||||
return resultValues;
|
||||
return prevResults;
|
||||
});
|
||||
|
||||
if (typeUnifyTask.myIsCancelled()) {
|
||||
throw new UnifyCancelException();
|
||||
if (typeUnifyTask.isExecutionCancelled()) {
|
||||
return resultValues;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeUnifyTask.myIsCancelled()) {
|
||||
throw new UnifyCancelException();
|
||||
}
|
||||
|
||||
return resultValuesFuture;
|
||||
return resultValues;
|
||||
}
|
||||
|
||||
@Override
|
@@ -11,19 +11,20 @@ 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.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Variance0Case extends VarianceCase {
|
||||
public class UnknownVarianceCase extends VarianceCase {
|
||||
|
||||
protected final int variance = 0;
|
||||
|
||||
protected Variance0Case(boolean isOderConstraint, TypeUnifyTask typeUnifyTask, UnifyContext context) {
|
||||
protected final AtomicBoolean shouldBreak = new AtomicBoolean(false);
|
||||
|
||||
protected UnknownVarianceCase(boolean isOderConstraint, TypeUnifyTask typeUnifyTask, UnifyContext context) {
|
||||
super(isOderConstraint, typeUnifyTask, context);
|
||||
}
|
||||
|
||||
@@ -51,7 +52,6 @@ public class Variance0Case extends VarianceCase {
|
||||
a = nextSetAsList.removeFirst();
|
||||
}
|
||||
|
||||
|
||||
Set<UnifyPair> finalA = a;
|
||||
if (!this.isOderConstraint && optOrigPair != null && optOrigPair.isPresent()) {
|
||||
if (optOrigPair.get().getBasePair().getLhsType() instanceof PlaceholderType) {
|
||||
@@ -63,20 +63,20 @@ public class Variance0Case extends VarianceCase {
|
||||
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());
|
||||
}
|
||||
nextSetasListRest = (nextSetAsList.size() > 5) ? nextSetAsList.subList(0, 5) : nextSetAsList;
|
||||
}
|
||||
|
||||
nextSetAsList.removeAll(nextSetasListRest);
|
||||
// */
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Tuple<Set<Set<UnifyPair>>, Set<Set<Set<UnifyPair>>>>> computeParallel(
|
||||
public CompletableFuture<ComputationResults> computeParallel(
|
||||
Set<Set<UnifyPair>> elems,
|
||||
Set<UnifyPair> eq,
|
||||
List<Set<Constraint<UnifyPair>>> oderConstraints,
|
||||
@@ -88,82 +88,98 @@ public class Variance0Case 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);
|
||||
newElemsOrig.add(a);
|
||||
|
||||
/* FORK ANFANG */
|
||||
TypeUnify2Task forkOrig = new TypeUnify2Task(newElemsOrig, newEqOrig, newOderConstraintsOrig, a, fc, context, rekTiefe, new HashSet<>(methodSignatureConstraint));
|
||||
Set<UnifyPair> newMethodSignatureConstraintOrig = new HashSet<>(methodSignatureConstraint);
|
||||
if (isOderConstraint) {
|
||||
methodSignatureConstraint.addAll(((Constraint<UnifyPair>) a).getmethodSignatureConstraint());
|
||||
}
|
||||
TypeUnify2Task forkOrig = new TypeUnify2Task(newElemsOrig, newEqOrig, newOderConstraintsOrig, a, fc, context, rekTiefe, newMethodSignatureConstraintOrig);
|
||||
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) -> {
|
||||
CompletableFuture<ComputationResults> resultValues = forkOrigFuture.thenApply(
|
||||
(currentThreadResult) -> {
|
||||
forkOrig.context.logger().debug("final Orig 0");
|
||||
forkOrig.closeLogFile();
|
||||
return new Tuple<>(currentThreadResult, prevResults.getSecond());
|
||||
return new ComputationResults(currentThreadResult);
|
||||
});
|
||||
|
||||
//forks.add(forkOrig);
|
||||
if (typeUnifyTask.myIsCancelled()) {
|
||||
throw new UnifyCancelException();
|
||||
}
|
||||
/* FORK ENDE */
|
||||
|
||||
context.logger().debug("a in " + variance + " " + a);
|
||||
context.logger().debug("nextSetasListRest: " + nextSetasListRest.toString());
|
||||
|
||||
int i = 0;
|
||||
Set<Set<UnifyPair>>[] additionalResults = new HashSet[nextSetasListRest.size()];
|
||||
Constraint<UnifyPair>[] extendConstraints = new Constraint[nextSetasListRest.size()];
|
||||
while (!nextSetasListRest.isEmpty()) {
|
||||
Set<UnifyPair> nSaL = nextSetasListRest.removeFirst();
|
||||
nextSetAsList.remove(nSaL);
|
||||
context.logger().debug("0 RM" + nSaL.toString());
|
||||
final int finalI = i++;
|
||||
|
||||
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 {
|
||||
Set<UnifyPair> nSaL = nextSetasListRest.removeFirst();
|
||||
context.logger().debug(() -> "0 RM" + nSaL.toString());
|
||||
|
||||
if (this.isOderConstraint) {
|
||||
Constraint<UnifyPair> extendConstraint = ((Constraint<UnifyPair>) nSaL).getExtendConstraint();
|
||||
nextSetasListOderConstraints.add(extendConstraint);
|
||||
extendConstraints[finalI] = extendConstraint;
|
||||
}
|
||||
else if (!sameEqSet.isEmpty() && !typeUnifyTask.checkNoContradiction(nSaL, sameEqSet, result)) {
|
||||
TypeUnifyTask.noShortendElements++;
|
||||
continue;
|
||||
}
|
||||
|
||||
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));
|
||||
Set<UnifyPair> newMethodSignatureConstraint = new HashSet<>(methodSignatureConstraint);
|
||||
if (isOderConstraint) {
|
||||
methodSignatureConstraint.addAll(((Constraint<UnifyPair>) nSaL).getmethodSignatureConstraint());
|
||||
}
|
||||
|
||||
TypeUnify2Task fork = new TypeUnify2Task(newElems, newEq, newOderConstraints, nSaL, fc, context, rekTiefe, newMethodSignatureConstraint);
|
||||
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();
|
||||
}
|
||||
resultValues = resultValues.thenCombine(forkFuture, (compResult, forkResult) -> {
|
||||
additionalResults[finalI] = forkResult;
|
||||
context.logger().error("finalI: " + finalI);
|
||||
return compResult;
|
||||
});
|
||||
}
|
||||
|
||||
return resultValues;
|
||||
|
||||
int finalI1 = i;
|
||||
return resultValues.thenCompose(compResult -> {
|
||||
var oldResult = compResult.mainResult;
|
||||
|
||||
for (int e = 0; e < finalI1; e++) {
|
||||
Set<Set<UnifyPair>> currentResult = additionalResults[e];
|
||||
|
||||
boolean oldResultInvalid = typeUnifyTask.isUndefinedPairSetSet(oldResult);
|
||||
boolean currentResultInvalid = typeUnifyTask.isUndefinedPairSetSet(currentResult);
|
||||
|
||||
if (!oldResult.isEmpty() && !oldResultInvalid) {
|
||||
boolean shouldBreak = this.eraseInvalidSets(rekTiefe, new HashSet<>(), nextSetAsList);
|
||||
if (shouldBreak) {
|
||||
return CompletableFuture.completedFuture(compResult);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.isOderConstraint) {
|
||||
nextSetasListOderConstraints.add(extendConstraints[e]);
|
||||
}
|
||||
|
||||
if (!currentResultInvalid && oldResultInvalid) {
|
||||
//wenn korrektes Ergebnis gefunden alle Fehlerfaelle loeschen
|
||||
oldResult = currentResult;
|
||||
} else if (oldResultInvalid == currentResultInvalid || oldResult.isEmpty()) {
|
||||
//alle Fehlerfaelle und alle korrekten Ergebnis jeweils adden
|
||||
Set<Set<UnifyPair>> finalOldResult = oldResult;
|
||||
context.logger().debug(() -> "RES var1 ADD:" + finalOldResult.toString() + " " + currentResult.toString());
|
||||
oldResult.addAll(currentResult);
|
||||
}
|
||||
}
|
||||
|
||||
compResult.mainResult = oldResult;
|
||||
return CompletableFuture.completedFuture(compResult);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -186,7 +202,6 @@ public class Variance0Case extends VarianceCase {
|
||||
if (!this.isOderConstraint) {
|
||||
return true;
|
||||
} else {
|
||||
|
||||
nextSetAsList.removeAll(nextSetasListOderConstraints);
|
||||
nextSetasListOderConstraints = new ArrayList<>();
|
||||
context.logger().debug("Removed: " + nextSetasListOderConstraints);
|
||||
@@ -194,19 +209,16 @@ public class Variance0Case extends VarianceCase {
|
||||
List<Set<UnifyPair>> notInherited = smallerSetasList.stream()
|
||||
.filter(x -> !((Constraint<UnifyPair>) x).isInherited())
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
final List<Set<UnifyPair>> notErased = new ArrayList<>();
|
||||
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()
|
@@ -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 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);
|
||||
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);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ public abstract class VarianceCase {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public abstract CompletableFuture<Tuple<Set<Set<UnifyPair>>, Set<Set<Set<UnifyPair>>>>> computeParallel(
|
||||
public abstract CompletableFuture<ComputationResults> computeParallel(
|
||||
Set<Set<UnifyPair>> elems,
|
||||
Set<UnifyPair> eq,
|
||||
List<Set<Constraint<UnifyPair>>> oderConstraints,
|
||||
@@ -104,4 +104,29 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -5,6 +5,7 @@ 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.PlaceholderRegistry;
|
||||
import de.dhbwstuttgart.typeinference.unify.TypeUnifyTaskHelper;
|
||||
import de.dhbwstuttgart.typeinference.unify.UnifyContext;
|
||||
import de.dhbwstuttgart.util.Logger;
|
||||
import java.io.IOException;
|
||||
@@ -126,7 +127,7 @@ public class FiniteClosure implements IFiniteClosure, ISerializableData {
|
||||
}
|
||||
|
||||
// Build the alternative representation with strings as keys
|
||||
strInheritanceGraph = new HashMap<>();
|
||||
strInheritanceGraph = TypeUnifyTaskHelper.getPresizedHashMap(inheritanceGraph.size());
|
||||
for(UnifyType key : inheritanceGraph.keySet()) {
|
||||
if(!strInheritanceGraph.containsKey(key.getName()))
|
||||
strInheritanceGraph.put(key.getName(), new HashSet<>());
|
||||
@@ -238,9 +239,9 @@ public class FiniteClosure implements IFiniteClosure, ISerializableData {
|
||||
result.add(new Pair<>(theta1.apply(sigma), fBounded));
|
||||
}
|
||||
}
|
||||
|
||||
HashSet<UnifyType> resut = result.stream().map(x -> x.getKey()).collect(Collectors.toCollection(HashSet::new));
|
||||
if(resut.equals(types.stream().map(x -> x.getKey()).collect(Collectors.toCollection(HashSet::new))))
|
||||
|
||||
HashSet<UnifyType> resut = result.stream().map(Pair::getKey).collect(Collectors.toCollection(HashSet::new));
|
||||
if(resut.equals(types.stream().map(Pair::getKey).collect(Collectors.toCollection(HashSet::new))))
|
||||
return resut;
|
||||
return computeSmaller(result);
|
||||
}
|
||||
@@ -272,8 +273,8 @@ public class FiniteClosure implements IFiniteClosure, ISerializableData {
|
||||
@Override
|
||||
//Eingefuegt PL 2018-05-24 F-Bounded Problematik
|
||||
public Set<UnifyType> greater(UnifyType type, Set<UnifyType> fBounded, SourceLoc location) {
|
||||
Set<UnifyType> ret;
|
||||
if ((ret = greaterHash.get(new hashKeyType(type))) != null) {
|
||||
Set<UnifyType> ret = greaterHash.get(new hashKeyType(type));
|
||||
if (ret != null) {
|
||||
//context.logger().info(greaterHash);
|
||||
return new HashSet<>(ret);
|
||||
}
|
||||
@@ -506,35 +507,42 @@ public class FiniteClosure implements IFiniteClosure, ISerializableData {
|
||||
public Set<UnifyType> grArg(ReferenceType type, Set<UnifyType> fBounded) {
|
||||
Set<UnifyType> result = new HashSet<UnifyType>();
|
||||
result.add(type);
|
||||
smaller(type, fBounded).forEach(x -> result.add(new SuperType(x)));
|
||||
greater(type,fBounded).forEach(x -> result.add(new ExtendsType(x)));
|
||||
smaller(type, fBounded).forEach(x -> result.add(new SuperType(x)));
|
||||
greater(type,fBounded).forEach(x -> result.add(new ExtendsType(x)));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<UnifyType> grArg(FunNType type, Set<UnifyType> fBounded) {
|
||||
Set<UnifyType> result = new HashSet<UnifyType>();
|
||||
Set<UnifyType> smaller = smaller(type, fBounded);
|
||||
Set<UnifyType> greater = greater(type, fBounded);
|
||||
|
||||
Set<UnifyType> result = new HashSet<UnifyType>((int)((1 + smaller.size() + greater.size()) * 1.5));
|
||||
result.add(type);
|
||||
smaller(type, fBounded).forEach(x -> result.add(new SuperType(x)));
|
||||
greater(type, fBounded).forEach(x -> result.add(new ExtendsType(x)));
|
||||
smaller.forEach(x -> result.add(new SuperType(x)));
|
||||
greater.forEach(x -> result.add(new ExtendsType(x)));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<UnifyType> grArg(ExtendsType type, Set<UnifyType> fBounded) {
|
||||
Set<UnifyType> result = new HashSet<UnifyType>();
|
||||
result.add(type);
|
||||
UnifyType t = type.getExtendedType();
|
||||
greater(t, fBounded).forEach(x -> result.add(new ExtendsType(x)));
|
||||
Set<UnifyType> greater = greater(t, fBounded);
|
||||
|
||||
Set<UnifyType> result = new HashSet<UnifyType>((int)((1 + greater.size()) * 1.5));
|
||||
result.add(type);
|
||||
greater.forEach(x -> result.add(new ExtendsType(x)));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<UnifyType> grArg(SuperType type, Set<UnifyType> fBounded) {
|
||||
Set<UnifyType> result = new HashSet<UnifyType>();
|
||||
result.add(type);
|
||||
UnifyType t = type.getSuperedType();
|
||||
smaller(t, fBounded).forEach(x -> result.add(new SuperType(x)));
|
||||
Set<UnifyType> smaller = smaller(t, fBounded);
|
||||
|
||||
Set<UnifyType> result = TypeUnifyTaskHelper.getPresizedHashSet(1 + smaller.size());
|
||||
result.add(type);
|
||||
smaller.forEach(x -> result.add(new SuperType(x)));
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -566,29 +574,33 @@ public class FiniteClosure implements IFiniteClosure, ISerializableData {
|
||||
|
||||
@Override
|
||||
public Set<UnifyType> smArg(ExtendsType type, Set<UnifyType> fBounded) {
|
||||
Set<UnifyType> result = new HashSet<UnifyType>();
|
||||
result.add(type);
|
||||
UnifyType t = type.getExtendedType();
|
||||
result.add(t);
|
||||
smaller(t, fBounded).forEach(x -> {
|
||||
result.add(new ExtendsType(x));
|
||||
result.add(x);
|
||||
});
|
||||
Set<UnifyType> smaller = smaller(t, fBounded);
|
||||
|
||||
Set<UnifyType> result = TypeUnifyTaskHelper.getPresizedHashSet(2 * (1 + smaller.size()));
|
||||
result.add(type);
|
||||
result.add(t);
|
||||
smaller.forEach(x -> {
|
||||
result.add(new ExtendsType(x));
|
||||
result.add(x);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Set<UnifyType> smArg(SuperType type, Set<UnifyType> fBounded) {
|
||||
Set<UnifyType> result = new HashSet<UnifyType>();
|
||||
result.add(type);
|
||||
UnifyType t = type.getSuperedType();
|
||||
result.add(t);
|
||||
//*** ACHTUNG das koennte FALSCH sein PL 2018-05-23 evtl. HashSet durch smArg durchschleifen
|
||||
greater(t, fBounded).forEach(x -> {
|
||||
result.add(new SuperType(x));
|
||||
result.add(x);
|
||||
});
|
||||
Set<UnifyType> greater = greater(t, fBounded);
|
||||
|
||||
Set<UnifyType> result = TypeUnifyTaskHelper.getPresizedHashSet(2 * (1 + greater.size()));
|
||||
result.add(type);
|
||||
result.add(t);
|
||||
//*** ACHTUNG das koennte FALSCH sein PL 2018-05-23 evtl. HashSet durch smArg durchschleifen
|
||||
greater.forEach(x -> {
|
||||
result.add(new SuperType(x));
|
||||
result.add(x);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -603,7 +615,7 @@ public class FiniteClosure implements IFiniteClosure, ISerializableData {
|
||||
public Set<UnifyType> getAllTypesByName(String typeName) {
|
||||
if(!strInheritanceGraph.containsKey(typeName))
|
||||
return new HashSet<>();
|
||||
return strInheritanceGraph.get(typeName).stream().map(x -> x.getContent()).collect(Collectors.toCollection(HashSet::new));
|
||||
return strInheritanceGraph.get(typeName).stream().map(Node::getContent).collect(Collectors.toCollection(HashSet::new));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -170,30 +170,66 @@ public class OrderingUnifyPair extends OrderingExtend<Set<UnifyPair>> {
|
||||
left.add(p2);
|
||||
left.add(p4);
|
||||
*/
|
||||
|
||||
|
||||
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));
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
//context.logger().info(left.toString());
|
||||
//Fall 2
|
||||
//if (lefteq.iterator().next().getLhsType().getName().equals("AJO")) {
|
||||
@@ -201,54 +237,14 @@ 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);
|
||||
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(righteqOder);
|
||||
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 {
|
||||
@@ -273,59 +269,43 @@ 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();
|
||||
if ((compareEq = compareEq(lefteqOder.iterator().next().getGroundBasePair(), righteqOder.iterator().next().getGroundBasePair())) == -1) {
|
||||
ArrayList<UnifyPair> matchList =
|
||||
rightleOder.stream().map(x -> {
|
||||
UnifyPair leftElem = leftleOder.stream()
|
||||
compareEq = compareEq(lefteqOder.iterator().next().getGroundBasePair(), righteqOder.iterator().next().getGroundBasePair());
|
||||
|
||||
if (compareEq == -1) {
|
||||
ArrayList<UnifyPair> matchList =
|
||||
rightleOder.stream().map(x -> {
|
||||
UnifyPair leftElem = leftleOder.stream()
|
||||
.filter(y -> y.getGroundBasePair().getLhsType().equals(x.getGroundBasePair().getLhsType()))
|
||||
.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;
|
||||
}
|
||||
.findAny().orElseThrow();
|
||||
return new UnifyPair(x.getRhsType(), leftElem.getRhsType(), PairOperator.EQUALSDOT);}
|
||||
)
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
|
||||
return (m.match(matchList).isPresent()) ? -1 : 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().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;
|
||||
}
|
||||
.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;
|
||||
} else {
|
||||
/*
|
||||
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) {
|
||||
}
|
||||
}
|
||||
((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();
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
@@ -392,12 +372,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().get().forEach(x -> uni.add((PlaceholderType) x.getLhsType(), x.getRhsType()));
|
||||
if (!lseq.getRhsType().getName().equals(rseq.getRhsType().getName())
|
||||
int_Unifier.getValue().orElseThrow().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(x -> uni.apply(x)).collect(Collectors.toCollection(HashSet::new));
|
||||
Set <UnifyPair> rsleuni = rightlewc.stream().map(x -> uni.apply(x)).collect(Collectors.toCollection(HashSet::new));
|
||||
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));
|
||||
BinaryOperator<HashMap<UnifyType,UnifyPair>> combiner = (x,y) -> { x.putAll(y); return x;};
|
||||
|
||||
HashMap<UnifyType,UnifyPair> hm;
|
||||
@@ -418,6 +398,7 @@ public class OrderingUnifyPair extends OrderingExtend<Set<UnifyPair>> {
|
||||
}
|
||||
} else {
|
||||
if (!leftlewc.isEmpty()) {
|
||||
/*
|
||||
Set<UnifyPair> subst;
|
||||
subst = leftlewc.stream().map(x -> {
|
||||
if (x.getLhsType() instanceof PlaceholderType) {
|
||||
@@ -426,6 +407,7 @@ 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);
|
||||
}
|
||||
|
@@ -2,11 +2,14 @@ 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;
|
||||
@@ -16,11 +19,12 @@ 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, "");
|
||||
}
|
||||
@@ -54,7 +58,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) {
|
||||
@@ -69,10 +73,11 @@ 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 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());
|
||||
};
|
||||
}
|
||||
|
||||
@@ -83,7 +88,15 @@ public class Logger {
|
||||
*/
|
||||
protected void print(String s, LogLevel logLevel) {
|
||||
String coloredPrefix = this.getPrefix(logLevel);
|
||||
if (logLevel.value > LogLevel.WARNING.value) {
|
||||
|
||||
// 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()) {
|
||||
System.out.println(coloredPrefix + s);
|
||||
}
|
||||
else {
|
||||
@@ -92,11 +105,11 @@ public class Logger {
|
||||
}
|
||||
|
||||
public boolean isLogLevelActive(LogLevel logLevel) {
|
||||
return logLevel.value >= ConsoleInterface.logLevel.value;
|
||||
return logLevel.isHigherOrEqualTo(ConsoleInterface.logLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
@@ -113,6 +126,20 @@ public class Logger {
|
||||
}
|
||||
}
|
||||
|
||||
public String findLogCaller() {
|
||||
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
|
||||
final String thisFileName = stackTrace[0].getFileName();
|
||||
int i = 0;
|
||||
StackTraceElement currentElement = stackTrace[i];
|
||||
while (++i < stackTrace.length) {
|
||||
currentElement = stackTrace[i];
|
||||
if (!Objects.equals(thisFileName, currentElement.getFileName())) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ".(" + currentElement.getFileName() + ":" + currentElement.getLineNumber() + ")";
|
||||
}
|
||||
|
||||
/**
|
||||
* Base method for logging a string value. Should mostly be used by the Logger internal functions that
|
||||
* abstract the logLevel away from the parameters
|
||||
@@ -123,6 +150,8 @@ public class Logger {
|
||||
*/
|
||||
public void log(String s, LogLevel logLevel) {
|
||||
if (isLogLevelActive(logLevel)) {
|
||||
// prepend the call to the logger instance
|
||||
// s = findLogCaller() + "\n" + s;
|
||||
this.print(s, logLevel);
|
||||
this.write(s);
|
||||
}
|
||||
@@ -140,7 +169,7 @@ public class Logger {
|
||||
|
||||
|
||||
/**
|
||||
* Replaces the old FileWriter.write() call
|
||||
* Output a debug message
|
||||
* @param s The string to log
|
||||
*/
|
||||
public void debug(String s) {
|
||||
@@ -154,7 +183,7 @@ public class Logger {
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the old System.out.println() call
|
||||
* Output an info message
|
||||
* @param s The string to log
|
||||
*/
|
||||
public void info(String s) {
|
||||
@@ -195,6 +224,21 @@ 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
|
||||
@@ -208,7 +252,7 @@ public class Logger {
|
||||
" | " + stackTraceElement.toString()
|
||||
).collect(Collectors.joining("\n"));
|
||||
|
||||
// if there will be a cause printed afterward, announce it with the print of the exception
|
||||
// if there is a cause printed afterward, announce it with the print of the exception
|
||||
if (throwable.getCause() != null) {
|
||||
s += "\n\nCaused by: ";
|
||||
}
|
||||
@@ -235,22 +279,50 @@ public class Logger {
|
||||
|
||||
|
||||
/**
|
||||
* An enum representing the different log levels as integers
|
||||
* 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>
|
||||
*/
|
||||
public enum LogLevel {
|
||||
// all the output
|
||||
/** Highly specific output only for debugging */
|
||||
DEBUG(0),
|
||||
// a lot of info about the process
|
||||
/** Informational output about the current state of the program */
|
||||
INFO(1),
|
||||
// warnings and up
|
||||
/** Warnings about potential issues or an unexpected state **/
|
||||
WARNING(2),
|
||||
// only errors and exceptions
|
||||
ERROR(3);
|
||||
/** Invalid states, errors and exceptions */
|
||||
ERROR(3),
|
||||
/** Successfully executed key steps of the program */
|
||||
SUCCESS(4);
|
||||
|
||||
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);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -260,7 +332,7 @@ public class Logger {
|
||||
private static class NullLogger extends Logger {
|
||||
@Override
|
||||
public void log(String s, LogLevel logLevel) {
|
||||
// do nothing. Yay
|
||||
// Do nothing. Yay
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,9 +1,12 @@
|
||||
package server;
|
||||
|
||||
import de.dhbwstuttgart.core.ConsoleInterface;
|
||||
import de.dhbwstuttgart.core.JavaTXCompiler;
|
||||
import de.dhbwstuttgart.core.JavaTXServer;
|
||||
import de.dhbwstuttgart.environment.CompilationEnvironment;
|
||||
import de.dhbwstuttgart.server.SocketClient;
|
||||
import de.dhbwstuttgart.server.packet.SetAutoclosePacket;
|
||||
import de.dhbwstuttgart.server.packet.UnifyRequestPacket;
|
||||
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
|
||||
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
|
||||
import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory;
|
||||
@@ -27,6 +30,7 @@ import java.io.Writer;
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
@@ -39,6 +43,10 @@ import static org.junit.Assert.*;
|
||||
@Ignore("Server tests create huge overhead, so they are ignored until required")
|
||||
public class ServerTest {
|
||||
|
||||
public ServerTest() {
|
||||
ConsoleInterface.unifyServerUrl = Optional.of("ws://localhost:5000");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkServer_Scalar() throws IOException, ClassNotFoundException {
|
||||
compareLocalAndServerResult("Scalar.jav");
|
||||
@@ -52,11 +60,11 @@ public class ServerTest {
|
||||
protected void compareLocalAndServerResult(final String filename) throws IOException, ClassNotFoundException {
|
||||
File file = Path.of(TestCodegen.path.toString(), filename).toFile();
|
||||
|
||||
// get information from compiler
|
||||
// get information from the compiler
|
||||
JavaTXCompiler compiler = new JavaTXCompiler(List.of(file));
|
||||
|
||||
// NOW: simulate the call to method typeInference. Once via server and once locally
|
||||
// if everything works, they should neither interfere with each other, nor differ in their result
|
||||
// if everything works, they should neither interfere with each other nor differ in their result
|
||||
|
||||
// get the values from the compiler
|
||||
PlaceholderRegistry placeholderRegistry = JavaTXCompiler.defaultClientPlaceholderRegistry; //new PlaceholderRegistry();
|
||||
@@ -86,8 +94,10 @@ public class ServerTest {
|
||||
PlaceholderRegistry prCopy = JavaTXCompiler.defaultClientPlaceholderRegistry.deepClone();
|
||||
UnifyResultModel urm = new UnifyResultModel(cons, finiteClosure);
|
||||
UnifyContext context = new UnifyContext(Logger.NULL_LOGGER, true, urm, usedTasks, prCopy);
|
||||
SocketClient socketClient = new SocketClient("ws://localhost:5000");
|
||||
List<ResultSet> serverResult = socketClient.execute(finiteClosure, cons, unifyCons, context);
|
||||
SocketClient.execute(SetAutoclosePacket.create());
|
||||
List<ResultSet> serverResult = SocketClient.executeAndGet(
|
||||
UnifyRequestPacket.create(finiteClosure, cons, unifyCons, context.placeholderRegistry())
|
||||
).getResultSet(context);
|
||||
|
||||
// close the server
|
||||
server.forceStop();
|
||||
|
22
testOut/test.java
Normal file
22
testOut/test.java
Normal file
@@ -0,0 +1,22 @@
|
||||
import java.util.Vector;
|
||||
import java.util.List;
|
||||
|
||||
class Main {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
|
||||
var grid = new Vector<Vector<Boolean>>(List.of(
|
||||
new Vector<Boolean>(List.of(false, false, false)),
|
||||
new Vector<Boolean>(List.of(false, false, false)),
|
||||
new Vector<Boolean>(List.of(false, true, false))
|
||||
));
|
||||
|
||||
BFS img = new BFS();
|
||||
Pos pos = img.search(grid);
|
||||
|
||||
System.out.println("Found at: x=" + pos.x + " | y=" + pos.y);
|
||||
}
|
||||
|
||||
|
||||
}
|
Reference in New Issue
Block a user