Compare commits

...

7 Commits

Author SHA1 Message Date
acce38e8b1 Fix #372 by using package name
All checks were successful
SonarQube Scan / SonarQube Trigger (push) Successful in 3m50s
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 1m38s
2025-09-19 12:16:26 +02:00
dbd7f4fcfe Signature and Descriptor confusion resolved, fix #377
All checks were successful
SonarQube Scan / SonarQube Trigger (push) Successful in 2m43s
2025-09-19 12:01:01 +02:00
9114642370 Undo test breakage
All checks were successful
SonarQube Scan / SonarQube Trigger (push) Successful in 3m48s
2025-09-18 18:56:08 +02:00
8ac0f96bd6 Fix #376
Some checks failed
SonarQube Scan / SonarQube Trigger (push) Has been cancelled
2025-09-18 18:54:39 +02:00
pl@gohorb.ba-horb.de
b29eb71238 Merge branch 'master' of https://gitea.hb.dhbw-stuttgart.de/JavaTX/JavaCompilerCore
All checks were successful
SonarQube Scan / SonarQube Trigger (push) Successful in 3m40s
2025-09-18 16:43:46 +02:00
pl@gohorb.ba-horb.de
e9ce071e2b modified: src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java
Die Parameter von Lambda-Ausdruecken wurden mit der Variance 1 belegt.
2025-09-18 16:39:12 +02:00
3567bae0d7 Decouple Generics from ASTToTargetAST
All checks were successful
SonarQube Scan / SonarQube Trigger (push) Successful in 3m16s
2025-09-17 17:19:23 +02:00
20 changed files with 133 additions and 107 deletions

View File

@@ -4,7 +4,7 @@ import java.lang.Integer;
import java.lang.Boolean;
public class MatrixOP extends Vector<Vector<Integer>> {
MatrixOP () {
}
@@ -36,8 +36,8 @@ public class MatrixOP extends Vector<Vector<Integer>> {
v2.addElement(erg);
j++; }
ret.addElement(v2);
i++;
i++;
}
return ret;
};
}
}

View File

