Rework FunNGenerator to use target types
This commit is contained in:
parent
9d942a7014
commit
15e94111d4
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -7,7 +7,7 @@ public record TargetGenericType(String name) implements TargetType {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toGenericSignature() {
|
||||
public String toDescriptor() {
|
||||
return "T" + getInternalName() + ";";
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@ public record TargetPrimitiveType(String name) implements TargetType {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toGenericSignature() {
|
||||
public String toDescriptor() {
|
||||
return toSignature();
|
||||
}
|
||||
|
||||
|
@ -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 += ">";
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -53,7 +53,7 @@ public sealed interface TargetType
|
||||
}
|
||||
|
||||
String toSignature();
|
||||
String toGenericSignature();
|
||||
String toDescriptor();
|
||||
String getInternalName();
|
||||
String name();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user