Fix #340
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 44s

This commit is contained in:
Daniel Holle 2024-07-23 15:33:09 +02:00
parent ba8810e5df
commit edafbbc5a0
4 changed files with 45 additions and 36 deletions

View File

@ -1641,7 +1641,7 @@ public class Codegen {
var fromParams = converter.convert(fromMethod.getParameterList(), converter.generics.javaGenerics()).stream().map(m -> m.pattern().type()).toArray(TargetType[]::new); var fromParams = converter.convert(fromMethod.getParameterList(), converter.generics.javaGenerics()).stream().map(m -> m.pattern().type()).toArray(TargetType[]::new);
fromDescriptor = TargetMethod.getDescriptor(fromReturn, fromParams); fromDescriptor = TargetMethod.getDescriptor(fromReturn, fromParams);
} else { } else {
fromReturn = funNType.arity() > 1 ? TargetType.Object : null; fromReturn = funNType.returnArguments() > 0 ? TargetType.Object : null;
fromDescriptor = funNType.toMethodDescriptor(); fromDescriptor = funNType.toMethodDescriptor();
} }

View File

@ -34,13 +34,12 @@ public class FunNGenerator {
int start; int start;
public List<TargetType> parameters = new ArrayList<>(); public List<TargetType> parameters = new ArrayList<>();
final String descriptor; final String descriptor;
final List<TargetType> inParams; public final List<TargetType> inParams;
public GenericParameters(List<TargetType> params) { public GenericParameters(List<TargetType> params, int numReturns) {
this.inParams = params; this.inParams = params;
var type = new TargetRefType(FunNGenerator.getSuperClassName(params.size() - 1), params); var type = new TargetRefType(FunNGenerator.getSuperClassName(params.size() - 1, numReturns), params);
descriptor = applyDescriptor(type, this); descriptor = applyDescriptor(type, this);
System.out.println(this.parameters);
} }
public TargetType getReturnType() { public TargetType getReturnType() {
@ -86,7 +85,7 @@ public class FunNGenerator {
return applyNameDescriptor(type).replace("/", "$").replace(";", "$_$"); return applyNameDescriptor(type).replace("/", "$").replace(";", "$_$");
} }
public static byte[] generateSuperBytecode(int numberArguments) { public static byte[] generateSuperBytecode(int numberArguments, int numReturnTypes) {
StringBuilder superFunNClassSignature = new StringBuilder("<"); StringBuilder superFunNClassSignature = new StringBuilder("<");
StringBuilder superFunNMethodSignature = new StringBuilder("("); StringBuilder superFunNMethodSignature = new StringBuilder("(");
StringBuilder superFunNMethodDescriptor = new StringBuilder("("); StringBuilder superFunNMethodDescriptor = new StringBuilder("(");
@ -97,22 +96,27 @@ public class FunNGenerator {
superFunNMethodDescriptor.append(objectSignature); superFunNMethodDescriptor.append(objectSignature);
} }
superFunNClassSignature.append(String.format("%s:%s>%s", returnGeneric, objectSignature, objectSignature)); superFunNClassSignature.append(String.format("%s:%s>%s", returnGeneric, objectSignature, objectSignature));
superFunNMethodSignature.append(String.format(")T%s;", returnGeneric)); if (numReturnTypes > 0) {
superFunNMethodDescriptor.append(String.format(")%s", objectSignature)); superFunNMethodSignature.append(String.format(")T%s;", returnGeneric));
superFunNMethodDescriptor.append(String.format(")%s", objectSignature));
} else {
superFunNMethodSignature.append(")V");
superFunNMethodDescriptor.append(")V");
}
System.out.println(superFunNMethodSignature); System.out.println(superFunNMethodSignature);
ClassWriter classWriter = new ClassWriter(0); ClassWriter classWriter = new ClassWriter(0);
MethodVisitor methodVisitor; MethodVisitor methodVisitor;
classWriter.visit(bytecodeVersion, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, getSuperClassName(numberArguments), superFunNClassSignature.toString(), objectSuperType, null); 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 = classWriter.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, methodName, superFunNMethodDescriptor.toString(), superFunNMethodSignature.toString(), null);
methodVisitor.visitEnd(); methodVisitor.visitEnd();
classWriter.visitEnd(); classWriter.visitEnd();
return classWriter.toByteArray(); return classWriter.toByteArray();
} }
public static String getSuperClassName(int numberArguments) { public static String getSuperClassName(int numberArguments, int returnArguments) {
return String.format("Fun%d$$", numberArguments); return returnArguments > 0 ? String.format("Fun%d$$", numberArguments) : String.format("FunVoid%d$$", numberArguments);
} }
public static byte[] generateSpecializedBytecode(GenericParameters gep, List<String> superInterfaces) { public static byte[] generateSpecializedBytecode(GenericParameters gep, List<String> superInterfaces) {
@ -138,7 +142,7 @@ public class FunNGenerator {
} }
var interfaces = new ArrayList<>(superInterfaces); var interfaces = new ArrayList<>(superInterfaces);
interfaces.add(getSuperClassName(argumentTypes.size())); interfaces.add(getSuperClassName(argumentTypes.size(), returnType != null ? 1 : 0));
ClassWriter classWriter = new ClassWriter(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.visit(bytecodeVersion, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, getSpecializedClassName(argumentTypes, returnType), funNClassSignature.toString(), objectSuperType, interfaces.toArray(String[]::new));
@ -162,13 +166,19 @@ public class FunNGenerator {
} }
public static String getSpecializedClassName(List<TargetType> argumentTypes, TargetType returnType) { public static String getSpecializedClassName(List<TargetType> argumentTypes, TargetType returnType) {
return String.format("Fun%d$$%s%s", 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(), argumentTypes.size(),
argumentTypes arguments);
.stream()
.map(FunNGenerator::encodeType)
.collect(Collectors.joining()),
encodeType(returnType));
} }
public static List<TargetType> getArguments(List<TargetType> list) { public static List<TargetType> getArguments(List<TargetType> list) {
@ -179,8 +189,8 @@ public class FunNGenerator {
} }
public static TargetType getReturnType(List<TargetType> list) { public static TargetType getReturnType(List<TargetType> list) {
if(list.size() == 0) if(list.isEmpty())
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException();
return list.get(list.size() - 1); return list.getLast();
} }
} }

