Compare commits

..

24 Commits

Author SHA1 Message Date
61653c5d88 modified: src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java 2023-05-25 10:05:10 +02:00
3cd608a4ac modified: src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnify.java
modified:   src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java
2023-05-15 16:56:04 +02:00
deec0ae706 Start branch unif23NoOptParallel
modified:   Makefile
	modified:   src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java
	modified:   src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java
2023-04-24 17:18:45 +02:00
d6a79ea3a1 modified: src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java 2023-04-11 22:45:15 +02:00
1f909f13ee modified: src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java 2023-04-11 18:01:44 +02:00
be6f4bd578 Merge remote-tracking branch 'origin/targetBytecode' into unif23 2023-04-11 15:52:26 +02:00
478efd5649 Merge branch 'unif23' of ssh://gohorb.ba-horb.de/bahome/projekt/git/JavaCompilerCore into unif23 2023-04-11 15:40:27 +02:00
c73e57cf2b new file: resources/bytecode/javFiles/Scalar.jav 2023-04-11 15:35:15 +02:00
ce29f4bcf1 Merge branch 'unif23' of ssh://gohorb.ba-horb.de/bahome/projekt/git/JavaCompilerCore into Unif23
Conflicts:
	src/test/java/targetast/TestComplete.java
2023-04-10 22:14:46 +02:00
42821f3215 modified: src/main/java/de/dhbwstuttgart/typeinference/unify/RuleSet.java
modified:   src/test/java/targetast/TestComplete.java
2023-04-10 22:07:47 +02:00
f68afc88a6 modified: src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java 2023-04-06 17:58:32 +02:00
82061474b2 modified: resources/bytecode/javFiles/Scalar.jav
modified:   src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java
2023-04-04 17:26:13 +02:00
d849bc127f Merge remote-tracking branch 'origin/targetBytecode' into unif23 2023-04-04 16:47:19 +02:00
6815d8fc0a modified: Makefile
modified:   src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java
2023-03-31 17:58:02 +02:00
317f8b1aad new file: Makefile
deleted:    Test.java
	modified:   src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java
2023-03-31 15:54:17 +02:00
79335449d0 modified: src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java
Statistics fertig (Version 1)
2023-03-23 12:00:04 +01:00
14606a846e modified: src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java
modified:   src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnify.java
	modified:   src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnify2Task.java
	modified:   src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java
2023-03-22 19:01:36 +01:00
2b67230a15 Consider public and standard constructors ones 2023-03-21 16:31:45 +01:00
29b05b56cc Merge branch 'targetBytecode' into unif23 2023-03-21 16:29:14 +01:00
08b9fc0ea3 modified: src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java
statistics eingefuegt
2023-03-21 16:23:18 +01:00
070dd16999 modified: src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java 2023-03-21 10:30:13 +01:00
9d7e46925d modified: src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java 2023-03-21 10:26:55 +01:00
d780d322f0 modified: src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java
modified:   src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java
2023-03-20 18:33:58 +01:00
867f3d39e8 modified: src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java
modified:   src/test/java/targetast/TestComplete.java
2023-03-20 16:05:28 +01:00
25 changed files with 257 additions and 632 deletions

3
Makefile Normal file

@ -0,0 +1,3 @@
NoOptParallel:
mvn -DskipTests package
cp target/JavaTXcompiler-0.1-jar-with-dependencies.jar target/JavaTXcompiler-0.1-jar-with-dependencies_NoOptParallel.jar

