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) // This will be used if the class is not standard class (not in API)
ClassLoader cLoader2; ClassLoader cLoader2;
//ToDo methodCallType wird nicht korrekt resolved, da kein Constraint vorhanden ist
String methCallType = resultSet.resolveType(methodCall.getType()).resolvedType.acceptTV(new TypeToDescriptor()); String methCallType = resultSet.resolveType(methodCall.getType()).resolvedType.acceptTV(new TypeToDescriptor());
String[] typesOfParams = getTypes(methodCall.arglist.getArguments()); String[] typesOfParams = getTypes(methodCall.arglist.getArguments());
try { try {
@ -817,9 +818,10 @@ public class BytecodeGenMethod implements StatementVisitor {
//ToDo Etienne: Für Type Erasure wichtig?! //ToDo Etienne: Für Type Erasure wichtig?!
} else if(!helper.isInCurrPkg(clazz)){ } else if(!helper.isInCurrPkg(clazz)){
if(clazz.contains(CONSTANTS.$$)) { if(clazz.contains(CONSTANTS.$$)) {
//ToDo Methoden Deskriptor neu setzen
//ToDo Receiver neu setzen?!
mDesc = helper.getDescriptorOfApplyMethod(methCallType); mDesc = helper.getDescriptorOfApplyMethod(methCallType);
helper.generateBCForFunN(mDesc); helper.generateBCForFunN(typesOfParams, methCallType);
// mDesc = helper.generateBCForFunN(methCallType,typesOfParams);
}else { }else {
try { try {
cLoader2 = new DirectoryClassLoader(path, classLoader); 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)) .filter(c -> c.getConstraint().getLeft().equals(tph) || c.getEqualsTPHs().contains(tph))
.findFirst(); .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; package de.dhbwstuttgart.bytecode.utilities;
import de.dhbwstuttgart.bytecode.signature.Signature; import de.dhbwstuttgart.bytecode.signature.Signature;
import de.dhbwstuttgart.bytecode.signature.TypeToSignature;
import de.dhbwstuttgart.syntaxtree.FormalParameter; import de.dhbwstuttgart.syntaxtree.FormalParameter;
import de.dhbwstuttgart.syntaxtree.statement.ArgumentList; import de.dhbwstuttgart.syntaxtree.statement.ArgumentList;
import de.dhbwstuttgart.syntaxtree.statement.Expression; import de.dhbwstuttgart.syntaxtree.statement.Expression;
import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression; import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression;
import de.dhbwstuttgart.syntaxtree.type.*;
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;
@ -12,9 +14,11 @@ import org.objectweb.asm.signature.SignatureVisitor;
import org.objectweb.asm.signature.SignatureWriter; import org.objectweb.asm.signature.SignatureWriter;
import java.io.*; import java.io.*;
import java.sql.Ref;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import static org.objectweb.asm.Opcodes.*; import static org.objectweb.asm.Opcodes.*;
@ -55,36 +59,39 @@ public class ByteCodeForFunNGenerator {
writeClassFile(name, classWriter.toByteArray(), path); writeClassFile(name, classWriter.toByteArray(), path);
} }
public static void generateBCForFunN(ArgumentList argumentList, String methDesc, File path) { /**
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); * //ToDo beschreiben
List<Expression> arguments = argumentList.getArguments(); *
* @param typesOfFormalParameters
/* //ToDo neu machen * @param returnType
int numberOfParams = arguments.size(); * @param path
//ToDo Classname anpassen *
String className = CONSTANTS.FUN + numberOfParams + CONSTANTS.$$; * @since Studienarbeit Type Erasure
* @author Etienne Zink
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);
*/ */
public static void generateBCForFunN(String[] typesOfFormalParameters, String returnType, File path) {
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
int numberOfParameters = typesOfFormalParameters.length;
generateSuperFunNInterface(numberOfParameters, path);
SignatureWriter signatureWriter = new SignatureWriter(); String className = getBaseFunClassname(numberOfParameters);
int numberOfParams = 0; String classSignature = String.format("L%s;L%s<", Type.getInternalName(Object.class), className);
SignatureVisitor paramVisitor = signatureWriter.visitParameterType();
for (Expression argument:arguments) { //ToDo testen ob der Klassenname und -signatur so passt
paramVisitor.visitTypeVariable(CONSTANTS.T + ++numberOfParams); 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); System.out.println("Generated className: " + className);
Signature sig = new Signature(numberOfParams); System.out.println("Generated signature: " + classSignature);
String name = CONSTANTS.FUN + numberOfParams + CONSTANTS.$$;
classWriter.visit(V1_8, ACC_PUBLIC + ACC_INTERFACE + ACC_ABSTRACT, name, sig.toString(), Type.getInternalName(Object.class), null); classWriter.visit(V1_8, ACC_PUBLIC | ACC_INTERFACE | ACC_ABSTRACT, className, classSignature,
MethodVisitor mvApply = classWriter.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "apply", methDesc, signatureWriter.toString(), null); Type.getInternalName(Object.class), new String[]{getBaseFunClassname(numberOfParameters)});
mvApply.visitEnd(); writeClassFile(className, classWriter.toByteArray(), path);
writeClassFile(name, classWriter.toByteArray(), path);
} }
/** /**
@ -101,7 +108,7 @@ public class ByteCodeForFunNGenerator {
public static boolean generateSuperFunNInterface(int numberOfParameters, File path){ public static boolean generateSuperFunNInterface(int numberOfParameters, File path){
if(alreadyGeneratedFunN.contains(numberOfParameters)) return true; if(alreadyGeneratedFunN.contains(numberOfParameters)) return true;
//ToDo Etienne: Generierung der Signaturen/Deskriptoren vielleicht auslagern? Bzw. schauen ob nicht schon vorhanden und anpassen! //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 classSignature = "<";
String methodSignature = "("; String methodSignature = "(";
String methodDescriptor = "("; String methodDescriptor = "(";
@ -128,6 +135,18 @@ public class ByteCodeForFunNGenerator {
return alreadyGeneratedFunN.contains(numberOfParameters); 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}. * 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?! //ToDo Etienne: Für Type Erasure wichtig?!
public void generateBCForFunN(String methodDescriptor) { public void generateBCForFunN(String[] typesOfFormalParams, String receiverType) {
ByteCodeForFunNGenerator.generateBCForFunN(methCall.arglist,methodDescriptor,path); //ToDo return Descriptor auf apply Methode?
ByteCodeForFunNGenerator.generateBCForFunN(typesOfFormalParams, receiverType,path);
} }
//ToDo Etienne: Für Type Erasure wichtig //ToDo Etienne: Für Type Erasure wichtig

View File

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