Erstellung echter Funktionstypen hinzugefügt.

Rückgabetypen dieser werden nicht korrekt aufgelöst.
Dies muss geändert werden.
Deskriptoren nicht angepasst.
Da Basis-Interface FunN$$ mit erstellt wird, sind Tests noch korrekt.
This commit is contained in:
Etienne Zink 2022-03-17 12:00:23 +01:00
parent 65448c3bf3
commit c7c50f4669
5 changed files with 82 additions and 32 deletions

View File

@ -770,6 +770,7 @@ public class BytecodeGenMethod implements StatementVisitor {
// This will be used if the class is not standard class (not in API)
ClassLoader cLoader2;
//ToDo methodCallType wird nicht korrekt resolved, da kein Constraint vorhanden ist
String methCallType = resultSet.resolveType(methodCall.getType()).resolvedType.acceptTV(new TypeToDescriptor());
String[] typesOfParams = getTypes(methodCall.arglist.getArguments());
try {
@ -817,9 +818,10 @@ public class BytecodeGenMethod implements StatementVisitor {
//ToDo Etienne: Für Type Erasure wichtig?!
} else if(!helper.isInCurrPkg(clazz)){
if(clazz.contains(CONSTANTS.$$)) {
//ToDo Methoden Deskriptor neu setzen
//ToDo Receiver neu setzen?!
mDesc = helper.getDescriptorOfApplyMethod(methCallType);
helper.generateBCForFunN(mDesc);
// mDesc = helper.generateBCForFunN(methCallType,typesOfParams);
helper.generateBCForFunN(typesOfParams, methCallType);
}else {
try {
cLoader2 = new DirectoryClassLoader(path, classLoader);

View File

@ -99,4 +99,34 @@ public class TypeToSignature implements TypeVisitor<String> {
.filter(c -> c.getConstraint().getLeft().equals(tph) || c.getEqualsTPHs().contains(tph))
.findFirst();
}
/**
* //ToDo beschreiben
*
* @param type
* @return
*
* @since Studienarbeit Type Erasure
* @author Etienne Zink
*/
public String visit(RefTypeOrTPHOrWildcardOrGeneric type){
String returnString = "";
if (type instanceof GenericRefType){
GenericRefType genericRefType = (GenericRefType) type;
returnString += visit(genericRefType);
} else if (type instanceof RefType){
RefType refType = (RefType) type;
returnString += visit(refType);
} else if (type instanceof TypePlaceholder){
TypePlaceholder typePlaceholder = (TypePlaceholder) type;
returnString += visit(typePlaceholder);
} else if (type instanceof SuperWildcardType){
SuperWildcardType superWildcardType = (SuperWildcardType) type;
returnString += visit(superWildcardType);
} else if (type instanceof ExtendsWildcardType) {
ExtendsWildcardType extendsWildcardType = (ExtendsWildcardType) type;
returnString += visit(extendsWildcardType);
}
return returnString;
}
}

View File

@ -1,10 +1,12 @@
package de.dhbwstuttgart.bytecode.utilities;
import de.dhbwstuttgart.bytecode.signature.Signature;
import de.dhbwstuttgart.bytecode.signature.TypeToSignature;
import de.dhbwstuttgart.syntaxtree.FormalParameter;
import de.dhbwstuttgart.syntaxtree.statement.ArgumentList;
import de.dhbwstuttgart.syntaxtree.statement.Expression;
import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression;
import de.dhbwstuttgart.syntaxtree.type.*;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;
@ -12,9 +14,11 @@ import org.objectweb.asm.signature.SignatureVisitor;
import org.objectweb.asm.signature.SignatureWriter;
import java.io.*;
import java.sql.Ref;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;
import static org.objectweb.asm.Opcodes.*;
@ -55,36 +59,39 @@ public class ByteCodeForFunNGenerator {
writeClassFile(name, classWriter.toByteArray(), path);
}
public static void generateBCForFunN(ArgumentList argumentList, String methDesc, File path) {
/**
* //ToDo beschreiben
*
* @param typesOfFormalParameters
* @param returnType
* @param path
*
* @since Studienarbeit Type Erasure
* @author Etienne Zink
*/
public static void generateBCForFunN(String[] typesOfFormalParameters, String returnType, File path) {
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
List<Expression> arguments = argumentList.getArguments();
int numberOfParameters = typesOfFormalParameters.length;
generateSuperFunNInterface(numberOfParameters, path);
/* //ToDo neu machen
int numberOfParams = arguments.size();
//ToDo Classname anpassen
String className = CONSTANTS.FUN + numberOfParams + CONSTANTS.$$;
String className = getBaseFunClassname(numberOfParameters);
String classSignature = String.format("L%s;L%s<", Type.getInternalName(Object.class), className);
Signature sig = new Signature(numberOfParams);
classWriter.visit(V1_8, ACC_PUBLIC | ACC_INTERFACE | ACC_ABSTRACT, className, sig.toString(),
Type.getInternalName(Object.class), new String[]{String.format("Fun%d$$", numberOfParams)});
writeClassFile(className, classWriter.toByteArray(), path);
*/
SignatureWriter signatureWriter = new SignatureWriter();
int numberOfParams = 0;
SignatureVisitor paramVisitor = signatureWriter.visitParameterType();
for (Expression argument:arguments) {
paramVisitor.visitTypeVariable(CONSTANTS.T + ++numberOfParams);
//ToDo testen ob der Klassenname und -signatur so passt
for (String typeOfFormalParameter: typesOfFormalParameters) {
className += String.format("%s$_$", typeOfFormalParameter);
classSignature += String.format("L%s;", typeOfFormalParameter);
}
className += returnType;
className = className.replace('/', '$');
classSignature += String.format("L%s>;", returnType);
signatureWriter.visitReturnType().visitTypeVariable(CONSTANTS.R);
Signature sig = new Signature(numberOfParams);
String name = CONSTANTS.FUN + numberOfParams + CONSTANTS.$$;
classWriter.visit(V1_8, ACC_PUBLIC + ACC_INTERFACE + ACC_ABSTRACT, name, sig.toString(), Type.getInternalName(Object.class), null);
MethodVisitor mvApply = classWriter.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "apply", methDesc, signatureWriter.toString(), null);
mvApply.visitEnd();
writeClassFile(name, classWriter.toByteArray(), path);
System.out.println("Generated className: " + className);
System.out.println("Generated signature: " + classSignature);
classWriter.visit(V1_8, ACC_PUBLIC | ACC_INTERFACE | ACC_ABSTRACT, className, classSignature,
Type.getInternalName(Object.class), new String[]{getBaseFunClassname(numberOfParameters)});
writeClassFile(className, classWriter.toByteArray(), path);
}
/**
@ -101,7 +108,7 @@ public class ByteCodeForFunNGenerator {
public static boolean generateSuperFunNInterface(int numberOfParameters, File path){
if(alreadyGeneratedFunN.contains(numberOfParameters)) return true;
//ToDo Etienne: Generierung der Signaturen/Deskriptoren vielleicht auslagern? Bzw. schauen ob nicht schon vorhanden und anpassen!
String className = String.format("Fun%d$$", numberOfParameters);
String className = getBaseFunClassname(numberOfParameters);
String classSignature = "<";
String methodSignature = "(";
String methodDescriptor = "(";
@ -128,6 +135,18 @@ public class ByteCodeForFunNGenerator {
return alreadyGeneratedFunN.contains(numberOfParameters);
}
/**
*
* @param countParameters
* @return the String of the super Fun$$ type
*
* @since Studienarbeit Type Erasure
* @author Etienne Zink
*/
private static String getBaseFunClassname(int countParameters){
return String.format("Fun%d$$", countParameters);
}
/**
* Generates a {@code class-File} for the class {@code className} with the {@code bytecode}.
*

View File

@ -221,8 +221,9 @@ public class MethodCallHelper {
}
//ToDo Etienne: Für Type Erasure wichtig?!
public void generateBCForFunN(String methodDescriptor) {
ByteCodeForFunNGenerator.generateBCForFunN(methCall.arglist,methodDescriptor,path);
public void generateBCForFunN(String[] typesOfFormalParams, String receiverType) {
//ToDo return Descriptor auf apply Methode?
ByteCodeForFunNGenerator.generateBCForFunN(typesOfFormalParams, receiverType,path);
}
//ToDo Etienne: Für Type Erasure wichtig

View File

@ -64,6 +64,4 @@ public class OLFunTest {
public static void cleanUp(){
TestCleanUp.cleanUpDirectory(new File(generatedByteCodeDirectory), f -> f.getName().contains(".class"));
}
public static Integer apply(Integer x) {return x;}
}