From edafbbc5a0005bfcf23eff033cb2035e0faa03af Mon Sep 17 00:00:00 2001 From: Daniel Holle Date: Tue, 23 Jul 2024 15:33:09 +0200 Subject: [PATCH] Fix #340 --- .../de/dhbwstuttgart/bytecode/Codegen.java | 2 +- .../dhbwstuttgart/bytecode/FunNGenerator.java | 48 +++++++++++-------- .../target/generate/ASTToTargetAST.java | 17 ++++--- .../target/tree/type/TargetFunNType.java | 14 +++--- 4 files changed, 45 insertions(+), 36 deletions(-) diff --git a/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java b/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java index d5b11caa..578e2821 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java @@ -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); fromDescriptor = TargetMethod.getDescriptor(fromReturn, fromParams); } else { - fromReturn = funNType.arity() > 1 ? TargetType.Object : null; + fromReturn = funNType.returnArguments() > 0 ? TargetType.Object : null; fromDescriptor = funNType.toMethodDescriptor(); } diff --git a/src/main/java/de/dhbwstuttgart/bytecode/FunNGenerator.java b/src/main/java/de/dhbwstuttgart/bytecode/FunNGenerator.java index 819f5a3e..9b6bd15f 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/FunNGenerator.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/FunNGenerator.java @@ -34,13 +34,12 @@ public class FunNGenerator { int start; public List parameters = new ArrayList<>(); final String descriptor; - final List inParams; + public final List inParams; - public GenericParameters(List params) { + public GenericParameters(List params, int numReturns) { 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); - System.out.println(this.parameters); } public TargetType getReturnType() { @@ -86,7 +85,7 @@ public class FunNGenerator { return applyNameDescriptor(type).replace("/", "$").replace(";", "$_$"); } - public static byte[] generateSuperBytecode(int numberArguments) { + public static byte[] generateSuperBytecode(int numberArguments, int numReturnTypes) { StringBuilder superFunNClassSignature = new StringBuilder("<"); StringBuilder superFunNMethodSignature = new StringBuilder("("); StringBuilder superFunNMethodDescriptor = new StringBuilder("("); @@ -97,22 +96,27 @@ public class FunNGenerator { superFunNMethodDescriptor.append(objectSignature); } superFunNClassSignature.append(String.format("%s:%s>%s", returnGeneric, objectSignature, objectSignature)); - superFunNMethodSignature.append(String.format(")T%s;", returnGeneric)); - superFunNMethodDescriptor.append(String.format(")%s", 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), 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.visitEnd(); classWriter.visitEnd(); return classWriter.toByteArray(); } - public static String getSuperClassName(int numberArguments) { - return String.format("Fun%d$$", numberArguments); + 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 superInterfaces) { @@ -138,7 +142,7 @@ public class FunNGenerator { } 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.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 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 - .stream() - .map(FunNGenerator::encodeType) - .collect(Collectors.joining()), - encodeType(returnType)); + arguments); } public static List getArguments(List list) { @@ -179,8 +189,8 @@ public class FunNGenerator { } public static TargetType getReturnType(List list) { - if(list.size() == 0) + if(list.isEmpty()) throw new IndexOutOfBoundsException(); - return list.get(list.size() - 1); + return list.getLast(); } } diff --git a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java index f80ec109..36fa146b 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java @@ -480,10 +480,10 @@ public class ASTToTargetAST { } var filteredParams = new ArrayList(); 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)); } - return TargetFunNType.fromParams(params, filteredParams, params.size()); + return TargetFunNType.fromParams(params, filteredParams, gep.getReturnType() != null ? 1 : 0); } private boolean isSubtype(TargetType test, TargetType other) { @@ -547,17 +547,16 @@ public class ASTToTargetAST { } var params = refType.getParaList().stream().map(type -> { - var res = convert(type, generics); - if (res == null) res = new TargetRefType("java.lang.Void"); - return res; + return convert(type, generics); }).toList(); 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())) { usedFunNSuperTypes.add(params.size()); - var code = FunNGenerator.generateSuperBytecode(params.size() - 1); - var superClassName = FunNGenerator.getSuperClassName(params.size() - 1); + 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) { @@ -569,7 +568,7 @@ public class ASTToTargetAST { } FunNGenerator.GenericParameters gep = null; if (!usedFunN.containsKey(className)) { - gep = new FunNGenerator.GenericParameters(params); + gep = new FunNGenerator.GenericParameters(params, returnType != null ? 1 : 0); usedFunN.put(className, gep); } else { gep = usedFunN.get(className); diff --git a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetFunNType.java b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetFunNType.java index 1c998662..db6343de 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/type/TargetFunNType.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/type/TargetFunNType.java @@ -4,24 +4,24 @@ import de.dhbwstuttgart.bytecode.FunNGenerator; import java.util.List; -public record TargetFunNType(String name, List params, int arity) implements TargetSpecializedType { +public record TargetFunNType(String name, List funNParams, List params, int returnArguments) implements TargetSpecializedType { - public static TargetFunNType fromParams(List params, int arity) { - return fromParams(params, params, arity); + public static TargetFunNType fromParams(List params, int returnArguments) { + return fromParams(params, params, returnArguments); } - public static TargetFunNType fromParams(List params, List realParams, int arity) { + public static TargetFunNType fromParams(List params, List realParams, int returnArguments) { 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() { var res = "("; - for (var i = 0; i < arity - 1; i++) { + for (var i = 0; i < funNParams.size() - 1; i++) { res += "Ljava/lang/Object;"; } res += ")"; - if (arity > 0) { + if (returnArguments > 0) { res += "Ljava/lang/Object;"; } else { res += "V";