Remove everything that doesn't touch constraints
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 49s

This commit is contained in:
Daniel Holle 2024-08-07 16:40:06 +02:00
parent edafbbc5a0
commit 494ce63838
127 changed files with 80 additions and 14925 deletions

View File

@ -8,3 +8,4 @@ public class Main {
ConsoleInterface.main(args);
}
}
c

View File

@ -1,7 +0,0 @@
package de.dhbwstuttgart.bytecode;
public class CodeGenException extends RuntimeException {
public CodeGenException(String cause) {
super(cause);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,196 +0,0 @@
package de.dhbwstuttgart.bytecode;
import de.dhbwstuttgart.target.tree.TargetGeneric;
import de.dhbwstuttgart.target.tree.type.*;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.objectweb.asm.Opcodes.*;
/**
* //ToDo beschreiben
*
* @since Studienarbeit Type Erasure
* @author etiennezink
*/
public class FunNGenerator {
private static final String argumentGenericBase = "T";
private static final String returnGeneric = "R";
private static final String methodName = "apply";
private static final int bytecodeVersion = V1_8;
private static final String objectSuperType = Type.getInternalName(Object.class).replace('.','/');
private static final String objectSignature = applySignature(TargetType.Object);
private static final String VOID = "Ljava/lang/Void;";
public static class GenericParameters {
int start;
public List<TargetType> parameters = new ArrayList<>();
final String descriptor;
public final List<TargetType> inParams;
public GenericParameters(List<TargetType> params, int numReturns) {
this.inParams = params;
var type = new TargetRefType(FunNGenerator.getSuperClassName(params.size() - 1, numReturns), params);
descriptor = applyDescriptor(type, this);
}
public TargetType getReturnType() {
return FunNGenerator.getReturnType(inParams);
}
public List<TargetType> getArguments() {
return FunNGenerator.getArguments(inParams);
}
}
private static String applyDescriptor(TargetType type, GenericParameters gep) {
if (type == null) return VOID;
var res = "L" + type.getInternalName();
if (type instanceof TargetSpecializedType a) {
if (a.params().size() > 0) {
res += "<";
for (var param : a.params()) {
if (param instanceof TargetGenericType gp) {
gep.parameters.add(param);
res += "TT" + gep.start + ";";
gep.start += 1;
} else {
res += applyDescriptor(param, gep);
}
}
res += ">";
}
} else {
gep.parameters.add(null);
return type.toDescriptor();
}
res += ";";
return res;
}
private static String applySignature(TargetType a) { return a.toSignature(); }
private static String applyNameDescriptor(TargetType a){ return a instanceof TargetGenericType ? "LTPH;" : String.format("%s", applySignature(a)); }
public static String encodeType(TargetType type) {
if (type == null) return VOID;
return applyNameDescriptor(type).replace("/", "$").replace(";", "$_$");
}
public static byte[] generateSuperBytecode(int numberArguments, int numReturnTypes) {
StringBuilder superFunNClassSignature = new StringBuilder("<");
StringBuilder superFunNMethodSignature = new StringBuilder("(");
StringBuilder superFunNMethodDescriptor = new StringBuilder("(");
for (int currentParameter = 1; currentParameter <= numberArguments; currentParameter++){
superFunNClassSignature.append(String.format("%s%d:%s", argumentGenericBase, currentParameter, objectSignature));
superFunNMethodSignature.append(String.format("T%s;", argumentGenericBase + currentParameter));
superFunNMethodDescriptor.append(objectSignature);
}
superFunNClassSignature.append(String.format("%s:%s>%s", returnGeneric, objectSignature, objectSignature));
if (numReturnTypes > 0) {
superFunNMethodSignature.append(String.format(")T%s;", returnGeneric));
superFunNMethodDescriptor.append(String.format(")%s", objectSignature));
} else {
superFunNMethodSignature.append(")V");
superFunNMethodDescriptor.append(")V");
}
System.out.println(superFunNMethodSignature);
ClassWriter classWriter = new ClassWriter(0);
MethodVisitor methodVisitor;
classWriter.visit(bytecodeVersion, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, getSuperClassName(numberArguments, numReturnTypes), superFunNClassSignature.toString(), objectSuperType, null);
methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, methodName, superFunNMethodDescriptor.toString(), superFunNMethodSignature.toString(), null);
methodVisitor.visitEnd();
classWriter.visitEnd();
return classWriter.toByteArray();
}
public static String getSuperClassName(int numberArguments, int returnArguments) {
return returnArguments > 0 ? String.format("Fun%d$$", numberArguments) : String.format("FunVoid%d$$", numberArguments);
}
public static byte[] generateSpecializedBytecode(GenericParameters gep, List<String> superInterfaces) {
var argumentTypes = gep.getArguments();
var returnType = gep.getReturnType();
StringBuilder funNClassSignature = new StringBuilder(objectSignature + gep.descriptor);
boolean containsGeneric = false;
String genericSignature = "<";
for (var i = 0; i < gep.start; i++) {
genericSignature += String.format("T%d:%s", i, objectSignature);
containsGeneric = true;
}
genericSignature += ">";
if (containsGeneric) funNClassSignature.insert(0, genericSignature);
for (var superInterface : superInterfaces) {
funNClassSignature.append('L');
funNClassSignature.append(superInterface);
funNClassSignature.append(';');
}
var interfaces = new ArrayList<>(superInterfaces);
interfaces.add(getSuperClassName(argumentTypes.size(), returnType != null ? 1 : 0));
ClassWriter classWriter = new ClassWriter(0);
classWriter.visit(bytecodeVersion, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, getSpecializedClassName(argumentTypes, returnType), funNClassSignature.toString(), objectSuperType, interfaces.toArray(String[]::new));
classWriter.visitEnd();
return classWriter.toByteArray();
}
private static void collectGenericTypeArguments(Map<TargetGenericType, Integer> generics, TargetType typeArgument) {
if (typeArgument instanceof TargetSpecializedType specializedType) {
for (var arg : specializedType.params())
collectGenericTypeArguments(generics, arg);
} else if (typeArgument instanceof TargetGenericType genericType) {
if (generics.containsKey(genericType))
generics.put(genericType, generics.get(genericType) + 1);
else generics.put(genericType, 0);
}
}
public static String getSpecializedClassName(GenericParameters gep) {
return getSpecializedClassName(getArguments(gep.inParams), getReturnType(gep.inParams));
}
public static String getSpecializedClassName(List<TargetType> argumentTypes, TargetType returnType) {
var arguments = argumentTypes
.stream()
.map(FunNGenerator::encodeType)
.collect(Collectors.joining());
if (returnType != null)
return String.format("Fun%d$$%s%s",
argumentTypes.size(),
arguments,
encodeType(returnType));
else return String.format("FunVoidImpl%d$$%s",
argumentTypes.size(),
arguments);
}
public static List<TargetType> getArguments(List<TargetType> list) {
return list
.stream()
.limit(Math.max(0, list.size() - 1))
.collect(Collectors.toList());
}
public static TargetType getReturnType(List<TargetType> list) {
if(list.isEmpty())
throw new IndexOutOfBoundsException();
return list.getLast();
}
}

View File

@ -1,30 +0,0 @@
package de.dhbwstuttgart.bytecode;
import org.objectweb.asm.*;
public class JavaTXSignatureAttribute extends Attribute {
public String signature;
public JavaTXSignatureAttribute() {
super("JavaTXSignature");
}
protected JavaTXSignatureAttribute(String signature) {
this();
this.signature = signature;
}
@Override
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));
}
@Override
protected ByteVector write(ClassWriter classWriter, byte[] code, int codeLength, int maxStack, int maxLocals) {
var data = new ByteVector();
data.putShort(classWriter.newConst(this.signature));
return data;
}
}

View File

@ -39,7 +39,7 @@ public class ConsoleInterface {
}
JavaTXCompiler compiler = new JavaTXCompiler(input, classpath, outputPath != null ? new File(outputPath) : null);
//compiler.typeInference();
compiler.generateBytecode();
compiler.run();
}

View File