@ -1,4 +1,4 @@
import java.util.Vector;
//import java.util.Vector;
import java.lang.Integer;
import java.lang.Float;
//import java.lang.Byte;
@ -6,21 +6,11 @@ import java.lang.Float;
public class Scalar extends Vector<Integer> {
Scalar(v) {
Integer i;
i = 0;
while(i < v.size()) {
this.add(v.elementAt(i));
i=i+1;
}
}
mul(v) {
var ret = 0;
var i = 0;
while(i < size()) {
ret = ret + this.elementAt(i) * v.elementAt(i);
i = i+1;
}
return ret;
}

@ -1,11 +0,0 @@
import java.lang.String;
class TXGenerics {
a;
b;
test() {
var c = new Cycle();
c.m(a, b);
}
}

@ -5,7 +5,7 @@ public class TestContraVariant {
x = y;
return y;
}
main(x) {
return m(x);
}

@ -1,12 +1,10 @@
public class TestTwoCalls {
// <O> O -> O
id(b) {
var c = b;
return c;
}
// <T, S> (S, T) -> T
main(x,y) {
id(x);
return id(y);

@ -1000,7 +1000,7 @@ public class Codegen {
private void generateConstructor(TargetConstructor constructor) {
MethodVisitor mv = cw.visitMethod(constructor.access() | ACC_PUBLIC, "<init>", constructor.getDescriptor(), constructor.getSignature(), null);
if (constructor.txGenerics() != null)
mv.visitAttribute(new JavaTXSignatureAttribute(constructor.getTXSignature()));
mv.visitAttribute(new JavaTXSignatureAttribute(cw.newConst(constructor.getTXSignature())));
mv.visitCode();
var state = new State(null, mv, 1);
@ -1027,7 +1027,7 @@ public class Codegen {
// TODO The older codegen has set ACC_PUBLIC for all methods, good for testing but bad for everything else
MethodVisitor mv = cw.visitMethod(method.access() | ACC_PUBLIC, method.name(), method.getDescriptor(), method.getSignature(), null);
if (method.txSignature() != null) {
mv.visitAttribute(new JavaTXSignatureAttribute(method.getTXSignature()));
mv.visitAttribute(new JavaTXSignatureAttribute(cw.newConst(method.getTXSignature())));
}
System.out.println(method.getDescriptor());
@ -1044,14 +1044,11 @@ public class Codegen {
}
private static String generateSignature(TargetClass clazz, Set<TargetGeneric> generics) {
String ret = "";
if (generics.size() > 0) {
ret += "<";
for (var generic : generics) {
ret += generic.name() + ":" + generic.bound().toDescriptor();
}
ret += ">";
String ret = "<";
for (var generic : generics) {
ret += generic.name() + ":" + generic.bound().toDescriptor();
}
ret += ">";
ret += clazz.superType().toDescriptor();
return ret;
@ -1063,7 +1060,7 @@ public class Codegen {
clazz.implementingInterfaces().stream().map(TargetType::toSignature).toArray(String[]::new)
);
if (clazz.txGenerics() != null)
cw.visitAttribute(new JavaTXSignatureAttribute(generateSignature(clazz, clazz.txGenerics())));
cw.visitAttribute(new JavaTXSignatureAttribute(cw.newConst(generateSignature(clazz, clazz.txGenerics()))));
clazz.fields().forEach(this::generateField);
clazz.constructors().forEach(this::generateConstructor);

@ -3,13 +3,10 @@ package de.dhbwstuttgart.bytecode;
import org.objectweb.asm.*;
public class JavaTXSignatureAttribute extends Attribute {
public String signature;
final int signature;
public JavaTXSignatureAttribute() {
protected JavaTXSignatureAttribute(int signature) {
super("JavaTXSignature");
}
protected JavaTXSignatureAttribute(String signature) {
this();
this.signature = signature;
}
@ -17,14 +14,13 @@ public class JavaTXSignatureAttribute extends Attribute {
protected Attribute read(ClassReader classReader, int offset, int length, char[] charBuffer, int codeAttributeOffset, Label[] labels) {
var data = new byte[length];
System.arraycopy(classReader.b, offset, data, 0, length);
var constantPoolOffset = data[0] << 8 | data[1];
return new JavaTXSignatureAttribute((String) classReader.readConst(constantPoolOffset, charBuffer));
return new JavaTXSignatureAttribute(data[0] << 8 | data[1]);
}
@Override
protected ByteVector write(ClassWriter classWriter, byte[] code, int codeLength, int maxStack, int maxLocals) {
var data = new ByteVector();
data.putShort(classWriter.newConst(this.signature));
data.putShort(this.signature);
return data;
}
}

@ -58,6 +58,7 @@ import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.sql.Timestamp;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@ -69,11 +70,12 @@ public class JavaTXCompiler {
//public static JavaTXCompiler INSTANCE;
final CompilationEnvironment environment;
Boolean resultmodel = false;
Boolean resultmodel = true;
public final Map<File, SourceFile> sourceFiles = new HashMap<>();
Boolean log = false; //gibt an ob ein Log-File nach System.getProperty("user.dir")+""/logFiles/"" geschrieben werden soll?
public volatile UnifyTaskModel usedTasks = new UnifyTaskModel();
private final DirectoryClassLoader classLoader;
static Writer statistics;
public JavaTXCompiler(File sourceFile) throws IOException, ClassNotFoundException {
this(Arrays.asList(sourceFile), null);
@ -86,6 +88,8 @@ public class JavaTXCompiler {
this(sourceFiles, null);
}
public JavaTXCompiler(List<File> sources, List<File> contextPath) throws IOException, ClassNotFoundException {
statistics = new FileWriter(new File(System.getProperty("user.dir") + "/" + sources.get(0).getName() + "_"+ new Timestamp(System.currentTimeMillis())));
statistics.write("test");
if(contextPath == null || contextPath.isEmpty()){
//When no contextPaths are given, the working directory is the sources root
contextPath = Lists.newArrayList(new File(System.getProperty("user.dir")));
@ -578,6 +582,7 @@ public class JavaTXCompiler {
unifyCons = unifyCons.map(distributeInnerVars);
logFile.write("\nUnify_distributeInnerVars: " + unifyCons.toString());
TypeUnify unify = new TypeUnify();
unify.statistics = statistics;
// Set<Set<UnifyPair>> results = new HashSet<>(); Nach vorne gezogen
logFile.write("FC:\\" + finiteClosure.toString() + "\n");
for (SourceFile sf : this.sourceFiles.values()) {
@ -730,6 +735,7 @@ public class JavaTXCompiler {
System.out.println("Constraints for Generated Generics: " + " ???");
logFile.write("RES_FINAL: " + li.getResults().toString() + "\n");
logFile.flush();
statistics.close();
return li.getResults();
}
/* UnifyResultModel End */
@ -765,6 +771,7 @@ public class JavaTXCompiler {
} catch (IOException e) {
System.err.println("kein LogFile");
}
statistics.close();
return results.stream()
.map((unifyPairs -> new ResultSet(UnifyTypeFactory.convert(unifyPairs, Pair.generateTPHMap(cons)))))
.collect(Collectors.toList());

@ -49,17 +49,4 @@ public class GenericDeclarationList extends SyntaxTreeNode implements Iterable<G
public String toString() {
return this.gtvs.toString();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
GenericDeclarationList that = (GenericDeclarationList) o;
return gtvs.equals(that.gtvs);
}
@Override
public int hashCode() {
return Objects.hash(gtvs);
}
}

@ -6,7 +6,6 @@ import org.antlr.v4.runtime.Token;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* Entspricht einem GenericTypeVar, jedoch mit Bounds
@ -46,7 +45,7 @@ public class GenericTypeVar extends SyntaxTreeNode
public String toString()
{
return "BoGTV " + this.name + " " + this.bounds;
return "BoGTV " + this.name;
}
public String getName(){
@ -62,17 +61,4 @@ public class GenericTypeVar extends SyntaxTreeNode
public void accept(ASTVisitor visitor) {
visitor.visit(this);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
GenericTypeVar that = (GenericTypeVar) o;
return bounds.equals(that.bounds) && name.equals(that.name);
}
@Override
public int hashCode() {
return Objects.hash(bounds, name);
}
}

@ -1,16 +1,19 @@
package de.dhbwstuttgart.syntaxtree.factory;
import java.io.IOException;
import java.lang.reflect.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Type;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import de.dhbwstuttgart.bytecode.JavaTXSignatureAttribute;
import de.dhbwstuttgart.exceptions.NotImplementedException;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.GenericContext;
import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.parser.scope.JavaClassRegistry;
import de.dhbwstuttgart.syntaxtree.Field;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.type.*;
@ -19,14 +22,7 @@ import de.dhbwstuttgart.syntaxtree.*;
import de.dhbwstuttgart.syntaxtree.statement.Block;
import de.dhbwstuttgart.syntaxtree.statement.Statement;
import de.dhbwstuttgart.syntaxtree.type.WildcardType;
import de.dhbwstuttgart.target.tree.type.TargetRefType;
import de.dhbwstuttgart.util.Pair;
import javassist.bytecode.SignatureAttribute;
import org.antlr.v4.runtime.Token;
import org.apache.commons.io.IOUtils;
import org.objectweb.asm.*;
import org.objectweb.asm.signature.SignatureReader;
import org.objectweb.asm.signature.SignatureVisitor;
/**
* Anmerkung:
@ -36,76 +32,21 @@ import org.objectweb.asm.signature.SignatureVisitor;
public class ASTFactory {
public static ClassOrInterface createClass(java.lang.Class jreClass){
// TODO Inner classes
var methodSignatures = new HashMap<Pair<String, String>, String>();
String classSignature = null;
// Load class with asm to figure out if there's a JavaTX signature
try {
var path = jreClass.getName().replace('.', '/') + ".class";
var classLoader = jreClass.getClassLoader();
if (classLoader != null) {
var bytes = IOUtils.toByteArray(Objects.requireNonNull(classLoader.getResourceAsStream(path)));
var classReader = new ClassReader(bytes);
var classVisitor = new ClassVisitor(Opcodes.ASM7) {
String classSignature;
@Override
public void visitAttribute(Attribute attribute) {
if (attribute.type.equals("JavaTXSignature")) {
classSignature = ((JavaTXSignatureAttribute) attribute).signature;
}
super.visitAttribute(attribute);
}
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
classSignature = signature;
super.visit(version, access, name, signature, superName, interfaces);
}
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
methodSignatures.put(new Pair<>(name, descriptor), signature);
return new MethodVisitor(Opcodes.ASM7) {
@Override
public void visitAttribute(Attribute attribute) {
if (attribute.type.equals("JavaTXSignature")) {
methodSignatures.put(new Pair<>(name, descriptor), ((JavaTXSignatureAttribute) attribute).signature);
}
super.visitAttribute(attribute);
}
};
}
};
classReader.accept(classVisitor, new Attribute[]{new JavaTXSignatureAttribute()}, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
classSignature = classVisitor.classSignature;
}
} catch (IOException e) {
// Skip
}
JavaClassName name = new JavaClassName(jreClass.getName());
List<Method> methoden = new ArrayList<>();
List<de.dhbwstuttgart.syntaxtree.Constructor> konstruktoren = new ArrayList<>();
for(java.lang.reflect.Constructor constructor : jreClass.getConstructors()){
var signature = methodSignatures.get(new Pair<>(constructor.getName(), org.objectweb.asm.Type.getConstructorDescriptor(constructor)));
createConstructor(constructor, signature, jreClass).map(c -> konstruktoren.add(c));
for(java.lang.reflect.Constructor constructor : jreClass.getDeclaredConstructors()){
createConstructor(constructor, jreClass).map(c -> konstruktoren.add(c));
}
Set<java.lang.reflect.Method> allMethods = new HashSet<>(Arrays.asList(jreClass.getMethods()));
Set<java.lang.reflect.Method> allDeclaredMethods = new HashSet<>(Arrays.asList(jreClass.getDeclaredMethods()));
Set<java.lang.reflect.Method> allInheritedMethods = new HashSet<>(allMethods);
allInheritedMethods.removeAll(allDeclaredMethods);
for(java.lang.reflect.Method method : allDeclaredMethods){
var signature = methodSignatures.get(new Pair<>(method.getName(), org.objectweb.asm.Type.getMethodDescriptor(method)));
methoden.add(createMethod(method, signature, jreClass, false));
methoden.add(createMethod(method, jreClass, false));
}
for(java.lang.reflect.Method method : allInheritedMethods){
var signature = methodSignatures.get(new Pair<>(method.getName(), org.objectweb.asm.Type.getMethodDescriptor(method)));
methoden.add(createMethod(method, signature, jreClass, true));
methoden.add(createMethod(method, jreClass, true));
}
List<Field> felder = new ArrayList<>();
for(java.lang.reflect.Field field : jreClass.getDeclaredFields()){
@ -131,8 +72,7 @@ public class ASTFactory {
for(Type jreInterface : jreClass.getGenericInterfaces()){
implementedInterfaces.add((RefType) createType(jreInterface));
}
GenericDeclarationList genericDeclarationList = createGenerics(jreClass.getTypeParameters(), jreClass, null, classSignature);
GenericDeclarationList genericDeclarationList = createGenerics(jreClass.getTypeParameters(), jreClass, null);
Token offset = new NullToken(); //Braucht keinen Offset, da diese Klasse nicht aus einem Quellcode geparst wurde
@ -147,7 +87,7 @@ public class ASTFactory {
// return createClass(classType).getType();
//}
private static Optional<de.dhbwstuttgart.syntaxtree.Constructor> createConstructor(Constructor constructor, String signature, Class inClass) {
private static Optional<de.dhbwstuttgart.syntaxtree.Constructor> createConstructor(Constructor constructor, Class inClass) {
String name = constructor.getName();
RefTypeOrTPHOrWildcardOrGeneric returnType = createType(inClass);
Parameter[] jreParams = constructor.getParameters();
@ -161,7 +101,7 @@ public class ASTFactory {
}
ParameterList parameterList = new ParameterList(params, new NullToken());
Block block = new Block(new ArrayList<Statement>(), new NullToken());
GenericDeclarationList gtvDeclarations = createGenerics(constructor.getTypeParameters(), inClass, constructor.getName(), signature);
GenericDeclarationList gtvDeclarations = createGenerics(constructor.getTypeParameters(), inClass, constructor.getName());
Token offset = new NullToken();
int modifier = constructor.getModifiers();
@ -172,7 +112,7 @@ public class ASTFactory {
return Optional.of(new de.dhbwstuttgart.syntaxtree.Constructor(modifier, name,returnType, parameterList, block, gtvDeclarations, offset /*, new ArrayList<>() geloescht PL 2018-11-24 */));
}
public static Method createMethod(java.lang.reflect.Method jreMethod, String signature, java.lang.Class inClass, Boolean isInherited){
public static Method createMethod(java.lang.reflect.Method jreMethod, java.lang.Class inClass, Boolean isInherited){
String name = jreMethod.getName();
RefTypeOrTPHOrWildcardOrGeneric returnType;
Type jreRetType;
@ -193,142 +133,19 @@ public class ASTFactory {
}
ParameterList parameterList = new ParameterList(params, new NullToken());
Block block = new Block(new ArrayList<Statement>(), new NullToken());
GenericDeclarationList gtvDeclarations = createGenerics(jreMethod.getTypeParameters(), inClass, jreMethod.getName(), signature);
GenericDeclarationList gtvDeclarations = createGenerics(jreMethod.getTypeParameters(), inClass, jreMethod.getName());
Token offset = new NullToken();
return new Method(jreMethod.getModifiers(), name,returnType, parameterList, block, gtvDeclarations, offset, isInherited);
}
public static GenericDeclarationList createGenerics(TypeVariable[] typeParameters, Class context, String methodName, String signature) {
if (signature == null) {
List<de.dhbwstuttgart.syntaxtree.GenericTypeVar> gtvs = new ArrayList<>();
for(TypeVariable jreTV : typeParameters){
de.dhbwstuttgart.syntaxtree.GenericTypeVar gtv = createGeneric(jreTV, jreTV.getName(), context, methodName);
gtvs.add(gtv);
}
return new GenericDeclarationList(gtvs, new NullToken());
} else {
var res = createGenerics(signature);
return res;
public static GenericDeclarationList createGenerics(TypeVariable[] typeParameters, Class context, String methodName){
List<de.dhbwstuttgart.syntaxtree.GenericTypeVar> gtvs = new ArrayList<>();
for(TypeVariable jreTV : typeParameters){
de.dhbwstuttgart.syntaxtree.GenericTypeVar gtv = createGeneric(jreTV, jreTV.getName(), context, methodName);
gtvs.add(gtv);
}
}
public static GenericDeclarationList createGenerics(String signature) {
if (signature == null) return new GenericDeclarationList(new ArrayList<>(), new NullToken());
var gtvs = new ArrayList<GenericTypeVar>();
var signatureVisitor = new SignatureVisitor(Opcodes.ASM7) {
List<RefTypeOrTPHOrWildcardOrGeneric> bounds = new ArrayList<>();
final Stack<RefTypeOrTPHOrWildcardOrGeneric> bound = new Stack<>();
final Stack<RefType> classTypes = new Stack<>();
// All hail the mighty visitor pattern
final SignatureVisitor doNothing = new SignatureVisitor(Opcodes.ASM7) {};
char wildcard = '=';
@Override
public SignatureVisitor visitSuperclass() {
return doNothing;
}
@Override
public SignatureVisitor visitParameterType() {
return doNothing;
}
@Override
public SignatureVisitor visitReturnType() {
return doNothing;
}
@Override
public SignatureVisitor visitExceptionType() {
return doNothing;
}
@Override
public void visitFormalTypeParameter(String name) {
bounds = new ArrayList<>();
gtvs.add(new GenericTypeVar(name, bounds, new NullToken(), new NullToken()));
}
@Override
public void visitTypeVariable(String name) {
var refType = new GenericRefType(name, new NullToken());
if (classTypes.isEmpty()) {
((List<RefTypeOrTPHOrWildcardOrGeneric>) gtvs.get(gtvs.size() - 1).getBounds()).add(refType);
} else {
pushType(refType);
}
}
@Override
public void visitClassType(String name) {
var refType = new RefType(new JavaClassName(name.replaceAll("/", ".")), new ArrayList<>(), new NullToken());
classTypes.push(refType);
pushType(refType);
}
void pushType(RefTypeOrTPHOrWildcardOrGeneric refType) {
if (wildcard == SignatureVisitor.SUPER) {
bound.push(new SuperWildcardType(refType, new NullToken()));
} else if (wildcard == SignatureVisitor.EXTENDS) {
bound.push(new ExtendsWildcardType(refType, new NullToken()));
} else {
bound.push(refType);
}
}
@Override
public SignatureVisitor visitTypeArgument(char wildcard) {
this.wildcard = wildcard;
return this;
}
boolean equals(RefTypeOrTPHOrWildcardOrGeneric a, RefTypeOrTPHOrWildcardOrGeneric b) {
if (b instanceof SuperWildcardType wc)
return equals(a, wc.getInnerType());
else if (b instanceof ExtendsWildcardType wc)
return equals(a, wc.getInnerType());
return a == b;
}
@Override
public void visitEnd() {
wildcard = '=';
var classType = (RefType) classTypes.pop();
if (!classTypes.isEmpty()) {
var next = classTypes.peek();
var par = bound.pop();
var toAdd = new ArrayList<RefTypeOrTPHOrWildcardOrGeneric>();
while (!equals(next, par)) {
toAdd.add(par);
par = bound.pop();
}
var element = par;
if (par instanceof WildcardType wc) {
element = wc.getInnerType();
}
Collections.reverse(toAdd);
((RefType) element).getParaList().addAll(toAdd);
bound.push(par);
} else {
if (bound.peek() != classType) {
classType.getParaList().add(bound.pop());
bounds.add(classType);
} else {
bounds.add(bound.pop());
}
}
}
};
var sr = new SignatureReader(signature);
sr.accept(signatureVisitor);
return new GenericDeclarationList(gtvs, new NullToken());
return new GenericDeclarationList(gtvs,new NullToken());
}
private static RefTypeOrTPHOrWildcardOrGeneric createType(java.lang.reflect.Type type){

@ -5,8 +5,6 @@ import de.dhbwstuttgart.syntaxtree.ASTVisitor;
import de.dhbwstuttgart.typeinference.result.ResultSetVisitor;
import org.antlr.v4.runtime.Token;
import java.util.Objects;
/**
* Stellt eine Wildcard mit oberer Grenze dar.
* z.B. void test(? extends Number var){..}
@ -56,16 +54,9 @@ public class ExtendsWildcardType extends WildcardType{
visitor.visit(this);
}
@Override
public int hashCode() {
return Objects.hashCode(this.innerType);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ExtendsWildcardType that = (ExtendsWildcardType) o;
return that.innerType.equals(this.innerType);
// TODO Auto-generated method stub
return false;
}
}

@ -4,8 +4,6 @@ import de.dhbwstuttgart.syntaxtree.ASTVisitor;
import de.dhbwstuttgart.typeinference.result.ResultSetVisitor;
import org.antlr.v4.runtime.Token;
import java.util.Objects;
public class GenericRefType extends RefTypeOrTPHOrWildcardOrGeneric
{
private String name;
@ -35,20 +33,14 @@ public class GenericRefType extends RefTypeOrTPHOrWildcardOrGeneric
visitor.visit(this);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
GenericRefType that = (GenericRefType) o;
return name.equals(that.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
@Override
@Override
public boolean equals(Object o) {
// TODO Auto-generated method stub
return false;
}
@Override
public String toString()
{
return "GTV " + this.name;

@ -2,12 +2,9 @@ package de.dhbwstuttgart.syntaxtree.type;
import de.dhbwstuttgart.syntaxtree.ASTVisitor;
import de.dhbwstuttgart.syntaxtree.GenericTypeVar;
import de.dhbwstuttgart.typeinference.result.ResultSetVisitor;
import org.antlr.v4.runtime.Token;
import java.util.Objects;
/**
* Stellt eine Wildcard mit unterer Grenze dar.
* z.B. void test(? super Integer var){..}
@ -68,16 +65,9 @@ public class SuperWildcardType extends WildcardType{
visitor.visit(this);
}
@Override
public int hashCode() {
return Objects.hashCode(this.innerType);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SuperWildcardType that = (SuperWildcardType) o;
return that.innerType.equals(this.innerType);
// TODO Auto-generated method stub
return false;
}
}

@ -16,10 +16,8 @@ import de.dhbwstuttgart.target.tree.expression.TargetExpression;
import de.dhbwstuttgart.target.tree.type.*;
import de.dhbwstuttgart.typeinference.constraints.Pair;
import de.dhbwstuttgart.typeinference.result.*;
import org.objectweb.asm.Attribute;
import java.util.*;
import java.util.concurrent.CyclicBarrier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@ -172,6 +170,7 @@ public class ASTToTargetAST {
for (var pair : simplifiedConstraints) {
if (pair.left.equals(typeVariable) && typeVariables.contains(pair.right)) {
addToPairs(result, new PairTPHsmallerTPH(pair.left, equality.getOrDefault(pair.right, pair.right)));
typeVariables.add(pair.right);
}
}
}
@ -197,7 +196,7 @@ public class ASTToTargetAST {
RefTypeOrTPHOrWildcardOrGeneric T2 = superType;
if (T2 instanceof TypePlaceholder tph) T2 = equality.getOrDefault(tph, tph);
System.out.println("T1s: " + T1s + " T2: " + T2);
System.out.println("T1s: " + T1s + "\nT2: " + T2);
//Ende
superType = methodCall.receiverType;
@ -212,7 +211,7 @@ public class ASTToTargetAST {
var optMethod = findMethod(owner, methodCall.name, methodCall.getArgumentList());
if (optMethod.isEmpty()) return;
var method = optMethod.get();
var generics = generics(owner, method).txGenerics();
var generics = generics(owner, method).javaGenerics();
// transitive and
var all = transitiveClosure(generics);
@ -227,24 +226,24 @@ public class ASTToTargetAST {
// Loop from hell
outer:
for (var R1 : typeVariables) {
if (typeVariablesOfClass.contains(R1)) continue;
for (var tph : typeVariables) {
if (typeVariablesOfClass.contains(tph)) continue;
for (var generic : all) {
if (!(generic.getRight() instanceof TypePlaceholder type))
continue;
for (var pair : simplifiedConstraints) {
if (!(pair.left.equals(R1) && pair.right.equals(generic.getLeft())))
if (!(pair.left.equals(tph) && pair.right.equals(generic.getLeft())))
continue;
for (var R2 : typeVariables) {
for (var tph2 : typeVariables) {
for (var pair2 : simplifiedConstraints) {
if (!(pair2.right.equals(R2) && pair2.left.equals(type)))
if (!(pair2.right.equals(tph2) && pair2.left.equals(type)))
continue;
if (R1.equals(R2)) continue;
if (!T1s.contains(R1) || !R2.equals(T2)) continue;
if (tph.equals(tph2)) continue;
if (!T1s.contains(tph) || !tph2.equals(T2)) continue;
var newPair = new PairTPHsmallerTPH(R1, R2);
var newPair = new PairTPHsmallerTPH(tph, tph2);
newPairs.add(newPair);
if (!containsRelation(result, newPair))
@ -269,7 +268,7 @@ public class ASTToTargetAST {
@Override
public void visit(Assign assign) {
superType = assign.rightSide.getType();
superType = assign.lefSide.getType();
assign.rightSide.accept(this);
}
@ -522,6 +521,9 @@ public class ASTToTargetAST {
super.visit(methodCall);
typeVariables.addAll(findTypeVariables(methodCall.getType(), equality));
}
@Override
public void visit(Assign assign) {}
});
}
@ -552,11 +554,10 @@ public class ASTToTargetAST {
methodFindConstraints(owner, method, simplifiedConstraints, txTypeVariables, classGenerics.userDefinedGenerics, txTypeVariablesOfClass, txResult, txEquality);
{ // Java Generics
eliminateTransitives(javaResult);
var referenced = new HashSet<TypePlaceholder>();
eliminateCycles(javaResult, equality, referenced);
eliminateInfima(javaResult, equality);
eliminateInfima(javaResult, equality, referenced);
var usedTphs = new HashSet<TypePlaceholder>();
// For eliminating inner type variables we need to figure out which ones are actually used
@ -570,13 +571,11 @@ public class ASTToTargetAST {
eliminateInnerTypeVariables(referenced, javaResult);
equalizeTypeVariables(javaResult, equality);
usedTPHsOfMethods.put(method, usedTphs);
addMissingObjectBounds(javaResult, genericsOfClass);
}
{
var referenced = new HashSet<TypePlaceholder>();
// JavaTX Generics
eliminateTransitives(txResult);
eliminateInfima(txResult, txEquality);
eliminateInfima(txResult, txEquality, referenced);
for (var param : method.getParameterList().getFormalparalist()) {
referenced.addAll(findTypeVariables(param.getType(), txEquality));
@ -585,36 +584,12 @@ public class ASTToTargetAST {
referenced.addAll(txTypeVariablesOfClass);
eliminateInnerTypeVariables(referenced, txResult);
addMissingObjectBounds(txResult, txGenericsOfClass);
}
System.out.println(method.name + ": " + txResult + " & " + javaResult);
return generics;
}
private void eliminateChain(Set<ResultPair<?, ?>> result, List<TypePlaceholder> chain) {
for (var pair : new HashSet<>(result)) {
if (pair instanceof PairTPHsmallerTPH ptph && chain.get(chain.size() - 1).equals(ptph.left)) {
if (chain.contains(ptph.right)) return;
var copy = new ArrayList<>(chain);
copy.add(ptph.right);
if (copy.size() > 2)
result.remove(new PairTPHsmallerTPH(chain.get(0), ptph.right));
eliminateChain(result, copy);
}
}
}
void eliminateTransitives(Set<ResultPair<?,?>> result) {
for (var pair : new HashSet<>(result)) if (pair instanceof PairTPHsmallerTPH ptph) {
var first = ptph.left;
var chain = new ArrayList<TypePlaceholder>();
chain.add(ptph.left);
chain.add(ptph.right);
eliminateChain(result, chain);
}
}
void findAllBounds(RefTypeOrTPHOrWildcardOrGeneric type, Set<ResultPair<?, ?>> generics, Map<TypePlaceholder, TypePlaceholder> equality) {
if (type instanceof TypePlaceholder tph) {
tph = equality.getOrDefault(tph, tph);
@ -659,86 +634,34 @@ public class ASTToTargetAST {
findAllBounds(field.getType(), txResult, txEquality);
}
eliminateTransitives(javaResult);
eliminateTransitives(txResult);
System.out.println(javaResult);
var referenced = new HashSet<TypePlaceholder>();
eliminateCycles(javaResult, equality, referenced);
eliminateInfima(javaResult, equality);
eliminateInfima(javaResult, equality, referenced);
var txReferenced = new HashSet<TypePlaceholder>();
eliminateInfima(txResult, txEquality);
eliminateInfima(txResult, txEquality, txReferenced);
eliminateInnerTypeVariablesOfClass(classOrInterface, javaResult, equality, referenced);
equalizeTypeVariables(javaResult, equality);
eliminateInnerTypeVariablesOfClass(classOrInterface, txResult, txEquality, txReferenced);
addMissingObjectBounds(javaResult, null);
addMissingObjectBounds(txResult, null);
System.out.println("Class " + classOrInterface.getClassName().getClassName() + ": " + txResult + ", " + javaResult);
return generics;
}
void addMissingObjectBounds(Set<ResultPair<?,?>> result, Set<ResultPair<?, ?>> filter) {
outer: for (var p1 : new HashSet<>(result)) {
if (p1 instanceof PairTPHsmallerTPH ptph) {
for (var p2 : new HashSet<>(result)) {
if (ptph.right.equals(p2.getLeft()))
continue outer;
}
if (filter == null || filter.stream().noneMatch((pair) -> pair.getLeft().equals(ptph.right)))
result.add(new PairTPHequalRefTypeOrWildcardType(ptph.right, OBJECT));
}
}
}
void equalizeTypeVariables(Set<ResultPair<?, ?>> input, Map<TypePlaceholder, TypePlaceholder> equality) {
System.out.println(input);
for (var pair : new HashSet<>(input)) {
if (pair instanceof PairTPHsmallerTPH ptph) {
var chain = new ArrayList<TypePlaceholder>();
chain.add(ptph.left);
chain.add(ptph.right);
outer: while (true) {
var added = false;
for (var pair2 : input) {
if (pair2 instanceof PairTPHsmallerTPH ptph2 && ptph2.left.equals(chain.get(chain.size() - 1))) {
if (chain.contains(ptph2.right)) break outer;
chain.add(ptph2.right);
added = true;
System.out.println(pair + " " + ptph.left.getVariance() + " " + ptph.right.getVariance());
if (ptph.left.getVariance() == 1 && ptph.right.getVariance() == -1) {
addToEquality(equality, ptph.left, ptph.right);
input.remove(ptph);
for (var pair2 : new HashSet<>(simplifiedConstraints)) {
if (pair2.right.equals(ptph.left)) {
simplifiedConstraints.remove(pair2);
simplifiedConstraints.add(new PairTPHsmallerTPH(pair2.left, ptph.right));
}
}
if (!added) break;
}
var variance = chain.get(0).getVariance();
if (variance != 1) continue;
var index = 0;
for (var tph : chain) {
if (variance == 1 && tph.getVariance() == -1) {
variance = -1;
}
if (variance == -1 && tph.getVariance() == 1) {
break;
}
index++;
}
if (variance == 1) continue;
var start = chain.get(0);
var prev = start;
for (var i = 1; i < index; i++) {
var cur = chain.get(i);
addToEquality(equality, cur, start);
input.remove(new PairTPHsmallerTPH(prev, chain.get(i)));
for (var pair2 : new HashSet<>(input)) {
// TODO Maybe this would be unnecessary if we were to add the = constraints later on
if (pair2 instanceof PairTPHequalRefTypeOrWildcardType && pair2.getLeft().equals(cur)) {
input.remove(pair2);
input.add(new PairTPHequalRefTypeOrWildcardType(start, pair2.getRight()));
}
}
prev = chain.get(i);
}
}
}
@ -816,15 +739,6 @@ public class ASTToTargetAST {
var cycles = findCycles(input);
for (var cycle : cycles) {
var newTph = TypePlaceholder.fresh(new NullToken());
var variance = cycle.get(0).getVariance();
for (var tph : cycle) {
if (tph.getVariance() != variance) {
variance = 0;
break;
}
}
newTph.setVariance(variance);
referenced.add(newTph);
addToPairs(input, new PairTPHequalRefTypeOrWildcardType(newTph, OBJECT));
cycle.add(cycle.get(0)); // Make it a complete cycle
@ -838,7 +752,7 @@ public class ASTToTargetAST {
}
}
void eliminateInfima(Set<ResultPair<?, ?>> input, Map<TypePlaceholder, TypePlaceholder> equality) {
void eliminateInfima(Set<ResultPair<?, ?>> input, Map<TypePlaceholder, TypePlaceholder> equality, Set<TypePlaceholder> referenced) {
var foundInfima = false;
do {
foundInfima = false;
@ -853,16 +767,7 @@ public class ASTToTargetAST {
if (infima.size() > 1) {
foundInfima = true;
var newTph = TypePlaceholder.fresh(new NullToken());
var variance = infima.stream().findFirst().get().right.getVariance();
for (var pair : infima) {
if (pair.right.getVariance() != variance) {
variance = 0;
break;
}
}
newTph.setVariance(variance);
//referenced.add(newTph);
referenced.add(newTph);
addToPairs(input, new PairTPHsmallerTPH(left, newTph));
input.removeAll(infima);
for (var infimum : infima) {

@ -22,15 +22,11 @@ public record TargetMethod(int access, String name, TargetBlock block, Signature
}
public static String getSignature(Set<TargetGeneric> generics, List<MethodParameter> parameters, TargetType returnType) {
String ret = "";
if (generics.size() > 0) {
ret += "<";
for (var generic : generics) {
ret += generic.name() + ":" + generic.bound().toDescriptor();
}
ret += ">";
String ret = "<";
for (var generic : generics) {
ret += generic.name() + ":" + generic.bound().toDescriptor();
}
ret += "(";
ret += ">(";
for (var param : parameters) {
ret += param.type().toDescriptor();
}

@ -495,7 +495,7 @@ public class TYPEStmt implements StatementVisitor{
@Override
public void visit(Return returnExpr) {
returnExpr.retexpr.accept(this);
constraintsSet.addUndConstraint(new Pair(returnExpr.getType(),info.getCurrentTypeScope().getReturnType(), PairOperator.SMALLERDOT));
constraintsSet.addUndConstraint(new Pair(returnExpr.getType(),info.getCurrentTypeScope().getReturnType(), PairOperator.EQUALSDOT));
}
@Override
@ -610,8 +610,8 @@ public class TYPEStmt implements StatementVisitor{
//Fuer Bytecodegenerierung PL 2020-03-09 wird derzeit nicht benutzt ENDE
methodConstraint.add(new Pair(assumption.getReturnType(resolver), forMethod.getType(), PairOperator.SMALLERDOT));
extendsMethodConstraint.add(new Pair(assumption.getReturnType(resolver), forMethod.getType(), PairOperator.SMALLERDOT));
methodConstraint.add(new Pair(assumption.getReturnType(resolver), forMethod.getType(), PairOperator.EQUALSDOT));
extendsMethodConstraint.add(new Pair(assumption.getReturnType(resolver), forMethod.getType(), PairOperator.EQUALSDOT));
//methodConstraint.add(new Pair(assumption.getReturnType(resolver), forMethod.getType(), PairOperator.EQUALSDOT));
//extendsMethodConstraint.add(new Pair(assumption.getReturnType(resolver), forMethod.getType(), PairOperator.EQUALSDOT));

@ -13,6 +13,7 @@ import java.util.function.Function;
import java.util.stream.Collectors;
import de.dhbwstuttgart.exceptions.DebugException;
import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unify.interfaces.IRuleSet;
import de.dhbwstuttgart.typeinference.unify.model.ExtendsType;
@ -390,26 +391,51 @@ public class RuleSet implements IRuleSet{
if((pair.getPairOp() != PairOperator.SMALLERDOT) && (pair.getPairOp() != PairOperator.SMALLERNEQDOT))
return false;
if (pair.getPairOp() == PairOperator.SMALLERNEQDOT) {
UnifyType lhs = pair.getLhsType();
UnifyType rhs = pair.getRhsType();
if (lhs instanceof WildcardType) {
lhs = ((WildcardType)lhs).getWildcardedType();
}
if (rhs instanceof WildcardType) {
rhs = ((WildcardType)rhs).getWildcardedType();
}
if (lhs.equals(rhs)){
return false;
}
UnifyType lhsType = pair.getLhsType();
UnifyType rhsType = pair.getRhsType();
/*
* ty <. ? extends ty' is wrong
*/
if (rhsType instanceof ExtendsType) {
return false;
}
/*
* ? super ty <. ty' is wrong
* except Ty' = Object or ty' = ? super Object
*/
if ((lhsType instanceof SuperType) &&
(!(rhsType.equals(new ReferenceType("java.lang.Object", false)))) &&
!(rhsType.equals(new SuperType (new ReferenceType("java.lang.Object", false))))) {
return false;
}
/*
* ? extends ty <. ty' is equivalent to ty < ty'
*/
if (lhsType instanceof ExtendsType) {
lhsType = ((WildcardType)lhsType).getWildcardedType();
}
/*
* ty <. ? super ty' ist equivalent to ty <. ty'
*/
if (rhsType instanceof SuperType) {
rhsType = ((WildcardType)rhsType).getWildcardedType();
}
/*
* SMALLERNEQDOT => type must not be equal
*/
if (pair.getPairOp() == PairOperator.SMALLERNEQDOT && lhsType.equals(rhsType)){
return false;
}
UnifyType lhsType = pair.getLhsType();
if(!(lhsType instanceof ReferenceType) && !(lhsType instanceof PlaceholderType))
return false;
UnifyType rhsType = pair.getRhsType();
if(!(rhsType instanceof ReferenceType) && !(rhsType instanceof PlaceholderType))
return false;

@ -18,6 +18,7 @@ import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
public class TypeUnify {
public static Writer statistics;
/**
* unify parallel ohne result modell
* @param undConstrains
@ -73,13 +74,16 @@ public class TypeUnify {
* @return
*/
public UnifyResultModel unifyParallel(Set<UnifyPair> undConstrains, List<Set<Constraint<UnifyPair>>> oderConstraints, IFiniteClosure fc, Writer logFile, Boolean log, UnifyResultModel ret, UnifyTaskModel usedTasks) {
TypeUnifyTask unifyTask = new TypeUnifyTask(undConstrains, oderConstraints, fc, true, logFile, log, 0, ret, usedTasks);
TypeUnifyTask unifyTask = //new TypeUnifyTask(undConstrains, oderConstraints, fc, true, logFile, log, 0, ret, usedTasks);
new TypeUnifyTask(undConstrains, oderConstraints, fc, true, logFile, log, 0, ret, usedTasks, statistics);
ForkJoinPool pool = new ForkJoinPool();
pool.invoke(unifyTask);
Set<Set<UnifyPair>> res = unifyTask.join();
try {
logFile.write("\nnoShortendElements: " + unifyTask.noShortendElements +"\n");
logFile.flush();
unifyTask.statistics.write("Backtracking: " + unifyTask.noBacktracking);
unifyTask.statistics.write("\nLoops: " + unifyTask.noLoop);
}
catch (IOException e) {
System.err.println("no log-File");
@ -107,6 +111,7 @@ public class TypeUnify {
*/
public Set<Set<UnifyPair>> unifyOderConstraints(Set<UnifyPair> undConstrains, List<Set<Constraint<UnifyPair>>> oderConstraints, IFiniteClosure fc, Writer logFile, Boolean log, UnifyResultModel ret, UnifyTaskModel usedTasks) {
TypeUnifyTask unifyTask = new TypeUnifyTask(undConstrains, oderConstraints, fc, false, logFile, log, 0, ret, usedTasks);
unifyTask.statistics = statistics;
Set<Set<UnifyPair>> res = unifyTask.compute();
try {
logFile.write("\nnoShortendElements: " + unifyTask.noShortendElements +"\n");

@ -19,6 +19,16 @@ public class TypeUnify2Task extends TypeUnifyTask {
Set<Set<UnifyPair>> setToFlatten;
Set<UnifyPair> methodSignatureConstraintUebergabe;
//statistics
TypeUnify2Task(Set<Set<UnifyPair>> setToFlatten, Set<UnifyPair> eq,
List<Set<Constraint<UnifyPair>>> oderConstraints,
Set<UnifyPair> nextSetElement,
IFiniteClosure fc, boolean parallel, Writer logFile, Boolean log, int rekTiefe, UnifyResultModel urm, UnifyTaskModel usedTasks,
Set<UnifyPair> methodSignatureConstraintUebergabe, Writer statistics) {
this(setToFlatten, eq, oderConstraints, nextSetElement, fc, parallel, logFile, log, rekTiefe, urm, usedTasks, methodSignatureConstraintUebergabe );
}
public TypeUnify2Task(Set<Set<UnifyPair>> setToFlatten, Set<UnifyPair> eq, List<Set<Constraint<UnifyPair>>> oderConstraints, Set<UnifyPair> nextSetElement, IFiniteClosure fc, boolean parallel, Writer logFile, Boolean log, int rekTiefe, UnifyResultModel urm, UnifyTaskModel usedTasks, Set<UnifyPair> methodSignatureConstraintUebergabe) {
super(eq, oderConstraints, fc, parallel, logFile, log, rekTiefe, urm, usedTasks);
this.setToFlatten = setToFlatten;

@ -21,6 +21,7 @@ import java.util.stream.Stream;
import org.apache.commons.io.output.NullOutputStream;
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.exceptions.TypeinferenceException;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory;
@ -46,6 +47,7 @@ import de.dhbwstuttgart.typeinference.unify.model.UnifyType;
import de.dhbwstuttgart.typeinference.unify.model.WildcardType;
import de.dhbwstuttgart.util.Pair;
import de.dhbwstuttgart.typeinference.unify.model.OrderingUnifyPair;
import de.dhbwstuttgart.core.JavaTXCompiler;
import java.io.File;
import java.io.FileWriter;
@ -80,7 +82,7 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
private static int totalnoOfThread = 0;
int thNo;
protected boolean one = false;
Integer MaxNoOfThreads = 8;
Integer MaxNoOfThreads = 128;
public static final String rootDirectory = System.getProperty("user.dir")+"/test/logFiles/";
Writer logFile;
@ -125,12 +127,16 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
static int noBacktracking;
static int noLoop;
static Integer noShortendElements = 0;
Boolean myIsCanceled = false;
volatile UnifyTaskModel usedTasks;
static Writer statistics;
public TypeUnifyTask() {
rules = new RuleSet();
}
@ -149,7 +155,11 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
}
*/
//statistics
public TypeUnifyTask(Set<UnifyPair> eq, List<Set<Constraint<UnifyPair>>> oderConstraints, IFiniteClosure fc, boolean parallel, Writer logFile, Boolean log, int rekTiefe, UnifyResultModel urm, UnifyTaskModel usedTasks, Writer statistics) {
this(eq,oderConstraints, fc, parallel, logFile, log, rekTiefe, urm, usedTasks);
this.statistics = statistics;
}
public TypeUnifyTask(Set<UnifyPair> eq, List<Set<Constraint<UnifyPair>>> oderConstraints, IFiniteClosure fc, boolean parallel, Writer logFile, Boolean log, int rekTiefe, UnifyResultModel urm, UnifyTaskModel usedTasks) {
synchronized (this) {
this.eq = eq;
@ -248,7 +258,7 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
protected Set<Set<UnifyPair>> compute() {
if (one) {
System.out.println("two");
//System.out.println("two");
}
one = true;
Set<UnifyPair> neweq = new HashSet<>(eq);
@ -592,6 +602,7 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
urm.notify(eqPrimePrimeSet);
writeStatistics("Result: " + eqPrimePrimeSet.toString());
}
}
else if(eqPrimePrime.isPresent()) {
@ -646,6 +657,10 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
//oneElems: Alle 1-elementigen Mengen, die nur ein Paar
//a <. theta, theta <. a oder a =. theta enthalten
//statistics
//writeStatistics("\nNumber of Constraints (" + rekTiefe + "): " + topLevelSets.size());
Set<Set<UnifyPair>> oneElems = new HashSet<>();
oneElems.addAll(topLevelSets.stream()
.filter(x -> x.size()==1)
@ -663,6 +678,9 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
Set<? extends Set<UnifyPair>> nextSet = optNextSet.get();
//writeLog("nextSet: " + nextSet.toString());
List<Set<UnifyPair>> nextSetasList =new ArrayList<>(nextSet);
//writeStatistics(" Start Number of elements ( " /* + nextSetasList.get(0).stream().findFirst().get().getBasePair()*/ +"): (" + rekTiefe + "): " + nextSetasList.size());
/*
try {
//List<Set<UnifyPair>>
@ -774,8 +792,12 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
}
/* sameEqSet-Bestimmung Ende */
int hilf = 0;
Set<UnifyPair> a = null;
while (nextSetasList.size() > 0) {
//statistics
//writeStatistics(" Actual Number of elements( " + nextSetasList.get(0).stream().findFirst().get().getBasePair() +"): (" + rekTiefe + "): " + nextSetasList.size());
Set<UnifyPair> a_last = a;
/* Liste der Faelle für die parallele Verarbeitung
@ -794,6 +816,8 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
writeLog("nextSet: " + nextSet.toString());
writeLog("nextSetasList: " + nextSetasList.toString());
/* staistics Nextvar an Hand Varianzbestimmung auskommentieren Anfang
if (variance == 1) {
a = oup.max(nextSetasList.iterator());
nextSetasList.remove(a);
@ -865,7 +889,10 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
}
}
}
Nextvar an Hand Varianzbestimmung auskommentieren Ende */
a = nextSetasList.remove(0); //statisticsList
//writeStatistics(a.toString());
if (oderConstraint) {//Methodconstraints werden abgespeichert für die Bytecodegenerierung von Methodenaufrufen
methodSignatureConstraint.addAll(((Constraint<UnifyPair>)a).getmethodSignatureConstraint());
//System.out.println("ERSTELLUNG: " +methodSignatureConstraint);
@ -887,11 +914,13 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
/* Wenn bei (a \in theta) \in a zu Widerspruch in oneElems wird
* a verworfen und zu nächstem Element von nextSetasList gegangen
*/
/* statistics sameEq wird nicht betrachtet ANGFANG
if (!oderConstraint && !sameEqSet.isEmpty() && !checkNoContradiction(a, sameEqSet, result)) {
a = null;
noShortendElements++;
continue;
}
statistics sameEq wird nicht betrachtet ENDE */
/* Wenn parallel gearbeitet wird, wird je nach Varianz ein neuer Thread
* gestartet, der parallel weiterarbeitet.
@ -918,19 +947,22 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
writeLog("a in " + variance + " "+ a);
writeLog("nextSetasListRest: " + nextSetasListRest.toString());
}
while (!nextSetasListRest.isEmpty()) {
Set<UnifyPair> nSaL = nextSetasListRest.remove(0);
synchronized (this) { nextSetasList.remove(nSaL);
while (!nextSetasList.isEmpty()) {
Set<UnifyPair> nSaL = nextSetasList.remove(0);
synchronized (this) { //nextSetasList.remove(nSaL);
writeLog("1 RM" + nSaL.toString());
}
if (!oderConstraint) {
/* statistics sameEq wird nicht betrachtet ANGFANG
//ueberpruefung ob zu a =. ty \in nSaL in sameEqSet ein Widerspruch besteht
if (!sameEqSet.isEmpty() && !checkNoContradiction(nSaL, sameEqSet, result)) {
nSaL = null;
noShortendElements++;
continue;
}
statistics sameEq wird nicht betrachtet ENDE */
}
else {
nextSetasListOderConstraints.add(((Constraint<UnifyPair>)nSaL).getExtendConstraint());
@ -1017,19 +1049,21 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
writeLog("a in " + variance + " "+ a);
writeLog("nextSetasListRest: " + nextSetasListRest.toString());
}
while (!nextSetasListRest.isEmpty()) {
Set<UnifyPair> nSaL = nextSetasListRest.remove(0);
synchronized (this) { nextSetasList.remove(nSaL);
while (!nextSetasList.isEmpty()) {
Set<UnifyPair> nSaL = nextSetasList.remove(0);
synchronized (this) { //nextSetasList.remove(nSaL);
writeLog("-1 RM" + nSaL.toString());
}
if (!oderConstraint) {
/* statistics sameEq wird nicht betrachtet ANGFANG
//ueberpruefung ob zu a =. ty \in nSaL in sameEqSet ein Widerspruch besteht
if (!sameEqSet.isEmpty() && !checkNoContradiction(nSaL, sameEqSet, result)) {
nSaL = null;
noShortendElements++;
continue;
}
statistics sameEq wird nicht betrachtet ENDE */
}
else {
nextSetasListOderConstraints.add(((Constraint<UnifyPair>)nSaL).getExtendConstraint());
@ -1117,9 +1151,9 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
writeLog("a in " + variance + " "+ a);
writeLog("nextSetasListRest: " + nextSetasListRest.toString());
}
while (!nextSetasListRest.isEmpty()) {
Set<UnifyPair> nSaL = nextSetasListRest.remove(0);
nextSetasList.remove(nSaL); //PL einkommentiert 20-02-03
while (!nextSetasList.isEmpty()) {
Set<UnifyPair> nSaL = nextSetasList.remove(0);
//nextSetasList.remove(nSaL); //PL einkommentiert 20-02-03
Set<UnifyPair> newEq = new HashSet<>(eq);
Set<Set<UnifyPair>> newElems = new HashSet<>(elems);
List<Set<Constraint<UnifyPair>>> newOderConstraints = new ArrayList<>(oderConstraints);
@ -1179,6 +1213,9 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
}}}
//Ab hier alle parallele Berechnungen wieder zusammengeführt.
//if (hilf == 1)
//System.out.println();
//writeStatistics("Zusammengeführt(" + rekTiefe + "): " + nextSetasList.size());
if (oderConstraint) {//Wenn weiteres Element nextSetasList genommen wird, muss die vorherige methodsignatur geloescht werden
methodSignatureConstraint.removeAll(((Constraint<UnifyPair>)a).getmethodSignatureConstraint());
//System.out.println("REMOVE: " +methodSignatureConstraint);
@ -1192,6 +1229,7 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
|| (!isUndefinedPairSetSet(res) && !isUndefinedPairSetSet(result))
|| result.isEmpty()) {
/* auskommentiert damit alle Lösungen reinkommen ANFANG
if ((!result.isEmpty() && !res.isEmpty() && !isUndefinedPairSetSet(res) && !isUndefinedPairSetSet(result)) //korrekte Loesungen aus und-constraints
&& (a.stream().map(x-> (x.getBasePair() != null)).reduce(true, (x, y) -> (x && y)))) //bei oder-Constraints nicht ausfuehren
{
@ -1213,7 +1251,7 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
//Alle Variablen bestimmen die nicht hinzugefügt wurden in a_last
//System.out.println(a_last);
if (a_last != null) {
try {//PL eingefuegt 2019-03-06 da bei map mmer wieder Nullpointer kamen
a_last.forEach(x -> {writeLog("a_last_elem:" + x + " basepair: " + x.getBasePair());});//PL 2019-05-13 ins try hinzugefuegt Nullpointer-Exception ist in der Zeile aufgetaucht.
List<PlaceholderType> varsLast_a =
@ -1265,9 +1303,11 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
}
catch (NullPointerException e) {
writeLog("NullPointerException: " + a_last.toString());
}
}}
}
else {
else
auskommentiert damit alle Lösungen reinkommen ANFANG */
{
//alle Fehlerfaelle und alle korrekten Ergebnis jeweils adden
writeLog("RES Fst: result: " + result.toString() + " res: " + res.toString());
result.addAll(res);
@ -1287,7 +1327,7 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
//wenn korrektes Ergebnis gefunden alle Fehlerfaelle loeschen
result = par_res;
if (!par_res.isEmpty() && par_res.iterator().next() instanceof WildcardType) {
System.out.println("");
//System.out.println("");
}
}
else {
@ -1303,7 +1343,7 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
//break;
}
/* auskommentiert um alle Max und min Betrachtung auszuschalten ANFANG */
/* auskommentiert um alle Max und min Betrachtung auszuschalten ANFANG
if (!result.isEmpty() && (!isUndefinedPairSetSet(res) || !aParDef.isEmpty())) {
if (nextSetasList.iterator().hasNext() && nextSetasList.iterator().next().stream().filter(x -> x.getLhsType().getName().equals("B")).findFirst().isPresent() && nextSetasList.size()>1)
System.out.print("");
@ -1411,6 +1451,7 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
else { if (variance == 0) {
writeLog("a: " + rekTiefe + " variance: " + variance + a.toString());
if (!oderConstraint) {
writeStatistics("break");
break;
}
else {
@ -1439,7 +1480,7 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
writeLog("a: " + rekTiefe + " variance: " + variance + a.toString());
}
}
/* auskommentiert um alle Max und min Betrachtung auszuschalten ENDE */
auskommentiert um alle Max und min Betrachtung auszuschalten ENDE */
if (isUndefinedPairSetSet(res) && aParDef.isEmpty()) {
int nofstred= 0;
@ -1472,8 +1513,9 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
return new Pair<>(su, x.getGroundBasePair());})
.collect(Collectors.toCollection(HashSet::new));
if (res.size() > 1) {
System.out.println();
//System.out.println();
}
/* statistics no erase
writeLog("nextSetasList vor filter-Aufruf: " + nextSetasList);
if (!oderConstraint) {//PL 2023-02-08 eingefuegt: Bei oderconstraints sind Subststitutionen nicht als Substitutionen in idesem Sinne zu sehen
nextSetasList = nextSetasList.stream().filter(x -> {
@ -1486,6 +1528,7 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
.collect(Collectors.toCollection(ArrayList::new));
}
writeLog("nextSetasList nach filter-Aufruf: " + nextSetasList);
*/
nofstred = nextSetasList.size();
//NOCH NICHT korrekt PL 2018-10-12
//nextSetasList = nextSetasList.stream().filter(y -> couldBecorrect(reducedUndefResSubstGroundedBasePair, y))
@ -1503,8 +1546,11 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
writeLog("Number of all erased Elements (undef): " + noAllErasedElements.toString());
noBacktracking++;
writeLog("Number of Backtracking: " + noBacktracking);
System.out.println("");
//writeStatistics("Number of erased elements: " + (len - nextSetasList.size()));
//writeStatistics("Number of Backtracking: " + noBacktracking);
//System.out.println("");
}
else //writeStatistics("res: " + res.toString());
//if (nextSetasList.size() == 0 && isUndefinedPairSetSet(result) && nextSet.size() > 1) {
// return result;
//}
@ -1513,6 +1559,9 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
//}
//else result.stream().filter(y -> !isUndefinedPairSet(y));
writeLog("res: " + res.toString());
//writeStatistics(" End Number of Elements (" + rekTiefe + "): " + nextSetasList.size());
noLoop++;
//writeStatistics("Number of Loops: " + noLoop);
}
//2020-02-02: if (variance ==2) Hier Aufruf von filterOverriding einfuegen
writeLog("Return computeCR: " + result.toString());
@ -2008,7 +2057,7 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
//System.out.println(pair);
if (first) { //writeLog(pair.toString()+"\n");
if (((PlaceholderType)(pair.getLhsType())).getName().equals("AR")) {
System.out.println("AR");
//System.out.println("AR");
}
Set<Set<UnifyPair>> x1 = unifyCase1(pair, fc);
if (pairOp == PairOperator.SMALLERNEQDOT) {
@ -2576,4 +2625,18 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
}
}
}
void writeStatistics(String str) {
if (finalresult) {
synchronized ( this ) {
try {
statistics.write("Thread No. " + thNo + ": " + str + "\n");
statistics.flush();
}
catch (IOException e) {
System.err.println("kein StatisticsFile");
}
}}
}
}

@ -1,6 +1,5 @@
package de.dhbwstuttgart.util;
import java.util.Objects;
import java.util.Optional;
public class Pair<T, T1> {
@ -23,17 +22,4 @@ public class Pair<T, T1> {
public String toString() {
return "(" + key.toString() + "," + value.toString() + ")\n";
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Pair<?, ?> pair = (Pair<?, ?>) o;
return Objects.equals(key, pair.key) && Objects.equals(value, pair.value);
}
@Override
public int hashCode() {
return Objects.hash(key, value);
}
}

@ -1,105 +0,0 @@
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.GenericContext;
import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.syntaxtree.GenericDeclarationList;
import de.dhbwstuttgart.syntaxtree.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
import de.dhbwstuttgart.syntaxtree.type.*;
import de.dhbwstuttgart.target.generate.ASTToTargetAST;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.*;
public class GenericsParserTest {
@Test
public void testMethodNoGenerics() {
var signature = "()V";
var generics = ASTFactory.createGenerics(signature);
assertEquals(generics, new GenericDeclarationList(List.of(), new NullToken()));
}
@Test
public void testMethodSimpleGenerics() {
var signature = "<T:Ljava/lang/Object;>()V";
var generics = ASTFactory.createGenerics(signature);
assertEquals(generics, new GenericDeclarationList(
List.of(new GenericTypeVar("T", List.of(ASTToTargetAST.OBJECT), new NullToken(), new NullToken())), new NullToken())
);
}
@Test
public void testMethodExtends() {
var signature = "<T:Ljava/lang/Class<TT;>;>()V";
var generics = ASTFactory.createGenerics(signature);
assertEquals(generics, new GenericDeclarationList(
List.of(new GenericTypeVar("T", List.of(
new RefType(new JavaClassName("java.lang.Class"), List.of(new GenericRefType("T", new NullToken())), new NullToken())),
new NullToken(), new NullToken())), new NullToken()
)
);
}
@Test
public void testMethodVariance() {
var signature = "<T:Ljava/lang/Class<+TT;>;>()V";
var generics = ASTFactory.createGenerics(signature);
assertEquals(generics, new GenericDeclarationList(
List.of(new GenericTypeVar("T", List.of(
new RefType(new JavaClassName("java.lang.Class"), List.of(
new ExtendsWildcardType(new GenericRefType("T", new NullToken()), new NullToken())
), new NullToken())),
new NullToken(), new NullToken())),
new NullToken())
);
}
@Test
public void testMethodTypeVars() {
var signature = "<A:TB;B:LClassA;C:LClassB<TA;>;D:TB;>()V";
var generics = ASTFactory.createGenerics(signature);
assertEquals(generics, new GenericDeclarationList(
List.of(
new GenericTypeVar("A", List.of(new GenericRefType("B", new NullToken())), new NullToken(), new NullToken()),
new GenericTypeVar("B", List.of(new RefType(new JavaClassName("ClassA"), new NullToken())), new NullToken(), new NullToken()),
new GenericTypeVar("C", List.of(new RefType(new JavaClassName("ClassB"),
List.of(new GenericRefType("A", new NullToken())),
new NullToken())), new NullToken(), new NullToken()
),
new GenericTypeVar("D", List.of(new GenericRefType("B", new NullToken())), new NullToken(), new NullToken())
),
new NullToken()
));
}
@Test
public void testMethodComplex() {
var signature = "<T:LClassA<+TT;LClassB<+LClassA;-LClassC<LClassA;>;>;>;U:LClassC<LClassC;>;>()V";
var generics = ASTFactory.createGenerics(signature);
assertEquals(generics, new GenericDeclarationList(
List.of(new GenericTypeVar("T", List.of(
new RefType(new JavaClassName("ClassA"), List.of(
new ExtendsWildcardType(new GenericRefType("T", new NullToken()), new NullToken()),
new RefType(new JavaClassName("ClassB"), List.of(
new ExtendsWildcardType(new RefType(new JavaClassName("ClassA"), new NullToken()), new NullToken()),
new SuperWildcardType(
new RefType(new JavaClassName("ClassC"), List.of(
new RefType(new JavaClassName("ClassA"), new NullToken())
), new NullToken()), new NullToken())
), new NullToken())
), new NullToken())
), new NullToken(), new NullToken()),
new GenericTypeVar("U", List.of(
new RefType(new JavaClassName("ClassC"), List.of(
new RefType(new JavaClassName("ClassC"), new NullToken())
), new NullToken())
), new NullToken(), new NullToken())),
new NullToken()
));
}
}

@ -281,6 +281,7 @@ public class TestComplete {
@Test
public void scalarTest() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Scalar.jav");
var scalar = classFiles.get("Scalar");
@ -575,11 +576,6 @@ public class TestComplete {
assertEquals(fstArgm2, m2.getGenericReturnType());
}
@Test
public void testTXGenerics() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "TXGenerics.jav");
var instance = classFiles.get("TXGenerics").getDeclaredConstructor().newInstance();
}
@Test
public void typedIdTest() throws Exception {

@ -90,15 +90,16 @@ public class TestGenerics {
var generics = result.genericsResults.get(0);
assertEquals(0, generics.get(result.clazz).size());
assertEquals(1, generics.get(m).size());
assertEquals(2, generics.get(m).size());
assertEquals(2, generics.get(main).size());
var N = generics.getBounds(m.getParameterList().getParameterAt(0).getType(), result.clazz, m);
var N2 = generics.getBounds(m.getReturnType(), result.clazz, m);
var NChain = new BoundsList(new Bound(true, ASTToTargetAST.OBJECT));
assertEquals(N, N2);
assertEquals(N2, NChain);
assertEquals(N, NChain);
var Q = generics.getBounds(m.getReturnType(), result.clazz, m);
var QChain = new BoundsList(new Bound(true, TypePlaceholder.of("N")), new Bound(true, ASTToTargetAST.OBJECT));
assertEquals(Q, QChain);
var R = generics.getBounds(main.getParameterList().getParameterAt(0).getType(), result.clazz, main);
assertEquals(R, NChain);
@ -303,18 +304,17 @@ public class TestGenerics {
var main = result.findMethod("main");
var generics = result.genericsResults.get(0);
var O = generics.getBounds(id.getReturnType(), result.clazz, id);
var O2 = generics.getBounds(id.getParameterList().getParameterAt(0).getType(), result.clazz, id);
assertEquals(O, O2);
assertEquals(O2, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT)));
var Q = generics.getBounds(id.getReturnType(), result.clazz, id);
var N = generics.getBounds(id.getParameterList().getParameterAt(0).getType(), result.clazz, id);
assertEquals(Q, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT)));
assertEquals(N, new BoundsList(new Bound(true, TypePlaceholder.of("Q")), new Bound(true, ASTToTargetAST.OBJECT)));
// TODO Maybe test in other ways if the parameter generics equals the return generics
var S = generics.getBounds(main.getReturnType(), result.clazz, main);
var S2 = generics.getBounds(main.getParameterList().getParameterAt(0).getType(), result.clazz, main);
var T = generics.getBounds(main.getParameterList().getParameterAt(1).getType(), result.clazz, main);
assertEquals(S, S2);
assertEquals(S2, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT)));
assertEquals(T, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT)));
var Q2 = generics.getBounds(main.getReturnType(), result.clazz, main);
var R = generics.getBounds(main.getParameterList().getParameterAt(0).getType(), result.clazz, main);
var S = generics.getBounds(main.getParameterList().getParameterAt(1).getType(), result.clazz, main);
assertEquals(Q2, new BoundsList(new Bound(true, ASTToTargetAST.OBJECT)));
assertEquals(R, new BoundsList(new Bound(true, TypePlaceholder.of("Q")), new Bound(true, ASTToTargetAST.OBJECT)));
assertEquals(S, new BoundsList(new Bound(true, TypePlaceholder.of("Q")), new Bound(true, ASTToTargetAST.OBJECT)));
}
@Test