View File

@ -480,10 +480,10 @@ public class ASTToTargetAST {
} }
var filteredParams = new ArrayList<TargetType>(); var filteredParams = new ArrayList<TargetType>();
for (var i = 0; i < newParams.size(); i++) { for (var i = 0; i < newParams.size(); i++) {
if (gep.parameters.get(i) != null) if (i < gep.inParams.size() && gep.inParams.get(i) != null)
filteredParams.add(newParams.get(i)); filteredParams.add(newParams.get(i));
} }
return TargetFunNType.fromParams(params, filteredParams, params.size()); return TargetFunNType.fromParams(params, filteredParams, gep.getReturnType() != null ? 1 : 0);
} }
private boolean isSubtype(TargetType test, TargetType other) { private boolean isSubtype(TargetType test, TargetType other) {
@ -547,17 +547,16 @@ public class ASTToTargetAST {
} }
var params = refType.getParaList().stream().map(type -> { var params = refType.getParaList().stream().map(type -> {
var res = convert(type, generics); return convert(type, generics);
if (res == null) res = new TargetRefType("java.lang.Void");
return res;
}).toList(); }).toList();
if (name.matches("Fun\\d+\\$\\$")) { // TODO This seems like a bad idea if (name.matches("Fun\\d+\\$\\$")) { // TODO This seems like a bad idea
var className = FunNGenerator.getSpecializedClassName(FunNGenerator.getArguments(params), FunNGenerator.getReturnType(params)); var returnType = FunNGenerator.getReturnType(params);
var className = FunNGenerator.getSpecializedClassName(FunNGenerator.getArguments(params), returnType);
if (!usedFunNSuperTypes.contains(params.size())) { if (!usedFunNSuperTypes.contains(params.size())) {
usedFunNSuperTypes.add(params.size()); usedFunNSuperTypes.add(params.size());
var code = FunNGenerator.generateSuperBytecode(params.size() - 1); var code = FunNGenerator.generateSuperBytecode(params.size() - 1, returnType != null ? 1 : 0);
var superClassName = FunNGenerator.getSuperClassName(params.size() - 1); var superClassName = FunNGenerator.getSuperClassName(params.size() - 1, returnType != null ? 1 : 0);
try { try {
classLoader.findClass(superClassName); classLoader.findClass(superClassName);
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
@ -569,7 +568,7 @@ public class ASTToTargetAST {
} }
FunNGenerator.GenericParameters gep = null; FunNGenerator.GenericParameters gep = null;
if (!usedFunN.containsKey(className)) { if (!usedFunN.containsKey(className)) {
gep = new FunNGenerator.GenericParameters(params); gep = new FunNGenerator.GenericParameters(params, returnType != null ? 1 : 0);
usedFunN.put(className, gep); usedFunN.put(className, gep);
} else { } else {
gep = usedFunN.get(className); gep = usedFunN.get(className);

View File

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