@ -1,7 +1,6 @@
//PL 2018-12-19: typeInferenceOld nach typeInference uebertragen
package de.dhbwstuttgart.core;
import de.dhbwstuttgart.bytecode.Codegen;
import de.dhbwstuttgart.environment.CompilationEnvironment;
import de.dhbwstuttgart.environment.DirectoryClassLoader;
import de.dhbwstuttgart.exceptions.DebugException;
@ -19,7 +18,6 @@ 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.UnifyTypeFactory;
import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType;
import de.dhbwstuttgart.syntaxtree.type.GenericRefType;
import de.dhbwstuttgart.syntaxtree.type.RefType;
@ -27,38 +25,15 @@ import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.syntaxtree.type.TypeVisitor;
import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter;
import de.dhbwstuttgart.target.generate.ASTToTargetAST;
import de.dhbwstuttgart.target.generate.GenericsResult;
import de.dhbwstuttgart.typeinference.constraints.Constraint;
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
import de.dhbwstuttgart.typeinference.constraints.Pair;
import de.dhbwstuttgart.typeinference.result.ResultSet;
import de.dhbwstuttgart.typeinference.typeAlgo.TYPE;
import de.dhbwstuttgart.typeinference.unify.RuleSet;
import de.dhbwstuttgart.typeinference.unify.TypeUnify;
import de.dhbwstuttgart.typeinference.unify.distributeVariance;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unify.model.PairOperator;
import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
import de.dhbwstuttgart.typeinference.unify.model.UnifyType;
import de.dhbwstuttgart.typeinference.unify.TypeUnifyTask;
import de.dhbwstuttgart.typeinference.unify.UnifyResultListener;
import de.dhbwstuttgart.typeinference.unify.UnifyResultListenerImpl;
import de.dhbwstuttgart.typeinference.unify.UnifyResultModel;
import de.dhbwstuttgart.typeinference.unify.UnifyTaskModel;
import java.io.*;
import java.lang.reflect.Modifier;
import java.nio.file.Path;
import java.util.*;
import java.util.Map.Entry;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.apache.commons.io.output.NullOutputStream;
public class JavaTXCompiler {
// public static JavaTXCompiler INSTANCE;
@ -67,12 +42,15 @@ public class JavaTXCompiler {
public final Map<File, SourceFile> sourceFiles = new HashMap<>();
Boolean log = true; //gibt an ob ein Log-File nach System.getProperty("user.dir")+""/logFiles/"" geschrieben werden soll?
public volatile UnifyTaskModel usedTasks = new UnifyTaskModel();
public final DirectoryClassLoader classLoader;
public final List<File> classPath;
private final File outputPath;
public final JavaClassRegistry classRegistry = new JavaClassRegistry();
public record ClassEntry(File classFile, ClassOrInterface cif) {}
public final Map<JavaClassName, ClassEntry> loadedClasses = new HashMap<>();
public DirectoryClassLoader getClassLoader() {
return classLoader;
}
@ -108,6 +86,30 @@ public class JavaTXCompiler {
// INSTANCE = this;
}
private SourceFile parse(File sourceFile) throws IOException, java.lang.ClassNotFoundException {
if (sourceFiles.containsKey(sourceFile)) return sourceFiles.get(sourceFile);
SourceFileContext tree = JavaTXParser.parse(sourceFile);
environment.addClassesToRegistry(classRegistry, tree, sourceFile, this);
SyntaxTreeGenerator generator = new SyntaxTreeGenerator(this, classRegistry, new GenericsRegistry(null), sourceFile.getName());
var classes = new ArrayList<ClassOrInterface>();
var sf = new SourceFile("", classes, generator.imports);
addSourceFile(sourceFile, sf);
generator.convert(classes, tree, environment.packageCrawler);
sf.setPackageName(generator.pkgName);
sf.imports.addAll(generator.imports);
return sf;
}
public void run() throws IOException, ClassNotFoundException {
for (var file : sourceFiles.keySet()) {
var sf = sourceFiles.get(file);
if (sf.isGenerated()) continue;
sf.setGenerated();
parse(file);
getConstraints(file);
}
}
private void addSourceFile(File file, SourceFile sf) {
sourceFiles.put(file, sf);
}
@ -239,446 +241,6 @@ public class JavaTXCompiler {
return allClasses;
}
/*
* public List<ResultSet> typeInferenceOld() throws ClassNotFoundException { List<ClassOrInterface> allClasses = new ArrayList<>();//environment.getAllAvailableClasses(); //Alle Importierten Klassen in allen geparsten Sourcefiles kommen ins FC for(SourceFile sf : this.sourceFiles.values()) { allClasses.addAll(getAvailableClasses(sf)); allClasses.addAll(sf.getClasses()); }
*
* final ConstraintSet<Pair> cons = getConstraints();
*
* FiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses); System.out.println(finiteClosure); ConstraintSet<UnifyPair> unifyCons = UnifyTypeFactory.convert(cons);
*
* TypeUnify unify = new TypeUnify(); Set<Set<UnifyPair>> results = new HashSet<>(); try { File logPath = new File(System.getProperty("user.dir")+"/target/logFiles/"); logPath.mkdirs(); FileWriter logFile = new FileWriter(new File(logPath, "log")); logFile.write("FC:\\" + finiteClosure.toString()+"\n"); for(SourceFile sf : this.sourceFiles.values()) { logFile.write(ASTTypePrinter.print(sf)); } logFile.flush(); Set<List<Constraint<UnifyPair>>> cardProd = unifyCons.cartesianProduct(); for
* (List<Constraint<UnifyPair>> xCons : cardProd ){ Set<UnifyPair> xConsSet = new HashSet<>(); for (Constraint<UnifyPair> constraint : xCons) { xConsSet.addAll(constraint); } //.collect(Collectors.toCollection(ArrayList::new)))) System.out.println(xConsSet); Set<String> methodParaTypeVarNames = allClasses.stream().map(x -> x.getMethods().stream().map(y -> y.getParameterList().getFormalparalist() .stream().filter(z -> z.getType() instanceof TypePlaceholder) .map(z ->
* ((TypePlaceholder)z.getType()).getName()).collect(Collectors.toCollection( HashSet::new))) .reduce(new HashSet<String>(), (a,b) -> { a.addAll(b); return a;}, (a,b) -> { a.addAll(b); return a;} ) ) .reduce(new HashSet<String>(), (a,b) -> { a.addAll(b); return a;} );
*
* Set<String> constructorParaTypeVarNames = allClasses.stream().map(x -> x.getConstructors().stream().map(y -> y.getParameterList().getFormalparalist() .stream().filter(z -> z.getType() instanceof TypePlaceholder) .map(z -> ((TypePlaceholder)z.getType()).getName()).collect(Collectors.toCollection( HashSet::new))) .reduce(new HashSet<String>(), (a,b) -> { a.addAll(b); return a;}, (a,b) -> { a.addAll(b); return a;} ) ) .reduce(new HashSet<String>(), (a,b) -> { a.addAll(b); return a;} );
*
* Set<String> paraTypeVarNames = methodParaTypeVarNames; paraTypeVarNames.addAll(constructorParaTypeVarNames);
*
* Set<String> returnTypeVarNames = allClasses.stream().map(x -> x.getMethods().stream().filter(y -> y.getReturnType() instanceof TypePlaceholder) .map(z -> ((TypePlaceholder)z.getReturnType()).getName()).collect(Collectors. toCollection(HashSet::new))).reduce((a,b) -> { a.addAll(b); return a;} ).get();
*
* Set<String> fieldTypeVarNames = allClasses.stream().map(x -> x.getFieldDecl().stream().filter(y -> y.getReturnType() instanceof TypePlaceholder) .map(z -> ((TypePlaceholder)z.getReturnType()).getName()).collect(Collectors. toCollection(HashSet::new))).reduce((a,b) -> { a.addAll(b); return a;} ).get();
*
* returnTypeVarNames.addAll(fieldTypeVarNames);
*
* xConsSet = xConsSet.stream().map(x -> { //Hier muss ueberlegt werden, ob //1. alle Argument- und Retuntyp-Variablen in allen UnifyPairs // mit disableWildcardtable() werden. //2. alle Typvariablen mit Argument- oder Retuntyp-Variablen //in Beziehung auch auf disableWildcardtable() gesetzt werden muessen //PL 2018-04-23 if ((x.getLhsType() instanceof PlaceholderType)) { if (paraTypeVarNames.contains(x.getLhsType().getName())) { ((PlaceholderType)x.getLhsType()).setVariance((byte)1);
* ((PlaceholderType)x.getLhsType()).disableWildcardtable(); } if (returnTypeVarNames.contains(x.getLhsType().getName())) { ((PlaceholderType)x.getLhsType()).setVariance((byte)-1); ((PlaceholderType)x.getLhsType()).disableWildcardtable(); } } if ((x.getRhsType() instanceof PlaceholderType)) { if (paraTypeVarNames.contains(x.getRhsType().getName())) { ((PlaceholderType)x.getRhsType()).setVariance((byte)1); ((PlaceholderType)x.getRhsType()).disableWildcardtable(); } if
* (returnTypeVarNames.contains(x.getRhsType().getName())) { ((PlaceholderType)x.getRhsType()).setVariance((byte)-1); ((PlaceholderType)x.getRhsType()).disableWildcardtable(); } } return x;//HIER DIE JEWEILS RECHT BZW. LINKE SEITE AUF GLEICHE VARIANZ SETZEN WIE DIE JEWEILS ANDERE SEITE }).map( y -> { if ((y.getLhsType() instanceof PlaceholderType) && (y.getRhsType() instanceof PlaceholderType)) { if (((PlaceholderType)y.getLhsType()).getVariance() != 0 &&
* ((PlaceholderType)y.getRhsType()).getVariance() == 0) { ((PlaceholderType)y.getRhsType()).setVariance(((PlaceholderType)y.getLhsType( )).getVariance()); } if (((PlaceholderType)y.getLhsType()).getVariance() == 0 && ((PlaceholderType)y.getRhsType()).getVariance() != 0) { ((PlaceholderType)y.getLhsType()).setVariance(((PlaceholderType)y.getRhsType( )).getVariance()); } } return y; } ) .collect(Collectors.toCollection(HashSet::new)); varianceInheritance(xConsSet); Set<Set<UnifyPair>> result =
* unify.unifySequential(xConsSet, finiteClosure, logFile, log); //Set<Set<UnifyPair>> result = unify.unify(xConsSet, finiteClosure); System.out.println("RESULT: " + result); logFile.write("RES: " + result.toString()+"\n"); logFile.flush(); results.addAll(result); }
*
* results = results.stream().map(x -> { Optional<Set<UnifyPair>> res = new RuleSet().subst(x.stream().map(y -> { if (y.getPairOp() == PairOperator.SMALLERDOTWC) y.setPairOp(PairOperator.EQUALSDOT); return y; //alle Paare a <.? b erden durch a =. b ersetzt }).collect(Collectors.toCollection(HashSet::new))); if (res.isPresent()) {//wenn subst ein Erg liefert wurde was veraendert return new TypeUnifyTask().applyTypeUnificationRules(res.get(), finiteClosure); } else return x; //wenn nichts
* veraendert wurde wird x zurueckgegeben }).collect(Collectors.toCollection(HashSet::new)); System.out.println("RESULT Final: " + results); logFile.write("RES_FINAL: " + results.toString()+"\n"); logFile.flush(); logFile.write("PLACEHOLDERS: " + PlaceholderType.EXISTING_PLACEHOLDERS); logFile.flush(); } catch (IOException e) { e.printStackTrace(); } return results.stream().map((unifyPairs -> new ResultSet(UnifyTypeFactory.convert(unifyPairs,
* generateTPHMap(cons))))).collect(Collectors.toList()); }
*/
/**
* Vererbt alle Variancen bei Paaren (a <. theta) oder (Theta <. a) wenn a eine Variance !=0 hat auf alle Typvariablen in Theta.
*
*
*/
/*
* private void varianceInheritance(Set<UnifyPair> eq) { Set<PlaceholderType> usedTPH = new HashSet<>(); Set<PlaceholderType> phSet = eq.stream().map(x -> { Set<PlaceholderType> pair = new HashSet<>(); if (x.getLhsType() instanceof PlaceholderType) pair.add((PlaceholderType)x.getLhsType()); if (x.getRhsType() instanceof PlaceholderType) pair.add((PlaceholderType)x.getRhsType()); return pair; }).reduce(new HashSet<>(), (a,b) -> { a.addAll(b); return a;} , (c,d) -> { c.addAll(d); return c;});
*
* ArrayList<PlaceholderType> phSetVariance = new ArrayList<>(phSet); phSetVariance.removeIf(x -> (x.getVariance() == 0)); while(!phSetVariance.isEmpty()) { PlaceholderType a = phSetVariance.remove(0); usedTPH.add(a); //HashMap<PlaceholderType,Integer> ht = new HashMap<>(); //ht.put(a, a.getVariance()); Set<UnifyPair> eq1 = new HashSet<>(eq); eq1.removeIf(x -> !(x.getLhsType() instanceof PlaceholderType && ((PlaceholderType)x.getLhsType()).equals(a))); eq1.stream().forEach(x -> {
* x.getRhsType().accept(new distributeVariance(), a.getVariance());}); eq1 = new HashSet<>(eq); eq1.removeIf(x -> !(x.getRhsType() instanceof PlaceholderType && ((PlaceholderType)x.getRhsType()).equals(a))); eq1.stream().forEach(x -> { x.getLhsType().accept(new distributeVariance(), a.getVariance());}); phSetVariance = new ArrayList<>(phSet); phSetVariance.removeIf(x -> (x.getVariance() == 0 || usedTPH.contains(x))); } }
*/
public UnifyResultModel typeInferenceAsync(UnifyResultListener resultListener, Writer logFile) throws ClassNotFoundException, IOException {
List<ClassOrInterface> allClasses = new ArrayList<>();// environment.getAllAvailableClasses();
// Alle Importierten Klassen in allen geparsten Sourcefiles kommen ins FC
for (Entry<File, SourceFile> source : this.sourceFiles.entrySet()) {
SourceFile sf = source.getValue();
allClasses.addAll(getAvailableClasses(sf));
allClasses.addAll(sf.getClasses());
allClasses.addAll(CompilationEnvironment.loadDefaultPackageClasses(sf.getPkgName(), source.getKey(), this).stream().map(ASTFactory::createClass).collect(Collectors.toList()));
}
final ConstraintSet<Pair> cons = new ConstraintSet<>();
for (var f : this.sourceFiles.keySet()) {
cons.addAll(getConstraints(f));
}
Set<Set<UnifyPair>> results = new HashSet<>();
UnifyResultModel urm = null;
// urm.addUnifyResultListener(resultListener);
try {
logFile = logFile == null ? new FileWriter(new File("log_" + sourceFiles.keySet().iterator().next().getName())) : logFile;
IFiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses, logFile, getClassLoader(), this);
System.out.println(finiteClosure);
urm = new UnifyResultModel(cons, finiteClosure);
urm.addUnifyResultListener(resultListener);
ConstraintSet<UnifyPair> unifyCons = UnifyTypeFactory.convert(this, cons);
Function<UnifyPair, UnifyPair> distributeInnerVars = x -> {
UnifyType lhs, rhs;
if (((lhs = x.getLhsType()) instanceof PlaceholderType) && ((rhs = x.getRhsType()) instanceof PlaceholderType) && (((PlaceholderType) lhs).isInnerType() || ((PlaceholderType) rhs).isInnerType())) {
((PlaceholderType) lhs).setInnerType(true);
((PlaceholderType) rhs).setInnerType(true);
}
return x;
};
logFile.write(unifyCons.toString());
unifyCons = unifyCons.map(distributeInnerVars);
logFile.write(unifyCons.toString());
TypeUnify unify = new TypeUnify();
// Set<Set<UnifyPair>> results = new HashSet<>(); Nach vorne gezogen
logFile.write("FC:\\" + finiteClosure.toString() + "\n");
for (SourceFile f : this.sourceFiles.values()) {
logFile.write(ASTTypePrinter.print(f));
}
logFile.flush();
Set<String> methodParaTypeVarNames = allClasses.stream().map(x -> x.getMethods().stream().map(y -> y.getParameterList().getFormalparalist().stream().filter(z -> z.getType() instanceof TypePlaceholder).map(z -> ((TypePlaceholder) z.getType()).getName()).collect(Collectors.toCollection(HashSet::new))).reduce(new HashSet<String>(), (a, b) -> {
a.addAll(b);
return a;
}, (a, b) -> {
a.addAll(b);
return a;
})).reduce(new HashSet<String>(), (a, b) -> {
a.addAll(b);
return a;
});
Set<String> constructorParaTypeVarNames = allClasses.stream().map(x -> x.getConstructors().stream().map(y -> y.getParameterList().getFormalparalist().stream().filter(z -> z.getType() instanceof TypePlaceholder).map(z -> ((TypePlaceholder) z.getType()).getName()).collect(Collectors.toCollection(HashSet::new))).reduce(new HashSet<String>(), (a, b) -> {
a.addAll(b);
return a;
}, (a, b) -> {
a.addAll(b);
return a;
})).reduce(new HashSet<String>(), (a, b) -> {
a.addAll(b);
return a;
});
Set<String> paraTypeVarNames = methodParaTypeVarNames;
paraTypeVarNames.addAll(constructorParaTypeVarNames);
Set<String> returnTypeVarNames = allClasses.stream().map(x -> x.getMethods().stream().filter(y -> y.getReturnType() instanceof TypePlaceholder).map(z -> ((TypePlaceholder) z.getReturnType()).getName()).collect(Collectors.toCollection(HashSet::new))).reduce((a, b) -> {
a.addAll(b);
return a;
}).get();
Set<String> fieldTypeVarNames = allClasses.stream().map(x -> x.getFieldDecl().stream().filter(y -> y.getReturnType() instanceof TypePlaceholder).map(z -> ((TypePlaceholder) z.getReturnType()).getName()).collect(Collectors.toCollection(HashSet::new))).reduce((a, b) -> {
a.addAll(b);
return a;
}).get();
returnTypeVarNames.addAll(fieldTypeVarNames);
unifyCons = unifyCons.map(x -> {
// Hier muss ueberlegt werden, ob
// 1. alle Argument- und Retuntyp-Variablen in allen UnifyPairs
// mit disableWildcardtable() werden.
// 2. alle Typvariablen mit Argument- oder Retuntyp-Variablen
// in Beziehung auch auf disableWildcardtable() gesetzt werden muessen
// PL 2018-04-23
if ((x.getLhsType() instanceof PlaceholderType)) {
if (paraTypeVarNames.contains(x.getLhsType().getName())) {
((PlaceholderType) x.getLhsType()).setVariance((byte) 1);
((PlaceholderType) x.getLhsType()).disableWildcardtable();
}
if (returnTypeVarNames.contains(x.getLhsType().getName())) {
((PlaceholderType) x.getLhsType()).setVariance((byte) -1);
((PlaceholderType) x.getLhsType()).disableWildcardtable();
}
}
if ((x.getRhsType() instanceof PlaceholderType)) {
if (paraTypeVarNames.contains(x.getRhsType().getName())) {
((PlaceholderType) x.getRhsType()).setVariance((byte) 1);
((PlaceholderType) x.getRhsType()).disableWildcardtable();
}
if (returnTypeVarNames.contains(x.getRhsType().getName())) {
((PlaceholderType) x.getRhsType()).setVariance((byte) -1);
((PlaceholderType) x.getRhsType()).disableWildcardtable();
}
}
return x;// HIER DIE JEWEILS RECHT BZW. LINKE SEITE AUF GLEICHE VARIANZ SETZEN WIE DIE
// JEWEILS ANDERE SEITE
});
Set<PlaceholderType> varianceTPHold;
Set<PlaceholderType> varianceTPH = new HashSet<>();
varianceTPH = varianceInheritanceConstraintSet(unifyCons);
/*
* PL 2018-11-07 wird in varianceInheritanceConstraintSet erledigt do { //PL 2018-11-05 Huellenbildung Variance auf alle TPHs der Terme auf der jeweiligen //anderen Seite übertragen varianceTPHold = new HashSet<>(varianceTPH); varianceTPH = varianceInheritanceConstraintSet(unifyCons); unifyCons.map( y -> { if ((y.getLhsType() instanceof PlaceholderType) && (y.getRhsType() instanceof PlaceholderType)) { if (((PlaceholderType)y.getLhsType()).getVariance() != 0 &&
* ((PlaceholderType)y.getRhsType()).getVariance() == 0) { ((PlaceholderType)y.getRhsType()).setVariance(((PlaceholderType)y.getLhsType( )).getVariance()); } if (((PlaceholderType)y.getLhsType()).getVariance() == 0 && ((PlaceholderType)y.getRhsType()).getVariance() != 0) { ((PlaceholderType)y.getLhsType()).setVariance(((PlaceholderType)y.getRhsType( )).getVariance()); } } return y; } ); } while (!varianceTPHold.equals(varianceTPH));
*/
// Set<Set<UnifyPair>> result = unify.unifySequential(xConsSet, finiteClosure,
// logFile, log);
// Set<Set<UnifyPair>> result = unify.unify(xConsSet, finiteClosure);
List<Set<Constraint<UnifyPair>>> oderConstraints = unifyCons.getOderConstraints()/*
* .stream().map(x -> { Set<Set<UnifyPair>> ret = new HashSet<>(); for (Constraint<UnifyPair> y : x) { ret.add(new HashSet<>(y)); } return ret; }).collect(Collectors. toCollection(ArrayList::new))
*/;
unify.unifyAsync(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, logFile, log, urm, usedTasks);
} catch (IOException e) {
System.err.println("kein LogFile");
}
return urm;
}
public List<ResultSet> typeInference(File file) throws ClassNotFoundException, IOException {
var sf = sourceFiles.get(file);
Set<ClassOrInterface> allClasses = new HashSet<>();// environment.getAllAvailableClasses();
allClasses.addAll(getAvailableClasses(sf));
allClasses.addAll(sf.getClasses());
var newClasses = CompilationEnvironment.loadDefaultPackageClasses(sf.getPkgName(), file, this).stream().map(ASTFactory::createClass).collect(Collectors.toSet());
for (var clazz : newClasses) {
// Don't load classes that get recompiled
if (sf.getClasses().stream().anyMatch(nf -> nf.getClassName().equals(clazz.getClassName())))
continue;
if (allClasses.stream().noneMatch(old -> old.getClassName().equals(clazz.getClassName())))
allClasses.add(clazz);
}
final ConstraintSet<Pair> cons = getConstraints(file);
Set<Set<UnifyPair>> results = new HashSet<>();
try {
var logFolder = new File(System.getProperty("user.dir") + "/logFiles/");
if (log) logFolder.mkdirs();
Writer logFile = log ? new FileWriter(new File(logFolder, "log_" + sourceFiles.keySet().iterator().next().getName())) : new OutputStreamWriter(new NullOutputStream());
IFiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses.stream().toList(), logFile, classLoader, this);
System.out.println(finiteClosure);
ConstraintSet<UnifyPair> unifyCons = UnifyTypeFactory.convert(this, cons);
System.out.println("xxx1");
Function<UnifyPair, UnifyPair> distributeInnerVars = x -> {
UnifyType lhs, rhs;
if (((lhs = x.getLhsType()) instanceof PlaceholderType) && ((rhs = x.getRhsType()) instanceof PlaceholderType) && (((PlaceholderType) lhs).isInnerType() || ((PlaceholderType) rhs).isInnerType())) {
((PlaceholderType) lhs).setInnerType(true);
((PlaceholderType) rhs).setInnerType(true);
}
return x;
};
logFile.write("Unify:" + unifyCons.toString());
System.out.println("Unify:" + unifyCons.toString());
unifyCons = unifyCons.map(distributeInnerVars);
logFile.write("\nUnify_distributeInnerVars: " + unifyCons.toString());
TypeUnify unify = new TypeUnify();
// Set<Set<UnifyPair>> results = new HashSet<>(); Nach vorne gezogen
logFile.write("FC:\\" + finiteClosure.toString() + "\n");
logFile.write(ASTTypePrinter.print(sf));
System.out.println(ASTTypePrinter.print(sf));
logFile.flush();
Set<String> methodParaTypeVarNames = allClasses.stream().map(x -> x.getMethods().stream().map(y -> y.getParameterList().getFormalparalist().stream().filter(z -> z.getType() instanceof TypePlaceholder).map(z -> ((TypePlaceholder) z.getType()).getName()).collect(Collectors.toCollection(HashSet::new))).reduce(new HashSet<String>(), (a, b) -> {
a.addAll(b);
return a;
}, (a, b) -> {
a.addAll(b);
return a;
})).reduce(new HashSet<String>(), (a, b) -> {
a.addAll(b);
return a;
});
Set<String> constructorParaTypeVarNames = allClasses.stream().map(x -> x.getConstructors().stream().map(y -> y.getParameterList().getFormalparalist().stream().filter(z -> z.getType() instanceof TypePlaceholder).map(z -> ((TypePlaceholder) z.getType()).getName()).collect(Collectors.toCollection(HashSet::new))).reduce(new HashSet<String>(), (a, b) -> {
a.addAll(b);
return a;
}, (a, b) -> {
a.addAll(b);
return a;
})).reduce(new HashSet<String>(), (a, b) -> {
a.addAll(b);
return a;
});
Set<String> paraTypeVarNames = methodParaTypeVarNames;
paraTypeVarNames.addAll(constructorParaTypeVarNames);
Set<String> returnTypeVarNames = allClasses.stream().map(x -> x.getMethods().stream().filter(y -> y.getReturnType() instanceof TypePlaceholder).map(z -> ((TypePlaceholder) z.getReturnType()).getName()).collect(Collectors.toCollection(HashSet::new))).reduce((a, b) -> {
a.addAll(b);
return a;
}).get();
Set<String> fieldTypeVarNames = allClasses.stream().map(x -> x.getFieldDecl().stream().filter(y -> y.getReturnType() instanceof TypePlaceholder).map(z -> ((TypePlaceholder) z.getReturnType()).getName()).collect(Collectors.toCollection(HashSet::new))).reduce((a, b) -> {
a.addAll(b);
return a;
}).get();
returnTypeVarNames.addAll(fieldTypeVarNames);
unifyCons = unifyCons.map(x -> {
// Hier muss ueberlegt werden, ob
// 1. alle Argument- und Retuntyp-Variablen in allen UnifyPairs
// mit disableWildcardtable() werden.
// 2. alle Typvariablen mit Argument- oder Retuntyp-Variablen
// in Beziehung auch auf disableWildcardtable() gesetzt werden muessen
// PL 2018-04-23
if ((x.getLhsType() instanceof PlaceholderType)) {
if (paraTypeVarNames.contains(x.getLhsType().getName())) {
((PlaceholderType) x.getLhsType()).setVariance((byte) 1);
((PlaceholderType) x.getLhsType()).disableWildcardtable();
}
if (returnTypeVarNames.contains(x.getLhsType().getName())) {
((PlaceholderType) x.getLhsType()).setVariance((byte) -1);
((PlaceholderType) x.getLhsType()).disableWildcardtable();
}
}
if ((x.getRhsType() instanceof PlaceholderType)) {
if (paraTypeVarNames.contains(x.getRhsType().getName())) {
((PlaceholderType) x.getRhsType()).setVariance((byte) 1);
((PlaceholderType) x.getRhsType()).disableWildcardtable();
}
if (returnTypeVarNames.contains(x.getRhsType().getName())) {
((PlaceholderType) x.getRhsType()).setVariance((byte) -1);
((PlaceholderType) x.getRhsType()).disableWildcardtable();
}
}
return x;// HIER DIE JEWEILS RECHT BZW. LINKE SEITE AUF GLEICHE VARIANZ SETZEN WIE DIE
// JEWEILS ANDERE SEITE
});
// PL 2020-02-05 alle Oder-Constraints Receiver und Parameter werden auf
// variance 1 gesetzt
// Es wird davon ausgegangen, dass in OderConstraints in Bedingungen für
// Parameter die Typen der Argumente links stehen
// und die Typen der Rückgabewerte immer rechts stehen
/*
* unifyCons.getOderConstraints().forEach(z -> z.forEach(y -> y.forEach(x -> { if ((x.getLhsType() instanceof PlaceholderType) && x.getPairOp().compareTo(PairOperator.SMALLERDOT) == 0) { ((PlaceholderType) x.getLhsType()).setVariance((byte)1); } else if ((x.getRhsType() instanceof PlaceholderType) && x.getPairOp().compareTo(PairOperator.EQUALSDOT) == 0) { ((PlaceholderType) x.getRhsType()).setVariance((byte)-1); } })));
*/
System.out.println("Unify nach Oder-Constraints-Anpassung:" + unifyCons.toString());
Set<PlaceholderType> varianceTPHold;
Set<PlaceholderType> varianceTPH = new HashSet<>();
varianceTPH = varianceInheritanceConstraintSet(unifyCons);
/*
* PL 2018-11-07 wird in varianceInheritanceConstraintSet erledigt do { //PL 2018-11-05 Huellenbildung Variance auf alle TPHs der Terme auf der jeweiligen //anderen Seite übertragen varianceTPHold = new HashSet<>(varianceTPH); varianceTPH = varianceInheritanceConstraintSet(unifyCons); unifyCons.map( y -> { if ((y.getLhsType() instanceof PlaceholderType) && (y.getRhsType() instanceof PlaceholderType)) { if (((PlaceholderType)y.getLhsType()).getVariance() != 0 &&
* ((PlaceholderType)y.getRhsType()).getVariance() == 0) { ((PlaceholderType)y.getRhsType()).setVariance(((PlaceholderType)y.getLhsType( )).getVariance()); } if (((PlaceholderType)y.getLhsType()).getVariance() == 0 && ((PlaceholderType)y.getRhsType()).getVariance() != 0) { ((PlaceholderType)y.getLhsType()).setVariance(((PlaceholderType)y.getRhsType( )).getVariance()); } } return y; } ); } while (!varianceTPHold.equals(varianceTPH));
*/
// Set<Set<UnifyPair>> result = unify.unifySequential(xConsSet, finiteClosure,
// logFile, log);
// Set<Set<UnifyPair>> result = unify.unify(xConsSet, finiteClosure);
List<Set<Constraint<UnifyPair>>> oderConstraints = unifyCons.getOderConstraints()// .stream().map(x -> {
/*
* Set<Set<UnifyPair>> ret = new HashSet<>(); for (Constraint<UnifyPair> y : x) { ret.add(new HashSet<>(y)); } return ret; }).collect(Collectors.toCollection(ArrayList::new))
*/;
if (resultmodel) {
/* UnifyResultModel Anfang */
UnifyResultModel urm = new UnifyResultModel(cons, finiteClosure);
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("Constraints for Generated Generics: " + " ???");
logFile.write("RES_FINAL: " + li.getResults().toString() + "\n");
logFile.flush();
return li.getResults();
}
/* UnifyResultModel End */
else {
// Set<Set<UnifyPair>> result = unify.unify(unifyCons.getUndConstraints(),
// oderConstraints, finiteClosure, logFile, log, new UnifyResultModel(cons,
// finiteClosure));
Set<Set<UnifyPair>> result = unify.unifyOderConstraints(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, logFile, log, new UnifyResultModel(cons, finiteClosure), usedTasks);
System.out.println("RESULT: " + result);
logFile.write("RES: " + result.toString() + "\n");
logFile.flush();
results.addAll(result);
results = results.stream().map(x -> {
Optional<Set<UnifyPair>> res = new RuleSet().subst(x.stream().map(y -> {
if (y.getPairOp() == PairOperator.SMALLERDOTWC)
y.setPairOp(PairOperator.EQUALSDOT);
return y; // alle Paare a <.? b erden durch a =. b ersetzt
}).collect(Collectors.toCollection(HashSet::new)));
if (res.isPresent()) {// wenn subst ein Erg liefert wurde was veraendert
return new TypeUnifyTask().applyTypeUnificationRules(res.get(), finiteClosure);
} else
return x; // wenn nichts veraendert wurde wird x zurueckgegeben
}).collect(Collectors.toCollection(HashSet::new));
System.out.println("RESULT Final: " + results);
System.out.println("Constraints for Generated Generics: " + " ???");
logFile.write("RES_FINAL: " + results.toString() + "\n");
logFile.flush();
logFile.write("PLACEHOLDERS: " + PlaceholderType.EXISTING_PLACEHOLDERS);
logFile.flush();
}
} catch (IOException e) {
System.err.println("kein LogFile");
}
return results.stream().map((unifyPairs -> new ResultSet(UnifyTypeFactory.convert(unifyPairs, Pair.generateTPHMap(cons))))).collect(Collectors.toList());
}
/**
* Vererbt alle Variancen bei Paaren (a <. theta) oder (Theta <. a) wenn a eine Variance !=0 hat auf alle Typvariablen in Theta.
*
*
*/
private Set<PlaceholderType> varianceInheritanceConstraintSet(ConstraintSet<UnifyPair> cons) {
Set<UnifyPair> eq = cons.getAll();
Set<PlaceholderType> usedTPH = new HashSet<>();
Set<PlaceholderType> phSet = eq.stream().map(x -> {
Set<PlaceholderType> pair = new HashSet<>();
if (x.getLhsType() instanceof PlaceholderType)
pair.add((PlaceholderType) x.getLhsType());
if (x.getRhsType() instanceof PlaceholderType)
pair.add((PlaceholderType) x.getRhsType());
return pair;
}).reduce(new HashSet<>(), (a, b) -> {
a.addAll(b);
return a;
}, (c, d) -> {
c.addAll(d);
return c;
});
ArrayList<PlaceholderType> phSetVariance = new ArrayList<>(phSet);
phSetVariance.removeIf(x -> (x.getVariance() == 0));
while (!phSetVariance.isEmpty()) {
PlaceholderType a = phSetVariance.remove(0);
usedTPH.add(a);
// HashMap<PlaceholderType,Integer> ht = new HashMap<>();
// ht.put(a, a.getVariance());
// ConstraintSet<UnifyPair> eq1 = cons;
// eq1.removeIf(x -> !(x.getLhsType() instanceof PlaceholderType &&
// ((PlaceholderType)x.getLhsType()).equals(a)));
// durch if-Abfrage im foreach geloest
cons.forEach(x -> {
if (x.getLhsType() instanceof PlaceholderType && ((PlaceholderType) x.getLhsType()).equals(a)) {
x.getRhsType().accept(new distributeVariance(), a.getVariance());
}
});
// ` eq1 = new HashSet<>(eq);
// eq1.removeIf(x -> !(x.getRhsType() instanceof PlaceholderType &&
// ((PlaceholderType)x.getRhsType()).equals(a)));
// durch if-Abfrage im foreach geloest
cons.forEach(x -> {
if (x.getRhsType() instanceof PlaceholderType && ((PlaceholderType) x.getRhsType()).equals(a)) {
x.getLhsType().accept(new distributeVariance(), a.getVariance());
}
});
phSetVariance = new ArrayList<>(phSet); // macht vermutlich keinen Sinn PL 2018-10-18, doch, es koennen neue
// TPHs mit Variancen dazugekommen sein PL 2018-11-07
phSetVariance.removeIf(x -> (x.getVariance() == 0 || usedTPH.contains(x)));
}
return usedTPH;
}
public final JavaClassRegistry classRegistry = new JavaClassRegistry();
public record ClassEntry(File classFile, ClassOrInterface cif) {}
public final Map<JavaClassName, ClassEntry> loadedClasses = new HashMap<>();
private SourceFile parse(File sourceFile) throws IOException, java.lang.ClassNotFoundException {
if (sourceFiles.containsKey(sourceFile)) return sourceFiles.get(sourceFile);
SourceFileContext tree = JavaTXParser.parse(sourceFile);
environment.addClassesToRegistry(classRegistry, tree, sourceFile, this);
SyntaxTreeGenerator generator = new SyntaxTreeGenerator(this, classRegistry, new GenericsRegistry(null), sourceFile.getName());
var classes = new ArrayList<ClassOrInterface>();
var sf = new SourceFile("", classes, generator.imports);
addSourceFile(sourceFile, sf);
generator.convert(classes, tree, environment.packageCrawler);
sf.setPackageName(generator.pkgName);
sf.imports.addAll(generator.imports);
return sf;
}
/**
* When an import tries to import a JavaTX class it first looks it up in the cache and
* if it doesn't exist it's going to compile it and add it to the source files list
@ -698,10 +260,7 @@ public class JavaTXCompiler {
addSourceFile(file, sf);
generator.convert(classes, tree, environment.packageCrawler);
sf.setPackageName(generator.pkgName);
var classFiles = generateBytecode(file);
sf.setGenerated();
writeClassFile(classFiles, outputPath != null ? outputPath : new File("."), false);
var clazz = classLoader.loadClass(name.toString());
var classOrInterface = ASTFactory.createClass(clazz);
loadedClasses.put(name, new ClassEntry(new File(outputPath, clazz.getName() + ".class"), classOrInterface));
@ -723,85 +282,6 @@ public class JavaTXCompiler {
return null;
}
public void generateBytecode() throws ClassNotFoundException, IOException {
for (var file : sourceFiles.keySet()) {
var sf = sourceFiles.get(file);
if (sf.isGenerated()) continue;
var classes = generateBytecode(file);
sf.setGenerated();
writeClassFile(classes, outputPath == null ? file.getParentFile() : outputPath, outputPath == null);
}
}
/**
* @param path - output-Directory can be null, then class file output is in the same directory as the parsed source files
* @return
*/
public Map<JavaClassName, byte[]> generateBytecode(File sourceFile) throws ClassNotFoundException, IOException {
var sf = sourceFiles.get(sourceFile);
if (sf.isGenerated()) return null;
List<ResultSet> typeinferenceResult = this.typeInference(sourceFile);
var classes = generateBytecode(sf, typeinferenceResult);
sf.setGenerated();
return classes;
}
private Map<SourceFile, List<GenericsResult>> generatedGenerics = new HashMap<>();
public Map<SourceFile, List<GenericsResult>> getGeneratedGenerics() {
return generatedGenerics;
}
/**
* @param outputPath - can be null, then class file output is in the same directory as the parsed source files
* @param typeinferenceResult
* @throws IOException
*/
public void generateBytecode(File outputPath, List<ResultSet> typeinferenceResult) throws IOException {
for (File f : sourceFiles.keySet()) {
HashMap<JavaClassName, byte[]> classFiles = new HashMap<>();
SourceFile sf = sourceFiles.get(f);
File path = outputPath;
if (outputPath == null) {
path = f.getParentFile(); // Set path to path of the parsed .jav file
}
var generatedClasses = generateBytecode(sf, typeinferenceResult);
writeClassFile(generatedClasses, path, outputPath == null);
}
}
public synchronized Map<JavaClassName, byte[]> generateBytecode(SourceFile sf, List<ResultSet> typeInferenceResult) {
var converter = new ASTToTargetAST(this, typeInferenceResult, sf, classLoader);
var generatedClasses = new HashMap<JavaClassName, byte[]>();
for (var clazz : sf.getClasses()) {
var codegen = new Codegen(converter.convert(clazz), this, converter);
var code = codegen.generate();
generatedClasses.put(clazz.getClassName(), code);
converter.auxiliaries.forEach((name, source) -> {
generatedClasses.put(new JavaClassName(name), source);
});
}
generatedGenerics.put(sf, converter.javaGenerics());
converter.generateFunNTypes();
return generatedClasses;
}
public synchronized void writeClassFile(Map<JavaClassName, byte[]> classFiles, File path, boolean preserveHierarchy) throws IOException {
FileOutputStream output;
for (JavaClassName name : classFiles.keySet()) {
byte[] bytecode = classFiles.get(name);
System.out.println("generating " + name + ".class file ...");
var subPath = preserveHierarchy ? path : Path.of(path.toString(), name.getPackageName().split("\\.")).toFile();
File outputFile = new File(subPath, name.getClassName() + ".class");
outputFile.getAbsoluteFile().getParentFile().mkdirs();
System.out.println(outputFile);
output = new FileOutputStream(outputFile);
output.write(bytecode);
output.close();
System.out.println(name + ".class file generated");
}
}
/* PL 2020-03-17 mit TypeExchanger in FCGenerator.java zusammenfuehren */
/**

View File

@ -1,204 +0,0 @@
package de.dhbwstuttgart.parser.SyntaxTreeGenerator;
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.exceptions.DebugException;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.syntaxtree.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.Pattern;
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory;
import de.dhbwstuttgart.syntaxtree.type.*;
import de.dhbwstuttgart.typeinference.constraints.Pair;
import de.dhbwstuttgart.typeinference.unify.model.*;
import java.util.*;
import java.util.stream.Collectors;
import org.antlr.v4.runtime.Token;
public class FCGenerator {
/**
* Baut die FiniteClosure aus availableClasses.
* Klassen welche nicht in availableClasses vorkommen werden im Java Classpath nachgeschlagen.
*
* @param availableClasses - Alle geparsten Klassen
*/
public static Set<UnifyPair> toUnifyFC(JavaTXCompiler compiler, Collection<ClassOrInterface> availableClasses, ClassLoader classLoader) throws ClassNotFoundException {
return toFC(availableClasses, classLoader).stream().map(t -> UnifyTypeFactory.convert(compiler, t)).collect(Collectors.toSet());
}
public static Set<Pair> toFC(Collection<ClassOrInterface> availableClasses, ClassLoader classLoader) throws ClassNotFoundException {
HashSet<Pair> pairs = new HashSet<>();
//PL 2018-09-18: gtvs vor die for-Schleife gezogen, damit immer die gleichen Typeplaceholder eingesetzt werden.
HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> gtvs = new HashMap<>();
for(ClassOrInterface cly : availableClasses){
List<Pair> newPairs = getSuperTypes(cly, availableClasses, gtvs, classLoader);
pairs.addAll(newPairs);
//For all Functional Interfaces FI: FunN$$<... args auf dem Functional Interface ...> <. FI is added to FC
if (isFunctionalInterface(cly)) {
pairs.add(genImplFunType(cly, newPairs.get(0).TA1, gtvs));
}
}
return pairs;
}
private static Boolean isFunctionalInterface(ClassOrInterface cly) {
return (cly.isInterface() && (cly.isFunctionalInterface() || cly.getMethods().size() == 1));
}
private static Pair genImplFunType(ClassOrInterface cly, RefTypeOrTPHOrWildcardOrGeneric fIType, HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> gtvs) {
for(Method m : cly.getMethods()) {
if (!java.lang.reflect.Modifier.isAbstract(m.modifier))
continue;
List<RefTypeOrTPHOrWildcardOrGeneric> tl =
(m.getParameterList().getFormalparalist()
.stream().map(p -> p.getType().acceptTV(new TypeExchanger(gtvs)))
.collect(Collectors.toList()));
tl.add(m.getReturnType().acceptTV(new TypeExchanger(gtvs)));
return new Pair(new RefType(new JavaClassName("Fun" + (tl.size()-1) + "$$"), tl, new NullToken()),
fIType, PairOperator.SMALLER);
}
return null; //kann nicht passieren, da die Methode nur aufgerufen wird wenn cl Functional Interface ist
}
/**
* Bildet eine Kette vom übergebenen Typ bis hin zum höchsten bekannten Typ
* Als Generics werden TPHs benutzt, welche der Unifikationsalgorithmus korrekt interpretieren muss.
* Die verwendeten TPHs werden in der Kette nach oben gereicht, so erhält der selbe GTV immer den selben TPH
* @param forType
* @return
*/
private static List<Pair> getSuperTypes(ClassOrInterface forType, Collection<ClassOrInterface> availableClasses, ClassLoader classLoader) throws ClassNotFoundException {
return getSuperTypes(forType, availableClasses, new HashMap<>(), classLoader);
}
/**
*
* @param forType
* @param availableClasses
* @param gtvs
* @return
* @throws ClassNotFoundException
*/
private static List<Pair> getSuperTypes(ClassOrInterface forType, Collection<ClassOrInterface> availableClasses,
HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> gtvs, ClassLoader classLoader) throws ClassNotFoundException {
List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
//Die GTVs, die in forType hinzukommen:
HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> newGTVs = new HashMap<>();
//Generics mit gleichem Namen müssen den selben TPH bekommen
for(GenericTypeVar gtv : forType.getGenerics()){
if(!gtvs.containsKey(gtv.getName())){
TypePlaceholder replacePlaceholder = TypePlaceholder.fresh(new NullToken());
gtvs.put(gtv.getName(), replacePlaceholder);
newGTVs.put(gtv.getName(), replacePlaceholder);
}
params.add(gtvs.get(gtv.getName()));
}
List<RefType> superClasses = new ArrayList<>();
superClasses.add(forType.getSuperClass());
superClasses.addAll(forType.getSuperInterfaces());
List<Pair> retList = new ArrayList<>();
for(RefType superType : superClasses){
Optional<ClassOrInterface> hasSuperclass = availableClasses.stream().filter(cl -> superType.getName().equals(cl.getClassName())).findAny();
ClassOrInterface superClass;
if(!hasSuperclass.isPresent()) //Wenn es die Klasse in den available Klasses nicht gibt wird sie im Classpath gesucht. Ansonsten Exception
{
superClass = ASTFactory.createClass(classLoader.loadClass(superType.getName().toString()));
}else{
superClass = hasSuperclass.get();
}
/*
Die Parameter der superklasse müssen jetzt nach den Angaben in der Subklasse
modifiziert werden
Beispie: Matrix<A> extends Vector<Vector<A>>
Den ersten Parameter mit Vector<A> austauschen und dort alle Generics zu den Typplaceholdern in gtvs austauschen
*/
//Hier vermerken, welche Typen in der Superklasse ausgetauscht werden müssen
Iterator<GenericTypeVar> itGenParams = superClass.getGenerics().iterator();
Iterator<RefTypeOrTPHOrWildcardOrGeneric> itSetParams = superType.getParaList().iterator();
while(itSetParams.hasNext()){
RefTypeOrTPHOrWildcardOrGeneric setType = itSetParams.next();
//In diesem Typ die GTVs durch TPHs und Einsetzungen austauschen:
RefTypeOrTPHOrWildcardOrGeneric setSetType = setType.acceptTV(new TypeExchanger(gtvs));
newGTVs.put(itGenParams.next().getName(), setSetType);
}
//Für den superType kann man nun zum Austauschen der Generics wieder die gtvs nehmen:
//Die newGTVs sind nur für den superClass ClassOrInterface welches möglicherweise per reflection geladen wurde abgestimmt
RefTypeOrTPHOrWildcardOrGeneric superRefType = superType.acceptTV(new TypeExchanger(gtvs));
RefTypeOrTPHOrWildcardOrGeneric t1 = new RefType(forType.getClassName(), params, new NullToken());
RefTypeOrTPHOrWildcardOrGeneric t2 = superRefType;
Pair ret = new Pair(t1, t2, PairOperator.SMALLER);
List<Pair> superTypes;
//Rekursiver Aufruf. Abbruchbedingung ist Object als Superklasse:
if(superClass.getClassName().equals(ASTFactory.createObjectClass().getClassName())){
superTypes = Arrays.asList(new Pair(ASTFactory.createObjectType(), ASTFactory.createObjectType(), PairOperator.SMALLER));
}else{
superTypes = getSuperTypes(superClass, availableClasses, newGTVs, classLoader);
}
retList.add(ret);
retList.addAll(superTypes);
}
return retList;
}
/**
* Tauscht die GTVs in einem Typ gegen die entsprechenden Typen in der übergebenen Map aus.
*/
private static class TypeExchanger implements TypeVisitor<RefTypeOrTPHOrWildcardOrGeneric>{
private final HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> gtvs;
TypeExchanger(HashMap<String, RefTypeOrTPHOrWildcardOrGeneric> gtvs){
this.gtvs = gtvs;
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric visit(RefType refType) {
List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
for(RefTypeOrTPHOrWildcardOrGeneric param : refType.getParaList()){
params.add(param.acceptTV(this));
}
RefTypeOrTPHOrWildcardOrGeneric ret = new RefType(refType.getName(), params, new NullToken());
return ret;
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric visit(SuperWildcardType superWildcardType) {
throw new DebugException("Dieser Fall darf nicht auftreten");
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric visit(TypePlaceholder typePlaceholder) {
throw new DebugException("Dieser Fall darf nicht auftreten");
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric visit(ExtendsWildcardType extendsWildcardType) {
throw new DebugException("Dieser Fall darf nicht auftreten");
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric visit(GenericRefType genericRefType) {
if(! gtvs.containsKey(genericRefType.getParsedName()))
throw new DebugException("Dieser Fall darf nicht auftreten");
return gtvs.get(genericRefType.getParsedName());
}
}
}

View File

@ -1,14 +1,11 @@
package de.dhbwstuttgart.syntaxtree.factory;
import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Type;
import java.util.*;
import de.dhbwstuttgart.bytecode.JavaTXSignatureAttribute;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.syntaxtree.*;
@ -21,7 +18,6 @@ import de.dhbwstuttgart.syntaxtree.statement.Statement;
import de.dhbwstuttgart.syntaxtree.type.WildcardType;
import de.dhbwstuttgart.util.Pair;
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;
@ -42,52 +38,6 @@ public class ASTFactory {
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 && new File(path).exists()) {
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<>();

View File

@ -1,296 +0,0 @@
package de.dhbwstuttgart.syntaxtree.factory;
import java.io.Writer;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.exceptions.NotImplementedException;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.parser.SourceLoc;
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.FCGenerator;
import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.syntaxtree.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.type.*;
import de.dhbwstuttgart.syntaxtree.type.Void;
import de.dhbwstuttgart.syntaxtree.type.WildcardType;
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
import de.dhbwstuttgart.typeinference.constraints.Pair;
import de.dhbwstuttgart.typeinference.result.PairNoResult;
import de.dhbwstuttgart.typeinference.result.PairTPHEqualTPH;
import de.dhbwstuttgart.typeinference.result.PairTPHequalRefTypeOrWildcardType;
import de.dhbwstuttgart.typeinference.result.PairTPHsmallerTPH;
import de.dhbwstuttgart.typeinference.result.ResultPair;
import de.dhbwstuttgart.typeinference.unify.model.*;
import org.antlr.v4.runtime.Token;
public class UnifyTypeFactory {
private static ArrayList<PlaceholderType> PLACEHOLDERS = new ArrayList<>();
public static FiniteClosure generateFC(List<ClassOrInterface> fromClasses, Writer logFile, ClassLoader classLoader, JavaTXCompiler compiler) throws ClassNotFoundException {
/*
Die transitive Hülle muss funktionieren.
Man darf schreiben List<A> extends AL<A>
und Vector<B> extends List<B>
hier muss dann aber dennoch die Vererbung V < L < AL
hergestellt werden.
In einem solchen Vererbungsbaum dürfen die TPH auch die gleichen Namen haben.
Generell dürfen sie immer die gleichen Namen haben.
TODO: die transitive Hülle bilden
*/
return new FiniteClosure(FCGenerator.toUnifyFC(compiler, fromClasses, classLoader), logFile, compiler);
}
public static UnifyPair generateSmallerPair(UnifyType tl, UnifyType tr, SourceLoc location){
return new UnifyPair(tl, tr, PairOperator.SMALLER, location);
}
public static UnifyPair generateSmallerDotPair(UnifyType tl, UnifyType tr, SourceLoc location){
return new UnifyPair(tl, tr, PairOperator.SMALLERDOT, location);
}
public static UnifyPair generateSmallNotEqualDotPair(UnifyType tl, UnifyType tr, SourceLoc location){
return new UnifyPair(tl, tr, PairOperator.SMALLERNEQDOT, location);
}
public static UnifyPair generateEqualDotPair(UnifyType tl, UnifyType tr, SourceLoc location){
return new UnifyPair(tl, tr, PairOperator.EQUALSDOT, location);
}
/**
* Convert from
* ASTType -> UnifyType
*/
public static UnifyType convert(JavaTXCompiler compiler, RefTypeOrTPHOrWildcardOrGeneric t, Boolean innerType){
if (t instanceof GenericRefType){
return UnifyTypeFactory.convert(compiler, (GenericRefType)t, innerType);
} else if (t instanceof TypePlaceholder){
return UnifyTypeFactory.convert(compiler, (TypePlaceholder)t, innerType);
} else if (t instanceof ExtendsWildcardType){
return UnifyTypeFactory.convert(compiler, (ExtendsWildcardType)t, innerType);
} else if (t instanceof SuperWildcardType) {
return UnifyTypeFactory.convert(compiler, (SuperWildcardType) t, innerType);
} else if (t instanceof RefType){
return UnifyTypeFactory.convert(compiler, (RefType)t, innerType);
}
//Es wurde versucht ein Typ umzuwandeln, welcher noch nicht von der Factory abgedeckt ist
throw new NotImplementedException("Der Typ "+t+" kann nicht umgewandelt werden");
}
public static UnifyType convert(JavaTXCompiler compiler, RefType t, Boolean innerType){
//Check if it is a FunN Type:
Pattern p = Pattern.compile("Fun(\\d+)[$][$]");
Matcher m = p.matcher(t.getName().toString());
boolean b = m.matches();
if(b){
Integer N = Integer.valueOf(m.group(1));
if((N + 1) == t.getParaList().size()){
return convertFunN(compiler, t.getParaList(), false);
}
}
UnifyType ret;
List<UnifyType> params = new ArrayList<>();
if (t.getParaList() != null) {
for (RefTypeOrTPHOrWildcardOrGeneric pT : t.getParaList()) {
params.add(UnifyTypeFactory.convert(compiler, pT, true));
}
}
var clazz = compiler.getClass(t.getName());
if (clazz != null && clazz.isInterface() && clazz.isFunctionalInterface()) {
var method = clazz.getMethods().stream().filter(x -> Modifier.isAbstract(x.modifier)).findFirst().orElseThrow();
var methodParams = method.getParameterList().getFormalparalist().stream().map(x -> convert(compiler, x.getType(), true)).toList();
var generics = StreamSupport.stream(clazz.getGenerics().spliterator(), false).map(GenericTypeVar::getName).toList();
return new FunInterfaceType(t.getName().toString(), new TypeParams(params), methodParams, convert(compiler, method.getReturnType(), true), generics);
}
return new ReferenceType(t.getName().toString(),new TypeParams(params));
}
public static UnifyType convertFunN(JavaTXCompiler compiler, List<RefTypeOrTPHOrWildcardOrGeneric> paraList, Boolean innerType){
UnifyType ret;
List<UnifyType> params = new ArrayList<>();
if(paraList != null && paraList.size() > 0){
for(RefTypeOrTPHOrWildcardOrGeneric pT : paraList){
params.add(UnifyTypeFactory.convert(compiler, pT, false));
}
}
ret = FunNType.getFunNType(new TypeParams(params));
return ret;
}
public static UnifyType convert(JavaTXCompiler compiler, TypePlaceholder tph, Boolean innerType){
if (tph.getName().equals("AFR")) {
System.out.println("XXX"+innerType);
}
PlaceholderType ntph = new PlaceholderType(tph.getName());
ntph.setVariance(tph.getVariance());
ntph.setOrCons(tph.getOrCons());
int in = PLACEHOLDERS.indexOf(ntph);
if (in == -1) {
PLACEHOLDERS.add(ntph);
ntph.setInnerType(innerType);
return ntph;
}
else {
PlaceholderType oldpht = PLACEHOLDERS.get(in);
oldpht.setInnerType(oldpht.isInnerType() || innerType);
return oldpht;
}
}
public static UnifyType convert(JavaTXCompiler compiler, GenericRefType t, Boolean innerType){
return new ReferenceType(t.getParsedName(), true);
}
public static UnifyType convert(JavaTXCompiler compiler, WildcardType t, Boolean innerType){
if(t.isExtends())
return new ExtendsType(UnifyTypeFactory.convert(compiler, t.getInnerType(), false));
else if(t.isSuper())
return new SuperType(UnifyTypeFactory.convert(compiler, t.getInnerType(), false));
else throw new NotImplementedException();
}
public static ConstraintSet<UnifyPair> convert(JavaTXCompiler compiler, ConstraintSet<Pair> constraints) {
return constraints.map(c -> UnifyTypeFactory.convert(compiler, c));
}
//NEVER USED
//public static Constraint<UnifyPair> convert(Constraint<Pair> constraint){
// Constraint<UnifyPair> unifyPairConstraint = constraint.stream()
// .map(UnifyTypeFactory::convert)
// .collect(Collectors.toCollection( () -> new Constraint<UnifyPair> (constraint.isInherited(), convert(constraint.getExtendConstraint()))));
// return unifyPairConstraint;
//}
public static UnifyPair convert(JavaTXCompiler compiler, Pair p) {
UnifyPair ret = null;
if(p.GetOperator().equals(PairOperator.SMALLERDOT)) {
ret = generateSmallerDotPair(UnifyTypeFactory.convert(compiler, p.TA1, false)
, UnifyTypeFactory.convert(compiler, p.TA2, false), p.getLocation());
//return ret;
}else if(p.GetOperator().equals(PairOperator.SMALLERNEQDOT)) {
ret = generateSmallNotEqualDotPair(UnifyTypeFactory.convert(compiler, p.TA1, false)
, UnifyTypeFactory.convert(compiler, p.TA2, false), p.getLocation());
//return ret;
}else if(p.GetOperator().equals(PairOperator.EQUALSDOT)) {
ret = generateEqualDotPair(UnifyTypeFactory.convert(compiler, p.TA1, false)
, UnifyTypeFactory.convert(compiler, p.TA2, false), p.getLocation());
//return ret;
}else if(p.GetOperator().equals(PairOperator.SMALLER)){
ret = generateSmallerPair(UnifyTypeFactory.convert(compiler, p.TA1, false),
UnifyTypeFactory.convert(compiler, p.TA2, false), p.getLocation());
}else throw new NotImplementedException();
UnifyType lhs, rhs;
if (((lhs = ret.getLhsType()) instanceof PlaceholderType)
&& ((PlaceholderType)lhs).isWildcardable()
&& (rhs = ret.getLhsType()) instanceof PlaceholderType) {
if (lhs.getName().equals("AQ")) {
System.out.println("");
}
((PlaceholderType)rhs).enableWildcardtable();
}
if (((rhs = ret.getLhsType()) instanceof PlaceholderType)
&& ((PlaceholderType)rhs).isWildcardable()
&& (lhs = ret.getLhsType()) instanceof PlaceholderType) {
if (rhs.getName().equals("AQ")) {
System.out.println("");
}
((PlaceholderType)lhs).enableWildcardtable();
}
return ret;
}
/**
* Convert from
* UnifyType -> ASTType
*/
public static Set<ResultPair> convert(Set<UnifyPair> unifyPairSet, Map<String,TypePlaceholder> tphs) {
return unifyPairSet.stream().map(
unifyPair -> convert(unifyPair, tphs))
.collect(Collectors.toSet());
}
public static ResultPair convert(UnifyPair mp, Map<String,TypePlaceholder> tphs) {
if (mp == null) { return null;} //kann bei basePairs passieren
RefTypeOrTPHOrWildcardOrGeneric tl = UnifyTypeFactory.convert(mp.getLhsType(), tphs);
RefTypeOrTPHOrWildcardOrGeneric tr = UnifyTypeFactory.convert(mp.getRhsType(), tphs);
if(tl instanceof TypePlaceholder){
if(tr instanceof TypePlaceholder) {
if(mp.getPairOp().equals(PairOperator.EQUALSDOT)) {
return new PairTPHEqualTPH((TypePlaceholder)tl, (TypePlaceholder)tr);
//Einfach ignorieren TODO: Das hier muss ausgebessert werden:
//return new PairTPHequalRefTypeOrWildcardType((TypePlaceholder)tl, ASTFactory.createObjectType());
}else{
return new PairTPHsmallerTPH((TypePlaceholder)tl, (TypePlaceholder)tr, convert(mp.getBasePair(), tphs));
}
}else if(tr instanceof RefType){
return new PairTPHequalRefTypeOrWildcardType((TypePlaceholder)tl, (RefType) tr);
}else if(tr instanceof WildcardType){
return new PairTPHequalRefTypeOrWildcardType((TypePlaceholder)tl, (WildcardType) tr);
}else if(tr instanceof GenericRefType){
return new PairTPHequalRefTypeOrWildcardType((TypePlaceholder)tl, (GenericRefType) tr);
}else throw new NotImplementedException();
}else return new PairNoResult(tl, tr);//throw new NotImplementedException();
}
public static RefTypeOrTPHOrWildcardOrGeneric convert(ReferenceType t, Map<String,TypePlaceholder> tphs) {
if(JavaClassName.Void.equals(t.getName()))return new Void(new NullToken());
if (t.isGenTypeVar()) return new GenericRefType(t.getName(),new NullToken());
RefType ret = new RefType(new JavaClassName(t.getName()),convert(t.getTypeParams(), tphs),new NullToken());
return ret;
}
public static RefTypeOrTPHOrWildcardOrGeneric convert(FunNType t, Map<String,TypePlaceholder> tphs) {
RefType ret = new RefType(new JavaClassName(t.getName()), convert(t.getTypeParams(), tphs), new NullToken());
return ret;
}
public static RefTypeOrTPHOrWildcardOrGeneric convert(SuperType t, Map<String,TypePlaceholder> tphs) {
RefTypeOrTPHOrWildcardOrGeneric innerType = convert(t.getSuperedType(), tphs);
return new SuperWildcardType(innerType, new NullToken());
}
public static RefTypeOrTPHOrWildcardOrGeneric convert(ExtendsType t, Map<String,TypePlaceholder> tphs) {
RefTypeOrTPHOrWildcardOrGeneric innerType = convert(t.getExtendedType(), tphs);
return new ExtendsWildcardType(innerType, new NullToken());
}
public static RefTypeOrTPHOrWildcardOrGeneric convert(PlaceholderType t, Map<String,TypePlaceholder> tphs) {
TypePlaceholder ret = tphs.get(t.getName());
if(ret == null){ //Dieser TPH wurde vom Unifikationsalgorithmus erstellt
ret = TypePlaceholder.fresh(new NullToken());
tphs.put(t.getName(), ret);
}
ret.setVariance(t.getVariance());
return ret;
}
public static RefTypeOrTPHOrWildcardOrGeneric convert(UnifyType t, Map<String,TypePlaceholder> tphs) {
if(t instanceof FunNType)return convert((FunNType) t, tphs);
if(t instanceof ReferenceType)return convert((ReferenceType) t, tphs);
if(t instanceof SuperType)return convert((SuperType) t, tphs);
if(t instanceof ExtendsType)return convert((ExtendsType) t, tphs);
if(t instanceof PlaceholderType)return convert((PlaceholderType) t, tphs);
throw new NotImplementedException("Der Typ "+t+" kann nicht umgewandelt werden");
}
private static List<RefTypeOrTPHOrWildcardOrGeneric> convert(TypeParams typeParams, Map<String,TypePlaceholder> tphs) {
List<RefTypeOrTPHOrWildcardOrGeneric> ret = new ArrayList<>();
for(UnifyType uT : typeParams){
RefTypeOrTPHOrWildcardOrGeneric toAdd = convert(uT, tphs);
ret.add(toAdd);
}
return ret;
}
}

View File

@ -2,9 +2,6 @@
package de.dhbwstuttgart.syntaxtree.statement;
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation;
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
import de.dhbwstuttgart.typeinference.unify.model.PairOperator;
import org.antlr.v4.runtime.Token;
/*

View File

@ -1,18 +1,9 @@
package de.dhbwstuttgart.syntaxtree.statement;
import de.dhbwstuttgart.exceptions.TypeinferenceException;
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.typeinference.assumptions.FieldAssumption;
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation;
import de.dhbwstuttgart.typeinference.constraints.Constraint;
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
import de.dhbwstuttgart.typeinference.unify.model.PairOperator;
import org.antlr.v4.runtime.Token;
import java.util.HashSet;
import java.util.Set;
public class FieldVar extends Expression {
public final String fieldVarName;

View File

@ -1,15 +1,7 @@
package de.dhbwstuttgart.syntaxtree.statement;
import de.dhbwstuttgart.exceptions.TypeinferenceException;
import de.dhbwstuttgart.syntaxtree.*;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation;
import de.dhbwstuttgart.typeinference.constraints.Constraint;
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
import de.dhbwstuttgart.typeinference.assumptions.MethodAssumption;
import de.dhbwstuttgart.typeinference.constraints.Pair;
import de.dhbwstuttgart.typeinference.unify.model.PairOperator;
import org.antlr.v4.runtime.Token;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;

View File

@ -1,25 +1,10 @@
package de.dhbwstuttgart.syntaxtree.statement;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import de.dhbwstuttgart.exceptions.TypeinferenceException;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.assumptions.MethodAssumption;
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation;
import de.dhbwstuttgart.typeinference.constraints.Constraint;
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
import de.dhbwstuttgart.typeinference.constraints.Pair;
import de.dhbwstuttgart.typeinference.unify.model.PairOperator;
import org.antlr.v4.runtime.Token;
import de.dhbwstuttgart.exceptions.NotImplementedException;
public class NewClass extends MethodCall

View File

@ -1,602 +0,0 @@
package de.dhbwstuttgart.target.generate;
import de.dhbwstuttgart.bytecode.CodeGenException;
import de.dhbwstuttgart.bytecode.FunNGenerator;
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.environment.ByteArrayClassLoader;
import de.dhbwstuttgart.environment.IByteArrayClassLoader;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.syntaxtree.*;
import de.dhbwstuttgart.syntaxtree.Record;
import de.dhbwstuttgart.syntaxtree.factory.ASTFactory;
import de.dhbwstuttgart.syntaxtree.statement.*;
import de.dhbwstuttgart.syntaxtree.type.*;
import de.dhbwstuttgart.target.tree.*;
import de.dhbwstuttgart.target.tree.expression.*;
import de.dhbwstuttgart.target.tree.type.*;
import de.dhbwstuttgart.typeinference.result.*;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @author dholle
*/
public class ASTToTargetAST {
record SignaturePair(TypePlaceholder signature, RefTypeOrTPHOrWildcardOrGeneric parameter) {};
record SignaturePairTarget(TargetType signature, TargetType parameter) {}
public static RefType OBJECT = ASTFactory.createObjectType(); // TODO It would be better if I could call this directly but the hashcode seems to change
protected List<Generics> all;
public Generics generics;
final Map<ClassOrInterface, Set<GenericTypeVar>> userDefinedGenerics = new HashMap<>();
final Map<Method, Set<SignaturePair>> tphsInMethods = new HashMap<>();
private Method currentMethod;
public final JavaTXCompiler compiler;
public List<GenericsResult> txGenerics() {
return all.stream().map(generics -> new GenericsResult(generics.txGenerics)).toList();
}
public List<GenericsResult> javaGenerics() {
return all.stream().map(generics -> new GenericsResult(generics.javaGenerics)).toList();
}
public TargetExpression convert(Pattern pattern) {
var converter = new StatementToTargetExpression(this);
pattern.accept(converter);
return converter.result;
}
public record Generics(JavaGenerics javaGenerics, TxGenerics txGenerics) {
}
public IByteArrayClassLoader classLoader;
protected SourceFile sourceFile;
public ASTToTargetAST(List<ResultSet> resultSets) {
this(null, resultSets);
}
public ASTToTargetAST(JavaTXCompiler compiler, List<ResultSet> resultSets) {
this(compiler, resultSets, null, new ByteArrayClassLoader());
}
public ASTToTargetAST(JavaTXCompiler compiler, List<ResultSet> resultSets, SourceFile sourceFile, IByteArrayClassLoader classLoader) {
this.compiler = compiler;
this.classLoader = classLoader;
this.sourceFile = sourceFile;
all = new ArrayList<>();
for (var set : resultSets) {
all.add(new Generics(new JavaGenerics(this, set), new TxGenerics(this, set)));
}
this.generics = all.get(0);
}
public void addSignaturePair(TypePlaceholder signature, RefTypeOrTPHOrWildcardOrGeneric parameter) {
var set = tphsInMethods.getOrDefault(currentMethod, new HashSet<>());
set.add(new SignaturePair(signature, parameter));
tphsInMethods.put(currentMethod, set);
}
Optional<Method> findMethod(ClassOrInterface owner, String name, List<TargetType> argumentList) {
Optional<Method> method = Optional.empty();
while (method.isEmpty()) {
method = owner.getMethods().stream().filter(m -> m.name.equals(name) && parameterEquals(m.getParameterList(), argumentList)).findFirst();
if (owner.getClassName().toString().equals("java.lang.Object")) break;
owner = compiler.getClass(owner.getSuperClass().getName());
}
return method;
}
Optional<Constructor> findConstructor(ClassOrInterface owner, List<TargetType> argumentList) {
return owner.getConstructors().stream().filter(c -> parameterEquals(c.getParameterList(), argumentList)).findFirst();
}
boolean parameterEquals(ParameterList parameterList, List<TargetType> arguments) {
var pars = parameterList.getFormalparalist();
if (pars.size() != arguments.size())
return false;
for (var i = 0; i < pars.size(); i++) {
var type1 = convert(pars.get(i).getType(), generics.javaGenerics);
var type2 = arguments.get(i);
if (type1 instanceof TargetGenericType)
return true;
if (TargetType.toPrimitive(type2).equals(type1))
return true;
if (!type1.equals(type2))
return false;
}
return true;
}
Set<TargetGeneric> convert(Set<GenerateGenerics.Pair> result, GenerateGenerics generics) {
return result.stream().map(p -> {
if (p instanceof GenerateGenerics.PairLT pair) {
return new TargetGeneric(pair.left.resolve().getName(), convert(pair.right.resolve(), generics));
} else if (p instanceof GenerateGenerics.PairEQ pair) {
return new TargetGeneric(pair.left.resolve().getName(), convert(pair.right, generics));
} else {
throw new IllegalArgumentException();
}
}).collect(Collectors.toSet());
}
public List<TargetGeneric> convert(GenericTypeVar typeVar, GenerateGenerics generics) {
var ret = new ArrayList<TargetGeneric>();
for (var bound : typeVar.getBounds()) {
ret.add(new TargetGeneric(typeVar.getName(), generics.getTargetType(bound)));
}
return ret;
}
public List<List<TargetMethod>> groupOverloads(ClassOrInterface input, List<Method> methods) {
var res = new ArrayList<List<TargetMethod>>();
for (var method : methods) {
// Convert all methods
var methodsWithTphs = convert(input, method);
// Then check for methods with the same signature
var mapOfSignatures = new HashMap<TargetMethod.Signature, List<MethodWithTphs>>();
for (var m : methodsWithTphs) {
var methodsWithSameSignature = mapOfSignatures.getOrDefault(m.method.signature(), new ArrayList<>());
methodsWithSameSignature.add(m);
mapOfSignatures.put(m.method.signature(), methodsWithSameSignature);
}
var resMethods = new HashSet<TargetMethod>();
for (var methodsWithSignature : mapOfSignatures.values()) {
outer: for (var m1 : methodsWithSignature) {
for (var m2 : methodsWithSignature) {
for (var i = 0; i < m1.args.size(); i++) {
var arg1 = m1.args.get(i);
var arg2 = m2.args.get(i);
if (arg1.parameter.equals(arg2.parameter)) {
if (isSupertype(arg1.signature, arg2.signature) &&
!arg1.signature.equals(arg2.signature)) continue outer;
}
}
}
resMethods.add(m1.method);
}
}
res.add(resMethods.stream().toList());
}
return res;
}
public TargetStructure convert(ClassOrInterface input) {
Set<TargetGeneric> javaGenerics = new HashSet<>();
Set<TargetGeneric> txGenerics = new HashSet<>();
var genericsIter = input.getGenerics().iterator();
if (genericsIter.hasNext()) {
// Add empty set of generics to cache so that it doesn't try to calculate it later
var userDefinedGenerics = new HashSet<GenericTypeVar>();
this.userDefinedGenerics.put(input, userDefinedGenerics);
while (genericsIter.hasNext()) {
var next = genericsIter.next();
userDefinedGenerics.add(next);
// TODO Support multiple bounds
javaGenerics.add(new TargetGeneric(next.getName(), convert(next.getBounds().get(0))));
}
} else {
this.userDefinedGenerics.put(input, new HashSet<>());
// Generate generics only if there are no user defined ones
javaGenerics = convert(generics.javaGenerics.generics(input), generics.javaGenerics);
txGenerics = convert(generics.txGenerics.generics(input), generics.txGenerics);
}
TargetBlock fieldInitializer = null;
if (input.getfieldInitializations().isPresent())
fieldInitializer = convert(input.getfieldInitializations().get().block);
TargetBlock finalFieldInitializer = fieldInitializer;
var superInterfaces = input.getSuperInterfaces().stream().map(clazz -> convert(clazz, generics.javaGenerics)).toList();
var constructors = input.getConstructors().stream().map(constructor -> this.convert(input, constructor, finalFieldInitializer)).flatMap(List::stream).toList();
var fields = input.getFieldDecl().stream().map(this::convert).toList();
var methods = groupOverloads(input, input.getMethods()).stream().flatMap(List::stream).toList();
TargetMethod staticConstructor = null;
if (input.getStaticInitializer().isPresent())
staticConstructor = this.convert(input, input.getStaticInitializer().get()).stream().findFirst().orElseThrow().method;
if (input instanceof Record)
return new TargetRecord(input.getModifiers(), input.getClassName(), javaGenerics, txGenerics, superInterfaces, constructors, staticConstructor, fields, methods);
else if (input.isInterface())
return new TargetInterface(input.getModifiers(), input.getClassName(), javaGenerics, txGenerics, methods, superInterfaces, staticConstructor);
else return new TargetClass(input.getModifiers(), input.getClassName(), convert(input.getSuperClass(), generics.javaGenerics), javaGenerics, txGenerics, superInterfaces, constructors, staticConstructor, fields, methods);
}
public List<MethodParameter> convert(ParameterList input, GenerateGenerics generics) {
return input.getFormalparalist().stream().map(param ->
new MethodParameter((TargetPattern) convert(param))
).toList();
}
private boolean hasGeneric(Set<TargetGeneric> generics, GenericRefType type) {
return generics.stream().anyMatch(g -> g.name().equals(type.getParsedName()));
}
private Set<TargetGeneric> collectMethodGenerics(ClassOrInterface clazz, GenerateGenerics generateGenerics, Set<GenerateGenerics.Pair> generics, Method input) {
var convertedGenerics = new HashSet<>(convert(generics, generateGenerics));
outer: for (GenericTypeVar typeVar : input.getGenerics()) {
for (var classGeneric : clazz.getGenerics()) {
if (classGeneric.equals(typeVar)) {
continue outer;
}
}
convertedGenerics.addAll(convert(typeVar, generateGenerics));
}
/*
* var returnType = sigma.getType(input.getReturnType(), equality); if ((returnType instanceof GenericRefType refType) && !hasGeneric(convertedGenerics, refType)) { convertedGenerics.add(new TargetGeneric(refType.getParsedName(), convert(OBJECT))); } for (var param : input.getParameterList()) { var type = sigma.getType(param.getType(), equality); if (type instanceof GenericRefType refType && !hasGeneric(convertedGenerics, refType)) { convertedGenerics.add(new
* TargetGeneric(refType.getParsedName(), convert(OBJECT))); } }
*/
return convertedGenerics;
}
private List<TargetConstructor> convert(ClassOrInterface currentClass, Constructor input, TargetBlock fieldInitializer) {
generics = all.get(0);
List<TargetConstructor> result = new ArrayList<>();
Set<List<MethodParameter>> parameterSet = new HashSet<>();
this.currentMethod = input;
for (var s : all) {
generics = s;
var javaGenerics = this.generics.javaGenerics.generics(currentClass, input);
var txGenerics = this.generics.txGenerics.generics(currentClass, input);
List<MethodParameter> params = convert(input.getParameterList(), this.generics.javaGenerics);
if (parameterSet.stream().noneMatch(p -> p.equals(params))) {
List<MethodParameter> txParams = convert(input.getParameterList(), this.generics.txGenerics);
var javaMethodGenerics = collectMethodGenerics(currentClass, generics.javaGenerics(), javaGenerics, input);
var txMethodGenerics = collectMethodGenerics(currentClass, generics.txGenerics(), txGenerics, input);
result.add(new TargetConstructor(input.modifier, javaMethodGenerics, txMethodGenerics, params, txParams, convert(input.block), fieldInitializer));
parameterSet.add(params);
}
}
return result;
}
private String encodeName(String name, ParameterList params) {
var res = new StringBuilder();
res.append(name);
res.append('$');
for (var param : params.getFormalparalist()) {
if (param instanceof RecordPattern rp) {
res.append(FunNGenerator.encodeType(convert(param.getType())));
for (var pattern : rp.getSubPattern()) {
res.append(FunNGenerator.encodeType(convert(pattern.getType())));
}
}
}
return res.toString();
}
private List<TargetMethod> convert(ClassOrInterface clazz, List<Method> overloadedMethods) {
if (overloadedMethods.size() == 1) {
return convert(clazz, overloadedMethods.getFirst()).stream().map(m -> m.method()).toList();
}
var methods = new ArrayList<Method>();
for (var method : overloadedMethods) {
var newMethod = new Method(
method.modifier,
method.name,
//encodeName(method.name, method.getParameterList()),
method.getReturnType(),
method.getParameterList(),
method.block,
method.getGenerics(),
method.getOffset()
);
methods.add(newMethod);
}
// TODO Record overloading
/*var template = overloadedMethods.get(0);
var pParams = new ArrayList<Pattern>();
var i = 0;
for (var par : template.getParameterList()) {
pParams.add(switch (par) {
case RecordPattern rp -> new RecordPattern(rp.getSubPattern(), "par" + i, rp.getType(), new NullToken());
default -> par;
});
i++;
}
var params = new ParameterList(pParams, new NullToken());
var statements = new ArrayList<Statement>();
statements.add(new Return(makeRecordSwitch(template.getReturnType(), params, res), new NullToken()));
var block = new Block(statements, new NullToken());
var entryPoint = new Method(template.modifier, template.name, template.getReturnType(), params, block, template.getGenerics(), new NullToken());
res.add(entryPoint); // TODO*/
var res = new ArrayList<TargetMethod>();
for (var method : methods) {
var overloads = convert(clazz, method);
for (var m : overloads) {
var overload = m.method;
if (res.contains(overload)) throw new CodeGenException("Duplicate method found: " + overload.name() + " with signature " + overload.signature().getSignature());
res.add(overload);
}
}
return res;
}
private Expression makeRecordSwitch(RefTypeOrTPHOrWildcardOrGeneric returnType, ParameterList params, List<Method> overloadedMethods) {
var param = params.getFormalparalist().get(0);
assert param instanceof RecordPattern; // TODO
var cases = new ArrayList<SwitchBlock>();
for (var method : overloadedMethods) {
var statements = new ArrayList<Statement>();
/*statements.add(new MethodCall(
method.getReturnType(), new ExpressionReceiver(new This(new NullToken())), method.name,
params,
));*/
var block = new Block(statements, new NullToken());
var labels = new ArrayList<SwitchLabel>();
cases.add(new SwitchBlock(labels, block, true, new NullToken()));
}
var swtch = new Switch(new LocalVar("par0", param.getType(), new NullToken()), cases, returnType, false, new NullToken());
return swtch;
}
private Optional<Method> findSuperMethodToOverride(ClassOrInterface currentClass, String name, List<MethodParameter> params) {
var superClass = compiler.getClass(currentClass.getSuperClass().getName());
var methodStream = superClass.getMethods().stream();
for (var superInterface : currentClass.getSuperInterfaces()) {
methodStream = Stream.concat(methodStream, compiler.getClass(superInterface.getName()).getMethods().stream());
}
return methodStream.filter(m -> {
if (!m.name.equals(name)) return false;
var sParams = m.getParameterList();
if (sParams.getFormalparalist().size() != params.size()) return false;
for (var i = 0; i < params.size(); i++) {
var a = TargetType.toPrimitive(params.get(i).pattern().type());
var b = convert(sParams.getFormalparalist().get(i).getType());
if (!Objects.equals(a, b)) return false;
}
return true;
}).findFirst();
}
record MethodWithTphs(TargetMethod method, List<SignaturePairTarget> args) {}
private List<MethodWithTphs> convert(ClassOrInterface currentClass, Method method) {
generics = all.getFirst();
List<MethodWithTphs> result = new ArrayList<>();
this.currentMethod = method;
for (var s : all) {
generics = s;
var javaGenerics = this.generics.javaGenerics.generics(currentClass, method);
var txGenerics = this.generics.txGenerics.generics(currentClass, method);
List<MethodParameter> params = convert(method.getParameterList(), this.generics.javaGenerics);
var returnType = convert(method.getReturnType(), this.generics.javaGenerics);
var superMethod = findSuperMethodToOverride(currentClass, method.getName(), params);
if (superMethod.isPresent()) {
// If we find a super method to override, use its parameters and return types
var newReturnType = convert(superMethod.get().getReturnType(), this.generics.javaGenerics);
if (newReturnType instanceof TargetPrimitiveType && TargetType.toPrimitive(returnType).equals(newReturnType)) {
returnType = newReturnType;
params = convert(superMethod.get().getParameterList(), method.getParameterList(), this.generics.javaGenerics);
}
}
List<MethodParameter> txParams = convert(method.getParameterList(), this.generics.txGenerics);
var javaMethodGenerics = collectMethodGenerics(currentClass, generics.javaGenerics(), javaGenerics, method);
var txMethodGenerics = collectMethodGenerics(currentClass, generics.txGenerics(), txGenerics, method);
var javaSignature = new TargetMethod.Signature(javaMethodGenerics, params, returnType);
var txSignature = new TargetMethod.Signature(txMethodGenerics, txParams, convert(method.getReturnType(), this.generics.txGenerics));
var newMethod = new TargetMethod(method.modifier, method.name, convert(method.block), javaSignature, txSignature);
var concreteParams = tphsInMethods.getOrDefault(method, new HashSet<>()).stream().map(sig -> new SignaturePairTarget(convert(sig.signature), convert(sig.parameter))).toList();
result.add(new MethodWithTphs(newMethod, concreteParams));
}
return result;
}
private List<MethodParameter> convert(ParameterList superList, ParameterList paraList, JavaGenerics generics) {
var list = new ArrayList<MethodParameter>();
for (var i = 0; i < paraList.getFormalparalist().size(); i++) {
var param = paraList.getParameterAt(i);
list.add(new MethodParameter((TargetPattern) convert(param)).withType(convert(superList.getParameterAt(i).getType(), generics)));
}
return list;
}
protected TargetSwitch.Case convert(SwitchBlock block) {
return new TargetSwitch.Case(block.getLabels().stream().map(this::convert).toList(), convert((Block) block), block.isExpression);
}
protected TargetBlock convert(Block block) {
if (block == null) return null;
return new TargetBlock(block.statements.stream().map(this::convert).toList());
}
protected TargetBlock convertWrapInBlock(Expression expression) {
var res = convert(expression);
if (!(res instanceof TargetBlock))
return new TargetBlock(List.of(res));
return (TargetBlock) res;
}
protected TargetExpression convert(Expression expr) {
var converter = new StatementToTargetExpression(this);
expr.accept(converter);
return converter.result;
}
private TargetField convert(Field input) {
return new TargetField(input.modifier, convert(input.getType(), generics.javaGenerics), input.getName());
}
private final Map<String, FunNGenerator.GenericParameters> usedFunN = new HashMap<>();
private final Set<Integer> usedFunNSuperTypes = new HashSet<>();
public Map<String, byte[]> auxiliaries = new HashMap<>();
public TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input) {
return convert(input, generics.javaGenerics);
}
private static void collectArguments(TargetSpecializedType tspec, List<TargetType> newParams) {
for (var i = 0; i < tspec.params().size(); i++) {
var param = tspec.params().get(i);
if (param instanceof TargetSpecializedType fn) {
collectArguments(tspec, newParams);
} else {
newParams.add(param);
}
}
}
static TargetType flattenFunNType(List<TargetType> params, FunNGenerator.GenericParameters gep) {
var newParams = new ArrayList<TargetType>();
for (TargetType param : params) {
if (param instanceof TargetSpecializedType fn) {
collectArguments(fn, newParams);
} else {
newParams.add(param);
}
}
var filteredParams = new ArrayList<TargetType>();
for (var i = 0; i < newParams.size(); i++) {
if (i < gep.inParams.size() && gep.inParams.get(i) != null)
filteredParams.add(newParams.get(i));
}
return TargetFunNType.fromParams(params, filteredParams, gep.getReturnType() != null ? 1 : 0);
}
private boolean isSubtype(TargetType test, TargetType other) {
var testClass = compiler.getClass(new JavaClassName(test.name()));
var otherClass = compiler.getClass(new JavaClassName(other.name()));
if (testClass == null) return false;
while (testClass != null) {
if (testClass.equals(otherClass)) return true;
if (testClass.getClassName().equals(new JavaClassName("java.lang.Object"))) break;
testClass = compiler.getClass(testClass.getSuperClass().getName());
}
return false;
}
private boolean isSupertype(TargetType test, TargetType other) {
return isSubtype(other, test);
}
private boolean isSubtype(FunNGenerator.GenericParameters test, FunNGenerator.GenericParameters other) {
if (test.getArguments().size() != other.getArguments().size()) return false;
if (!isSubtype(test.getReturnType(), other.getReturnType())) return false;
for (int i = 0; i < test.getArguments().size(); i++) {
var arg1 = test.getArguments().get(i);
var arg2 = other.getArguments().get(i);
if (!isSupertype(arg1, arg2)) return false;
}
return true;
}
public void generateFunNTypes() {
for (var entry : usedFunN.entrySet()) {
var gep = entry.getValue();
var superInterfaces = usedFunN.values().stream()
.filter(g -> !g.equals(gep))
.filter(genericParameters -> isSubtype(gep, genericParameters))
.map(FunNGenerator::getSpecializedClassName)
.toList();
var code = FunNGenerator.generateSpecializedBytecode(gep, superInterfaces);
try {
classLoader.findClass(entry.getKey());
} catch (ClassNotFoundException e) {
try {
classLoader.loadClass(code);
} catch (LinkageError ignored) {}
}
auxiliaries.put(entry.getKey(), code);
}
}
protected TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input, GenerateGenerics generics) {
return input.acceptTV(new TypeVisitor<>() {
@Override
public TargetType visit(RefType refType) {
var name = refType.getName().toString();
if (name.equals("void"))
return null;
if (refType.isPrimitive()) {
return TargetType.toPrimitive(refType);
}
var params = refType.getParaList().stream().map(type -> {
return convert(type, generics);
}).toList();
if (name.matches("Fun\\d+\\$\\$")) { // TODO This seems like a bad idea
var returnType = FunNGenerator.getReturnType(params);
var className = FunNGenerator.getSpecializedClassName(FunNGenerator.getArguments(params), returnType);
if (!usedFunNSuperTypes.contains(params.size())) {
usedFunNSuperTypes.add(params.size());
var code = FunNGenerator.generateSuperBytecode(params.size() - 1, returnType != null ? 1 : 0);
var superClassName = FunNGenerator.getSuperClassName(params.size() - 1, returnType != null ? 1 : 0);
try {
classLoader.findClass(superClassName);
} catch (ClassNotFoundException e) {
try {
classLoader.loadClass(code);
} catch (LinkageError ignored) {}
}
auxiliaries.put(superClassName, code);
}
FunNGenerator.GenericParameters gep = null;
if (!usedFunN.containsKey(className)) {
gep = new FunNGenerator.GenericParameters(params, returnType != null ? 1 : 0);
usedFunN.put(className, gep);
} else {
gep = usedFunN.get(className);
}
return flattenFunNType(params, gep);
}
return new TargetRefType(name, params);
}
@Override
public TargetType visit(SuperWildcardType superWildcardType) {
return new TargetSuperWildcard(convert(superWildcardType.getInnerType(), generics));
}
@Override
public TargetType visit(TypePlaceholder typePlaceholder) {
return generics.getTargetType(typePlaceholder);
}
@Override
public TargetType visit(ExtendsWildcardType extendsWildcardType) {
return new TargetExtendsWildcard(convert(extendsWildcardType.getInnerType(), generics));
}
@Override
public TargetType visit(GenericRefType genericRefType) {
return new TargetGenericType(genericRefType.getParsedName());
}
});
}
}

View File

@ -1,24 +0,0 @@
package de.dhbwstuttgart.target.generate;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import java.util.List;
public record Bound(boolean isOnMethod, RefTypeOrTPHOrWildcardOrGeneric bound) {
public static Bound onMethod(String tph) {
return new Bound(true, TypePlaceholder.of(tph));
}
public static Bound onMethod(RefTypeOrTPHOrWildcardOrGeneric bound) {
return new Bound(true, bound);
}
public static Bound onClass(String tph) {
return new Bound(false, TypePlaceholder.of(tph));
}
public static Bound onClass(RefTypeOrTPHOrWildcardOrGeneric bound) {
return new Bound(false, bound);
}
}

View File

@ -1,52 +0,0 @@
package de.dhbwstuttgart.target.generate;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import java.util.AbstractList;
import java.util.List;
public class BoundsList extends AbstractList<Bound> {
private final List<Bound> bounds;
public final RefTypeOrTPHOrWildcardOrGeneric base;
public BoundsList(RefTypeOrTPHOrWildcardOrGeneric base, List<Bound> bounds) {
this.base = base;
this.bounds = bounds;
}
public BoundsList(List<Bound> bounds) {
this(null, bounds);
}
public BoundsList(Bound... bounds) {
this(null, List.of(bounds));
}
@Override
public Bound get(int index) {
return bounds.get(index);
}
@Override
public int size() {
return bounds.size();
}
@Override
public boolean equals(Object other) {
if (!(other instanceof BoundsList right)) return false;
if (size() != right.size()) return false;
for (var i = 0; i < size(); i++) {
var l = get(i);
var r = right.get(i);
if (l.isOnMethod() != r.isOnMethod()) return false;
if (i == size() - 1) {
if (!(l.bound() instanceof TypePlaceholder)) {
if (!(l.bound().equals(r.bound()))) return false;
}
}
}
return true;
}
}

View File

@ -1,104 +0,0 @@
package de.dhbwstuttgart.target.generate;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class CycleFinder {
private CycleFinder() {}
static Set<GenerateGenerics.TPH> allNodes(Set<? extends GenerateGenerics.Pair> input) {
return input.stream()
.filter(GenerateGenerics.PairLT.class::isInstance)
.map(GenerateGenerics.PairLT.class::cast)
.flatMap(pair -> Stream.of(pair.left, pair.right)).collect(Collectors.toSet());
}
static Set<GenerateGenerics.TPH> outgoingEdgesOf(GenerateGenerics.TPH tph, Set<? extends GenerateGenerics.Pair> input) {
return input.stream()
.filter(GenerateGenerics.PairLT.class::isInstance)
.map(GenerateGenerics.PairLT.class::cast)
.filter(pair -> pair.left.equals(tph))
.map(pair -> pair.right).collect(Collectors.toSet());
}
static boolean containsEdge(GenerateGenerics.TPH a, GenerateGenerics.TPH b, Set<? extends GenerateGenerics.Pair> input) {
return input.stream()
.filter(GenerateGenerics.PairLT.class::isInstance)
.map(GenerateGenerics.PairLT.class::cast)
.anyMatch(pair -> pair.left.equals(a) && pair.right.equals(b));
}
// Tiernan simple cycles algorithm
// Adapted from https://github.com/jgrapht/jgrapht/blob/master/jgrapht-core/src/main/java/org/jgrapht/alg/cycle/TiernanSimpleCycles.java
static Set<List<GenerateGenerics.TPH>> findCycles(Set<? extends GenerateGenerics.Pair> input) {
Map<GenerateGenerics.TPH, Integer> indices = new HashMap<>();
List<GenerateGenerics.TPH> path = new ArrayList<>();
Set<GenerateGenerics.TPH> pathSet = new HashSet<>();
Map<GenerateGenerics.TPH, Set<GenerateGenerics.TPH>> blocked = new HashMap<>();
Set<List<GenerateGenerics.TPH>> cycles = new HashSet<>();
int index = 0;
for (var tph : allNodes(input)) {
blocked.put(tph, new HashSet<>());
indices.put(tph, index++);
}
var vertexIterator = allNodes(input).iterator();
if (!vertexIterator.hasNext()) return cycles;
GenerateGenerics.TPH startOfPath = null;
GenerateGenerics.TPH endOfPath = vertexIterator.next();
GenerateGenerics.TPH temp = null;
int endIndex = 0;
boolean extensionFound = false;
path.add(endOfPath);
pathSet.add(endOfPath);
while (true) {
do {
extensionFound = false;
for (GenerateGenerics.TPH n : outgoingEdgesOf(endOfPath, input)) {
int cmp = indices.get(n).compareTo(indices.get(path.get(0)));
if ((cmp > 0) && !pathSet.contains(n) && !blocked.get(endOfPath).contains(n)) {
path.add(n);
pathSet.add(n);
endOfPath = n;
extensionFound = true;
break;
}
}
} while (extensionFound);
startOfPath = path.get(0);
if (containsEdge(endOfPath, startOfPath, input)) {
List<GenerateGenerics.TPH> cycle = new ArrayList<>(path);
cycles.add(cycle);
}
if (path.size() > 1) {
blocked.get(endOfPath).clear();
endIndex = path.size() - 1;
path.remove(endIndex);
pathSet.remove(endOfPath);
--endIndex;
temp = endOfPath;
endOfPath = path.get(endIndex);
blocked.get(endOfPath).add(temp);
continue;
}
if (vertexIterator.hasNext()) {
path.clear();
pathSet.clear();
endOfPath = vertexIterator.next();
path.add(endOfPath);
pathSet.add(endOfPath);
for (GenerateGenerics.TPH tph : blocked.keySet()) {
blocked.get(tph).clear();
}
continue;
}
break;
}
return cycles;
}
}

View File

@ -1,976 +0,0 @@
package de.dhbwstuttgart.target.generate;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.syntaxtree.Constructor;
import de.dhbwstuttgart.syntaxtree.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.statement.*;
import de.dhbwstuttgart.syntaxtree.type.*;
import de.dhbwstuttgart.syntaxtree.type.Void;
import de.dhbwstuttgart.target.tree.type.TargetGenericType;
import de.dhbwstuttgart.target.tree.type.TargetType;
import de.dhbwstuttgart.typeinference.result.PairTPHEqualTPH;
import de.dhbwstuttgart.typeinference.result.PairTPHequalRefTypeOrWildcardType;
import de.dhbwstuttgart.typeinference.result.PairTPHsmallerTPH;
import de.dhbwstuttgart.typeinference.result.ResultSet;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public abstract class GenerateGenerics {
private final ASTToTargetAST astToTargetAST;
public class TPH {
private final TypePlaceholder wrap;
TPH(TypePlaceholder wrap) {
this.wrap = wrap;
}
public TypePlaceholder resolve() {
return equality.getOrDefault(wrap, wrap);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TPH tph = (TPH) o;
return Objects.equals(resolve(), tph.resolve());
}
@Override
public int hashCode() {
return Objects.hash(resolve());
}
@Override
public String toString() {
return resolve().getName();
}
}
public abstract class Pair {
public final TPH left;
Pair(TPH left) {
this.left = left;
}
public abstract RefTypeOrTPHOrWildcardOrGeneric resolveRight();
}
public class PairLT extends Pair {
public final TPH right;
PairLT(TPH left, TPH right) {
super(left);
this.right = right;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PairLT pairLT = (PairLT) o;
return Objects.equals(right, pairLT.right) && Objects.equals(left, pairLT.left);
}
@Override
public int hashCode() {
return Objects.hash(right, left);
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric resolveRight() {
return right.resolve();
}
@Override
public String toString() {
return "(" + left + " < " + right + ")";
}
}
public class PairEQ extends Pair {
public final RefType right;
PairEQ(TPH left, RefType right) {
super(left);
this.right = right;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PairEQ pairLT = (PairEQ) o;
return Objects.equals(right, pairLT.right) && Objects.equals(left, pairLT.left);
}
@Override
public int hashCode() {
return Objects.hash(right, left);
}
@Override
public RefTypeOrTPHOrWildcardOrGeneric resolveRight() {
return right;
}
@Override
public String toString() {
return "(" + left + " = " + right + ")";
}
}
final Map<Method, Set<Pair>> computedGenericsOfMethods = new HashMap<>();
final Map<ClassOrInterface, Set<Pair>> computedGenericsOfClasses = new HashMap<>();
final Map<Method, Set<TPH>> usedTPHsOfMethods = new HashMap<>();
final Map<Method, Set<Pair>> familyOfMethods = new HashMap<>();
final Set<PairLT> simplifiedConstraints = new HashSet<>();
final Map<TPH, RefTypeOrTPHOrWildcardOrGeneric> concreteTypes = new HashMap<>();
final Map<TypePlaceholder, TypePlaceholder> equality = new HashMap<>();
GenerateGenerics(ASTToTargetAST astToTargetAST, ResultSet constraints) {
this.astToTargetAST = astToTargetAST;
for (var constraint : constraints.results) {
if (constraint instanceof PairTPHsmallerTPH p) {
System.out.println(p.left + " " + p.left.getVariance());
simplifiedConstraints.add(new PairLT(new TPH(p.left), new TPH(p.right)));
} else if (constraint instanceof PairTPHEqualTPH p) {
equality.put(p.getLeft(), p.getRight());
} else if (constraint instanceof PairTPHequalRefTypeOrWildcardType p) {
System.out.println(p.left + " = " + p.right);
concreteTypes.put(new TPH(p.left), p.right);
}
}
System.out.println("Simplified constraints: " + simplifiedConstraints);
}
Set<TPH> findTypeVariables(RefTypeOrTPHOrWildcardOrGeneric type) {
var result = new HashSet<TPH>();
if (type instanceof TypePlaceholder tph) {
var nTph = new TPH(tph);
if (concreteTypes.containsKey(nTph)) {
result.addAll(findTypeVariables(concreteTypes.get(nTph)));
return result;
}
result.add(nTph);
} else if (type instanceof RefType refType) {
for (var t : refType.getParaList())
result.addAll(findTypeVariables(t));
} else if (type instanceof ExtendsWildcardType wildcardType) {
result.addAll(findTypeVariables(wildcardType.getInnerType()));
} else if (type instanceof SuperWildcardType wildcardType) {
result.addAll(findTypeVariables(wildcardType.getInnerType()));
}
return result;
}
boolean containsRelation(Set<Pair> result, PairLT pair) {
// Check if both the right and the left are already part of a relation
var containsLeft = false;
for (var pair2 : result) {
if (pair2.left.equals(pair.left)) {
containsLeft = true;
break;
}
}
var containsRight = false;
for (var pair2 : result)
if (pair2 instanceof PairLT plt) {
if (plt.right.equals(pair.right)) {
containsRight = true;
break;
}
}
return containsLeft && containsRight;
}
void addToPairs(Set<Pair> input, Pair pair) {
if (pair instanceof PairLT plt) {
input.removeIf(pair2 -> {
if (pair2 instanceof PairEQ peq) {
return peq.left.equals(plt.left) && peq.right.equals(ASTToTargetAST.OBJECT);
}
return false;
});
} else if (input.stream().anyMatch(p -> p.left.equals(pair.left))) {
return;
}
input.add(pair);
}
void addToEquality(TypePlaceholder from, TypePlaceholder to, Set<TPH> referenced) {
for (var entry : new HashSet<>(equality.entrySet())) {
if (entry.getValue().equals(from)) {
equality.remove(entry.getKey());
equality.put(entry.getKey(), to);
}
}
System.out.println(from + " -> " + to + " " + from.getVariance());
//from.setVariance(to.getVariance());
equality.put(from, to);
referenced.remove(new TPH(from));
referenced.add(new TPH(to));
}
Set<Pair> transitiveClosure(Set<? extends Pair> generics) {
Set<Pair> all = new HashSet<>(generics);
Set<Pair> toAdd = new HashSet<>();
int sizeBefore;
do {
sizeBefore = all.size();
toAdd.clear();
for (var g1 : all) {
for (var g2 : all) {
if (g1 instanceof PairLT pair && g2 instanceof PairLT pair2) {
if (pair2.left.equals(pair.right))
toAdd.add(new PairLT(pair.left, pair2.right));
}
}
}
all.addAll(toAdd);
} while (sizeBefore < all.size());
return all;
}
private void methodFindConstraints(
ClassOrInterface owner, Method method,
Set<TPH> typeVariables,
Set<TPH> typeVariablesOfClass,
Set<Pair> result
) {
var userDefinedGenericsOfClass = astToTargetAST.userDefinedGenerics.get(owner);
// Type variables with bounds that are also type variables of the method
for (var typeVariable : new HashSet<>(typeVariables)) {
if (classHasGeneric(userDefinedGenericsOfClass, typeVariablesOfClass, typeVariable))
continue;
for (var pair : simplifiedConstraints) {
if (pair.left.equals(typeVariable) && typeVariables.contains(pair.right)) {
addToPairs(result, new PairLT(pair.left, pair.right));
}
}
}
if (method.block != null)
method.block.accept(new TracingStatementVisitor() {
private RefTypeOrTPHOrWildcardOrGeneric superType = new de.dhbwstuttgart.syntaxtree.type.Void(new NullToken());
@Override
public void visit(MethodCall methodCall) {
//Anfang es werden Paare von TPHs gespeichert, die bei den Generated Generics ueber die Methodengrenzen hinweg
//betrachtet werden muessen
//Definition 7.2 (Family of generated generics). T1 <. R1 <.^ R2 <. T2
Set<TPH> T1s =
methodCall.getArgumentList()
.getArguments()
.stream()
.map(TypableStatement::getType)
.collect(Collectors.toCollection(HashSet::new))
.stream().filter(TypePlaceholder.class::isInstance)
.map(TypePlaceholder.class::cast)
.map(TPH::new)
.collect(Collectors.toCollection(HashSet::new));
Set<TPH> T2s = new HashSet<>();
findTphs(superType, T2s);
System.out.println("T1s: " + T1s + " T2s: " + T2s);
//Ende
superType = methodCall.receiverType;
methodCall.receiver.accept(this);
for (int i = 0; i < methodCall.arglist.getArguments().size(); i++) {
superType = methodCall.arglist.getArguments().get(i).getType();
methodCall.arglist.getArguments().get(i).accept(this);
}
if (methodCall.receiver instanceof ExpressionReceiver expressionReceiver) {
if (expressionReceiver.expr instanceof This) {
var optMethod = astToTargetAST.findMethod(owner, methodCall.name, methodCall.signatureArguments().stream().map(astToTargetAST::convert).toList());
if (optMethod.isEmpty()) return;
var method2 = optMethod.get();
System.out.println("In: " + method.getName() + " Method: " + method2.getName());
var generics = family(owner, method2);
// transitive and
var all = transitiveClosure(generics);
// reflexive
var toAdd = new HashSet<Pair>();
for (var generic : all) {
toAdd.add(new PairLT(generic.left, generic.left));
}
all.addAll(toAdd);
HashSet<PairLT> newPairs = new HashSet<>();
// Loop from hell
outer:
for (var R1 : typeVariables) {
if (typeVariablesOfClass.contains(R1)) continue;
for (var generic : all)
if (generic instanceof PairLT ptph) {
for (var pair : simplifiedConstraints) {
if (!(pair.left.equals(R1) && pair.right.equals(ptph.left)))
continue;
for (var R2 : typeVariables) {
for (var pair2 : simplifiedConstraints) {
if (!(pair2.right.equals(R2) && pair2.left.equals(ptph.right)))
continue;
if (R1.equals(R2)) continue;
if (!T1s.contains(R1) || !T2s.contains(R2)) continue;
var newPair = new PairLT(R1, R2);
System.out.println("New pair: " + newPair);
newPairs.add(newPair);
if (!containsRelation(result, newPair))
addToPairs(result, newPair);
continue outer;
}
}
}
}
}
simplifiedConstraints.addAll(newPairs);
}
}
}
@Override
public void visit(LambdaExpression lambdaExpression) {
superType = new Void(new NullToken());
lambdaExpression.methodBody.accept(this);
}
@Override
public void visit(Assign assign) {
superType = assign.rightSide.getType();
assign.rightSide.accept(this);
}
@Override
public void visit(BinaryExpr binary) {
superType = new Void(new NullToken());
binary.lexpr.accept(this);
superType = new Void(new NullToken());
binary.rexpr.accept(this);
}
@Override
public void visit(Block block) {
for (var expr : block.statements) {
superType = new de.dhbwstuttgart.syntaxtree.type.Void(new NullToken());
expr.accept(this);
}
}
@Override
public void visit(IfStmt ifStmt) {
superType = new Void(new NullToken());
ifStmt.expr.accept(this);
superType = new Void(new NullToken());
ifStmt.then_block.accept(this);
superType = new Void(new NullToken());
if (ifStmt.else_block != null)
ifStmt.else_block.accept(this);
}
@Override
public void visit(Return aReturn) {
superType = aReturn.getType();
aReturn.retexpr.accept(this);
}
@Override
public void visit(WhileStmt whileStmt) {
superType = new Void(new NullToken());
whileStmt.expr.accept(this);
superType = new Void(new NullToken());
whileStmt.loopBlock.accept(this);
}
@Override
public void visit(ArgumentList arglist) {
for (int i = 0; i < arglist.getArguments().size(); i++) {
superType = arglist.getArguments().get(i).getType();
arglist.getArguments().get(i).accept(this);
}
}
});
var closure = transitiveClosure(simplifiedConstraints);
// Type variables with bounds that are also type variables of the class
for (var typeVariable : new HashSet<>(typeVariables)) {
if (typeVariablesOfClass.contains(typeVariable)) continue;
var pairs = new HashSet<PairLT>();
for (var pair : closure) {
if (!(pair instanceof PairLT ptph)) continue;
if (ptph.left.equals(typeVariable) && typeVariablesOfClass.contains(ptph.right)) {
pairs.add(new PairLT(ptph.left, ptph.right));
}
}
// Find the closest pair with the minimum amount of steps
PairLT minimalPair = null;
var minSteps = Integer.MAX_VALUE;
for (var pair : pairs) {
var left = pair.left;
var visited = new HashSet<TPH>();
var steps = 0;
while (!left.equals(pair.right)) {
visited.add(left);
var found = false;
for (var pair2 : simplifiedConstraints) {
if (left.equals(pair2.left) && !visited.contains(pair2.right)) {
left = pair2.right;
steps += 1;
found = true;
break;
}
}
if (!found) break;
}
if (steps < minSteps) {
minSteps = steps;
minimalPair = pair;
}
}
if (minimalPair != null)
addToPairs(result, minimalPair);
}
// All unbounded type variables (bounds not in method)
outer:
for (var typeVariable : typeVariables) {
if (classHasGeneric(userDefinedGenericsOfClass, typeVariablesOfClass, typeVariable))
continue;
for (var pair : result) {
if (pair.left.equals(typeVariable))
continue outer;
}
addToPairs(result, new PairEQ(typeVariable, ASTToTargetAST.OBJECT));
}
// All unbounded bounds
outer:
for (var pair : simplifiedConstraints) {
for (var pair2 : simplifiedConstraints) {
if (pair.right.equals(pair2.left))
continue outer;
}
if (!classHasGeneric(userDefinedGenericsOfClass, typeVariablesOfClass, pair.right) && typeVariables.contains(pair.right)) {
addToPairs(result, new PairEQ(pair.right, ASTToTargetAST.OBJECT));
}
}
}
private boolean classHasGeneric(Set<GenericTypeVar> userDefinedGenericsOfClass, Set<TPH> typeVariablesOfClass, TPH typeVariable) {
return typeVariablesOfClass.contains(typeVariable) || userDefinedGenericsOfClass.stream().anyMatch(g -> g.getName().equals(typeVariable.resolve().getName()));
}
private void methodFindTypeVariables(
Method method,
Set<TPH> typeVariables
) {
if (!(method instanceof Constructor))
typeVariables.addAll(findTypeVariables(method.getReturnType()));
for (var arg : method.getParameterList().getFormalparalist()) {
typeVariables.addAll(findTypeVariables(arg.getType()));
}
if (method.block != null)
method.block.accept(new TracingStatementVisitor() {
@Override
public void visit(LocalVarDecl localVarDecl) {
typeVariables.addAll(findTypeVariables(localVarDecl.getType()));
}
@Override
public void visit(MethodCall methodCall) {
super.visit(methodCall);
typeVariables.addAll(findTypeVariables(methodCall.getType()));
}
});
}
abstract void generics(ClassOrInterface owner, Method method, Set<Pair> result, Set<TPH> javaTypeVariablesOfClass);
Set<Pair> family(ClassOrInterface owner, Method method) {
Set<Pair> result = new HashSet<>();
if (familyOfMethods.containsKey(method))
return familyOfMethods.get(method);
familyOfMethods.put(method, result);
var classGenerics = generics(owner);
HashSet<TPH> typeVariablesOfClass = new HashSet<>();
for (var pair : classGenerics) {
typeVariablesOfClass.add(pair.left);
}
HashSet<TPH> javaTypeVariables = new HashSet<>();
methodFindTypeVariables(method, javaTypeVariables);
methodFindConstraints(owner, method, javaTypeVariables, typeVariablesOfClass, result);
eliminateTransitives(result);
return result;
}
Set<Pair> generics(ClassOrInterface owner, Method method) {
if (computedGenericsOfMethods.containsKey(method)) {
var cached = computedGenericsOfMethods.get(method);
System.out.println("Cached " + method.getName() + ": " + cached);
return cached;
}
var result = new HashSet<Pair>();
computedGenericsOfMethods.put(method, result);
var classGenerics = generics(owner);
HashSet<TPH> typeVariablesOfClass = new HashSet<>();
for (var pair : classGenerics) {
typeVariablesOfClass.add(pair.left);
}
result.addAll(family(owner, method));
var referenced = new HashSet<TPH>();
var usedTphs = new HashSet<TPH>();
// For eliminating inner type variables we need to figure out which ones are actually used
for (var param : method.getParameterList().getFormalparalist()) {
usedTphs.addAll(findTypeVariables(param.getType()));
}
usedTphs.addAll(findTypeVariables(method.getReturnType()));
referenced.addAll(usedTphs);
referenced.addAll(typeVariablesOfClass);
generics(owner, method, result, referenced);
usedTPHsOfMethods.put(method, usedTphs);
normalize(result, classGenerics, usedTphs);
System.out.println(this.getClass().getSimpleName() + " " + method.name + ": " + result);
return result;
}
private void eliminateChain(Set<Pair> result, List<TPH> chain) {
for (var pair : new HashSet<>(result)) {
if (pair instanceof PairLT 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 PairLT(chain.get(0), ptph.right));
eliminateChain(result, copy);
}
}
}
void eliminateTransitives(Set<Pair> result) {
for (var pair : new HashSet<>(result))
if (pair instanceof PairLT ptph) {
var first = ptph.left;
var chain = new ArrayList<TPH>();
chain.add(ptph.left);
chain.add(ptph.right);
eliminateChain(result, chain);
}
}
void findAllBounds(RefTypeOrTPHOrWildcardOrGeneric type, Set<Pair> generics) {
if (type instanceof TypePlaceholder tph) {
var nTph = new TPH(tph);
var concreteType = concreteTypes.get(nTph);
if (concreteType != null) {
findAllBounds(concreteType, generics);
return;
}
var found = false;
for (var rsp : simplifiedConstraints) {
if (rsp.left.equals(nTph)) {
var pair = new PairLT(new TPH(tph), rsp.right);
if (!generics.contains(pair)) {
addToPairs(generics, pair);
findAllBounds(rsp.right.resolve(), generics);
found = true;
}
}
}
if (!found)
addToPairs(generics, new PairEQ(nTph, ASTToTargetAST.OBJECT));
} else if (type instanceof RefType refType) {
refType.getParaList().forEach(t -> findAllBounds(t, generics));
}
}
abstract void generics(ClassOrInterface classOrInterface, Set<Pair> result, Set<TPH> referenced);
Set<Pair> generics(ClassOrInterface classOrInterface) {
if (computedGenericsOfClasses.containsKey(classOrInterface))
return computedGenericsOfClasses.get(classOrInterface);
Set<Pair> javaResult = new HashSet<>();
computedGenericsOfClasses.put(classOrInterface, javaResult);
for (var field : classOrInterface.getFieldDecl()) {
findAllBounds(field.getType(), javaResult);
}
var referenced = new HashSet<TPH>();
eliminateTransitives(javaResult);
generics(classOrInterface, javaResult, referenced);
var referencedByClass = new HashSet<TPH>();
for (var field : classOrInterface.getFieldDecl()) {
findTphs(field.getType(), referencedByClass);
}
normalize(javaResult, null, referencedByClass);
System.out.println(this.getClass().getSimpleName() + " Class " + classOrInterface.getClassName().getClassName() + ": " + javaResult);
return javaResult;
}
void normalize(Set<Pair> result, Set<Pair> classGenerics, Set<TPH> usedTphs) {
outer:
for (var tph : usedTphs) {
for (var p1 : new HashSet<>(result)) {
if (p1 instanceof PairLT ptph && ptph.left.equals(ptph.right))
result.remove(p1); // TODO This is a bit strange
if (p1.left.equals(tph)) continue outer;
}
if (classGenerics == null || classGenerics.stream().noneMatch((pair) -> pair.left.equals(tph)))
addToPairs(result, new PairEQ(tph, ASTToTargetAST.OBJECT));
}
}
private record ToAdd(TypePlaceholder left, TypePlaceholder right) {}
void equalizeTypeVariables(Set<Pair> input, Set<TPH> referenced) {
var elementsToAddToEquality = new ArrayList<ToAdd>();
for (var pair : new HashSet<>(input)) {
if (pair instanceof PairLT ptph && referenced.contains(ptph.left)) {
var chain = new ArrayList<TPH>();
chain.add(ptph.left);
chain.add(ptph.right);
outer:
while (true) {
var added = false;
for (var pair2 : input) {
if (pair2 instanceof PairLT ptph2 && ptph2.left.equals(chain.get(chain.size() - 1))) {
if (chain.contains(ptph2.right)) break outer;
chain.add(ptph2.right);
added = true;
}
}
if (!added) break;
}
System.out.println(chain + " " + chain.stream().map(e -> e.resolve().getVariance()).toList());
var variance = chain.get(0).resolve().getVariance();
if (variance != 1) continue;
var index = 0;
for (var tph : chain) {
if (variance == 1 && tph.resolve().getVariance() == -1) {
variance = -1;
}
if (variance == -1 && tph.resolve().getVariance() == 1 && referenced.contains(tph)) {
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);
if (!referenced.contains(cur)) continue;
elementsToAddToEquality.add(new ToAdd(cur.resolve(), start.resolve()));
//addToEquality(cur.resolve(), start.resolve(), referenced);
TPH finalPrev = prev;
input.removeIf(p -> p.equals(new PairLT(finalPrev, cur)));
for (var pair2 : new HashSet<>(input)) {
// TODO Maybe this would be unnecessary if we were to add the = constraints later on
if (pair2 instanceof PairEQ peq && pair.left.equals(cur)) {
input.remove(pair2);
input.add(new PairEQ(start, peq.right));
}
}
prev = chain.get(i);
}
}
}
for (var pair : elementsToAddToEquality) {
System.out.println(pair);
addToEquality(pair.left, pair.right, referenced);
}
}
void findTphs(RefTypeOrTPHOrWildcardOrGeneric type, Set<TPH> tphs) {
if (type instanceof RefType refType) {
refType.getParaList().forEach(t -> findTphs(t, tphs));
} else if (type instanceof TypePlaceholder tph) {
tph = equality.getOrDefault(tph, tph);
var concreteType = concreteTypes.get(new TPH(tph));
if (concreteType != null) {
findTphs(concreteType, tphs);
return;
}
tphs.add(new TPH(tph));
}
}
void eliminateInnerTypeVariablesOfClass(ClassOrInterface classOrInterface, Set<Pair> input, Set<TPH> referenced) {
for (var field : classOrInterface.getFieldDecl()) {
findTphs(field.getType(), referenced);
}
doIterationForMethods(classOrInterface);
for (var method : classOrInterface.getMethods()) {
var usedTPHs = usedTPHsOfMethods.get(method);
if (usedTPHs != null)
referenced.addAll(usedTPHs);
}
eliminateInnerTypeVariables(referenced, input);
}
void doIterationForMethods(ClassOrInterface classOrInterface) {
familyOfMethods.clear();
var oldFamily = new HashMap<Method, Set<Pair>>();
do {
oldFamily.clear();
oldFamily.putAll(familyOfMethods);
familyOfMethods.clear();
Stream.concat(classOrInterface.getMethods().stream(), classOrInterface.getConstructors().stream()).forEach(method -> {
family(classOrInterface, method);
});
} while(!oldFamily.equals(familyOfMethods));
Stream.concat(classOrInterface.getMethods().stream(), classOrInterface.getConstructors().stream()).forEach(method -> {
generics(classOrInterface, method);
});
}
private void findChain(Set<TPH> referenced, Set<Pair> input, Set<Pair> output, TPH start, TPH end, Set<TPH> chain) {
if (referenced.contains(end)) {
var pair = new PairLT(start, end);
output.add(pair);
return;
}
var foundNext = false;
for (var pair : input) {
if (pair instanceof PairLT ptph && ptph.left.equals(end)) {
if (chain.contains(ptph.right)) return;
chain = new HashSet<>(chain);
chain.add(ptph.right);
findChain(referenced, input, output, start, ptph.right, chain);
foundNext = true;
}
}
if (!foundNext) {
output.add(new PairEQ(start, ASTToTargetAST.OBJECT));
}
}
void eliminateInnerTypeVariables(Set<TPH> referenced, Set<Pair> input) {
var output = new HashSet<Pair>();
for (var tph : referenced) {
for (var pair : input) {
if (pair instanceof PairLT pthp && pthp.left.equals(tph)) {
var chain = new HashSet<TPH>();
chain.add(tph);
findChain(referenced, input, output, tph, pthp.right, chain);
}
}
}
for (var pair : input) {
if (pair instanceof PairEQ rtph) {
if (referenced.contains(rtph.left))
output.add(rtph);
}
}
input.clear();
input.addAll(output);
}
void eliminateCycles(Set<Pair> input, Set<TPH> referenced) {
var cycles = CycleFinder.findCycles(input);
for (var cycle : cycles) {
var newTph = TypePlaceholder.fresh(new NullToken());
var variance = cycle.get(0).resolve().getVariance();
for (var tph : cycle) {
if (tph.resolve().getVariance() != variance) {
variance = 0;
break;
}
}
newTph.setVariance(variance);
referenced.add(new TPH(newTph));
addToPairs(input, new PairEQ(new TPH(newTph), ASTToTargetAST.OBJECT));
cycle.add(cycle.get(0)); // Make it a complete cycle
for (var i = 0; i < cycle.size() - 1; i++) {
var left = cycle.get(i);
var right = cycle.get(i + 1);
var pair = new PairLT(left, right);
input.remove(pair);
addToEquality(left.resolve(), newTph, referenced);
}
}
}
Set<TPH> findConnectionToReturnType(Set<TPH> returnTypes, Set<Pair> input, Set<TPH> visited, TPH tph) {
if (returnTypes.contains(tph)) {
var res = new HashSet<TPH>();
res.add(tph);
return res;
} else {
for (var pair : input) if (pair instanceof PairLT ptph) {
if (ptph.left.equals(tph) && !visited.contains(ptph.right)) {
visited.add(ptph.right);
var result = findConnectionToReturnType(returnTypes, input, visited, ptph.right);
if (result.size() > 0) {
result.add(ptph.right);
return result;
};
}
}
}
return new HashSet<>();
}
void eliminateInfimaConnectedToReturnType(Method method, Set<Pair> input, Set<TPH> referenced) {
var foundInfima = false;
do {
foundInfima = false;
for (var constraint : new HashSet<>(input)) {
var left = constraint.left;
Set<PairLT> infima = new HashSet<>();
for (var pair : input) {
if (pair instanceof PairLT stph) {
if (pair.left.equals(constraint.left))
infima.add(stph);
}
}
if (infima.size() > 1) {
System.out.println(infima);
for (var pair : infima) {
var returnTypes = findTypeVariables(method.getReturnType());
var chain = findConnectionToReturnType(returnTypes, input, new HashSet<>(), pair.left);
System.out.println("Find: " + pair.left + " " + chain);
chain.remove(pair.left);
if (chain.size() > 0) {
for (var tph : chain)
addToEquality(pair.left.resolve(), tph.resolve(), referenced);
foundInfima = true;
}
}
}
}
} while (foundInfima);
input.removeIf((i) -> (i instanceof PairLT lt) && lt.left.equals(lt.right));
}
void eliminateInfima(Set<Pair> input, Set<TPH> referenced) {
var foundInfima = false;
do {
foundInfima = false;
for (var constraint : new HashSet<>(input)) {
var left = constraint.left;
Set<PairLT> infima = new HashSet<>();
for (var pair : input) {
if (pair instanceof PairLT stph) {
if (pair.left.equals(constraint.left))
infima.add(stph);
}
}
if (infima.size() > 1) {
foundInfima = true;
var newTph = TypePlaceholder.fresh(new NullToken());
var variance = infima.stream().findFirst().get().right.resolve().getVariance();
for (var pair : infima) {
if (pair.right.resolve().getVariance() != variance) {
variance = 0;
break;
}
}
newTph.setVariance(variance);
System.out.println(infima + " " + infima.stream().map(i -> i.right.resolve().getVariance()).toList());
System.out.println("Infima new TPH " + newTph + " variance " + variance);
//referenced.add(newTph);
addToPairs(input, new PairLT(left, new TPH(newTph)));
input.removeAll(infima);
for (var infimum : infima) {
addToEquality(infimum.right.resolve(), newTph, referenced);
new HashSet<>(input).forEach(pair -> {
if (pair.left.equals(infimum.right)) {
input.remove(pair);
if (pair instanceof PairLT stph) {
if (!newTph.equals(stph.right.resolve()))
addToPairs(input, new PairLT(new TPH(newTph), stph.right));
} else if (pair instanceof PairEQ rtph) {
addToPairs(input, new PairEQ(new TPH(newTph), rtph.right));
}
} else if (pair instanceof PairLT stph && stph.right.equals(infimum.right)) {
input.remove(pair);
if (!newTph.equals(stph.left.resolve()))
addToPairs(input, new PairLT(stph.left, new TPH(newTph)));
}
});
}
}
}
} while (foundInfima);
}
RefTypeOrTPHOrWildcardOrGeneric getType(RefTypeOrTPHOrWildcardOrGeneric type) {
if (type instanceof TypePlaceholder tph) {
if (equality.containsKey(tph)) {
return getType(equality.get(tph));
}
return concreteTypes.getOrDefault(new TPH(tph), tph);
}
return type;
}
TargetType getTargetType(RefTypeOrTPHOrWildcardOrGeneric in) {
if (in instanceof TypePlaceholder tph) {
if (equality.containsKey(tph)) {
return getTargetType(equality.get(tph));
}
var type = concreteTypes.get(new TPH(tph));
if (type == null) return new TargetGenericType(tph.getName());
return astToTargetAST.convert(type, this);
}
return astToTargetAST.convert(in, this);
}
}

View File

@ -1,76 +0,0 @@
package de.dhbwstuttgart.target.generate;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.target.tree.type.TargetType;
import java.util.*;
public class GenericsResult {
private final GenerateGenerics generics;
GenericsResult(GenerateGenerics generics) {
this.generics = generics;
}
public GenericsResultSet get(ClassOrInterface clazz) {
var generics = this.generics.computedGenericsOfClasses.get(clazz);
return new GenericsResultSet(generics, this.generics.equality);
}
// TODO Compute generics if not present?
public GenericsResultSet get(Method method) {
var generics = this.generics.computedGenericsOfMethods.get(method);
return new GenericsResultSet(generics, this.generics.equality);
}
public BoundsList getBounds(RefTypeOrTPHOrWildcardOrGeneric type, ClassOrInterface clazz) {
return getBounds(type, clazz, null);
}
public BoundsList getBounds(RefTypeOrTPHOrWildcardOrGeneric type, ClassOrInterface clazz, Method method) {
var resolvedType = resolve(type);
type = resolvedType;
if (type instanceof TypePlaceholder) {
var methodGenerics = get(method);
var classGenerics = get(clazz);
List<Bound> result = new ArrayList<>();
Optional<Bound> bound = Optional.empty();
do {
bound = Optional.empty();
for (var pair : methodGenerics) {
if (pair.left.resolve().equals(type)) {
type = pair.resolveRight();
bound = Optional.of(new Bound(true, type));
break;
}
}
if (bound.isEmpty()) {
for (var pair : classGenerics) {
if (pair.left.resolve().equals(type)) {
type = pair.resolveRight();
bound = Optional.of(new Bound(false, type));
break;
}
}
}
bound.ifPresent(result::add);
} while (bound.isPresent());
return new BoundsList(resolvedType, result);
}
return new BoundsList(resolvedType, List.of());
}
public RefTypeOrTPHOrWildcardOrGeneric resolve(RefTypeOrTPHOrWildcardOrGeneric type) {
if (type instanceof TypePlaceholder tph)
return this.generics.getType(tph);
return type;
}
public TargetType resolveTarget(RefTypeOrTPHOrWildcardOrGeneric type) {
return this.generics.getTargetType(type);
}
}

View File

@ -1,43 +0,0 @@
package de.dhbwstuttgart.target.generate;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.result.PairTPHequalRefTypeOrWildcardType;
import de.dhbwstuttgart.typeinference.result.PairTPHsmallerTPH;
import de.dhbwstuttgart.typeinference.result.ResultPair;
import java.util.*;
public class GenericsResultSet extends AbstractSet<GenerateGenerics.Pair> {
final Set<GenerateGenerics.Pair> backing;
final Map<TypePlaceholder, TypePlaceholder> equality;
public GenericsResultSet(Set<GenerateGenerics.Pair> backing, Map<TypePlaceholder, TypePlaceholder> equality) {
this.backing = backing == null ? new HashSet<>() : new HashSet<>(backing);
this.equality = equality;
}
@Override
public Iterator<GenerateGenerics.Pair> iterator() {
return backing.iterator();
}
@Override
public int size() {
return backing.size();
}
public Optional<ResultPair<?, ?>> getResultPairFor(TypePlaceholder tph) {
var tph2 = equality.getOrDefault(tph, tph);
return this.stream().filter(pair -> {
return pair.left.resolve().equals(tph2);
}).findFirst().map(pair -> {
ResultPair<?, ?> res = null;
if (pair instanceof GenerateGenerics.PairLT lt)
res = new PairTPHsmallerTPH(lt.left.resolve(), lt.right.resolve());
else if (pair instanceof GenerateGenerics.PairEQ eq)
res = new PairTPHequalRefTypeOrWildcardType(eq.left.resolve(), eq.right);
return res;
});
}
}

View File

@ -1,30 +0,0 @@
package de.dhbwstuttgart.target.generate;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.typeinference.result.ResultSet;
import java.util.Set;
final class JavaGenerics extends GenerateGenerics {
JavaGenerics(ASTToTargetAST astToTargetAST, ResultSet constraints) {
super(astToTargetAST, constraints);
}
@Override
void generics(ClassOrInterface owner, Method method, Set<Pair> result, Set<TPH> referenced) {
eliminateCycles(result, referenced);
eliminateInfimaConnectedToReturnType(method, result, referenced);
eliminateInfima(result, referenced);
equalizeTypeVariables(result, referenced);
eliminateInnerTypeVariables(referenced, result);
}
@Override
void generics(ClassOrInterface classOrInterface, Set<Pair> result, Set<TPH> referenced) {
eliminateCycles(result, referenced);
eliminateInfima(result, referenced);
eliminateInnerTypeVariablesOfClass(classOrInterface, result, referenced);
equalizeTypeVariables(result, referenced);
}
}

View File

@ -1,503 +0,0 @@
package de.dhbwstuttgart.target.generate;
import de.dhbwstuttgart.exceptions.DebugException;
import de.dhbwstuttgart.exceptions.NotImplementedException;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal;
import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.syntaxtree.*;
import de.dhbwstuttgart.syntaxtree.factory.PrimitiveMethodsGenerator;
import de.dhbwstuttgart.syntaxtree.statement.*;
import de.dhbwstuttgart.syntaxtree.type.*;
import de.dhbwstuttgart.target.tree.MethodParameter;
import de.dhbwstuttgart.target.tree.TargetGeneric;
import de.dhbwstuttgart.target.tree.TargetMethod;
import de.dhbwstuttgart.target.tree.expression.*;
import de.dhbwstuttgart.target.tree.type.*;
import javax.swing.text.html.Option;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
public class StatementToTargetExpression implements ASTVisitor {
public StatementToTargetExpression(ASTToTargetAST converter) {
this.converter = converter;
}
public TargetExpression result;
private final ASTToTargetAST converter;
@Override
public void visit(ArgumentList argumentList) {
throw new NotImplementedException();
}
@Override
public void visit(LambdaExpression lambdaExpression) {
var parameters = StreamSupport.stream(lambdaExpression.params.spliterator(), false)
.map(p -> (FormalParameter) p)
.map(p -> new MethodParameter(new TargetTypePattern(converter.convert(p.getType()), p.getName())))
.toList();
List<MethodParameter> captures = new ArrayList<>();
lambdaExpression.methodBody.accept(new TracingStatementVisitor() {
// TODO The same mechanism is implemented in Codegen, maybe use it from there?
final Stack<Set<String>> localVariables = new Stack<>();
{
localVariables.push(new HashSet<>());
}
boolean hasLocalVar(String name) {
for (var localVariables : this.localVariables) {
if (localVariables.contains(name))
return true;
}
return false;
}
@Override
public void visit(Block block) {
localVariables.push(new HashSet<>());
super.visit(block);
localVariables.pop();
}
@Override
public void visit(LocalVar localVar) {
super.visit(localVar);
var capture = new MethodParameter(new TargetTypePattern(converter.convert(localVar.getType()), localVar.name));
if (!hasLocalVar(localVar.name) && !parameters.contains(capture) && !captures.contains(capture))
captures.add(capture);
}
@Override
public void visit(LocalVarDecl varDecl) {
var localVariables = this.localVariables.peek();
localVariables.add(varDecl.getName());
}
@Override
public void visit(LambdaExpression lambda) {
} // Don't look at lambda expressions
});
TargetMethod.Signature signature = new TargetMethod.Signature(Set.of(), parameters, converter.convert(lambdaExpression.getReturnType()));;
var tpe = converter.convert(lambdaExpression.getType());
result = new TargetLambdaExpression(tpe, captures, signature, converter.convert(lambdaExpression.methodBody));
}
@Override
public void visit(Assign assign) {
TargetExpression left;
if (assign.lefSide instanceof AssignToLocal) {
left = converter.convert(((AssignToLocal) assign.lefSide).localVar);
} else {
left = converter.convert(((AssignToField) assign.lefSide).field);
}
result = new TargetAssign(converter.convert(assign.getType()), left, converter.convert(assign.rightSide));
}
@Override
public void visit(BinaryExpr binary) {
result = switch (binary.operation) {
case ADD -> new TargetBinaryOp.Add(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
case SUB -> new TargetBinaryOp.Sub(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
case MUL -> new TargetBinaryOp.Mul(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
case MOD -> new TargetBinaryOp.Rem(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
case AND -> new TargetBinaryOp.BAnd(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
case OR -> new TargetBinaryOp.BOr(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
case XOR -> new TargetBinaryOp.XOr(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
case DIV -> new TargetBinaryOp.Div(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
case LESSTHAN -> new TargetBinaryOp.Less(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
case BIGGERTHAN -> new TargetBinaryOp.Greater(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
case LESSEQUAL -> new TargetBinaryOp.LessOrEqual(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
case BIGGEREQUAL -> new TargetBinaryOp.GreaterOrEqual(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
case EQUAL -> new TargetBinaryOp.Equal(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
case NOTEQUAL -> new TargetBinaryOp.NotEqual(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr));
};
}
@Override
public void visit(BoolExpression bool) {
System.out.println("BoolExpression");
}
@Override
public void visit(Block block) {
result = converter.convert(block);
}
@Override
public void visit(CastExpr castExpr) {
result = new TargetCast(converter.convert(castExpr.getType()), converter.convert(castExpr.expr));
}
@Override
public void visit(EmptyStmt emptyStmt) {
result = null;
}
@Override
public void visit(FieldVar fieldVar) {
result = new TargetFieldVar(converter.convert(fieldVar.getType()), converter.convert(fieldVar.receiver.getType()), fieldVar.isStatic, converter.convert(fieldVar.receiver), fieldVar.fieldVarName);
}
@Override
public void visit(ForStmt forStmt) {
result = new TargetFor(
forStmt.initializer.stream().map(converter::convert).toList(),
forStmt.condition != null ? converter.convert(forStmt.condition) : null,
forStmt.loopExpr.stream().map(converter::convert).toList(),
converter.convertWrapInBlock(forStmt.block)
);
}
@Override
public void visit(ForEachStmt forEachStmt) {
result = new TargetForEach(converter.convert(forEachStmt.statement), converter.convert(forEachStmt.expression), converter.convertWrapInBlock(forEachStmt.block));
}
@Override
public void visit(IfStmt ifStmt) {
result = new TargetIf(converter.convert(ifStmt.expr), converter.convertWrapInBlock(ifStmt.then_block), ifStmt.else_block != null ? converter.convertWrapInBlock(ifStmt.else_block) : null);
}
@Override
public void visit(InstanceOf instanceOf) {
result = new TargetInstanceOf(converter.convert(instanceOf.getExpression()), converter.convert(instanceOf.getPattern()));
}
@Override
public void visit(LocalVar localVar) {
result = new TargetLocalVar(converter.convert(localVar.getType()), localVar.name);
}
@Override
public void visit(LocalVarDecl localVarDecl) {
// TODO No value, is this correct?
result = new TargetVarDecl(converter.convert(localVarDecl.getType()), localVarDecl.getName(), null);
}
static boolean convertsTo(TargetType from, TargetType to) {
if (to.equals(TargetType.Object))
return true; // TODO Consider type coercion and subtyping
return to.equals(from);
}
Optional<Method> findMethod(JavaClassName className, String name, List<TargetType> args) {
return converter.findMethod(converter.compiler.getClass(className), name, args);
}
@Override
public void visit(MethodCall methodCall) {
var receiverType = converter.convert(methodCall.receiver.getType());
var isFunNType = receiverType instanceof TargetFunNType;
var returnType = isFunNType ? TargetType.Object : converter.convert(methodCall.signature.get(methodCall.signature.size() - 1));
var receiverName = new JavaClassName(converter.convert(methodCall.receiver.getType()).name());
var argList = methodCall.signature.stream().map(converter::convert).toList();
argList = argList.subList(0, argList.size() - 1);
Method foundMethod = null;
var isStatic = false;
var isInterface = true;
var isPrivate = false;
var signature = methodCall.signatureArguments().stream().map(converter::convert).toList();
// Add used TPHs to containing method
for (var i = 0; i < methodCall.signatureArguments().size(); i++) {
converter.addSignaturePair(methodCall.signatureArguments().get(i), methodCall.arglist.getArguments().get(i).getType());
}
var receiverClass = converter.compiler.getClass(receiverName);
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);
ClassOrInterface finalReceiverClass = receiverClass;
foundMethod = thisMethod.orElseGet(() -> findMethod(finalReceiverClass.getSuperClass().getName(), methodCall.name, signature).orElseThrow());
} else if (!isFunNType) {
receiverClass = converter.compiler.getClass(receiverName);
if (receiverClass == null) throw new DebugException("Class " + receiverName + " does not exist!");
foundMethod = findMethod(receiverName, methodCall.name, signature).orElseThrow();
}
if (!isFunNType) {
returnType = converter.convert(foundMethod.getReturnType());
argList = foundMethod.getParameterList().getFormalparalist().stream().map(e -> converter.convert(e.getType())).toList();
isStatic = Modifier.isStatic(foundMethod.modifier);
isPrivate = Modifier.isPrivate(foundMethod.modifier);
isInterface = receiverClass.isInterface();
}
System.out.println(argList);
result = new TargetMethodCall(converter.convert(methodCall.getType()), returnType, argList, converter.convert(methodCall.receiver), methodCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), receiverType, methodCall.name, isStatic, isInterface, isPrivate);
}
@Override
public void visit(NewClass newClass) {
var receiverName = new JavaClassName(newClass.name);
var ctor = converter.findConstructor(converter.compiler.getClass(receiverName), newClass.signatureArguments().stream().map(converter::convert).toList());
var signature = ctor.orElseThrow().getParameterList().getFormalparalist().stream().map(e -> converter.convert(e.getType())).toList();
result = new TargetNew(new TargetRefType(newClass.name), signature, newClass.getArgumentList().getArguments().stream().map(converter::convert).toList());
}
@Override
public void visit(NewArray newArray) {
// TODO
throw new NotImplementedException();
}
@Override
public void visit(Return aReturn) {
result = new TargetReturn(converter.convert(aReturn.retexpr));
}
@Override
public void visit(ReturnVoid aReturn) {
result = new TargetReturn(null);
}
@Override
public void visit(Break aBreak) {
result = new TargetBreak();
}
@Override
public void visit(Continue aContinue) {
result = new TargetContinue();
}
@Override
public void visit(StaticClassName staticClassName) {
result = new TargetClassName(converter.convert(staticClassName.getType()));
}
@Override
public void visit(Super aSuper) {
result = new TargetSuper(converter.convert(aSuper.getType()));
}
@Override
public void visit(This aThis) {
result = new TargetThis(converter.convert(aThis.getType()));
}
@Override
public void visit(WhileStmt whileStmt) {
result = new TargetWhile(converter.convert(whileStmt.expr), converter.convert(whileStmt.loopBlock));
}
@Override
public void visit(DoStmt whileStmt) {
result = new TargetDo(converter.convert(whileStmt.expr), converter.convert(whileStmt.loopBlock));
}
// TODO These two might not be necessary
@Override
public void visit(AssignToField assignLeftSide) {
result = converter.convert(assignLeftSide.field);
}
@Override
public void visit(AssignToLocal assignLeftSide) {
result = converter.convert(assignLeftSide.localVar);
}
@Override
public void visit(SuperCall superCall) {
var aSuper = converter.convert(superCall.receiver.getType());
var type = converter.convert(superCall.getType());
var receiverName = new JavaClassName(converter.convert(superCall.receiver.getType()).name());
var clazz = converter.compiler.getClass(receiverName);
var signature = superCall.signatureArguments().stream().map(converter::convert).toList();
var method = converter.findConstructor(clazz, signature);
var params = superCall.getArgumentList().getArguments().stream().map(converter::convert).toList();
List<TargetType> argList;
if (method.isPresent()) {
argList = method.get().getParameterList().getFormalparalist().stream().map(e -> converter.convert(e.getType())).toList();
} else {
argList = params.stream().map(TargetExpression::type).toList();
}
result = new TargetMethodCall(type, null, argList, new TargetSuper(aSuper), params, aSuper, superCall.name, false, false, false);
}
@Override
public void visit(ThisCall thisCall) {
var aThis = converter.convert(thisCall.receiver.getType());
var type = converter.convert(thisCall.getType());
var parameters = thisCall.arglist.getArguments().stream().map(par -> converter.convert(par.getType())).toList();
result = new TargetMethodCall(type, type, parameters, new TargetThis(aThis), thisCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), aThis, thisCall.name, false, false, false);
}
@Override
public void visit(ExpressionReceiver expressionReceiver) {
result = converter.convert(expressionReceiver.expr);
}
@Override
public void visit(UnaryExpr unaryExpr) {
result = switch (unaryExpr.operation) {
case NOT -> new TargetUnaryOp.Not(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr));
case MINUS -> new TargetUnaryOp.Negate(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr));
case PREINCREMENT -> new TargetUnaryOp.PreIncrement(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr));
case PREDECREMENT -> new TargetUnaryOp.PreDecrement(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr));
case POSTINCREMENT -> new TargetUnaryOp.PostIncrement(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr));
case PLUS -> new TargetUnaryOp.Add(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr));
case POSTDECREMENT -> new TargetUnaryOp.PostDecrement(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr));
};
}
@Override
public void visit(Literal literal) {
if (literal.value instanceof Integer || literal.value instanceof Short || literal.value instanceof Byte) {
result = new TargetLiteral.IntLiteral((int) literal.value);
} else if (literal.value instanceof Float) {
result = new TargetLiteral.FloatLiteral((float) literal.value);
} else if (literal.value instanceof Double) {
result = new TargetLiteral.DoubleLiteral((double) literal.value);
} else if (literal.value instanceof Long) {
result = new TargetLiteral.LongLiteral((long) literal.value);
} else if (literal.value instanceof Character) {
result = new TargetLiteral.CharLiteral((char) literal.value);
} else if (literal.value instanceof String) {
result = new TargetLiteral.StringLiteral((String) literal.value);
} else if (literal.value instanceof Boolean) {
result = new TargetLiteral.BooleanLiteral((boolean) literal.value);
} else if (literal.value == null) {
result = new TargetLiteral.Null();
}
}
@Override
public void visit(Throw aThrow) {
result = new TargetThrow(converter.convert(aThrow.expr));
}
@Override
public void visit(Ternary ternary) {
result = new TargetTernary(converter.convert(ternary.getType()), converter.convert(ternary.cond), converter.convert(ternary.iftrue), converter.convert(ternary.iffalse));
}
@Override
public void visit(Switch switchStmt) {
var cases = switchStmt.getBlocks().stream().filter(s -> !s.isDefault()).map(converter::convert).toList();
TargetSwitch.Case default_ = null;
for (var block : switchStmt.getBlocks()) {
if (block.isDefault()) {
default_ = new TargetSwitch.Case(converter.convert((Block) block), block.isExpression);
}
}
result = new TargetSwitch(converter.convert(switchStmt.getSwitch()), cases, default_ , converter.convert(switchStmt.getType()), !switchStmt.getStatement());
}
@Override
public void visit(SwitchBlock switchBlock) {}
@Override
public void visit(SwitchLabel switchLabel) {
result = converter.convert(switchLabel.getPattern());
}
@Override
public void visit(Yield aYield) {
result = new TargetYield(converter.convert(aYield.retexpr));
}
@Override
public void visit(SourceFile sourceFile) {
}
@Override
public void visit(GenericTypeVar genericTypeVar) {
}
@Override
public void visit(GenericDeclarationList genericTypeVars) {
}
@Override
public void visit(Field field) {
}
@Override
public void visit(de.dhbwstuttgart.syntaxtree.Method field) {
}
@Override
public void visit(Constructor field) {
}
@Override
public void visit(ParameterList formalParameters) {
}
@Override
public void visit(ClassOrInterface classOrInterface) {
}
@Override
public void visit(RefType refType) {
}
@Override
public void visit(SuperWildcardType superWildcardType) {
}
@Override
public void visit(TypePlaceholder typePlaceholder) {
}
@Override
public void visit(ExtendsWildcardType extendsWildcardType) {
}
@Override
public void visit(GenericRefType genericRefType) {
}
@Override
public void visit(FormalParameter aPattern) {
result = new TargetTypePattern(converter.convert(aPattern.getType()), aPattern.getName());
}
@Override
public void visit(ExpressionPattern aPattern) {
result = converter.convert(aPattern.getExpression());
}
@Override
public void visit(RecordPattern aRecordPattern) {
result = new TargetComplexPattern(
converter.convert(aRecordPattern.getType()),
aRecordPattern.getName(),
aRecordPattern.getSubPattern().stream().map(x -> (TargetPattern) converter.convert(x)).toList()
);
}
@Override
public void visit(GuardedPattern aGuardedPattern) {
result = new TargetGuard((TargetPattern) converter.convert(aGuardedPattern.getNestedPattern()), converter.convert(aGuardedPattern.getCondition()));
}
}

View File

@ -1,218 +0,0 @@
package de.dhbwstuttgart.target.generate;
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
import de.dhbwstuttgart.syntaxtree.statement.*;
// This visitor walks the entire tree, individual methods may be overridden
public abstract class TracingStatementVisitor implements StatementVisitor {
@Override
public void visit(ThisCall thisCall) {
visit((MethodCall) thisCall);
}
@Override
public void visit(MethodCall methodCall) {
methodCall.receiver.accept(this);
methodCall.getArgumentList().accept(this);
}
@Override
public void visit(ArgumentList argumentList) {
argumentList.getArguments().forEach(expr -> expr.accept(this));
}
@Override
public void visit(LambdaExpression lambdaExpression) {
lambdaExpression.methodBody.accept(this);
}
@Override
public void visit(Assign assign) {
assign.rightSide.accept(this);
}
@Override
public void visit(BinaryExpr binary) {
binary.lexpr.accept(this);
binary.rexpr.accept(this);
}
@Override
public void visit(BoolExpression bool) {
bool.lexpr.accept(this);
bool.rexpr.accept(this);
}
@Override
public void visit(Block block) {
for (var expr : block.statements)
expr.accept(this);
}
@Override
public void visit(CastExpr castExpr) {
}
@Override
public void visit(EmptyStmt emptyStmt) {
}
@Override
public void visit(FieldVar fieldVar) {
}
@Override
public void visit(ForStmt forStmt) {
forStmt.block.accept(this);
}
@Override
public void visit(ForEachStmt forEachStmt) {
forEachStmt.block.accept(this);
}
@Override
public void visit(IfStmt ifStmt) {
ifStmt.then_block.accept(this);
if (ifStmt.else_block != null)
ifStmt.else_block.accept(this);
}
@Override
public void visit(InstanceOf instanceOf) {
}
@Override
public void visit(LocalVar localVar) {
}
@Override
public void visit(LocalVarDecl localVarDecl) {
}
@Override
public void visit(NewClass newClass) {
this.visit((MethodCall) newClass);
}
@Override
public void visit(NewArray newArray) {
newArray.expr.forEach(expr -> expr.accept(this));
}
@Override
public void visit(Return aReturn) {
aReturn.retexpr.accept(this);
}
@Override
public void visit(ReturnVoid aReturn) {
}
@Override
public void visit(Break aBreak) {
}
@Override
public void visit(Continue aContinue) {
}
@Override
public void visit(StaticClassName staticClassName) {
}
@Override
public void visit(Super aSuper) {
}
@Override
public void visit(This aThis) {
}
@Override
public void visit(WhileStmt whileStmt) {
whileStmt.loopBlock.accept(this);
}
@Override
public void visit(DoStmt whileStmt) {
whileStmt.loopBlock.accept(this);
}
@Override
public void visit(AssignToField assignLeftSide) {
}
@Override
public void visit(AssignToLocal assignLeftSide) {
}
@Override
public void visit(SuperCall superCall) {
visit((MethodCall) superCall);
}
@Override
public void visit(ExpressionReceiver expressionReceiver) {
expressionReceiver.expr.accept(this);
}
@Override
public void visit(UnaryExpr unaryExpr) {
unaryExpr.expr.accept(this);
}
@Override
public void visit(Literal literal) {
}
@Override
public void visit(Throw aThrow) {
}
@Override
public void visit(Switch switchStmt) {
}
@Override
public void visit(SwitchBlock switchBlock) {
}
@Override
public void visit(SwitchLabel switchLabel) {
}
@Override
public void visit(Yield aYield) {
}
@Override
public void visit(Ternary ternary) {
ternary.cond.accept(this);
ternary.iftrue.accept(this);
ternary.iffalse.accept(this);
}
}

View File

@ -1,25 +0,0 @@
package de.dhbwstuttgart.target.generate;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.typeinference.result.ResultSet;
import java.util.Set;
final class TxGenerics extends GenerateGenerics {
TxGenerics(ASTToTargetAST astToTargetAST, ResultSet constraints) {
super(astToTargetAST, constraints);
}
@Override
void generics(ClassOrInterface owner, Method method, Set<Pair> result, Set<TPH> referenced) {
eliminateInfima(result, referenced);
eliminateInnerTypeVariables(referenced, result);
}
@Override
void generics(ClassOrInterface classOrInterface, Set<Pair> result, Set<TPH> referenced) {
eliminateInfima(result, referenced);
eliminateInnerTypeVariablesOfClass(classOrInterface, result, referenced);
}
}

View File

@ -1,14 +0,0 @@
package de.dhbwstuttgart.target.tree;
import de.dhbwstuttgart.target.tree.expression.TargetPattern;
import de.dhbwstuttgart.target.tree.expression.TargetTypePattern;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record MethodParameter(TargetPattern pattern) {
public MethodParameter(TargetType type, String name) {
this(new TargetTypePattern(type, name));
}
public MethodParameter withType(TargetType type) {
return new MethodParameter(pattern.withType(type));
}
}

View File

@ -1,27 +0,0 @@
package de.dhbwstuttgart.target.tree;
import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.target.tree.expression.TargetBlock;
import de.dhbwstuttgart.target.tree.type.TargetRefType;
import de.dhbwstuttgart.target.tree.type.TargetType;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public record TargetClass(int modifiers, JavaClassName qualifiedName, TargetType superType, Set<TargetGeneric> generics, Set<TargetGeneric> txGenerics, List<TargetType> implementingInterfaces,
List<TargetConstructor> constructors, TargetMethod staticConstructor, List<TargetField> fields, List<TargetMethod> methods) implements TargetStructure {
public TargetClass(int modifiers, JavaClassName qualifiedName) {
this(modifiers, qualifiedName, TargetType.Object, new HashSet<>(), new HashSet<>(), new ArrayList<>(), new ArrayList<>(), null, new ArrayList<>(), new ArrayList<>());
}
public TargetClass(int modifiers, JavaClassName qualifiedName, List<TargetType> implementingInterfaces) {
this(modifiers, qualifiedName, TargetType.Object, new HashSet<>(), new HashSet<>(), implementingInterfaces, new ArrayList<>(), null, new ArrayList<>(), new ArrayList<>());
}
public void addField(int access, TargetRefType type, String name) {
this.fields.add(new TargetField(access, type, name));
}
}

View File

@ -1,24 +0,0 @@
package de.dhbwstuttgart.target.tree;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.target.tree.expression.TargetBlock;
import de.dhbwstuttgart.target.tree.type.TargetType;
import java.util.List;
import java.util.Set;
public record TargetConstructor(int access, Set<TargetGeneric> generics, Set<TargetGeneric> txGenerics, List<MethodParameter> parameters, List<MethodParameter> txParameters, TargetBlock block, TargetBlock fieldInitializer) {
public String getDescriptor() {
return TargetMethod.getDescriptor(null, parameters.stream().map(mp -> mp.pattern().type()).toArray(TargetType[]::new));
}
public String getSignature() {
return TargetMethod.getSignature(generics, parameters, null);
}
public String getTXSignature() {
return TargetMethod.getSignature(txGenerics, txParameters, null);
}
}

View File

@ -1,11 +0,0 @@
package de.dhbwstuttgart.target.tree;
import de.dhbwstuttgart.target.tree.type.TargetType;
import org.objectweb.asm.Opcodes;
public record TargetField(int access, TargetType type, String name) {
public boolean isStatic() {
return (access & Opcodes.ACC_STATIC) != 0;
}
}

View File

@ -1,6 +0,0 @@
package de.dhbwstuttgart.target.tree;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetGeneric(String name, TargetType bound) {
}

View File

@ -1,24 +0,0 @@
package de.dhbwstuttgart.target.tree;
import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.target.tree.type.TargetType;
import java.util.List;
import java.util.Set;
public record TargetInterface(int modifiers, JavaClassName qualifiedName, Set<TargetGeneric> generics, Set<TargetGeneric> txGenerics, List<TargetMethod> methods, List<TargetType> implementingInterfaces, TargetMethod staticConstructor) implements TargetStructure {
@Override
public TargetType superType() {
return null;
}
@Override
public List<TargetConstructor> constructors() {
return List.of();
}
@Override
public List<TargetField> fields() {
return List.of();
}
}

View File

@ -1,80 +0,0 @@
package de.dhbwstuttgart.target.tree;
import de.dhbwstuttgart.target.tree.expression.TargetBlock;
import de.dhbwstuttgart.target.tree.expression.TargetPattern;
import de.dhbwstuttgart.target.tree.type.TargetType;
import org.objectweb.asm.Opcodes;
import java.util.List;
import java.util.Objects;
import java.util.Set;
public record TargetMethod(int access, String name, TargetBlock block, Signature signature, Signature txSignature) {
public record Signature(Set<TargetGeneric> generics, List<MethodParameter> parameters, TargetType returnType) {
public String getSignature() {
return TargetMethod.getSignature(generics, parameters, returnType);
}
public String getDescriptor() {
return TargetMethod.getDescriptor(returnType, parameters.stream().map(MethodParameter::pattern).map(TargetPattern::type).toArray(TargetType[]::new));
}
}
public static String getDescriptor(TargetType returnType, TargetType... parameters) {
String ret = "(";
for (var parameterType : parameters) {
ret += parameterType.toSignature();
}
ret += ")";
if (returnType == null) ret += "V";
else ret += returnType.toSignature();
return ret;
}
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 += ">";
}
ret += "(";
for (var param : parameters) {
ret += param.pattern().type().toDescriptor();
}
ret += ")";
if (returnType == null) ret += "V";
else ret += returnType.toDescriptor();
return ret;
}
public String getDescriptor() {
return getDescriptor(signature.returnType, signature.parameters.stream().map(mp -> mp.pattern().type()).toArray(TargetType[]::new));
}
public String getSignature() {
return getSignature(signature.generics, signature.parameters, signature.returnType);
}
public String getTXSignature() {
return getSignature(txSignature.generics, txSignature.parameters, txSignature.returnType);
}
public boolean isStatic() {
return (access & Opcodes.ACC_STATIC) != 0;
}
@Override
public boolean equals(Object other) {
if (!(other instanceof TargetMethod otherMethod)) return false;
return otherMethod.signature.equals(this.signature) && otherMethod.name.equals(this.name);
}
@Override
public int hashCode() {
return Objects.hash(name, signature);
}
}

View File

@ -1,16 +0,0 @@
package de.dhbwstuttgart.target.tree;
import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.target.tree.type.TargetRefType;
import de.dhbwstuttgart.target.tree.type.TargetType;
import java.util.List;
import java.util.Set;
public record TargetRecord(int modifiers, JavaClassName qualifiedName, Set<TargetGeneric> generics, Set<TargetGeneric> txGenerics, List<TargetType> implementingInterfaces, List<TargetConstructor> constructors, TargetMethod staticConstructor, List<TargetField> fields, List<TargetMethod> methods) implements TargetStructure {
public static final TargetType RECORD = new TargetRefType("java.lang.Record");
public TargetType superType() {
return RECORD;
}
}

View File

@ -1,44 +0,0 @@
package de.dhbwstuttgart.target.tree;
import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.target.tree.expression.TargetBlock;
import de.dhbwstuttgart.target.tree.type.TargetType;
import java.util.List;
import java.util.Set;
public interface TargetStructure {
int modifiers();
JavaClassName qualifiedName();
TargetType superType();
Set<TargetGeneric> generics();
Set<TargetGeneric> txGenerics();
List<TargetType> implementingInterfaces();
List<TargetConstructor> constructors();
TargetMethod staticConstructor();
List<TargetField> fields();
List<TargetMethod> methods();
default String getName() {
return qualifiedName().toString().replaceAll("\\.", "/");
}
// These methods are only meant to be used for test cases, a Class record should be immutable!
default void addMethod(int access, String name, Set<TargetGeneric> generics, List<MethodParameter> parameterTypes, TargetType returnType, TargetBlock block) {
this.methods().add(new TargetMethod(access, name, block, new TargetMethod.Signature(generics, parameterTypes, returnType), null));
}
default void addMethod(int access, String name, List<MethodParameter> parameterTypes, TargetType returnType, TargetBlock block) {
addMethod(access, name, Set.of(), parameterTypes, returnType, block);
}
default void addConstructor(int access, Set<TargetGeneric> generics, List<MethodParameter> paramterTypes, TargetBlock block) {
this.constructors().add(new TargetConstructor(access, generics, Set.of(), paramterTypes, List.of(), block, null));
}
default void addConstructor(int access, List<MethodParameter> paramterTypes, TargetBlock block) {
addConstructor(access, Set.of(), paramterTypes, block);
}
}

View File

@ -1,6 +0,0 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetAssign(TargetType type, TargetExpression left, TargetExpression right) implements TargetStatementExpression {
}

View File

@ -1,85 +0,0 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.expression.TargetExpression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public sealed interface TargetBinaryOp extends TargetExpression {
TargetExpression left();
TargetExpression right();
// Arithmetic
record Add(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {
}
record Sub(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {
}
record Div(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {
}
record Mul(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {
}
record Rem(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {
}
// Bitwise
record BAnd(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {
}
record BOr(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {
}
record XOr(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {
}
record Shl(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {
}
record Shr(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {
}
record UShr(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {
}
// Conditional
record And(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {
}
record Or(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {
}
record Instof(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {
}
sealed interface TargetRelationalOp extends TargetBinaryOp {
@Override
default TargetType type() {
return TargetType.Boolean;
}
TargetType exprType();
}
// Comparison
// exprType is the type that both arguments get converted to before comparison
record Equal(TargetType exprType, TargetExpression left, TargetExpression right) implements TargetRelationalOp {
}
record Greater(TargetType exprType, TargetExpression left, TargetExpression right) implements TargetRelationalOp {
}
record GreaterOrEqual(TargetType exprType, TargetExpression left, TargetExpression right) implements TargetRelationalOp {
}
record Less(TargetType exprType, TargetExpression left, TargetExpression right) implements TargetRelationalOp {
}
record LessOrEqual(TargetType exprType, TargetExpression left, TargetExpression right) implements TargetRelationalOp {
}
record NotEqual(TargetType exprType, TargetExpression left, TargetExpression right) implements TargetRelationalOp {
}
}

View File

@ -1,8 +0,0 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
import java.util.List;
public record TargetBlock(List<TargetExpression> statements) implements TargetExpression {
}

View File

@ -1,7 +0,0 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
// TODO This needs a label
public record TargetBreak() implements TargetExpression {
}

View File

@ -1,6 +0,0 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetCast(TargetType type, TargetExpression expr) implements TargetExpression {
}

View File

@ -1,6 +0,0 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetClassName(TargetType type) implements TargetExpression {
}

View File

@ -1,12 +0,0 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
import java.util.List;
public record TargetComplexPattern(TargetType type, String name, List<TargetPattern> subPatterns) implements TargetPattern {
@Override
public TargetComplexPattern withType(TargetType type) {
return new TargetComplexPattern(type, name, subPatterns);
}
}

View File

@ -1,6 +0,0 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetContinue() implements TargetExpression {
}

View File

@ -1,4 +0,0 @@
package de.dhbwstuttgart.target.tree.expression;
public record TargetDo(TargetExpression cond, TargetExpression body) implements TargetExpression {
}

View File

@ -1,11 +0,0 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.*;
public sealed interface TargetExpression
permits TargetBinaryOp, TargetBlock, TargetBreak, TargetCast, TargetClassName, TargetContinue, TargetDo, TargetFieldVar, TargetFor, TargetForEach, TargetIf, TargetInstanceOf, TargetLambdaExpression, TargetLiteral, TargetLocalVar, TargetPattern, TargetReturn, TargetStatementExpression, TargetSuper, TargetSwitch, TargetTernary, TargetThis, TargetThrow, TargetUnaryOp, TargetVarDecl, TargetWhile, TargetYield {
default TargetType type() {
return null;
};
}

View File

@ -1,7 +0,0 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetRefType;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetFieldVar(TargetType type, TargetType owner, boolean isStatic, TargetExpression left, String right) implements TargetExpression {
}

View File

@ -1,6 +0,0 @@
package de.dhbwstuttgart.target.tree.expression;
import java.util.List;
public record TargetFor(List<TargetExpression> init, TargetExpression termination, List<TargetExpression> increment, TargetExpression body) implements TargetExpression {
}

View File

@ -1,4 +0,0 @@
package de.dhbwstuttgart.target.tree.expression;
public record TargetForEach(TargetExpression vardecl, TargetExpression expression, TargetExpression body) implements TargetExpression {
}

View File

@ -1,15 +0,0 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetGuard(TargetPattern inner, TargetExpression expression) implements TargetPattern {
@Override
public TargetGuard withType(TargetType type) {
return new TargetGuard(inner.withType(type), expression);
}
@Override
public TargetType type() {
return inner.type();
}
}

View File

@ -1,6 +0,0 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetIf(TargetExpression cond, TargetExpression if_body, TargetExpression else_body) implements TargetExpression {
}

View File

@ -1,12 +0,0 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.syntaxtree.statement.Expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetInstanceOf(TargetExpression left, TargetExpression right) implements TargetExpression {
@Override
public TargetType type() {
return TargetType.Boolean;
}
}

View File

@ -1,11 +0,0 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.MethodParameter;
import de.dhbwstuttgart.target.tree.TargetField;
import de.dhbwstuttgart.target.tree.TargetMethod;
import de.dhbwstuttgart.target.tree.type.TargetType;
import java.util.List;
public record TargetLambdaExpression(TargetType type, List<MethodParameter> captures, TargetMethod.Signature signature, TargetBlock block) implements TargetExpression {
}

View File

@ -1,68 +0,0 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public sealed interface TargetLiteral extends TargetExpression {
Object value();
record BooleanLiteral(Boolean value) implements TargetLiteral {
@Override
public TargetType type() {
return TargetType.Boolean;
}
}
record CharLiteral(Character value) implements TargetLiteral {
@Override
public TargetType type() {
return TargetType.Char;
}
}
record IntLiteral(Integer value) implements TargetLiteral {
@Override
public TargetType type() {
return TargetType.Integer;
}
}
record LongLiteral(Long value) implements TargetLiteral {
@Override
public TargetType type() {
return TargetType.Long;
}
}
record FloatLiteral(Float value) implements TargetLiteral {
@Override
public TargetType type() {
return TargetType.Float;
}
}
record DoubleLiteral(Double value) implements TargetLiteral {
@Override
public TargetType type() {
return TargetType.Double;
}
}
record StringLiteral(String value) implements TargetLiteral {
@Override
public TargetType type() {
return TargetType.String;
}
}
record Null() implements TargetLiteral {
@Override
public TargetType type() {
return TargetType.Object;
}
@Override
public Object value() {
return null;
}
}
}

View File

@ -1,6 +0,0 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetLocalVar(TargetType type, String name) implements TargetExpression {
}

View File

@ -1,17 +0,0 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.TargetMethod;
import de.dhbwstuttgart.target.tree.type.TargetType;
import java.util.List;
public record TargetMethodCall(TargetType type, TargetType returnType, List<TargetType> parameterTypes, TargetExpression expr, List<TargetExpression> args, TargetType owner, String name, boolean isStatic, boolean isInterface, boolean isPrivate) implements TargetStatementExpression {
public TargetMethodCall(TargetType type, TargetExpression expr, List<TargetExpression> args, TargetType owner, String name, boolean isStatic, boolean isInterface, boolean isPrivate) {
this(type, type, args.stream().map(TargetExpression::type).toList(), expr, args, owner, name, isStatic, isInterface, isPrivate);
}
public String getDescriptor() {
return TargetMethod.getDescriptor(returnType, parameterTypes.toArray(TargetType[]::new));
}
}

View File

@ -1,12 +0,0 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.TargetMethod;
import de.dhbwstuttgart.target.tree.type.TargetType;
import java.util.List;
public record TargetNew(TargetType type, List<TargetType> signature, List<TargetExpression> params) implements TargetStatementExpression {
public String getDescriptor() {
return TargetMethod.getDescriptor(null, signature.toArray(TargetType[]::new));
}
}

View File

@ -1,13 +0,0 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public sealed interface TargetPattern extends TargetExpression permits TargetComplexPattern, TargetGuard, TargetTypePattern {
default String name() {
return null;
}
TargetPattern withType(TargetType type);
TargetType type();
}

View File

@ -1,6 +0,0 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetReturn(TargetExpression expression) implements TargetExpression {
}

View File

@ -1,4 +0,0 @@
package de.dhbwstuttgart.target.tree.expression;
public sealed interface TargetStatementExpression extends TargetExpression permits TargetAssign, TargetMethodCall, TargetNew, TargetUnaryOp.PostDecrement, TargetUnaryOp.PostIncrement, TargetUnaryOp.PreDecrement, TargetUnaryOp.PreIncrement {
}

View File

@ -1,6 +0,0 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetSuper(TargetType type) implements TargetExpression {
}

View File

@ -1,30 +0,0 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
import java.util.List;
public record TargetSwitch(TargetExpression expr, List<Case> cases, Case default_, TargetType type, boolean isExpression) implements TargetExpression {
public TargetSwitch(TargetExpression expr, List<Case> cases, Case default_) {
this(expr, cases, default_, null, false);
}
public TargetSwitch(TargetExpression expr, List<Case> cases, Case default_, TargetType type) {
this(expr, cases, default_, type, true);
}
public TargetSwitch(TargetExpression expr, List<Case> cases, Case default_, boolean isExpression) {
this(expr, cases, default_, null, isExpression);
}
public record Case(List<TargetExpression> labels, TargetBlock body, boolean isSingleExpression) {
public Case(List<TargetExpression> labels, TargetBlock body) {
this(labels, body, false);
}
public Case(TargetBlock body, boolean isSingleExpression) {
this(List.of(), body, isSingleExpression);
}
}
}

View File

@ -1,6 +0,0 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetTernary(TargetType type, TargetExpression cond, TargetExpression iftrue, TargetExpression iffalse) implements TargetExpression {
}

View File

@ -1,6 +0,0 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetThis(TargetType type) implements TargetExpression {
}

View File

@ -1,4 +0,0 @@
package de.dhbwstuttgart.target.tree.expression;
public record TargetThrow(TargetExpression expr) implements TargetExpression {
}

View File

@ -1,10 +0,0 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetTypePattern(TargetType type, String name) implements TargetPattern {
@Override
public TargetTypePattern withType(TargetType type) {
return new TargetTypePattern(type, name);
}
}

View File

@ -1,16 +0,0 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public sealed interface TargetUnaryOp extends TargetExpression {
TargetExpression expr();
record Negate(TargetType type, TargetExpression expr) implements TargetUnaryOp {}
record Add(TargetType type, TargetExpression expr) implements TargetUnaryOp {}
record Not(TargetType type, TargetExpression expr) implements TargetUnaryOp {}
record PreIncrement(TargetType type, TargetExpression expr) implements TargetStatementExpression, TargetUnaryOp {}
record PostIncrement(TargetType type, TargetExpression expr) implements TargetStatementExpression, TargetUnaryOp {}
record PreDecrement(TargetType type, TargetExpression expr) implements TargetStatementExpression, TargetUnaryOp {}
record PostDecrement(TargetType type, TargetExpression expr) implements TargetStatementExpression, TargetUnaryOp {}
}

View File

@ -1,11 +0,0 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetVarDecl(TargetType varType, String name, TargetExpression value) implements TargetExpression {
@Override
public TargetType type() {
return null;
}
}

View File

@ -1,4 +0,0 @@
package de.dhbwstuttgart.target.tree.expression;
public record TargetWhile(TargetExpression cond, TargetExpression body) implements TargetExpression {
}

View File

@ -1,10 +0,0 @@
package de.dhbwstuttgart.target.tree.expression;
import de.dhbwstuttgart.target.tree.type.TargetType;
public record TargetYield(TargetExpression expression) implements TargetExpression {
@Override
public TargetType type() {
return expression.type();
}
}

View File

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

View File

@ -1,41 +0,0 @@
package de.dhbwstuttgart.target.tree.type;
import de.dhbwstuttgart.bytecode.FunNGenerator;
import java.util.List;
public record TargetFunNType(String name, List<TargetType> funNParams, List<TargetType> params, int returnArguments) implements TargetSpecializedType {
public static TargetFunNType fromParams(List<TargetType> params, int returnArguments) {
return fromParams(params, params, returnArguments);
}
public static TargetFunNType fromParams(List<TargetType> params, List<TargetType> realParams, int returnArguments) {
var name = FunNGenerator.getSpecializedClassName(FunNGenerator.getArguments(params), FunNGenerator.getReturnType(params));
return new TargetFunNType(name, params, realParams, returnArguments);
}
public String toMethodDescriptor() {
var res = "(";
for (var i = 0; i < funNParams.size() - 1; i++) {
res += "Ljava/lang/Object;";
}
res += ")";
if (returnArguments > 0) {
res += "Ljava/lang/Object;";
} else {
res += "V";
}
return res;
}
@Override
public String getInternalName() {
return name;
}
@Override
public String toSignature() {
return "L" + getInternalName() + ";";
}
}

View File

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

View File

@ -1,19 +0,0 @@
package de.dhbwstuttgart.target.tree.type;
public record TargetPrimitiveType(String name) implements TargetType {
@Override
public String toSignature() {
return getInternalName();
}
@Override
public String toDescriptor() {
return toSignature();
}
@Override
public String getInternalName() {
return name;
}
}

View File

@ -1,33 +0,0 @@
package de.dhbwstuttgart.target.tree.type;
import java.util.List;
import java.util.Objects;
public record TargetRefType(String name, List<TargetType> params) implements TargetSpecializedType {
public TargetRefType(String name) {
this(name, List.of());
}
public String getInternalName() {
return this.name.replaceAll("\\.", "/");
}
@Override
public String toSignature() {
return "L" + getInternalName() + ";";
}
// Type erasure means we need to override hashCode and equals to only consider the name
@Override
public int hashCode() {
return Objects.hashCode(name);
}
@Override
public boolean equals(Object other) {
if (other instanceof TargetRefType refType) {
return refType.name.equals(name);
}
return false;
}
}

View File

@ -1,21 +0,0 @@
package de.dhbwstuttgart.target.tree.type;
import java.util.List;
public sealed interface TargetSpecializedType extends TargetType permits TargetFunNType, TargetRefType {
List<TargetType> params();
@Override
default String toDescriptor() {
String ret = "L" + getInternalName();
if (params().size() > 0) {
ret += "<";
for (var param : params()) {
ret += param.toDescriptor();
}
ret += ">";
}
ret += ";";
return ret;
}
}

View File

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

View File

@ -1,73 +0,0 @@
package de.dhbwstuttgart.target.tree.type;
import de.dhbwstuttgart.syntaxtree.type.RefType;
public sealed interface TargetType
permits TargetExtendsWildcard, TargetGenericType, TargetSpecializedType, TargetSuperWildcard, TargetPrimitiveType {
// Builtin types
TargetRefType Boolean = new TargetRefType("java.lang.Boolean");
TargetRefType Char = new TargetRefType("java.lang.Character");
TargetRefType Byte = new TargetRefType("java.lang.Byte");
TargetRefType Short = new TargetRefType("java.lang.Short");
TargetRefType Integer = new TargetRefType("java.lang.Integer");
TargetRefType Long = new TargetRefType("java.lang.Long");
TargetRefType Float = new TargetRefType("java.lang.Float");
TargetRefType Double = new TargetRefType("java.lang.Double");
TargetRefType String = new TargetRefType("java.lang.String");
TargetRefType Object = new TargetRefType("java.lang.Object");
// Builtin types
TargetPrimitiveType boolean_ = new TargetPrimitiveType("Z");
TargetPrimitiveType char_ = new TargetPrimitiveType("C");
TargetPrimitiveType byte_ = new TargetPrimitiveType("B");
TargetPrimitiveType short_ = new TargetPrimitiveType("S");
TargetPrimitiveType int_ = new TargetPrimitiveType("I");
TargetPrimitiveType long_ = new TargetPrimitiveType("J");
TargetPrimitiveType float_ = new TargetPrimitiveType("F");
TargetPrimitiveType double_ = new TargetPrimitiveType("D");
static TargetType toPrimitive(TargetType type) {
if (type.equals(Boolean)) return boolean_;
if (type.equals(Char)) return char_;
if (type.equals(Byte)) return byte_;
if (type.equals(Short)) return short_;
if (type.equals(Integer)) return int_;
if (type.equals(Long)) return long_;
if (type.equals(Float)) return float_;
if (type.equals(Double)) return double_;
return type;
}
static TargetType toPrimitive(RefType type) {
return switch(type.getName().toString()) {
case "java.lang.Boolean" -> boolean_;
case "java.lang.Character" -> char_;
case "java.lang.Byte" -> byte_;
case "java.lang.Short" -> short_;
case "java.lang.Integer" -> int_;
case "java.lang.Long" -> long_;
case "java.lang.Float" -> float_;
case "java.lang.Double" -> double_;
default -> null;
};
}
static TargetType toWrapper(TargetType f) {
if (f.equals(boolean_)) return Boolean;
if (f.equals(char_)) return Char;
if (f.equals(byte_)) return Byte;
if (f.equals(short_)) return Short;
if (f.equals(int_)) return Integer;
if (f.equals(long_)) return Long;
if (f.equals(float_)) return Float;
if (f.equals(double_)) return Double;
return f;
}
String toSignature();
String toDescriptor();
String getInternalName();
String name();
}

View File

@ -1,7 +0,0 @@
package de.dhbwstuttgart.typedeployment;
public enum KindOfTypeInsertPoint {
NORMAL_INSERT,
GENERIC_CLASS_INSERT,
GENERERIC_METHOD_INSERT
}

View File

@ -1,82 +0,0 @@
package de.dhbwstuttgart.typedeployment;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import org.antlr.v4.parse.BlockSetTransformer.setAlt_return;
import de.dhbwstuttgart.syntaxtree.statement.This;
import de.dhbwstuttgart.typeinference.result.ResultPair;
public class TypeInsert {
/**
* point wird hauptsächlich zur Anzeige einer Annotation im Eclipse-plugin benutzt.
*/
public final TypeInsertPoint point;
Set<TypeInsertPoint> inserts;
ResultPair<?, ?> resultPair;
public TypeInsert(TypeInsertPoint point, Set<TypeInsertPoint> additionalPoints, ResultPair<?, ?> resultPair){
this.point = point;
inserts = additionalPoints;
this.resultPair = resultPair;
}
public String insert(String intoSource){
List<TypeInsertPoint> offsets = new ArrayList<>();
String ret = intoSource;
List<TypeInsertPoint> insertsSorted = new ArrayList<>();
insertsSorted.add(point);
insertsSorted.addAll(inserts);
Collections.sort(insertsSorted, new TypeInsertPoint.TypeInsertPointPositionComparator().reversed());
for(TypeInsertPoint insertPoint : insertsSorted) {
ret = insertPoint.insert(ret, new ArrayList<>());
offsets.add(insertPoint);
}
return ret;
}
public String getInsertString(){
return point.getInsertString();
}
public ResultPair<?, ?> getResultPair() {
return this.resultPair;
}
/* PL 2018-06-18
* Zwei TypeInsert's sind gleich, wenn ihre point's und ihre inserts' gleich sind
* eingefuegt damit man TypeReplaceMarker vergleichen kann
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object obj) {
if(!(obj instanceof TypeInsert)) {
return false;
}
else {
return ((TypeInsert)obj).point.equals(this.point);
}
}
public Set<TypeInsertPoint> getAdditionalPoints() {
TypeInsertPoint.TypeInsertPointPositionComparator comparator = new TypeInsertPoint.TypeInsertPointPositionComparator();
TreeSet<TypeInsertPoint> result = new TreeSet<>(comparator.reversed());
result.addAll(inserts);
return result;
}
public Set<TypeInsertPoint> getAdditionalPointsUnsorted() {
return inserts;
}
public String toString() {
return point.toString();
}
}

View File

@ -1,204 +0,0 @@
package de.dhbwstuttgart.typedeployment;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import de.dhbwstuttgart.target.generate.GenerateGenerics;
import de.dhbwstuttgart.target.generate.GenericsResult;
import de.dhbwstuttgart.target.generate.GenericsResultSet;
import de.dhbwstuttgart.typeinference.result.*;
import org.antlr.v4.runtime.Token;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.SourceFile;
import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType;
import de.dhbwstuttgart.syntaxtree.type.GenericRefType;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
/**
* TODO:
* Falls in Feldern Generics entstehen, dann werden diese als Klassenparameter eingesetzt
* Für die Instanzierung von Klassen kann man dann beispielsweise nur noch den Diamond-Operator verwenden
*
* Es müssen zu einem TPH alle in Beziehung stehenden Constraints gefunden werden
*
* Anmekung: Es wird nur ein RefType gleichzeitug eingesetzt.
* Steht dieser mit anderen Typen in Verbindung, so müssen diese nicht eingesetzt werden
* im Result set können nur TPHs mit <. Beziehung stehen
* Steht ein Typ A über TPHs mit anderen Typen B in Verbindung, so lassen sich diese auch im nächsten Durchgang
* inferieren, wenn A bereits eingesetzt wurde. Es werden dann eben zusätzliche Generics entstehen
*/
public class TypeInsertFactory {
public static Set<TypeInsert> createTypeInsertPoints(SourceFile forSourcefile, ResultSet withResults, GenericsResult generics) {
return new TypeInsertPlacer().getTypeInserts(forSourcefile, withResults, generics);
}
public static TypeInsert createInsertPoints(RefTypeOrTPHOrWildcardOrGeneric type, Token offset, ClassOrInterface cl, Method m,
ResultSet resultSet, GenericsResultSet constraints, GenericsResultSet classConstraints) {
/* PL 2020-04-11 auskommentiert
* try {
*/
ResolvedType resolvedType = resultSet.resolveType(type);
TypeInsertPoint insertPoint = new TypeInsertPoint(offset,
new TypeToInsertString(resolvedType.resolvedType, constraints, classConstraints).insert, KindOfTypeInsertPoint.NORMAL_INSERT);
/* PL 2020-04-11 auskommentiert
List<GenericGenratorResultForSourceFile> simplifyResults = JavaTXCompiler.INSTANCE.getGeneratedGenericResultsForAllSourceFiles(newResults);
for (GenericGenratorResultForSourceFile simplifyResultsEntries : simplifyResults) {
GenericsGeneratorResultForClass genericResultsForClass = simplifyResultsEntries.getSimplifyResultsByName(cl.getClassName());
return new TypeInsert(insertPoint, createGenericInsert(genericResultsForClass, cl, m, resultSet, offset), resolvedType.getResultPair());
}
return new TypeInsert(insertPoint, new HashSet<>(), resolvedType.getResultPair());
*/
//GenericsGeneratorResultForClass genericResultsForClass = genericResult.getSimplifyResultsByName("", cl.getClassName().toString());
return new TypeInsert(insertPoint, createGenericInsert(constraints, classConstraints, cl, m, resultSet, offset), resolvedType.getResultPair());
/* PL 2020-04-11 auskommentiert
} catch (ClassNotFoundException e) {
e.printStackTrace();
return null;
}
*/
}
private static synchronized Set<TypeInsertPoint> createGenericInsert(GenericsResultSet methodConstraints, GenericsResultSet classConstraints,ClassOrInterface cl, Method m, ResultSet resultSet, Token mOffset){
Set<TypeInsertPoint> result = createGenericClassInserts(classConstraints, cl);
if (m != null) {
//List<GenericsGeneratorResult> methodConstraints = genericResult.getMethodConstraintsByID(MethodUtility.createID(resolver, m));
result.addAll(createMethodConstraints(methodConstraints, m.getOffset() != null ? m.getOffset() : mOffset));
}
return result;
}
private static Set<TypeInsertPoint> createMethodConstraints(GenericsResultSet constraints, Token mOffset) {
Set<TypeInsertPoint> result = new HashSet<>();
Token offset = mOffset;
if (constraints.size() == 0) {
return result;
}
String insert = " <";
for (var genericInsertConstraint : constraints) {
if (genericInsertConstraint instanceof GenerateGenerics.PairEQ peq) {
insert += peq.left.resolve().getName();
} else if (genericInsertConstraint instanceof GenerateGenerics.PairLT psm) {
insert += psm.left.resolve().getName() + " extends " + psm.right.resolve().getName();
}
insert += ", ";
}
insert = insert.substring(0, insert.length() -2);
insert += ">";
result.add(new TypeInsertPoint(offset, insert, KindOfTypeInsertPoint.GENERERIC_METHOD_INSERT));
return result;
}
private static Set<TypeInsertPoint> createGenericClassInserts(GenericsResultSet classConstraints, ClassOrInterface cl) {
Set<TypeInsertPoint> result = new HashSet<>();
Token offset = cl.getGenerics().getOffset();
if (classConstraints == null || classConstraints.size() == 0) {
return result;
}
String insert = " <";
for (var genericInsertConstraint : classConstraints) {
if (genericInsertConstraint instanceof GenerateGenerics.PairEQ peq) {
insert += peq.left.resolve().getName();
} else if (genericInsertConstraint instanceof GenerateGenerics.PairLT psm) {
insert += psm.left.resolve().getName() + " extends " + psm.right.resolve().getName();
}
insert += ", ";
}
insert = insert.substring(0, insert.length() -2);
insert += ">";
result.add(new TypeInsertPoint(offset, insert, KindOfTypeInsertPoint.GENERIC_CLASS_INSERT));
return result;
}
}
class TypeToInsertString implements ResultSetVisitor{
String insert = "";
private GenericsResultSet constraints;
private GenericsResultSet classConstraints;
TypeToInsertString(RefTypeOrTPHOrWildcardOrGeneric type, GenericsResultSet constraints, GenericsResultSet classConstraints){
this.constraints = constraints;
this.classConstraints = classConstraints;
type.accept(this);
}
@Override
public void visit(PairTPHsmallerTPH p) {
}
@Override
public void visit(PairTPHequalRefTypeOrWildcardType p) {
}
@Override
public void visit(PairTPHEqualTPH p) {
}
@Override
public void visit(RefType resolved) {
insert = resolved.getName().toString();
if(resolved.getParaList().size() > 0){
insert += "<";
Iterator<RefTypeOrTPHOrWildcardOrGeneric> iterator = resolved.getParaList().iterator();
while(iterator.hasNext()){
RefTypeOrTPHOrWildcardOrGeneric typeParam = iterator.next();
insert += new TypeToInsertString(typeParam, constraints, classConstraints).insert;
if(iterator.hasNext())insert += ", ";
}
insert += ">";
}
}
@Override
public void visit(GenericRefType genericRefType) {
insert += genericRefType.getParsedName();
}
@Override
public void visit(SuperWildcardType superWildcardType) {
insert += "? super " + new TypeToInsertString(superWildcardType.getInnerType(), constraints, classConstraints).insert;
}
@Override
public void visit(TypePlaceholder typePlaceholder) {
ResultPair<?, ?> resultPair = null;
if (constraints != null)
resultPair = constraints.getResultPairFor(typePlaceholder).orElse(null);
if (resultPair == null)
resultPair = classConstraints.getResultPairFor(typePlaceholder).orElse(null);
if (resultPair != null)
insert += ((TypePlaceholder)resultPair.getLeft()).getName();
}
@Override
public void visit(ExtendsWildcardType extendsWildcardType) {
insert += "? extends " + new TypeToInsertString(extendsWildcardType.getInnerType(), constraints, classConstraints).insert;
}
}

View File

@ -1,88 +0,0 @@
package de.dhbwstuttgart.typedeployment;
import de.dhbwstuttgart.syntaxtree.*;
import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.target.generate.GenericsResult;
import de.dhbwstuttgart.target.generate.GenericsResultSet;
import de.dhbwstuttgart.typeinference.result.ResultPair;
import de.dhbwstuttgart.typeinference.result.ResultSet;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class TypeInsertPlacer extends AbstractASTWalker{
Set<TypeInsert> inserts = new HashSet<>();
private ResultSet withResults;
String pkgName;
private GenericsResult genericsResult;
public Set<TypeInsert> getTypeInserts(SourceFile forSourceFile, ResultSet withResults, GenericsResult genericsResult){
this.withResults = withResults;
this.genericsResult = genericsResult;
pkgName = forSourceFile.getPkgName();
forSourceFile.accept(this);
return inserts;
}
@Override
public void visit(ClassOrInterface classOrInterface) {
TypeInsertPlacerClass cl = new TypeInsertPlacerClass(classOrInterface, withResults, genericsResult);
this.inserts.addAll(cl.inserts);
}
}
class TypeInsertPlacerClass extends AbstractASTWalker{
protected final ResultSet results;
private GenericsResult generatedGenerics;
protected final ClassOrInterface cl;
public final Set<TypeInsert> inserts = new HashSet<>();
private Method method;
GenericsResultSet constraints;
GenericsResultSet classConstraints;
TypeInsertPlacerClass(ClassOrInterface forClass, ResultSet withResults, GenericsResult generatedGenerics){
this.cl = forClass;
this.method = null;
this.results = withResults;
this.generatedGenerics = generatedGenerics;
forClass.accept(this);
}
@Override
public void visit(Method method) {
this.method = method;
constraints = generatedGenerics.get(method);
classConstraints = generatedGenerics.get(cl);
if(method.getReturnType() instanceof TypePlaceholder)
inserts.add(TypeInsertFactory.createInsertPoints(
method.getReturnType(), method.getReturnType().getOffset(), cl, method, results, constraints, classConstraints));
super.visit(method);
}
@Override
public void visit(Field field) {
if(field.getType() instanceof TypePlaceholder){
classConstraints = generatedGenerics.get(cl);
inserts.add(TypeInsertFactory.createInsertPoints(
field.getType(), field.getType().getOffset(), cl, method, results, null, classConstraints));
}
super.visit(field);
}
@Override
public void visit(FormalParameter param) {
if(param.getType() instanceof TypePlaceholder)
inserts.add(TypeInsertFactory.createInsertPoints(
param.getType(), param.getType().getOffset(), cl, method, results, constraints, classConstraints));
super.visit(param);
}
@Override
public void visit(LambdaExpression lambdaExpression) {
//Lambda-Ausdrücke brauchen keine Typeinsetzungen
}
}

View File

@ -1,93 +0,0 @@
package de.dhbwstuttgart.typedeployment;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import org.antlr.v4.runtime.Token;
public class TypeInsertPoint {
public Token point;
private String insertString;
private int extraOffset = 0;
private KindOfTypeInsertPoint kind;
public TypeInsertPoint(Token point, String toInsert, KindOfTypeInsertPoint kind){
this.point = point;
this.kind = kind;
this.insertString = (toInsert.endsWith(" ")) ? toInsert : toInsert + " " ;
}
public boolean isGenericClassInsertPoint() {
return kind == KindOfTypeInsertPoint.GENERIC_CLASS_INSERT;
}
public String insert(String intoSource, List<TypeInsertPoint> additionalOffset){
return new StringBuilder(intoSource).insert(point.getStartIndex()+extraOffset, insertString).toString();
}
public String getInsertString() {
return insertString;
}
public void addExtraOffset(int toAdd) {
this.extraOffset += toAdd;
}
public int getPositionInCode() {
return point.getStartIndex() + extraOffset;
}
/* PL 2018-06-19
* Zwei TypeInsertPoint's sind gleich, wenn ihre point's gleich sind
* eingefuegt damit man TypeReplaceMarker vergleichen kann
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object obj) {
return this == obj;
/*
if(!(obj instanceof TypeInsertPoint)) {
return false;
}
else {
return
((TypeInsertPoint)obj).getPositionInCode() == this.getPositionInCode() &&
((TypeInsertPoint)obj).insertString.equals(this.insertString);
}
*/
}
public int hashCode() {
return getPositionInCode() * 11 * insertString.hashCode();
}
public Set<TypeInsertPoint> getAdditionalPoints() {
return this.getAdditionalPoints();
}
public String toString() {
return point.getLine() + ":" + point.getCharPositionInLine() + ":" + insertString;
}
public static final class TypeInsertPointPositionComparator implements Comparator<TypeInsertPoint> {
@Override
public int compare(TypeInsertPoint o1, TypeInsertPoint o2) {
if (o1.point == null && o2.point == null) {
return 0;
} else if (o2.point == null) {
return 1;
} else if (o1.point == null) {
return -1;
}
if (o1.getPositionInCode() > o2.getPositionInCode()) {
return 1;
} else if (o1.getPositionInCode() < o2.getPositionInCode()) {
return -1;
}
return 0;
}
}
}

View File

@ -0,0 +1,48 @@
package de.dhbwstuttgart.typeinference;
/**
* Operators of pairs of the unification.
* @author Florian Steurer
*/
public enum PairOperator {
/**
* The smaller operator (T < P) is used to express a subtyping relation between
* T and P for example in the finite closure. It is necessarily true.
*/
SMALLER,
/**
* The smallerdot operator (T <. P) is used to express a subtyping relation between
* of T and P in a CONSTRAINT during the unification. It is not necessarily true.
*/
SMALLERDOT,
/**
* The smallernedot operator for arguments (T <!=. P) is the same as SMALLERDOT without
* T == P. It is used for operations + / - / * / < / > / ... with the Supertype Number
*/
SMALLERNEQDOT,
/**
* The smallerdot operator for arguments (T <.? P) is used to express that
* T is an element of smArg(P) (or P is an element of grArg(T)) in a CONSTRAINT
* during the unification. It is not necessarily true.
*/
SMALLERDOTWC,
/**
* The equalsdot operator (T =. P) is used to express that two types during the unification
* should be equal. It is not necessarily true.
*/
EQUALSDOT;
@Override
public String toString() {
switch (this) {
case SMALLER: return "<";
case SMALLERDOT: return "<.";
case SMALLERNEQDOT: return "<!=.";
case SMALLERDOTWC: return "<.?";
default: return "=."; // EQUALSDOT
}
}
}

View File

@ -1,20 +1,9 @@
package de.dhbwstuttgart.typeinference.assumptions;
import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
import de.dhbwstuttgart.bytecode.CodeGenException;
import de.dhbwstuttgart.exceptions.DebugException;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.syntaxtree.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.TypeScope;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Set;
import java.util.Stack;
import java.util.stream.Collectors;
public class TypeInferenceBlockInformation extends TypeInferenceInformation {
private TypeScope methodContext;

View File

@ -1,8 +1,5 @@
package de.dhbwstuttgart.typeinference.constraints;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

View File

@ -1,10 +1,5 @@
package de.dhbwstuttgart.typeinference.constraints;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.unify.GuavaSetOperations;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
import java.util.*;
import java.util.function.BinaryOperator;
import java.util.function.Consumer;
@ -44,15 +39,6 @@ public class ConstraintSet<A> {
//cartesianProduct().toString();
}
public Set<List<Constraint<A>>> cartesianProduct(){
Set<Constraint<A>> toAdd = new HashSet<>();
toAdd.add(undConstraints);
List<Set<Constraint<A>>> allConstraints = new ArrayList<>();
allConstraints.add(toAdd);
allConstraints.addAll(oderConstraints);
return new GuavaSetOperations().cartesianProduct(allConstraints);
}
public <B> ConstraintSet<B> map(Function<? super A, ? extends B> o) {
Hashtable<Constraint<A>,Constraint<B>> CSA2CSB = new Hashtable<>();
ConstraintSet<B> ret = new ConstraintSet<>();

View File

@ -7,7 +7,7 @@ import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.parser.SourceLoc;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.unify.model.PairOperator;
import de.dhbwstuttgart.typeinference.PairOperator;
import org.antlr.v4.runtime.Token;

View File

@ -21,6 +21,7 @@ import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.syntaxtree.type.Void;
import de.dhbwstuttgart.typeinference.PairOperator;
import de.dhbwstuttgart.typeinference.assumptions.FieldAssumption;
import de.dhbwstuttgart.typeinference.assumptions.FunNClass;
import de.dhbwstuttgart.typeinference.assumptions.MethodAssumption;
@ -29,7 +30,6 @@ import de.dhbwstuttgart.typeinference.constraints.Constraint;
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
import de.dhbwstuttgart.typeinference.constraints.GenericsResolver;
import de.dhbwstuttgart.typeinference.constraints.Pair;
import de.dhbwstuttgart.typeinference.unify.model.PairOperator;
import org.antlr.v4.runtime.Token;
public class TYPEStmt implements StatementVisitor {

View File

@ -1,23 +0,0 @@
package de.dhbwstuttgart.typeinference.unify;
import java.util.List;
import java.util.Set;
import com.google.common.collect.Sets;
import de.dhbwstuttgart.typeinference.unify.interfaces.ISetOperations;
/**
* Implements set operations using google guava.
* @author DH10STF
*
*/
public class GuavaSetOperations implements ISetOperations {
@Override
public <B> Set<List<B>> cartesianProduct(List<? extends Set<? extends B>> sets) {
// Wraps the call to google guava
return Sets.cartesianProduct(sets);
}
}

View File

@ -1,108 +0,0 @@
package de.dhbwstuttgart.typeinference.unify;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import de.dhbwstuttgart.typeinference.unify.interfaces.IUnify;
import de.dhbwstuttgart.typeinference.unify.model.PairOperator;
import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType;
import de.dhbwstuttgart.typeinference.unify.model.TypeParams;
import de.dhbwstuttgart.typeinference.unify.model.Unifier;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
import de.dhbwstuttgart.typeinference.unify.model.UnifyType;
/**
* Implementation of the Martelli-Montanari unification algorithm.
* @author Florian Steurer
*/
public class MartelliMontanariUnify implements IUnify {
@Override
public Optional<Unifier> unify(Set<UnifyType> terms) {
// Sets with less than 2 terms are trivially unified
if(terms.size() < 2)
return Optional.of(Unifier.identity());
// For the the set of terms {t1,...,tn},
// build a list of equations {(t1 = t2), (t2 = t3), (t3 = t4), ....}
ArrayList<UnifyPair> termsList = new ArrayList<UnifyPair>();
Iterator<UnifyType> iter = terms.iterator();
UnifyType prev = iter.next();
while(iter.hasNext()) {
UnifyType next = iter.next();
termsList.add(new UnifyPair(prev, next, PairOperator.EQUALSDOT));
prev = next;
}
// Start with the identity unifier. Substitutions will be added later.
Unifier mgu = Unifier.identity();
// Apply rules while possible
int idx = 0;
while(idx < termsList.size()) {
UnifyPair pair = termsList.get(idx);
UnifyType rhsType = pair.getRhsType();
UnifyType lhsType = pair.getLhsType();
TypeParams rhsTypeParams = rhsType.getTypeParams();
TypeParams lhsTypeParams = lhsType.getTypeParams();
// REDUCE - Rule
if(!(rhsType instanceof PlaceholderType) && !(lhsType instanceof PlaceholderType)) {
Set<UnifyPair> result = new HashSet<>();
// f<...> = g<...> with f != g are not unifiable
if(!rhsType.getName().equals(lhsType.getName()))
return Optional.empty(); // conflict
// f<t1,...,tn> = f<s1,...,sm> are not unifiable
if(rhsTypeParams.size() != lhsTypeParams.size())
return Optional.empty(); // conflict
// f = g is not unifiable (cannot be f = f because erase rule would have been applied)
//if(rhsTypeParams.size() == 0)
//return Optional.empty();
// Unpack the arguments
for(int i = 0; i < rhsTypeParams.size(); i++)
result.add(new UnifyPair(rhsTypeParams.get(i), lhsTypeParams.get(i), PairOperator.EQUALSDOT));
termsList.remove(idx);
termsList.addAll(result);
continue;
}
// DELETE - Rule
if(pair.getRhsType().equals(pair.getLhsType())) {
termsList.remove(idx);
continue;
}
// SWAP - Rule
if(!(lhsType instanceof PlaceholderType) && (rhsType instanceof PlaceholderType)) {
termsList.remove(idx);
termsList.add(new UnifyPair(rhsType, lhsType, PairOperator.EQUALSDOT));
continue;
}
// OCCURS-CHECK
if(pair.getLhsType() instanceof PlaceholderType
&& pair.getRhsType().getTypeParams().occurs((PlaceholderType) pair.getLhsType()))
return Optional.empty();
// SUBST - Rule
if(lhsType instanceof PlaceholderType) {
mgu.add((PlaceholderType) lhsType, rhsType);
//PL 2018-04-01 nach checken, ob es richtig ist, dass keine Substitutionen uebergeben werden muessen.
termsList = termsList.stream().map(x -> mgu.apply(x)).collect(Collectors.toCollection(ArrayList::new));
idx = idx+1 == termsList.size() ? 0 : idx+1;
continue;
}
idx++;
}
return Optional.of(mgu);
}
}

View File

@ -1,93 +0,0 @@
package de.dhbwstuttgart.typeinference.unify;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import de.dhbwstuttgart.typeinference.unify.interfaces.IMatch;
import de.dhbwstuttgart.typeinference.unify.model.PairOperator;
import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType;
import de.dhbwstuttgart.typeinference.unify.model.TypeParams;
import de.dhbwstuttgart.typeinference.unify.model.Unifier;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
import de.dhbwstuttgart.typeinference.unify.model.UnifyType;
/**
* Implementation of match derived from unification algorithm.
* @author Martin Pluemicke
*/
public class Match implements IMatch {
@Override
//vorne muss das Pattern stehen
//A<X> =. A<Integer> ==> True
//A<Integer> =. A<X> ==> False
public Optional<Unifier> match(ArrayList<UnifyPair> termsList) {
// Start with the identity unifier. Substitutions will be added later.
Unifier mgu = Unifier.identity();
// Apply rules while possible
int idx = 0;
while(idx < termsList.size()) {
UnifyPair pair = termsList.get(idx);
UnifyType rhsType = pair.getRhsType();
UnifyType lhsType = pair.getLhsType();
TypeParams rhsTypeParams = rhsType.getTypeParams();
TypeParams lhsTypeParams = lhsType.getTypeParams();
// REDUCE - Rule
if(!(rhsType instanceof PlaceholderType) && !(lhsType instanceof PlaceholderType)) {
Set<UnifyPair> result = new HashSet<>();
// f<...> = g<...> with f != g are not unifiable
if(!rhsType.getName().equals(lhsType.getName()))
return Optional.empty(); // conflict
// f<t1,...,tn> = f<s1,...,sm> are not unifiable
if(rhsTypeParams.size() != lhsTypeParams.size())
return Optional.empty(); // conflict
// f = g is not unifiable (cannot be f = f because erase rule would have been applied)
//if(rhsTypeParams.size() == 0)
//return Optional.empty();
// Unpack the arguments
for(int i = 0; i < rhsTypeParams.size(); i++)
result.add(new UnifyPair(lhsTypeParams.get(i), rhsTypeParams.get(i), PairOperator.EQUALSDOT));
termsList.remove(idx);
termsList.addAll(result);
continue;
}
// DELETE - Rule
if(pair.getRhsType().equals(pair.getLhsType())) {
termsList.remove(idx);
continue;
}
// SWAP - Rule
if(!(lhsType instanceof PlaceholderType) && (rhsType instanceof PlaceholderType)) {
return Optional.empty(); // conflict
}
// OCCURS-CHECK
//deleted
// SUBST - Rule
if(lhsType instanceof PlaceholderType) {
mgu.add((PlaceholderType) lhsType, rhsType);
idx = idx+1 == termsList.size() ? 0 : idx+1;
//PL 2024-04-08 falsch da es sich nicht um Unifikation handelt
//termsList = termsList.stream().map(mgu::applyleft).collect(Collectors.toCollection(ArrayList::new));
//continue;
}
idx++;
}
return Optional.of(mgu);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,121 +0,0 @@
package de.dhbwstuttgart.typeinference.unify;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ForkJoinPool;
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.typeinference.constraints.Constraint;
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
import de.dhbwstuttgart.typeinference.constraints.Pair;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unify.model.FiniteClosure;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
public class TypeUnify {
/**
* unify parallel ohne result modell
* @param undConstrains
* @param oderConstraints
* @param fc
* @param logFile
* @param log
* @param cons
* @return
*/
public Set<Set<UnifyPair>> unify(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);
ForkJoinPool pool = new ForkJoinPool();
pool.invoke(unifyTask);
Set<Set<UnifyPair>> res = unifyTask.join();
try {
logFile.write("\nnoShortendElements: " + unifyTask.noShortendElements + "\n");
logFile.flush();
}
catch (IOException e) {
System.err.println("no log-File");
}
return res;
}
/**
* unify asynchron mit Rückgabe UnifyResultModel ohne dass alle results gesammelt sind
* @param undConstrains
* @param oderConstraints
* @param fc
* @param logFile
* @param log
* @param cons
* @param ret
* @return
*/
public UnifyResultModel unifyAsync(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);
ForkJoinPool pool = new ForkJoinPool();
pool.invoke(unifyTask);
return ret;
}
/**
* unify parallel mit Rückgabe UnifyResultModel nachdem alle results gesammelt sind
* @param undConstrains
* @param oderConstraints
* @param fc
* @param logFile
* @param log
* @param cons
* @param ret
* @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);
ForkJoinPool pool = new ForkJoinPool();
pool.invoke(unifyTask);
Set<Set<UnifyPair>> res = unifyTask.join();
try {
logFile.write("\nnoShortendElements: " + unifyTask.noShortendElements +"\n");
logFile.flush();
}
catch (IOException e) {
System.err.println("no log-File");
}
return ret;
}
/*
public Set<Set<UnifyPair>> unifySequential(Set<UnifyPair> eq, IFiniteClosure fc, FileWriter logFile, Boolean log) {
TypeUnifyTask unifyTask = new TypeUnifyTask(eq, fc, false, logFile, log);
Set<Set<UnifyPair>> res = unifyTask.compute();
return res;
}
*/
/**
* unify sequentiell mit oderconstraints
* @param undConstrains
* @param oderConstraints
* @param fc
* @param logFile
* @param log
* @param cons
* @return
*/
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);
Set<Set<UnifyPair>> res = unifyTask.compute();
try {
logFile.write("\nnoShortendElements: " + unifyTask.noShortendElements +"\n");
logFile.flush();
}
catch (IOException e) {
System.err.println("no log-File");
}
return res;
}
}

View File

@ -1,66 +0,0 @@
package de.dhbwstuttgart.typeinference.unify;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import de.dhbwstuttgart.typeinference.constraints.Constraint;
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
import de.dhbwstuttgart.typeinference.constraints.Pair;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
public class TypeUnify2Task extends TypeUnifyTask {
Set<Set<UnifyPair>> setToFlatten;
Set<UnifyPair> 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;
this.nextSetElement = nextSetElement;
this.methodSignatureConstraintUebergabe = methodSignatureConstraintUebergabe;
}
Set<UnifyPair> getNextSetElement() {
return nextSetElement;
}
@Override
protected Set<Set<UnifyPair>> compute() {
if (one) {
System.out.println("two");
}
one = true;
Set<Set<UnifyPair>> res = unify2(setToFlatten, eq, oderConstraintsField, fc, parallel, rekTiefeField, methodSignatureConstraintUebergabe);
/*if (isUndefinedPairSetSet(res)) {
return new HashSet<>(); }
else
*/
//writeLog("xxx");
//noOfThread--;
synchronized (usedTasks) {
if (this.myIsCancelled()) {
return new HashSet<>();
}
else {
return res;
}
}
}
public void closeLogFile() {
try {
logFile.close();
}
catch (IOException ioE) {
System.err.println("no log-File" + thNo);
}
}
}

View File

@ -1,11 +0,0 @@
package de.dhbwstuttgart.typeinference.unify;
import java.util.Set;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
public interface Unifikationsalgorithmus {
public Set<Set<UnifyPair>> apply (Set<UnifyPair> E);
}

View File

@ -1,18 +0,0 @@
package de.dhbwstuttgart.typeinference.unify;
import java.util.List;
import de.dhbwstuttgart.typeinference.result.ResultSet;
public class UnifyResultEvent {
private List<ResultSet> newTypeResult;
public UnifyResultEvent(List<ResultSet> newTypeResult) {
this.newTypeResult = newTypeResult;
}
public List<ResultSet> getNewTypeResult() {
return newTypeResult;
}
}

View File

@ -1,7 +0,0 @@
package de.dhbwstuttgart.typeinference.unify;
public interface UnifyResultListener {
void onNewTypeResultFound(UnifyResultEvent evt);
}

View File

@ -1,21 +0,0 @@
package de.dhbwstuttgart.typeinference.unify;
import java.util.ArrayList;
import java.util.List;
import de.dhbwstuttgart.typeinference.result.ResultSet;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
public class UnifyResultListenerImpl implements UnifyResultListener {
List<ResultSet> results = new ArrayList<>();
public synchronized void onNewTypeResultFound(UnifyResultEvent evt) {
results.addAll(evt.getNewTypeResult());
}
public List<ResultSet> getResults() {
return results;
}
}

View File

@ -1,59 +0,0 @@
package de.dhbwstuttgart.typeinference.unify;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory;
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
import de.dhbwstuttgart.typeinference.result.ResultSet;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unify.model.PairOperator;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
public class UnifyResultModel {
ConstraintSet<de.dhbwstuttgart.typeinference.constraints.Pair> cons;
IFiniteClosure fc;
public UnifyResultModel(ConstraintSet<de.dhbwstuttgart.typeinference.constraints.Pair> cons,
IFiniteClosure fc) {
this.cons = cons;
this.fc = fc;
}
private List<UnifyResultListener> listeners = new ArrayList<>();
public void addUnifyResultListener(UnifyResultListener listenerToAdd) {
listeners.add(listenerToAdd);
}
public void removeUnifyResultListener(UnifyResultListener listenerToRemove) {
listeners.remove(listenerToRemove);
}
public void notify(Set<Set<UnifyPair>> eqPrimePrimeSet) {
Set<Set<UnifyPair>> eqPrimePrimeSetRet = eqPrimePrimeSet.stream().map(x -> {
Optional<Set<UnifyPair>> res = new RuleSet().subst(x.stream().map(y -> {
if (y.getPairOp() == PairOperator.SMALLERDOTWC) y.setPairOp(PairOperator.EQUALSDOT);
return y; //alle Paare a <.? b erden durch a =. b ersetzt
}).collect(Collectors.toCollection(HashSet::new)));
if (res.isPresent()) {//wenn subst ein Erg liefert wurde was veraendert
return new TypeUnifyTask().applyTypeUnificationRules(res.get(), fc);
}
else return x; //wenn nichts veraendert wurde wird x zurueckgegeben
}).collect(Collectors.toCollection(HashSet::new));
List<ResultSet> newResult = eqPrimePrimeSetRet.stream().map(unifyPairs ->
new ResultSet(UnifyTypeFactory.convert(unifyPairs, de.dhbwstuttgart.typeinference.constraints.Pair.generateTPHMap(cons))))
.collect(Collectors.toList());
UnifyResultEvent evt = new UnifyResultEvent(newResult);
for (UnifyResultListener listener : listeners) {
listener.onNewTypeResultFound(evt);
}
}
}

View File

@ -1,18 +0,0 @@
package de.dhbwstuttgart.typeinference.unify;
import java.util.ArrayList;
public class UnifyTaskModel {
ArrayList<TypeUnifyTask> usedTasks = new ArrayList<>();
public synchronized void add(TypeUnifyTask t) {
usedTasks.add(t);
}
public synchronized void cancel() {
for(TypeUnifyTask t : usedTasks) {
t.myCancel(true);
}
}
}

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