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) {
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) {
@ -1018,10 +1018,10 @@ public class Codegen {
private static String generateSignature(TargetClass clazz) {
String ret = "<";
for (var generic : clazz.generics()) {
ret += generic.name() + ":" + generic.bound().toGenericSignature();
ret += generic.name() + ":" + generic.bound().toDescriptor();
}
ret += ">";
ret += clazz.superType().toGenericSignature();
ret += clazz.superType().toDescriptor();
return ret;
}

View File

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

View File

@ -1,6 +1,6 @@
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.FileOutputStream;
@ -11,13 +11,13 @@ public interface FunNUtilities {
byte[] generateSuperBytecode(int numberArguments);
String getSuperClassName(int numberArguments);
byte[] generateSpecializedBytecode(List<RefTypeOrTPHOrWildcardOrGeneric> argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType);
String getSpecializedClassName(List<RefTypeOrTPHOrWildcardOrGeneric> argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType);
String getSpecializedDescriptor(List<RefTypeOrTPHOrWildcardOrGeneric> argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType);
String getSpecializedSignature(List<RefTypeOrTPHOrWildcardOrGeneric> argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType);
byte[] generateSpecializedBytecode(List<TargetType> argumentTypes, TargetType returnType);
String getSpecializedClassName(List<TargetType> argumentTypes, TargetType returnType);
String getSpecializedDescriptor(List<TargetType> argumentTypes, TargetType returnType);
String getSpecializedSignature(List<TargetType> argumentTypes, TargetType returnType);
List<RefTypeOrTPHOrWildcardOrGeneric> getArguments(List<RefTypeOrTPHOrWildcardOrGeneric> list);
RefTypeOrTPHOrWildcardOrGeneric getReturnType(List<RefTypeOrTPHOrWildcardOrGeneric> list);
List<TargetType> getArguments(List<TargetType> list);
TargetType getReturnType(List<TargetType> list);
@Deprecated
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();
if (name.matches("Fun\\d+\\$\\$")) { // TODO This seems like a bad idea
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())) {
usedFunNSuperTypes.add(params.size());
var code = gen.generateSuperBytecode(params.size() - 1);
@ -685,7 +685,7 @@ public class ASTToTargetAST {
}
if (!usedFunN.contains(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);
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) {
String ret = "<";
for (var generic : generics) {
ret += generic.name() + ":" + generic.bound().toGenericSignature();
ret += generic.name() + ":" + generic.bound().toDescriptor();
}
ret += ">(";
for (var param : parameters) {
ret += param.type().toGenericSignature();
ret += param.type().toDescriptor();
}
ret += ")";
if (returnType == null) ret += "V";
else ret += returnType.toGenericSignature();
else ret += returnType.toDescriptor();
return ret;
}

View File

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

View File

@ -1,26 +1,16 @@
package de.dhbwstuttgart.target.tree.type;
import de.dhbwstuttgart.bytecode.funN.FunNGenerator;
import java.util.List;
import java.util.stream.Collectors;
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
public String getInternalName() {
// TODO This is duplicate code from FunNGenerator, I think we should change it to accept TargetTypes and refactor.
var returnType = params.get(params.size() - 1);
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(";", "$_$");
var gen = FunNGenerator.getInstance();
return gen.getSpecializedClassName(gen.getArguments(params), gen.getReturnType(params));
}
@Override

View File

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

View File

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

View File

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

View File

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

View File

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