Rework FunNGenerator to use target types

This commit is contained in:
Vic Nightfall 2022-11-14 15:28:00 +01:00
parent 9d942a7014
commit 15e94111d4
12 changed files with 55 additions and 71 deletions

View File

@ -975,7 +975,7 @@ public class Codegen {
} }
private void generateField(TargetField field) { private void generateField(TargetField field) {
cw.visitField(field.access() | ACC_PUBLIC, field.name(), field.type().toSignature(), field.type().toGenericSignature(), null); cw.visitField(field.access() | ACC_PUBLIC, field.name(), field.type().toSignature(), field.type().toDescriptor(), null);
} }
private void generateConstructor(TargetConstructor constructor) { private void generateConstructor(TargetConstructor constructor) {
@ -1018,10 +1018,10 @@ public class Codegen {
private static String generateSignature(TargetClass clazz) { private static String generateSignature(TargetClass clazz) {
String ret = "<"; String ret = "<";
for (var generic : clazz.generics()) { for (var generic : clazz.generics()) {
ret += generic.name() + ":" + generic.bound().toGenericSignature(); ret += generic.name() + ":" + generic.bound().toDescriptor();
} }
ret += ">"; ret += ">";
ret += clazz.superType().toGenericSignature(); ret += clazz.superType().toDescriptor();
return ret; return ret;
} }

View File

@ -3,8 +3,10 @@ package de.dhbwstuttgart.bytecode.funN;
import de.dhbwstuttgart.parser.scope.JavaClassName; import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.syntaxtree.type.GenericRefType; import de.dhbwstuttgart.syntaxtree.type.GenericRefType;
import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.target.tree.type.TargetGenericType;
import de.dhbwstuttgart.target.tree.type.TargetRefType;
import de.dhbwstuttgart.target.tree.type.TargetType;
import org.objectweb.asm.ClassWriter; import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type; import org.objectweb.asm.Type;
@ -23,24 +25,23 @@ import static org.objectweb.asm.Opcodes.*;
*/ */
public class FunNGenerator implements FunNUtilities{ public class FunNGenerator implements FunNUtilities{
private static FunNGenerator funNGenerator = new FunNGenerator(); private static final FunNGenerator funNGenerator = new FunNGenerator();
public static FunNGenerator getInstance(){ public static FunNGenerator getInstance(){
return funNGenerator; return funNGenerator;
} }
private final String argumentGenericBase = "T"; private static final String argumentGenericBase = "T";
private final String returnGeneric = "R"; private static final String returnGeneric = "R";
private final String methodName = "apply"; private static final String methodName = "apply";
private final int bytecodeVersion = V1_8; private final int bytecodeVersion = V1_8;
private final String objectSuperType = Type.getInternalName(Object.class).replace('.','/'); private final String objectSuperType = Type.getInternalName(Object.class).replace('.','/');
private final RefType objectRefType = new RefType(new JavaClassName(objectSuperType), null); private final String objectSignature = applySignature(TargetType.Object);
private final String objectSignature = applySignature(objectRefType);
private String applyDescriptor(RefTypeOrTPHOrWildcardOrGeneric a) { return a.acceptTV(new TypeToDescriptor(true)); } private String applyDescriptor(TargetType a) { return a.toDescriptor(); }
private String applySignature(RefTypeOrTPHOrWildcardOrGeneric a) { return a.acceptTV(new TypeToSignature(true)); } private String applySignature(TargetType a) { return a.toSignature(); }
private String applyNameDescriptor(RefTypeOrTPHOrWildcardOrGeneric a){ return a instanceof TypePlaceholder ? "LTPH;" : String.format("L%s;", applyDescriptor(a)); } private String applyNameDescriptor(TargetType a){ return a instanceof TargetGenericType ? "LTPH;" : String.format("L%s;", applyDescriptor(a)); }
@Override @Override
public byte[] generateSuperBytecode(int numberArguments) { public byte[] generateSuperBytecode(int numberArguments) {
@ -50,11 +51,11 @@ public class FunNGenerator implements FunNUtilities{
for (int currentParameter = 1; currentParameter <= numberArguments; currentParameter++){ for (int currentParameter = 1; currentParameter <= numberArguments; currentParameter++){
superFunNClassSignature.append(String.format("%s%d:%s",argumentGenericBase, currentParameter, objectSignature)); superFunNClassSignature.append(String.format("%s%d:%s",argumentGenericBase, currentParameter, objectSignature));
superFunNMethodSignature.append(String.format("T%s;", applySignature( new GenericRefType(argumentGenericBase + currentParameter, null)))); superFunNMethodSignature.append(String.format("T%s;", applySignature(new TargetRefType(argumentGenericBase + currentParameter))));
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;", applySignature(new GenericRefType(returnGeneric, null)))); superFunNMethodSignature.append(String.format(")T%s;", applySignature(new TargetRefType(returnGeneric))));
superFunNMethodDescriptor.append(String.format(")%s", objectSignature)); superFunNMethodDescriptor.append(String.format(")%s", objectSignature));
ClassWriter classWriter = new ClassWriter(0); ClassWriter classWriter = new ClassWriter(0);
@ -72,26 +73,19 @@ public class FunNGenerator implements FunNUtilities{
} }
@Override @Override
public byte[] generateSpecializedBytecode(List<RefTypeOrTPHOrWildcardOrGeneric> argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType) { public byte[] generateSpecializedBytecode(List<TargetType> argumentTypes, TargetType returnType) {
List<RefTypeOrTPHOrWildcardOrGeneric> parameters = Stream List<TargetType> parameters = Stream
.concat(argumentTypes.stream(), Stream.of(returnType)) .concat(argumentTypes.stream(), Stream.of(returnType))
.collect(Collectors.toList()); .collect(Collectors.toList());
RefType superFunN = new RefType(new JavaClassName(getSuperClassName(argumentTypes.size())), parameters , null); StringBuilder funNClassSignature = new StringBuilder(objectSignature + applySignature(new TargetRefType(getSuperClassName(argumentTypes.size()), parameters)));
StringBuilder funNClassSignature = new StringBuilder(objectSignature + (superFunN.acceptTV(new TypeToSignature(false))));
boolean containsGeneric = false; boolean containsGeneric = false;
String genericSignature = "<"; String genericSignature = "<";
for (RefTypeOrTPHOrWildcardOrGeneric typeArgument : parameters) { for (TargetType typeArgument : parameters) {
//ToDo Etienne: Refactor //ToDo Etienne: Refactor
if (typeArgument instanceof GenericRefType){ if (typeArgument instanceof TargetGenericType generic){
GenericRefType generic = (GenericRefType) typeArgument; if(genericSignature.contains(generic.name())) continue;
if(genericSignature.contains(generic.getParsedName())) continue; genericSignature += String.format("%s:%s", generic.name(), applyDescriptor(generic));
genericSignature += String.format("%s:%s", generic.getParsedName(), applyDescriptor(generic));
containsGeneric = true;
} else if(typeArgument instanceof TypePlaceholder){
TypePlaceholder placeholder = (TypePlaceholder) typeArgument;
if(genericSignature.contains(applySignature(placeholder).substring(1))) continue;
genericSignature += String.format("%s:%s", applySignature(placeholder).substring(1), objectSignature);
containsGeneric = true; containsGeneric = true;
} }
} }
@ -105,7 +99,7 @@ public class FunNGenerator implements FunNUtilities{
} }
@Override @Override
public String getSpecializedClassName(List<RefTypeOrTPHOrWildcardOrGeneric> argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType) { public String getSpecializedClassName(List<TargetType> argumentTypes, TargetType returnType) {
return String.format("Fun%d$$%s%s", return String.format("Fun%d$$%s%s",
argumentTypes.size(), argumentTypes.size(),
argumentTypes argumentTypes
@ -118,17 +112,17 @@ public class FunNGenerator implements FunNUtilities{
} }
@Override @Override
public String getSpecializedDescriptor(List<RefTypeOrTPHOrWildcardOrGeneric> argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType) { public String getSpecializedDescriptor(List<TargetType> argumentTypes, TargetType returnType) {
return applyDescriptor(new RefType(new JavaClassName(getSpecializedClassName(argumentTypes, returnType)), null)); return applyDescriptor(new TargetRefType(getSpecializedClassName(argumentTypes, returnType)));
} }
@Override @Override
public String getSpecializedSignature(List<RefTypeOrTPHOrWildcardOrGeneric> argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType) { public String getSpecializedSignature(List<TargetType> argumentTypes, TargetType returnType) {
return applySignature(new RefType(new JavaClassName(getSpecializedClassName(argumentTypes, returnType)), null)); return applySignature(new TargetRefType(getSpecializedClassName(argumentTypes, returnType)));
} }
@Override @Override
public List<RefTypeOrTPHOrWildcardOrGeneric> getArguments(List<RefTypeOrTPHOrWildcardOrGeneric> list) { public List<TargetType> getArguments(List<TargetType> list) {
return list return list
.stream() .stream()
.limit(Math.max(0, list.size() - 1)) .limit(Math.max(0, list.size() - 1))
@ -136,7 +130,7 @@ public class FunNGenerator implements FunNUtilities{
} }
@Override @Override
public RefTypeOrTPHOrWildcardOrGeneric getReturnType(List<RefTypeOrTPHOrWildcardOrGeneric> list) { public TargetType getReturnType(List<TargetType> list) {
if(list.size() == 0) if(list.size() == 0)
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException();
return list.get(list.size() - 1); return list.get(list.size() - 1);

View File

@ -1,6 +1,6 @@
package de.dhbwstuttgart.bytecode.funN; package de.dhbwstuttgart.bytecode.funN;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.target.tree.type.TargetType;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
@ -11,13 +11,13 @@ public interface FunNUtilities {
byte[] generateSuperBytecode(int numberArguments); byte[] generateSuperBytecode(int numberArguments);
String getSuperClassName(int numberArguments); String getSuperClassName(int numberArguments);
byte[] generateSpecializedBytecode(List<RefTypeOrTPHOrWildcardOrGeneric> argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType); byte[] generateSpecializedBytecode(List<TargetType> argumentTypes, TargetType returnType);
String getSpecializedClassName(List<RefTypeOrTPHOrWildcardOrGeneric> argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType); String getSpecializedClassName(List<TargetType> argumentTypes, TargetType returnType);
String getSpecializedDescriptor(List<RefTypeOrTPHOrWildcardOrGeneric> argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType); String getSpecializedDescriptor(List<TargetType> argumentTypes, TargetType returnType);
String getSpecializedSignature(List<RefTypeOrTPHOrWildcardOrGeneric> argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType); String getSpecializedSignature(List<TargetType> argumentTypes, TargetType returnType);
List<RefTypeOrTPHOrWildcardOrGeneric> getArguments(List<RefTypeOrTPHOrWildcardOrGeneric> list); List<TargetType> getArguments(List<TargetType> list);
RefTypeOrTPHOrWildcardOrGeneric getReturnType(List<RefTypeOrTPHOrWildcardOrGeneric> list); TargetType getReturnType(List<TargetType> list);
@Deprecated @Deprecated
public static boolean writeClassFile(String className, byte[] bytecode, File directory) { public static boolean writeClassFile(String className, byte[] bytecode, File directory) {

View File

@ -676,7 +676,7 @@ public class ASTToTargetAST {
var params = refType.getParaList().stream().map(ASTToTargetAST.this::convert).toList(); var params = refType.getParaList().stream().map(ASTToTargetAST.this::convert).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 gen = FunNGenerator.getInstance(); var gen = FunNGenerator.getInstance();
var className = gen.getSpecializedClassName(gen.getArguments(refType.getParaList()), gen.getReturnType(refType.getParaList())); var className = gen.getSpecializedClassName(gen.getArguments(params), gen.getReturnType(params));
if (!usedFunNSuperTypes.contains(params.size())) { if (!usedFunNSuperTypes.contains(params.size())) {
usedFunNSuperTypes.add(params.size()); usedFunNSuperTypes.add(params.size());
var code = gen.generateSuperBytecode(params.size() - 1); var code = gen.generateSuperBytecode(params.size() - 1);
@ -685,7 +685,7 @@ public class ASTToTargetAST {
} }
if (!usedFunN.contains(className)) { if (!usedFunN.contains(className)) {
usedFunN.add(className); usedFunN.add(className);
var code = gen.generateSpecializedBytecode(gen.getArguments(refType.getParaList()), gen.getReturnType(refType.getParaList())); var code = gen.generateSpecializedBytecode(gen.getArguments(params), gen.getReturnType(params));
var clazz = classLoader.loadClass(code); var clazz = classLoader.loadClass(code);
auxiliaries.put(clazz.getName(), code); auxiliaries.put(clazz.getName(), code);
} }

View File

@ -22,15 +22,15 @@ public record TargetMethod(int access, String name, Set<TargetGeneric> generics,
public static String getSignature(Set<TargetGeneric> generics, List<MethodParameter> parameters, TargetType returnType) { public static String getSignature(Set<TargetGeneric> generics, List<MethodParameter> parameters, TargetType returnType) {
String ret = "<"; String ret = "<";
for (var generic : generics) { for (var generic : generics) {
ret += generic.name() + ":" + generic.bound().toGenericSignature(); ret += generic.name() + ":" + generic.bound().toDescriptor();
} }
ret += ">("; ret += ">(";
for (var param : parameters) { for (var param : parameters) {
ret += param.type().toGenericSignature(); ret += param.type().toDescriptor();
} }
ret += ")"; ret += ")";
if (returnType == null) ret += "V"; if (returnType == null) ret += "V";
else ret += returnType.toGenericSignature(); else ret += returnType.toDescriptor();
return ret; return ret;
} }

View File

@ -7,8 +7,8 @@ public record TargetExtendsWildcard(TargetType innerType) implements TargetType
} }
@Override @Override
public String toGenericSignature() { public String toDescriptor() {
return "+" + innerType.toGenericSignature(); return "+" + innerType.toDescriptor();
} }
@Override @Override

View File

@ -1,26 +1,16 @@
package de.dhbwstuttgart.target.tree.type; package de.dhbwstuttgart.target.tree.type;
import de.dhbwstuttgart.bytecode.funN.FunNGenerator;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public record TargetFunNType(int N, List<TargetType> params) implements TargetSpecializedType { public record TargetFunNType(int N, List<TargetType> params) implements TargetSpecializedType {
private static String nameDescriptor(TargetType type) {
if (type instanceof TargetGenericType) return "LTPH;";
return type.toSignature();
}
@Override @Override
public String getInternalName() { public String getInternalName() {
// TODO This is duplicate code from FunNGenerator, I think we should change it to accept TargetTypes and refactor. var gen = FunNGenerator.getInstance();
var returnType = params.get(params.size() - 1); return gen.getSpecializedClassName(gen.getArguments(params), gen.getReturnType(params));
var argumentTypes = params.subList(0, params.size() - 1);
return java.lang.String.format("Fun%d$$%s%s",
argumentTypes.size(),
argumentTypes.stream().map(TargetFunNType::nameDescriptor).collect(Collectors.joining()),
nameDescriptor(returnType))
.replace('/', '$')
.replace(";", "$_$");
} }
@Override @Override

View File

@ -7,7 +7,7 @@ public record TargetGenericType(String name) implements TargetType {
} }
@Override @Override
public String toGenericSignature() { public String toDescriptor() {
return "T" + getInternalName() + ";"; return "T" + getInternalName() + ";";
} }

View File

@ -8,7 +8,7 @@ public record TargetPrimitiveType(String name) implements TargetType {
} }
@Override @Override
public String toGenericSignature() { public String toDescriptor() {
return toSignature(); return toSignature();
} }

View File

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

View File

@ -7,8 +7,8 @@ public record TargetSuperWildcard(TargetType innerType) implements TargetType {
} }
@Override @Override
public String toGenericSignature() { public String toDescriptor() {
return "-" + innerType.toGenericSignature(); return "-" + innerType.toDescriptor();
} }
@Override @Override

View File

@ -53,7 +53,7 @@ public sealed interface TargetType
} }
String toSignature(); String toSignature();
String toGenericSignature(); String toDescriptor();
String getInternalName(); String getInternalName();
String name(); String name();
} }