Refactoring der writeClassFile-Methode in ByteCodeForFunNGenerator.
This commit is contained in:
parent
c613ed7e12
commit
59d50bd2c6
@ -7,7 +7,6 @@ import de.dhbwstuttgart.syntaxtree.statement.Expression;
|
||||
import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.signature.SignatureVisitor;
|
||||
import org.objectweb.asm.signature.SignatureWriter;
|
||||
@ -15,6 +14,7 @@ import org.objectweb.asm.signature.SignatureWriter;
|
||||
import java.io.*;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import static org.objectweb.asm.Opcodes.*;
|
||||
|
||||
@ -22,6 +22,9 @@ public class ByteCodeForFunNGenerator {
|
||||
|
||||
/**
|
||||
* HashSet which contains the parameter number for which already a FunN$$ interface was generated.
|
||||
*
|
||||
* @since Studienarbeit Type Erasure
|
||||
* @author Etienne Zink
|
||||
*/
|
||||
private static HashSet<Integer> alreadyGeneratedFunN = new HashSet<>();
|
||||
|
||||
@ -48,53 +51,56 @@ public class ByteCodeForFunNGenerator {
|
||||
MethodVisitor mvApply = classWriter.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "apply", methDesc,
|
||||
methSig.toString(), null);
|
||||
mvApply.visitEnd();
|
||||
writeClassFile(classWriter.toByteArray(), name, 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);
|
||||
List<Expression> arguments = argumentList.getArguments();
|
||||
/* //ToDo neu machen
|
||||
int numberOfParams = arguments.size();
|
||||
//ToDo Classname anpassen
|
||||
String className = CONSTANTS.FUN + numberOfParams + CONSTANTS.$$;
|
||||
|
||||
SignatureWriter methSig = new SignatureWriter();
|
||||
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 = methSig.visitParameterType();
|
||||
Iterator<Expression> itr1 = argumentList.getArguments().iterator();
|
||||
SignatureVisitor paramVisitor = signatureWriter.visitParameterType();
|
||||
|
||||
while(itr1.hasNext()) {
|
||||
numberOfParams++;
|
||||
// getBounds
|
||||
paramVisitor.visitTypeVariable(CONSTANTS.T + numberOfParams);
|
||||
itr1.next();
|
||||
for (Expression argument:arguments) {
|
||||
paramVisitor.visitTypeVariable(CONSTANTS.T + ++numberOfParams);
|
||||
}
|
||||
|
||||
methSig.visitReturnType().visitTypeVariable(CONSTANTS.R);
|
||||
// ")"+lam.getReturn.getBounds
|
||||
signatureWriter.visitReturnType().visitTypeVariable(CONSTANTS.R);
|
||||
Signature sig = new Signature(numberOfParams);
|
||||
//ToDo Name anpassen und Signatur?
|
||||
//ToDo super anpassen
|
||||
//ToDo extends FunN$$ einfügen und Parameter dazu
|
||||
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,
|
||||
methSig.toString(), null);
|
||||
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(classWriter.toByteArray(), name, path);
|
||||
writeClassFile(name, classWriter.toByteArray(), path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function which generates a {@code .class-File} for the super interface
|
||||
* Function which generates a {@code class-File} for the super interface
|
||||
* Fun<{@code numberOfParameters}>$$ if it doesn't exist already.
|
||||
*
|
||||
* @param numberOfParameters
|
||||
* @return {@code true}, iff the {@code .class-File} exists after this method invocation
|
||||
* @return {@code true}, iff the {@code class-File} exists after this method invocation
|
||||
* based on {@link #alreadyGeneratedFunN alreadyGeneratedFunN}.
|
||||
*
|
||||
* @since Studienarbeit Type Erase
|
||||
* @author Etienne Zink
|
||||
*/
|
||||
public static boolean generateSuperFunNInterface(int numberOfParameters, File path){
|
||||
if(alreadyGeneratedFunN.contains(numberOfParameters)) return true;
|
||||
|
||||
String funNName = String.format("Fun%d$$", numberOfParameters);
|
||||
//ToDo Etienne: Generierung der Signaturen/Deskriptoren vielleicht auslagern?
|
||||
String className = String.format("Fun%d$$", numberOfParameters);
|
||||
String classSignature = "<";
|
||||
String methodSignature = "(";
|
||||
String methodDescriptor = "(";
|
||||
@ -108,38 +114,38 @@ public class ByteCodeForFunNGenerator {
|
||||
methodDescriptor += ")Ljava/lang/Object;";
|
||||
|
||||
ClassWriter classWriter = new ClassWriter(0);
|
||||
classWriter.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, funNName, classSignature, "java/lang/Object", null);
|
||||
classWriter.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, className, classSignature, "java/lang/Object", null);
|
||||
|
||||
MethodVisitor methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, "apply", methodDescriptor, methodSignature, null);
|
||||
methodVisitor.visitEnd();
|
||||
classWriter.visitEnd();
|
||||
|
||||
byte[] bytecode = classWriter.toByteArray();
|
||||
try (BufferedOutputStream writer = new BufferedOutputStream(new FileOutputStream(new File(path, funNName + ".class")))) {
|
||||
writer.write(bytecode);
|
||||
writer.flush();
|
||||
if(writeClassFile(className, bytecode, path)) {
|
||||
alreadyGeneratedFunN.add(numberOfParameters);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return alreadyGeneratedFunN.contains(numberOfParameters);
|
||||
}
|
||||
|
||||
|
||||
public static void writeClassFile(byte[] bytecode, String name, File path) {
|
||||
FileOutputStream output;
|
||||
try {
|
||||
System.out.println("generating " + name + ".class file...");
|
||||
output = new FileOutputStream(
|
||||
new File(path , name + CONSTANTS.EXTENSIONCLASS));
|
||||
/**
|
||||
* Generates a {@code class-File} for the class {@code className} with the {@code bytecode}.
|
||||
*
|
||||
* @param className of the class to generate
|
||||
* @param bytecode of the class
|
||||
* @param directory where the class should be saved to
|
||||
* @return {@code true}, iff the {@code class-File} could be generated.
|
||||
*
|
||||
* @since Studienarbeit Type Erasure
|
||||
* @author Etienne Zink
|
||||
*/
|
||||
private static boolean writeClassFile(String className, byte[] bytecode, File directory) {
|
||||
try (FileOutputStream output = new FileOutputStream(new File(directory , className + CONSTANTS.EXTENSIONCLASS))){
|
||||
output.write(bytecode);
|
||||
output.close();
|
||||
System.out.println(name + ".class file generated");
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
output.flush();
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user