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 de.dhbwstuttgart.syntaxtree.statement.LambdaExpression;
|
||||||
import org.objectweb.asm.ClassWriter;
|
import org.objectweb.asm.ClassWriter;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
import org.objectweb.asm.Opcodes;
|
|
||||||
import org.objectweb.asm.Type;
|
import org.objectweb.asm.Type;
|
||||||
import org.objectweb.asm.signature.SignatureVisitor;
|
import org.objectweb.asm.signature.SignatureVisitor;
|
||||||
import org.objectweb.asm.signature.SignatureWriter;
|
import org.objectweb.asm.signature.SignatureWriter;
|
||||||
@ -15,6 +14,7 @@ import org.objectweb.asm.signature.SignatureWriter;
|
|||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import static org.objectweb.asm.Opcodes.*;
|
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.
|
* 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<>();
|
private static HashSet<Integer> alreadyGeneratedFunN = new HashSet<>();
|
||||||
|
|
||||||
@ -48,53 +51,56 @@ public class ByteCodeForFunNGenerator {
|
|||||||
MethodVisitor mvApply = classWriter.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "apply", methDesc,
|
MethodVisitor mvApply = classWriter.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "apply", methDesc,
|
||||||
methSig.toString(), null);
|
methSig.toString(), null);
|
||||||
mvApply.visitEnd();
|
mvApply.visitEnd();
|
||||||
writeClassFile(classWriter.toByteArray(), name, path);
|
writeClassFile(name, classWriter.toByteArray(), path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void generateBCForFunN(ArgumentList argumentList, String methDesc, File path) {
|
public static void generateBCForFunN(ArgumentList argumentList, String methDesc, File path) {
|
||||||
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
|
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;
|
int numberOfParams = 0;
|
||||||
SignatureVisitor paramVisitor = methSig.visitParameterType();
|
SignatureVisitor paramVisitor = signatureWriter.visitParameterType();
|
||||||
Iterator<Expression> itr1 = argumentList.getArguments().iterator();
|
|
||||||
|
|
||||||
while(itr1.hasNext()) {
|
for (Expression argument:arguments) {
|
||||||
numberOfParams++;
|
paramVisitor.visitTypeVariable(CONSTANTS.T + ++numberOfParams);
|
||||||
// getBounds
|
|
||||||
paramVisitor.visitTypeVariable(CONSTANTS.T + numberOfParams);
|
|
||||||
itr1.next();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
methSig.visitReturnType().visitTypeVariable(CONSTANTS.R);
|
signatureWriter.visitReturnType().visitTypeVariable(CONSTANTS.R);
|
||||||
// ")"+lam.getReturn.getBounds
|
|
||||||
Signature sig = new Signature(numberOfParams);
|
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.$$;
|
String name = CONSTANTS.FUN + numberOfParams + CONSTANTS.$$;
|
||||||
classWriter.visit(V1_8, ACC_PUBLIC + ACC_INTERFACE + ACC_ABSTRACT, name, sig.toString(),
|
classWriter.visit(V1_8, ACC_PUBLIC + ACC_INTERFACE + ACC_ABSTRACT, name, sig.toString(), Type.getInternalName(Object.class), null);
|
||||||
Type.getInternalName(Object.class), null);
|
MethodVisitor mvApply = classWriter.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "apply", methDesc, signatureWriter.toString(), null);
|
||||||
MethodVisitor mvApply = classWriter.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "apply", methDesc,
|
|
||||||
methSig.toString(), null);
|
|
||||||
mvApply.visitEnd();
|
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.
|
* Fun<{@code numberOfParameters}>$$ if it doesn't exist already.
|
||||||
|
*
|
||||||
* @param numberOfParameters
|
* @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}.
|
* based on {@link #alreadyGeneratedFunN alreadyGeneratedFunN}.
|
||||||
|
*
|
||||||
* @since Studienarbeit Type Erase
|
* @since Studienarbeit Type Erase
|
||||||
* @author Etienne Zink
|
* @author Etienne Zink
|
||||||
*/
|
*/
|
||||||
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?
|
||||||
String funNName = String.format("Fun%d$$", numberOfParameters);
|
String className = String.format("Fun%d$$", numberOfParameters);
|
||||||
String classSignature = "<";
|
String classSignature = "<";
|
||||||
String methodSignature = "(";
|
String methodSignature = "(";
|
||||||
String methodDescriptor = "(";
|
String methodDescriptor = "(";
|
||||||
@ -108,38 +114,38 @@ public class ByteCodeForFunNGenerator {
|
|||||||
methodDescriptor += ")Ljava/lang/Object;";
|
methodDescriptor += ")Ljava/lang/Object;";
|
||||||
|
|
||||||
ClassWriter classWriter = new ClassWriter(0);
|
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 methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, "apply", methodDescriptor, methodSignature, null);
|
||||||
methodVisitor.visitEnd();
|
methodVisitor.visitEnd();
|
||||||
classWriter.visitEnd();
|
classWriter.visitEnd();
|
||||||
|
|
||||||
byte[] bytecode = classWriter.toByteArray();
|
byte[] bytecode = classWriter.toByteArray();
|
||||||
try (BufferedOutputStream writer = new BufferedOutputStream(new FileOutputStream(new File(path, funNName + ".class")))) {
|
if(writeClassFile(className, bytecode, path)) {
|
||||||
writer.write(bytecode);
|
|
||||||
writer.flush();
|
|
||||||
alreadyGeneratedFunN.add(numberOfParameters);
|
alreadyGeneratedFunN.add(numberOfParameters);
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
return alreadyGeneratedFunN.contains(numberOfParameters);
|
return alreadyGeneratedFunN.contains(numberOfParameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
public static void writeClassFile(byte[] bytecode, String name, File path) {
|
* Generates a {@code class-File} for the class {@code className} with the {@code bytecode}.
|
||||||
FileOutputStream output;
|
*
|
||||||
try {
|
* @param className of the class to generate
|
||||||
System.out.println("generating " + name + ".class file...");
|
* @param bytecode of the class
|
||||||
output = new FileOutputStream(
|
* @param directory where the class should be saved to
|
||||||
new File(path , name + CONSTANTS.EXTENSIONCLASS));
|
* @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.write(bytecode);
|
||||||
output.close();
|
output.flush();
|
||||||
System.out.println(name + ".class file generated");
|
return true;
|
||||||
} catch (FileNotFoundException e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user