@@ -132,6 +132,7 @@ public class Codegen {
}
private void boxPrimitive(State state, TargetType type) {
if (type instanceof TargetExtendsWildcard ew) type = ew.innerType();
var mv = state.mv;
if (type.equals(TargetType.Boolean) || type.equals(TargetType.boolean_)) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false);
@@ -153,6 +154,7 @@ public class Codegen {
}
private void unboxPrimitive(State state, TargetType type) {
if (type instanceof TargetExtendsWildcard ew) type = ew.innerType();
var mv = state.mv;
if (type.equals(TargetType.Boolean)) {
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false);
@@ -228,6 +230,9 @@ public class Codegen {
}
private void convertTo(State state, TargetType source, TargetType dest) {
if (source instanceof TargetExtendsWildcard ew) source = ew.innerType();
if (dest instanceof TargetExtendsWildcard ew) dest = ew.innerType();
var mv = state.mv;
if (source.equals(dest))
return;
@@ -640,7 +645,7 @@ public class Codegen {
} else if (op.expr() instanceof TargetFieldVar fieldVar) {
generate(state, fieldVar.left());
mv.visitInsn(SWAP);
mv.visitFieldInsn(PUTFIELD, fieldVar.owner().getInternalName(), fieldVar.right(), fieldVar.type().toSignature());
mv.visitFieldInsn(PUTFIELD, fieldVar.owner().getInternalName(), fieldVar.right(), fieldVar.type().toDescriptor());
}
}
@@ -803,7 +808,7 @@ public class Codegen {
var handle = new Handle(state.isStatic ? H_INVOKESTATIC : H_INVOKEVIRTUAL, clazz.getName(), impl.name(), implSignature.getDescriptor(), false);
var params = new ArrayList<TargetType>();
if(!state.isStatic) params.add(new TargetRefType(clazz.qualifiedName().getClassName()));
if(!state.isStatic) params.add(new TargetRefType(clazz.qualifiedName().toString()));
params.addAll(lambda.captures().stream().map(mp -> mp.pattern().type()).toList());
if (!state.isStatic)
@@ -942,7 +947,7 @@ public class Codegen {
mv.visitInsn(DUP);
else
mv.visitInsn(DUP_X1);
mv.visitFieldInsn(dot.isStatic() ? PUTSTATIC : PUTFIELD, dot.owner().getInternalName(), dot.right(), fieldType.toSignature());
mv.visitFieldInsn(dot.isStatic() ? PUTSTATIC : PUTFIELD, dot.owner().getInternalName(), dot.right(), fieldType.toDescriptor());
}
default -> throw new CodeGenException("Invalid assignment");
}
@@ -959,7 +964,7 @@ public class Codegen {
case TargetFieldVar dot: {
if (!dot.isStatic())
generate(state, dot.left());
mv.visitFieldInsn(dot.isStatic() ? GETSTATIC : GETFIELD, dot.left().type().getInternalName(), dot.right(), dot.type().toSignature());
mv.visitFieldInsn(dot.isStatic() ? GETSTATIC : GETFIELD, dot.left().type().getInternalName(), dot.right(), dot.type().toDescriptor());
unboxPrimitive(state, dot.type());
break;
}
@@ -1423,7 +1428,7 @@ public class Codegen {
throw new CodeGenException("Couldn't find suitable field accessor for '" + type.name() + "'");
var field = clazz.getFieldDecl().get(i);
var fieldType = converter.convert(field.getType());
state.mv.visitMethodInsn(INVOKEVIRTUAL, type.getInternalName(), field.getName(), "()" + fieldType.toSignature(), false);
state.mv.visitMethodInsn(INVOKEVIRTUAL, type.getInternalName(), field.getName(), "()" + fieldType.toDescriptor(), false);
}
private void bindPattern(State state, TargetType type, TargetPattern pat, Label start, int index, int depth) {
@@ -1528,7 +1533,7 @@ public class Codegen {
//if ((access & ACC_PRIVATE) == 0 && (access & ACC_PROTECTED) == 0) // TODO Implement access modifiers properly
// access |= ACC_PUBLIC;
cw.visitField(access, field.name(), field.type().toSignature(), field.type().toDescriptor(), null);
cw.visitField(access, field.name(), field.type().toDescriptor(), field.type().toSignature(), null);
}
private void generateStaticConstructor(TargetMethod constructor) {
@@ -1604,7 +1609,7 @@ public class Codegen {
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESTATIC, "java/util/List", "of", "([Ljava/lang/Object;)Ljava/util/List;", true);
mv.visitMethodInsn(INVOKESTATIC, className, "main", "(Ljava/util/List;)V", false);
mv.visitMethodInsn(INVOKESTATIC, new TargetRefType(clazz.qualifiedName().toString()).getInternalName(), "main", "(Ljava/util/List;)V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
@@ -1661,12 +1666,12 @@ public class Codegen {
if (!generics.isEmpty()) {
ret += "<";
for (var generic : generics) {
ret += generic.name() + ":" + generic.bound().toDescriptor();
ret += generic.name() + ":" + generic.bound().toSignature();
}
ret += ">";
}
if (clazz.superType() != null)
ret += clazz.superType().toDescriptor();
ret += clazz.superType().toSignature();
for (var intf : clazz.implementingInterfaces()) {
ret += intf.toSignature();
}
@@ -1778,7 +1783,7 @@ public class Codegen {
cw2.visitEnd();
var bytes = cw2.toByteArray();
converter.auxiliaries.put(className, bytes);
compiler.auxiliaries.put(className, bytes);
// TODO These class loading shenanigans happen in a few places, the tests load the classes individually.
// Instead we should just look at the folder.
@@ -1821,7 +1826,7 @@ public class Codegen {
bootstrapArgs[1] = String.join(";", clazz.fields().stream().map(TargetField::name).toArray(String[]::new));
for (var i = 0; i < clazz.fields().size(); i++) {
var field = clazz.fields().get(i);
var fieldRef = new Handle(H_GETFIELD, clazz.getName(), field.name(), field.type().toSignature(), false);
var fieldRef = new Handle(H_GETFIELD, clazz.getName(), field.name(), field.type().toDescriptor(), false);
bootstrapArgs[i + 2] = fieldRef;
}

View File

@@ -98,7 +98,7 @@ public class FunNGenerator {
}
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)); }
private static String applyNameDescriptor(TargetType a){ return a instanceof TargetGenericType ? "LTPH;" : String.format("%s", a.toDescriptor()); }
public static String encodeType(TargetType type) {
if (type == null) return VOID;

View File

@@ -2,6 +2,7 @@
package de.dhbwstuttgart.core;
import de.dhbwstuttgart.bytecode.Codegen;
import de.dhbwstuttgart.bytecode.FunNGenerator;
import de.dhbwstuttgart.environment.CompilationEnvironment;
import de.dhbwstuttgart.environment.DirectoryClassLoader;
import de.dhbwstuttgart.exceptions.DebugException;
@@ -73,6 +74,11 @@ public class JavaTXCompiler {
public final List<File> classPath;
private final File outputPath;
public final Map<String, FunNGenerator.GenericParameters> usedFunN = new HashMap<>();
public final Set<Integer> usedFunNSuperTypes = new HashSet<>();
public Map<String, byte[]> auxiliaries = new HashMap<>();
public DirectoryClassLoader getClassLoader() {
return classLoader;
}
@@ -646,7 +652,7 @@ public class JavaTXCompiler {
}
generatedGenerics.put(sf, converter.javaGenerics());
converter.generateFunNTypes();
converter.auxiliaries.forEach((name, source) -> {
auxiliaries.forEach((name, source) -> {
generatedClasses.put(new JavaClassName(name), source);
});
return generatedClasses;

View File

@@ -150,7 +150,7 @@ public class StatementGenerator {
} else {
type = methodparameters?
TypePlaceholder.fresh(fp.getStart(), 1, false)
: TypePlaceholder.fresh(fp.getStart());
: TypePlaceholder.fresh(fp.getStart(), 1, false);
}
ret.add(new FormalParameter(paramName, type, fp.getStart()));
localVars.put(paramName, type);
@@ -1065,7 +1065,7 @@ public class StatementGenerator {
List<Pattern> parameterList = new ArrayList<>();
for (IdentifierContext identifier : lambdaParams.identifier()) {
Token offset = identifier.getStart();
parameterList.add(new FormalParameter(identifier.getText(), TypePlaceholder.fresh(offset), offset));
parameterList.add(new FormalParameter(identifier.getText(), TypePlaceholder.fresh(offset, 1, false), offset));
}
params = new ParameterList(parameterList, lambdaParams.getStart());
} else if (lambdaParams.formalParameterList() != null) {
@@ -1075,7 +1075,7 @@ public class StatementGenerator {
List<Pattern> parameterList = new ArrayList<>();
for (LambdaLVTIParameterContext param : lambdaParams.lambdaLVTIList().lambdaLVTIParameter()) {
Token offset = param.getStart();
parameterList.add(new FormalParameter(param.identifier().getText(), TypePlaceholder.fresh(offset), offset));
parameterList.add(new FormalParameter(param.identifier().getText(), TypePlaceholder.fresh(offset, 1, false), offset));
}
params = new ParameterList(parameterList, lambdaParams.getStart());
} else {

View File

@@ -6,10 +6,12 @@ import de.dhbwstuttgart.syntaxtree.type.GenericRefType;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.target.tree.TargetGeneric;
import org.antlr.v4.runtime.Token;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.stream.Collectors;
/**
* Stellt jede Art von Klasse dar. Auch abstrakte Klassen und Interfaces
@@ -31,6 +33,7 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope {
private List<RefType> implementedInterfaces;
private List<RefType> permittedSubtypes;
private List<Constructor> constructors;
private Set<GenericTypeVar> userDefinedGenerics;
public ClassOrInterface(int modifiers, JavaClassName name, List<Field> fielddecl, Optional<Constructor> fieldInitializations, Optional<Method> staticInitializer, List<Method> methods, List<Constructor> constructors, GenericDeclarationList genericClassParameters, RefType superClass, Boolean isInterface, Boolean isFunctionalInterface, List<RefType> implementedInterfaces, List<RefType> permittedSubtypes, Token offset, String fileName) {
super(offset);
@@ -199,4 +202,22 @@ public class ClassOrInterface extends SyntaxTreeNode implements TypeScope {
public int hashCode() {
return Objects.hash(name);
}
public Set<GenericTypeVar> getUserDefinedGenerics() {
if (this.userDefinedGenerics != null) return this.userDefinedGenerics;
var genericsIter = getGenerics().iterator();
if (genericsIter.hasNext()) {
// Add empty set of generics to cache so that it doesn't try to calculate it later
this.userDefinedGenerics = new HashSet<>();
while (genericsIter.hasNext()) {
var next = genericsIter.next();
userDefinedGenerics.add(next);
}
} else {
this.userDefinedGenerics = new HashSet<>();
}
return this.userDefinedGenerics;
}
}

View File

@@ -5,8 +5,10 @@ import java.util.*;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.target.generate.ASTToTargetAST;
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation;
import de.dhbwstuttgart.typeinference.result.ResultSet;
//import sun.security.x509.X509CertInfo;
public class SourceFile extends SyntaxTreeNode {
@@ -18,6 +20,7 @@ public class SourceFile extends SyntaxTreeNode {
private boolean isGenerated;
public List<ClassOrInterface> availableClasses = new ArrayList<>();
public List<ASTToTargetAST.Generics> generics = new ArrayList<>();
/**
* Die SourceFile repräsntiert eine zu einem Syntaxbaum eingelesene Java-Datei.
@@ -40,6 +43,10 @@ public class SourceFile extends SyntaxTreeNode {
this.imports = new HashSet<>(sf.imports);
}
public void addResultSet(ResultSet rs) {
}
public void setPackageName(String packageName) {
this.pkgName = packageName;
}

View File

@@ -36,7 +36,6 @@ public class ASTToTargetAST {
public Generics generics;
public List<Generics> currentMethodOverloads;
final Map<ClassOrInterface, Set<GenericTypeVar>> userDefinedGenerics = new HashMap<>();
final Map<Method, Set<SignaturePair>> tphsInMethods = new HashMap<>();
private Method currentMethod;
@@ -61,9 +60,11 @@ public class ASTToTargetAST {
}
public record Generics(JavaGenerics javaGenerics, TxGenerics txGenerics) {
public Generics(JavaTXCompiler compiler, ResultSet set) {
this(new JavaGenerics(compiler, set), new TxGenerics(compiler, set));
}
}
public IByteArrayClassLoader classLoader;
protected SourceFile sourceFile;
@@ -81,9 +82,9 @@ public class ASTToTargetAST {
all = new ArrayList<>();
for (var set : resultSets) {
all.add(new Generics(new JavaGenerics(this, set), new TxGenerics(this, set)));
all.add(new Generics(compiler, set));
}
this.generics = all.get(0);
this.generics = all.getFirst();
}
public void addSignaturePair(TypePlaceholder signature, RefTypeOrTPHOrWildcardOrGeneric parameter) {
@@ -93,9 +94,13 @@ public class ASTToTargetAST {
}
Optional<Method> findMethod(ClassOrInterface owner, String name, List<TargetType> argumentList) {
return findMethod(owner, name, argumentList, this.generics.javaGenerics, this.compiler);
}
public static Optional<Method> findMethod(ClassOrInterface owner, String name, List<TargetType> argumentList, GenerateGenerics generics, JavaTXCompiler compiler) {
Optional<Method> method = Optional.empty();
while (method.isEmpty()) {
method = owner.getMethods().stream().filter(m -> m.name.equals(name) && parameterEquals(m.getParameterList(), argumentList)).findFirst();
method = owner.getMethods().stream().filter(m -> m.name.equals(name) && parameterEquals(m.getParameterList(), argumentList, generics)).findFirst();
if (owner.getClassName().toString().equals("java.lang.Object")) break;
owner = compiler.getClass(owner.getSuperClass().getName());
}
@@ -103,16 +108,16 @@ public class ASTToTargetAST {
}
Optional<Constructor> findConstructor(ClassOrInterface owner, List<TargetType> argumentList) {
return owner.getConstructors().stream().filter(c -> parameterEquals(c.getParameterList(), argumentList)).findFirst();
return owner.getConstructors().stream().filter(c -> parameterEquals(c.getParameterList(), argumentList, generics.javaGenerics)).findFirst();
}
boolean parameterEquals(ParameterList parameterList, List<TargetType> arguments) {
static boolean parameterEquals(ParameterList parameterList, List<TargetType> arguments, GenerateGenerics generics) {
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 type1 = generics.getTargetType(pars.get(i).getType());
var type2 = arguments.get(i);
if (type1 instanceof TargetGenericType)
return true;
@@ -350,19 +355,14 @@ public class ASTToTargetAST {
Set<TargetGeneric> javaGenerics = new HashSet<>();
Set<TargetGeneric> txGenerics = new HashSet<>();
var genericsIter = input.getGenerics().iterator();
if (genericsIter.hasNext()) {
var userDefinedGenerics = input.getUserDefinedGenerics();
if (!userDefinedGenerics.isEmpty()) {
// 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))));
for (var generic : userDefinedGenerics) {
// TODO Support multiple bouds
javaGenerics.add(new TargetGeneric(generic.getName(), convert(generic.getBounds().getFirst())));
}
} 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);
@@ -424,7 +424,7 @@ public class ASTToTargetAST {
}
private List<TargetConstructor> convert(ClassOrInterface currentClass, Constructor input, TargetBlock fieldInitializer) {
generics = all.get(0);
generics = all.getFirst();
List<TargetConstructor> result = new ArrayList<>();
Set<List<MethodParameter>> parameterSet = new HashSet<>();
this.currentMethod = input;
@@ -468,13 +468,6 @@ public class ASTToTargetAST {
}
}
private TargetType unwrap(TargetType type) {
if (type instanceof TargetRefType ref) {
if (!ref.params().isEmpty()) return new TargetRefType(ref.name());
}
return type;
}
private TargetExpression generatePatternOverloadsRec(int offset, TargetExpression switchExpr, List<TargetLocalVar> params, List<TargetPattern> patterns, List<TargetMethod> methods, TargetType classType) {
if (methods.isEmpty()) throw new DebugException("Couldn't find a candidate for switch overloading");
if (methods.size() == 1) {
@@ -745,11 +738,6 @@ public class ASTToTargetAST {
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);
}
@@ -818,20 +806,24 @@ public class ASTToTargetAST {
}
public void generateFunNTypes() {
for (var entry : usedFunN.entrySet()) {
for (var entry : compiler.usedFunN.entrySet()) {
var gep = entry.getValue();
var superInterfaces = usedFunN.values().stream()
var superInterfaces = compiler.usedFunN.values().stream()
.filter(g -> !g.equals(gep))
.filter(genericParameters -> isSubtype(gep, genericParameters))
.map(FunNGenerator::getSpecializedClassName)
.toList();
var code = FunNGenerator.generateSpecializedBytecode(gep, superInterfaces);
auxiliaries.put(entry.getKey(), code);
compiler.auxiliaries.put(entry.getKey(), code);
}
}
protected TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input, GenerateGenerics generics) {
public TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input, GenerateGenerics generics) {
return convert(input, generics, compiler);
}
public static TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input, GenerateGenerics generics, JavaTXCompiler compiler) {
return input.acceptTV(new TypeVisitor<>() {
@Override
public TargetType visit(RefType refType) {
@@ -843,31 +835,31 @@ public class ASTToTargetAST {
}
var params = refType.getParaList().stream().map(type -> {
return convert(type, generics);
return convert(type, generics, compiler);
}).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());
if (!compiler.usedFunNSuperTypes.contains(params.size())) {
compiler.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);
compiler.classLoader.findClass(superClassName);
} catch (ClassNotFoundException e) {
try {
classLoader.loadClass(superClassName, code);
compiler.classLoader.loadClass(superClassName, code);
} catch (LinkageError ignored) {}
}
auxiliaries.put(superClassName, code);
compiler.auxiliaries.put(superClassName, code);
}
FunNGenerator.GenericParameters gep = null;
if (!usedFunN.containsKey(className)) {
if (!compiler.usedFunN.containsKey(className)) {
gep = new FunNGenerator.GenericParameters(params, returnType != null ? 1 : 0);
usedFunN.put(className, gep);
compiler.usedFunN.put(className, gep);
} else {
gep = usedFunN.get(className);
gep = compiler.usedFunN.get(className);
}
return flattenFunNType(params, gep);
}
@@ -876,7 +868,7 @@ public class ASTToTargetAST {
@Override
public TargetType visit(SuperWildcardType superWildcardType) {
return new TargetSuperWildcard(convert(superWildcardType.getInnerType(), generics));
return new TargetSuperWildcard(convert(superWildcardType.getInnerType(), generics, compiler));
}
@Override
@@ -886,7 +878,7 @@ public class ASTToTargetAST {
@Override
public TargetType visit(ExtendsWildcardType extendsWildcardType) {
return new TargetExtendsWildcard(convert(extendsWildcardType.getInnerType(), generics));
return new TargetExtendsWildcard(convert(extendsWildcardType.getInnerType(), generics, compiler));
}
@Override

View File

@@ -1,5 +1,7 @@
package de.dhbwstuttgart.target.generate;
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.parser.JavaTXParser;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.syntaxtree.*;
import de.dhbwstuttgart.syntaxtree.statement.*;
@@ -18,7 +20,7 @@ import java.util.stream.Stream;
public abstract class GenerateGenerics {
private final ASTToTargetAST astToTargetAST;
private final JavaTXCompiler compiler;
public class TPH {
private final TypePlaceholder wrap;
@@ -134,8 +136,8 @@ public abstract class GenerateGenerics {
Map<TPH, RefTypeOrTPHOrWildcardOrGeneric> concreteTypes = new HashMap<>();
Map<TypePlaceholder, TypePlaceholder> equality = new HashMap<>();
GenerateGenerics(ASTToTargetAST astToTargetAST, ResultSet constraints) {
this.astToTargetAST = astToTargetAST;
GenerateGenerics(JavaTXCompiler compiler, ResultSet constraints) {
this.compiler = compiler;
for (var constraint : constraints.results) {
if (constraint instanceof PairTPHsmallerTPH p) {
System.out.println(p.left + " " + p.left.getVariance());
@@ -281,7 +283,7 @@ public abstract class GenerateGenerics {
Set<TPH> typeVariablesOfClass,
Set<Pair> result
) {
var userDefinedGenericsOfClass = astToTargetAST.userDefinedGenerics.get(owner);
var userDefinedGenericsOfClass = owner.getUserDefinedGenerics();
// Type variables with bounds that are also type variables of the method
for (var typeVariable : new HashSet<>(typeVariables)) {
@@ -329,7 +331,7 @@ public abstract class GenerateGenerics {
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());
var optMethod = ASTToTargetAST.findMethod(owner, methodCall.name, methodCall.signatureArguments().stream().map(x -> getTargetType(x)).toList(), GenerateGenerics.this, compiler);
if (optMethod.isEmpty()) return;
var method2 = optMethod.get();
System.out.println("In: " + method.getName() + " Method: " + method2.getName());
@@ -1005,8 +1007,8 @@ public abstract class GenerateGenerics {
}
var type = concreteTypes.get(new TPH(tph));
if (type == null) return new TargetGenericType(tph.getName());
return astToTargetAST.convert(type, this);
return ASTToTargetAST.convert(type, this, compiler);
}
return astToTargetAST.convert(in, this);
return ASTToTargetAST.convert(in, this, compiler);
}
}

View File

@@ -69,8 +69,4 @@ public class GenericsResult {
return this.generics.getType(tph);
return type;
}
public TargetType resolveTarget(RefTypeOrTPHOrWildcardOrGeneric type) {
return this.generics.getTargetType(type);
}
}

View File

@@ -1,5 +1,6 @@
package de.dhbwstuttgart.target.generate;
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.typeinference.result.ResultSet;
@@ -7,8 +8,8 @@ import de.dhbwstuttgart.typeinference.result.ResultSet;
import java.util.Set;
final class JavaGenerics extends GenerateGenerics {
JavaGenerics(ASTToTargetAST astToTargetAST, ResultSet constraints) {
super(astToTargetAST, constraints);
JavaGenerics(JavaTXCompiler compiler, ResultSet constraints) {
super(compiler, constraints);
}
@Override

View File

@@ -1,5 +1,6 @@
package de.dhbwstuttgart.target.generate;
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.typeinference.result.ResultSet;
@@ -7,8 +8,8 @@ import de.dhbwstuttgart.typeinference.result.ResultSet;
import java.util.Set;
final class TxGenerics extends GenerateGenerics {
TxGenerics(ASTToTargetAST astToTargetAST, ResultSet constraints) {
super(astToTargetAST, constraints);
TxGenerics(JavaTXCompiler compiler, ResultSet constraints) {
super(compiler, constraints);
}
@Override

View File

@@ -36,30 +36,30 @@ public record TargetMethod(int access, String name, TargetBlock block, Signature
public static String getDescriptor(TargetType returnType, TargetType... parameters) {
String ret = "(";
for (var parameterType : parameters) {
ret += parameterType.toSignature();
ret += parameterType.toDescriptor();
}
ret += ")";
if (returnType == null) ret += "V";
else ret += returnType.toSignature();
else ret += returnType.toDescriptor();
return ret;
}
public static String getSignature(Set<TargetGeneric> generics, List<MethodParameter> parameters, TargetType returnType) {
String ret = "";
if (generics.size() > 0) {
if (!generics.isEmpty()) {
ret += "<";
for (var generic : generics) {
ret += generic.name() + ":" + generic.bound().toDescriptor();
ret += generic.name() + ":" + generic.bound().toSignature();
}
ret += ">";
}
ret += "(";
for (var param : parameters) {
ret += param.pattern().type().toDescriptor();
ret += param.pattern().type().toSignature();
}
ret += ")";
if (returnType == null) ret += "V";
else ret += returnType.toDescriptor();
else ret += returnType.toSignature();
return ret;
}

View File

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

View File

@@ -33,9 +33,4 @@ public record TargetFunNType(String name, List<TargetType> funNParams, List<Targ
public String getInternalName() {
return name;
}
@Override
public String toSignature() {
return "L" + getInternalName() + ";";
}
}

View File

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

View File

@@ -12,11 +12,6 @@ public record TargetRefType(String name, List<TargetType> params) implements Tar
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() {

View File

@@ -6,16 +6,21 @@ public sealed interface TargetSpecializedType extends TargetType permits TargetF
List<TargetType> params();
@Override
default String toDescriptor() {
default String toSignature() {
String ret = "L" + getInternalName();
if (params().size() > 0) {
if (!params().isEmpty()) {
ret += "<";
for (var param : params()) {
ret += param.toDescriptor();
ret += param.toSignature();
}
ret += ">";
}
ret += ";";
return ret;
}
@Override
default String toDescriptor() {
return "L" + getInternalName() + ";";
}
}

View File

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

View File

@@ -66,7 +66,7 @@ public class TestCodegen {
converter.generateFunNTypes();
for (var entry : converter.auxiliaries.entrySet()) {
for (var entry : compiler.auxiliaries.entrySet()) {
writeClassFile(entry.getKey(), entry.getValue());
}
}
@@ -112,7 +112,7 @@ public class TestCodegen {
converter.generateFunNTypes();
for (var entry : converter.auxiliaries.entrySet()) {
for (var entry : compiler.auxiliaries.entrySet()) {
writeClassFile(entry.getKey(), entry.getValue());
}