forked from i21017/JavaCompilerCore
Compare commits
4 Commits
feat/unify
...
feat/unify
Author | SHA1 | Date | |
---|---|---|---|
|
1af31e4513 | ||
|
5b06f0a249 | ||
|
512b10542e | ||
|
3b1185d9d0 |
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));
|
||||
}
|
||||
|
||||
}
|
@@ -24,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;
|
||||
@@ -100,6 +101,8 @@ public class JavaTXCompiler {
|
||||
public JavaTXCompiler(List<File> sources, List<File> contextPath, File outputPath) throws IOException, ClassNotFoundException {
|
||||
// ensure new default placeholder registry for tests
|
||||
defaultClientPlaceholderRegistry = new PlaceholderRegistry();
|
||||
NameGenerator.reset();
|
||||
ASTToTargetAST.OBJECT = ASTFactory.createObjectType();
|
||||
|
||||
var path = new ArrayList<>(contextPath);
|
||||
if (contextPath.isEmpty()) {
|
||||
|
@@ -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) {
|
||||
|
@@ -1,6 +1,8 @@
|
||||
package de.dhbwstuttgart.typeinference.unify.cartesianproduct;
|
||||
|
||||
import de.dhbwstuttgart.exceptions.UnifyCancelException;
|
||||
import de.dhbwstuttgart.typeinference.constraints.Constraint;
|
||||
import de.dhbwstuttgart.typeinference.unify.TypeUnify2Task;
|
||||
import de.dhbwstuttgart.typeinference.unify.TypeUnifyTask;
|
||||
import de.dhbwstuttgart.typeinference.unify.UnifyContext;
|
||||
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
|
||||
@@ -13,12 +15,15 @@ import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class UnknownVarianceCase extends VarianceCase {
|
||||
|
||||
protected final int variance = 0;
|
||||
|
||||
protected final AtomicBoolean shouldBreak = new AtomicBoolean(false);
|
||||
|
||||
protected UnknownVarianceCase(boolean isOderConstraint, TypeUnifyTask typeUnifyTask, UnifyContext context) {
|
||||
super(isOderConstraint, typeUnifyTask, context);
|
||||
}
|
||||
@@ -46,6 +51,28 @@ public class UnknownVarianceCase extends VarianceCase {
|
||||
} else {
|
||||
a = nextSetAsList.removeFirst();
|
||||
}
|
||||
|
||||
Set<UnifyPair> finalA = a;
|
||||
if (!this.isOderConstraint && optOrigPair != null && optOrigPair.isPresent()) {
|
||||
if (optOrigPair.get().getBasePair().getLhsType() instanceof PlaceholderType) {
|
||||
nextSetasListRest = typeUnifyTask.oup.maxElements(
|
||||
nextSetAsList.stream().filter(a_next -> typeUnifyTask.oup.compare(finalA, a_next) != 1).toList()
|
||||
);
|
||||
} else {
|
||||
nextSetasListRest = typeUnifyTask.oup.minElements(
|
||||
nextSetAsList.stream().filter(a_next -> typeUnifyTask.oup.compare(finalA, a_next) != -1).toList()
|
||||
);
|
||||
}
|
||||
} else if (this.isOderConstraint) {
|
||||
nextSetasListRest = typeUnifyTask.oup.maxElements(
|
||||
nextSetAsList.stream().filter(a_next -> typeUnifyTask.oup.compare(finalA, a_next) != 1).toList()
|
||||
);
|
||||
} else {
|
||||
nextSetasListRest = (nextSetAsList.size() > 5) ? nextSetAsList.subList(0, 5) : nextSetAsList;
|
||||
}
|
||||
|
||||
nextSetAsList.removeAll(nextSetasListRest);
|
||||
// */
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -61,9 +88,98 @@ public class UnknownVarianceCase extends VarianceCase {
|
||||
Set<Set<UnifyPair>> result,
|
||||
Set<Set<UnifyPair>> aParDef
|
||||
) {
|
||||
elems.add(a);
|
||||
return typeUnifyTask.unify2(elems, eq, oderConstraints, fc, context.parallel(), rekTiefe, new HashSet<>(methodSignatureConstraint))
|
||||
.thenApply(ComputationResults::new);
|
||||
Set<UnifyPair> newEqOrig = new HashSet<>(eq);
|
||||
Set<Set<UnifyPair>> newElemsOrig = new HashSet<>(elems);
|
||||
List<Set<Constraint<UnifyPair>>> newOderConstraintsOrig = new ArrayList<>(oderConstraints);
|
||||
newElemsOrig.add(a);
|
||||
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);
|
||||
CompletableFuture<Set<Set<UnifyPair>>> forkOrigFuture = CompletableFuture.supplyAsync(forkOrig::compute, context.executor()).thenCompose(f -> f);
|
||||
CompletableFuture<ComputationResults> resultValues = forkOrigFuture.thenApply(
|
||||
(currentThreadResult) -> {
|
||||
forkOrig.context.logger().debug("final Orig 0");
|
||||
forkOrig.closeLogFile();
|
||||
return new ComputationResults(currentThreadResult);
|
||||
});
|
||||
|
||||
int i = 0;
|
||||
Set<Set<UnifyPair>>[] additionalResults = new HashSet[nextSetasListRest.size()];
|
||||
Constraint<UnifyPair>[] extendConstraints = new Constraint[nextSetasListRest.size()];
|
||||
while (!nextSetasListRest.isEmpty()) {
|
||||
final int finalI = i++;
|
||||
|
||||
Set<UnifyPair> nSaL = nextSetasListRest.removeFirst();
|
||||
context.logger().debug(() -> "0 RM" + nSaL.toString());
|
||||
|
||||
if (this.isOderConstraint) {
|
||||
Constraint<UnifyPair> extendConstraint = ((Constraint<UnifyPair>) nSaL).getExtendConstraint();
|
||||
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);
|
||||
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, (compResult, forkResult) -> {
|
||||
additionalResults[finalI] = forkResult;
|
||||
context.logger().error("finalI: " + finalI);
|
||||
return compResult;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
@@ -100,10 +216,25 @@ public class UnknownVarianceCase extends VarianceCase {
|
||||
nextSetAsList.removeAll(erased);
|
||||
|
||||
context.logger().debug("Removed: " + erased);
|
||||
|
||||
context.logger().debug("Not Removed: " + nextSetAsList);
|
||||
|
||||
for (Set<UnifyPair> aPar : aParDef) {
|
||||
smallerSetasList.clear();
|
||||
smallerSetasList.addAll(typeUnifyTask.oup.smallerThan(aPar, nextSetAsList));
|
||||
notInherited = smallerSetasList.stream()
|
||||
.filter(x -> !((Constraint<UnifyPair>) x).isInherited())
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
notErased.clear();
|
||||
notInherited.forEach(x -> notErased.addAll(typeUnifyTask.oup.smallerEqThan(x, smallerSetasList)));
|
||||
erased = new ArrayList<>(smallerSetasList);
|
||||
erased.removeAll(notErased);
|
||||
nextSetAsList.removeAll(erased);
|
||||
context.logger().debug("Removed: " + erased);
|
||||
context.logger().debug("Not Removed: " + nextSetAsList);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@@ -126,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
|
||||
@@ -136,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);
|
||||
}
|
||||
|
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