Compare commits

...

7 Commits

Author SHA1 Message Date
d6ed0689bc Fix test
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 1m33s
2025-07-23 11:56:34 +02:00
d7676f36e3 Fix #371
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 1m55s
2025-07-23 11:44:10 +02:00
julian
9e323759d6 sort resultsets before printing them to the console to enhance comparability between results
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 1m28s
2025-07-16 11:17:53 +02:00
558083166d Fix subtyping of function types
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 1m45s
2025-07-15 15:02:15 +02:00
julian
aec2f9a399 adjust FiniteClosure to only use imported types + some necessary ones
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 1m37s
2025-07-15 14:06:51 +02:00
pl@gohorb.ba-horb.de
31df7a65f0 deleted: ../resources/bytecode/javFiles/Bug365a.jav
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 10m24s
modified:   ../src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java
	modified:   ../src/test/java/TestComplete.java
2025-07-08 17:44:55 +02:00
pl@gohorb.ba-horb.de
185989ba62 --- a/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java
+++ b/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java
@@ -73,7 +73,7 @@ public class TYPEStmt implements StatementVisitor {

     @Override
     public void visit(LambdaExpression lambdaExpression) {
-        TypePlaceholder tphRetType = TypePlaceholder.fresh(new NullToken());
+        TypePlaceholder tphRetType = TypePlaceholder.fresh(new NullToken(), -1, false);
         List<RefTypeOrTPHOrWildcardOrGeneric> lambdaParams = lambdaExpression.params.getFormalparalist().stream().map((formalParameter -> formalParameter.getType())).collect(Collectors.toList());
         lambdaParams.add(tphRetType);
         // lambdaParams.add(0,tphRetType);
@@ -635,6 +635,7 @@ public class TYPEStmt implements StatementVisitor {
             params.add(resolver.resolve(new GenericRefType(gtv.getName(), new NullToken())));
         }
         RefTypeOrTPHOrWildcardOrGeneric receiverType;

	modified:   ../src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java
2025-07-08 14:32:05 +02:00
17 changed files with 729 additions and 648 deletions

View File

@@ -1,12 +1,13 @@
import java.lang.String;
import java.lang.Object;
public class Bug365{
swap(f){
return x -> y -> f.apply(y).apply(x);
}
swap(f){
return x -> y -> z -> f.apply(z).apply(x).apply(y);
swap(Fun1$$<String, Fun1$$<String, Fun1$$<String, Object>>> f){
return x -> y -> z -> f.apply(z).apply(y).apply(x);
}
public ex1() {

View File

@@ -1,13 +0,0 @@
import java.lang.String;
public class Bug365a{
swap(f){
return x -> y -> f.apply(y).apply(x);
}
public ex2() {
var func = x -> y -> x + y;
return swap(func).apply("A").apply("B");
}
}

View File

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

View File

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

View File

@@ -39,6 +39,10 @@ public class FunNGenerator {
public final List<TargetType> inParams;
public final List<TargetType> realParams;
public GenericParameters(TargetFunNType funNType) {
this(funNType.funNParams(), funNType.returnArguments());
}
public GenericParameters(List<TargetType> params, int numReturns) {
this.realParams = params;
this.inParams = flattenTypeParams(params);

View File

@@ -393,7 +393,12 @@ public class JavaTXCompiler {
logFile.write(ASTTypePrinter.print(sf));
System.out.println(ASTTypePrinter.print(sf));
logFile.flush();
System.out.println("Unify nach Oder-Constraints-Anpassung:" + unifyCons.toString());
List<UnifyPair> andConstraintsSorted = unifyCons.getUndConstraints().stream()
.sorted(Comparator.comparing(UnifyPair::getPairOp).thenComparing(UnifyPair::getLhsType, Comparator.comparing(UnifyType::getName)))
.collect(Collectors.toList());
System.out.println(andConstraintsSorted);
Set<PlaceholderType> varianceTPHold;
Set<PlaceholderType> varianceTPH = new HashSet<>();
varianceTPH = varianceInheritanceConstraintSet(unifyCons);
@@ -416,7 +421,14 @@ public class JavaTXCompiler {
UnifyResultListenerImpl li = new UnifyResultListenerImpl();
urm.addUnifyResultListener(li);
unify.unifyParallel(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, logFile, log, urm, usedTasks);
System.out.println("RESULT Final: " + li.getResults());
//System.out.println("RESULT Final: " + li.getResults());
var finalResults = li.getResults().stream().sorted().toList();
int i = 0;
System.out.println("RESULT Final: ");
for (var result : finalResults){
System.out.println("Result: " + i++);
System.out.println(result.getSortedResults());
}
System.out.println("Constraints for Generated Generics: " + " ???");
logFile.write("RES_FINAL: " + li.getResults().toString() + "\n");
logFile.flush();

View File

@@ -1099,9 +1099,9 @@ public class StatementGenerator {
block = lambdaGenerator.convert(expression.lambdaBody().block(), true);
}
List<RefTypeOrTPHOrWildcardOrGeneric> funNParams = new ArrayList<>();
funNParams.add(TypePlaceholder.fresh(expression.getStart()));// ret-Type
funNParams.add(TypePlaceholder.fresh(expression.getStart(), -1, false));// ret-Type
params.getFormalparalist().forEach(formalParameter -> // Für jeden Parameter einen TPH anfügen:
funNParams.add(TypePlaceholder.fresh(expression.getStart())));
funNParams.add(TypePlaceholder.fresh(expression.getStart(), 1, false)));
RefTypeOrTPHOrWildcardOrGeneric lambdaType = TypePlaceholder.fresh(expression.getStart());
// RefType lambdaType = new
// RefType(reg.getName("Fun"+params.getFormalparalist().size()),

View File

@@ -22,6 +22,10 @@ public class JavaClassRegistry {
}
}
public Set<JavaClassName> getAllClassNames(){
return existingClasses.keySet();
}
public void addName(String className, int numberOfGenerics) {
existingClasses.put(new JavaClassName(className), numberOfGenerics);
}

View File

@@ -11,6 +11,8 @@ import de.dhbwstuttgart.syntaxtree.Record;
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
import de.dhbwstuttgart.syntaxtree.statement.*;
import de.dhbwstuttgart.syntaxtree.type.*;
import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter;
import de.dhbwstuttgart.syntaxtree.visual.OutputGenerator;
import de.dhbwstuttgart.target.tree.*;
import de.dhbwstuttgart.target.tree.expression.*;
import de.dhbwstuttgart.target.tree.type.*;
@@ -780,7 +782,15 @@ public class ASTToTargetAST {
return TargetFunNType.fromParams(params, filteredParams, gep.getReturnType() != null ? 1 : 0);
}
private FunNGenerator.GenericParameters convertToParameters(TargetFunNType input) {
return null;
}
private boolean isSubtype(TargetType test, TargetType other) {
if (other.equals(TargetType.Object)) return true;
if (test instanceof TargetFunNType tfun && other instanceof TargetFunNType ofun)
return isSubtype(new FunNGenerator.GenericParameters(tfun), new FunNGenerator.GenericParameters(ofun));
var testClass = compiler.getClass(new JavaClassName(test.name()));
var otherClass = compiler.getClass(new JavaClassName(other.name()));
if (testClass == null) return false;

View File

@@ -138,7 +138,10 @@ public class StatementToTargetExpression implements ASTVisitor {
@Override
public void visit(BoolExpression bool) {
System.out.println("BoolExpression");
result = switch(bool.operation) {
case OR -> new TargetBinaryOp.Or(converter.convert(bool.getType()), converter.convert(bool.lexpr), converter.convert(bool.rexpr));
case AND -> new TargetBinaryOp.And(converter.convert(bool.getType()), converter.convert(bool.lexpr), converter.convert(bool.rexpr));
};
}
@Override

View File

@@ -6,7 +6,7 @@ import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
public class Constraint<A> extends HashSet<A> {
public class Constraint<A> extends HashSet<A> implements Comparable<Constraint<A>> {
private static final long serialVersionUID = 1L;
private Boolean isInherited = false;//wird beides nur für die Method-Constraints benoetigt
private Boolean isImplemented = false;
@@ -74,4 +74,8 @@ public class Constraint<A> extends HashSet<A> {
return super.toString();
}
@Override
public int compareTo(Constraint<A> o) {
return this.toString().compareTo(o.toString());
}
}

View File

@@ -5,7 +5,7 @@ import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
/**
* Paare, welche das Unifikationsergebnis darstellen
*/
public abstract class ResultPair<A extends RefTypeOrTPHOrWildcardOrGeneric,B extends RefTypeOrTPHOrWildcardOrGeneric> {
public abstract class ResultPair<A extends RefTypeOrTPHOrWildcardOrGeneric, B extends RefTypeOrTPHOrWildcardOrGeneric> implements Comparable<ResultPair<A,B>> {
private final A left;
private final B right;
@@ -59,4 +59,13 @@ public abstract class ResultPair<A extends RefTypeOrTPHOrWildcardOrGeneric,B ext
return true;
}
@Override
public int compareTo(ResultPair<A, B> o) {
if (o == null) {
return 1; // this is greater than null
}
return o.left.toString().compareTo(this.left.toString());
}
}

View File

@@ -1,6 +1,8 @@
package de.dhbwstuttgart.typeinference.result;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import de.dhbwstuttgart.exceptions.NotImplementedException;
@@ -12,7 +14,7 @@ import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
@SuppressWarnings("rawtypes")
public class ResultSet {
public class ResultSet implements Comparable<ResultSet>{
public final Set<ResultPair> results;
public Set<ResultPair<TypePlaceholder, TypePlaceholder>> genIns;
@@ -23,6 +25,10 @@ public class ResultSet {
results.forEach(x -> { if (x instanceof PairTPHsmallerTPH) { this.genIns.add(x);}} );
}
public List<ResultPair> getSortedResults() {
return results.stream().sorted().toList();
}
public boolean contains(ResultPair toCheck) {
return this.results.contains(toCheck);
}
@@ -63,6 +69,21 @@ public class ResultSet {
public int hashCode() {
return results.hashCode();
}
@Override
public int compareTo(ResultSet o) {
List<ResultPair> thisSorted = this.getSortedResults();
List<ResultPair> otherSorted = o.getSortedResults();
int sizeCompare = Integer.compare(thisSorted.size(), otherSorted.size());
if (sizeCompare != 0) return sizeCompare;
for (int i = 0; i < thisSorted.size(); i++) {
int cmp = thisSorted.get(i).compareTo(otherSorted.get(i));
if (cmp != 0) return cmp;
}
return 0;
}
}
class Resolver implements ResultSetVisitor {

View File

@@ -73,7 +73,7 @@ public class TYPEStmt implements StatementVisitor {
@Override
public void visit(LambdaExpression lambdaExpression) {
TypePlaceholder tphRetType = TypePlaceholder.fresh(new NullToken());
TypePlaceholder tphRetType = TypePlaceholder.fresh(new NullToken(), -1, false);
List<RefTypeOrTPHOrWildcardOrGeneric> lambdaParams = lambdaExpression.params.getFormalparalist().stream().map((formalParameter -> formalParameter.getType())).collect(Collectors.toList());
lambdaParams.add(tphRetType);
// lambdaParams.add(0,tphRetType);
@@ -635,18 +635,8 @@ public class TYPEStmt implements StatementVisitor {
params.add(resolver.resolve(new GenericRefType(gtv.getName(), new NullToken())));
}
RefTypeOrTPHOrWildcardOrGeneric receiverType;
//alle Variance auf COntravariant setzen
if (receiver instanceof FunNClass) {
params.forEach(x -> {
if (x instanceof TypePlaceholder) {
((TypePlaceholder) x).setVariance(1);
}}
);
//Returntyp auf Contravariance setzen.
RefTypeOrTPHOrWildcardOrGeneric para;
if ((para= params.getLast()) instanceof TypePlaceholder) {
((TypePlaceholder) para).setVariance(-1);
}
receiverType = new RefType(new JavaClassName(receiver.getClassName().toString() + "$$"), params, new NullToken()); // new FunN(params);
} else {
receiverType = new RefType(receiver.getClassName(), params, new NullToken());

View File

@@ -5,14 +5,7 @@ import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.Modifier;
import java.sql.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.BinaryOperator;
import java.util.function.Predicate;
@@ -40,6 +33,7 @@ import org.apache.commons.io.output.NullWriter;
/**
* The finite closure for the type unification
*
* @author Florian Steurer
*/
public class FiniteClosure //extends Ordering<UnifyType> //entfernt PL 2018-12-11
@@ -49,9 +43,11 @@ implements IFiniteClosure {
Writer logFile;
static Boolean log = false;
public void setLogTrue() {
log = true;
}
/**
* A map that maps every type to the node in the inheritance graph that contains that type.
*/
@@ -127,8 +123,49 @@ implements IFiniteClosure {
childNode.getDescendants().stream().forEach(x -> x.addPredecessor(parentNode));
//PL eingefuegt 2020-05-07 File UnitTest InheritTest.java
this.inheritanceGraph.forEach((x,y) -> { if (y.getDescendants().contains(parentNode)) { y.addDescendant(childNode); y.addAllDescendant(childNode.getDescendants());};
if (y.getPredecessors().contains(childNode)) { y.addPredecessor(parentNode); y.addAllPredecessor(parentNode.getPredecessors());};} );
this.inheritanceGraph.forEach((x, y) -> {
if (y.getDescendants().contains(parentNode)) {
y.addDescendant(childNode);
y.addAllDescendant(childNode.getDescendants());
}
;
if (y.getPredecessors().contains(childNode)) {
y.addPredecessor(parentNode);
y.addAllPredecessor(parentNode.getPredecessors());
}
;
});
}
List<String> classesToKeep = new ArrayList<>(compiler.classRegistry.getAllClassNames().stream().map(JavaClassName::toString).toList());
classesToKeep.add("java.lang.Object");
classesToKeep.add("java.lang.Number");
classesToKeep.add("java.util.Collection");
classesToKeep.add("java.lang.Iterable");
//filter out all types not imported
Iterator<Map.Entry<UnifyType, Node<UnifyType>>> iterator = inheritanceGraph.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<UnifyType, Node<UnifyType>> entry = iterator.next();
var name = entry.getKey().getName();
if (!classesToKeep.contains(name)) {
iterator.remove();
} else {
Node<UnifyType> node = entry.getValue();
// Remove unwanted predecessors
node.getPredecessors().removeIf(pred ->
!classesToKeep.contains(pred.getContent().getName())
);
// Remove unwanted descendants
node.getDescendants().removeIf(desc ->
!classesToKeep.contains(desc.getContent().getName())
);
}
}
// Build the alternative representation with strings as keys
@@ -159,6 +196,7 @@ implements IFiniteClosure {
/**
* Returns all types of the finite closure that are subtypes of the argument.
*
* @return The set of subtypes of the argument.
*/
@Override
@@ -205,8 +243,7 @@ implements IFiniteClosure {
// if T = T' then T <* T'
try {
result.add(new Pair<>(t, fBounded));
}
catch (StackOverflowError e) {
} catch (StackOverflowError e) {
System.out.println("");
}
@@ -273,6 +310,7 @@ implements IFiniteClosure {
/**
* Returns all types of the finite closure that are supertypes of the argument.
*
* @return The set of supertypes of the argument.
*/
@Override
@@ -371,8 +409,7 @@ implements IFiniteClosure {
//F-Bounded Endlosrekursion
HashSet<UnifyType> res = new HashSet<UnifyType>();
paramCandidates.add(res);
}
else {
} else {
paramCandidates.add(grArg(t.getTypeParams().get(i), new HashSet<>(fBounded)));
}
}
@@ -656,6 +693,7 @@ implements IFiniteClosure {
/**
* Takes a set of candidates for each position and computes all possible permutations.
*
* @param candidates The length of the list determines the number of type params. Each set
* contains the candidates for the corresponding position.
*/
@@ -667,6 +705,7 @@ implements IFiniteClosure {
/**
* Takes a set of candidates for each position and computes all possible permutations.
*
* @param candidates The length of the list determines the number of type params. Each set
* contains the candidates for the corresponding position.
* @param idx Idx for the current permutatiton.
@@ -699,7 +738,10 @@ implements IFiniteClosure {
*/
public int compare(UnifyType left, UnifyType right, PairOperator pairop) {
try {logFile.write("left: "+ left + " right: " + right + " pairop: " + pairop +"\n");} catch (IOException ie) {}
try {
logFile.write("left: " + left + " right: " + right + " pairop: " + pairop + "\n");
} catch (IOException ie) {
}
if (left.getName().equals("Matrix") || right.getName().equals("Matrix"))
System.out.println("");
/*
@@ -736,8 +778,7 @@ implements IFiniteClosure {
&& ((ex = ((WildcardType) right).wildcardedType) instanceof PlaceholderType)
&& ((PlaceholderType) left).getName().equals(((PlaceholderType) ex).getName())) {// a <.? ? extends a oder a <.? ? super a
return -1;
}
else {
} else {
return 0;
}
}
@@ -746,8 +787,7 @@ implements IFiniteClosure {
&& ((ex = ((WildcardType) left).wildcardedType) instanceof PlaceholderType)
&& ((PlaceholderType) right).getName().equals(((PlaceholderType) ex).getName())) {// ? extends a <. a oder ? super a <. a
return 1;
}
else {
} else {
return 0;
}
}
@@ -758,12 +798,14 @@ implements IFiniteClosure {
Set<UnifyPair> smallerRes = unifyTask.applyTypeUnificationRules(hs, this);
//if (left.getName().equals("Vector") || right.getName().equals("AbstractList"))
{try {
{
try {
logFile.write("\nsmallerRes: " + smallerRes);//"smallerHash: " + greaterHash.toString());
logFile.flush();
} catch (IOException e) {
System.err.println("no LogFile");
}
}
catch (IOException e) {
System.err.println("no LogFile");}}
//Gleichungen der Form a <./=. Theta oder Theta <./=. a oder a <./=. b sind ok.
Predicate<UnifyPair> delFun = x -> !((x.getLhsType() instanceof PlaceholderType ||
@@ -775,9 +817,9 @@ implements IFiniteClosure {
try {
logFile.write("\nsmallerLen: " + smallerLen + "\n");
logFile.flush();
} catch (IOException e) {
System.err.println("no LogFile");
}
catch (IOException e) {
System.err.println("no LogFile");}
if (smallerLen == 0) return -1;
else {
up = new UnifyPair(right, left, pairop);
@@ -787,12 +829,14 @@ implements IFiniteClosure {
Set<UnifyPair> greaterRes = unifyTask.applyTypeUnificationRules(hs, this);
//if (left.getName().equals("Vector") || right.getName().equals("AbstractList"))
{try {
{
try {
logFile.write("\ngreaterRes: " + greaterRes);//"smallerHash: " + greaterHash.toString());
logFile.flush();
} catch (IOException e) {
System.err.println("no LogFile");
}
}
catch (IOException e) {
System.err.println("no LogFile");}}
//Gleichungen der Form a <./=. Theta oder Theta <./=. a oder a <./=. b sind ok.
long greaterLen = greaterRes.stream().filter(delFun).count();

View File

@@ -1441,18 +1441,8 @@ public class TestComplete {
var instance = clazz.getDeclaredConstructor().newInstance();
var m = clazz.getDeclaredMethod("ex1");
assertEquals("ABC", m.invoke(instance));
//var ex2 = clazz.getDeclaredMethod("ex2");
//assertEquals(0.0, ex2.invoke(instance));
}
@Test
public void testBug365a() throws Exception {
var classFiles = generateClassFiles(createClassLoader(), "Bug365a.jav");
var clazz = classFiles.get("Bug365");
var instance = clazz.getDeclaredConstructor().newInstance();
var m = clazz.getDeclaredMethod("ex1");
assertEquals("ABC", m.invoke(instance));
//var ex2 = clazz.getDeclaredMethod("ex2");
//assertEquals(0.0, ex2.invoke(instance));
var ex2 = clazz.getDeclaredMethod("ex2");
assertEquals("BAC", ex2.invoke(instance));
}
@Test
public void testBug366() throws Exception {
@@ -1461,4 +1451,12 @@ public class TestComplete {
var m = clazz.getDeclaredMethod("test");
assertEquals(30, m.invoke(null));
}
@Test
public void testBug371() throws Exception {
var classFiles = generateClassFiles(createClassLoader(), "Bug371.jav");
var clazz = classFiles.get("Bug371");
var m = clazz.getDeclaredMethod("test");
assertEquals(true, m.invoke(null));
}
}