Implementierung von getBytecode() in FunN und Hinzufügen entsprechender Tests.

This commit is contained in:
Etienne Zink 2022-03-21 11:29:37 +01:00
parent 918a2cc04d
commit 6381d09174
2 changed files with 66 additions and 11 deletions

View File

@ -1,6 +1,7 @@
package de.dhbwstuttgart.intermediate.generation;
import de.dhbwstuttgart.intermediate.types.IntermediateGenericType;
import de.dhbwstuttgart.intermediate.types.IntermediateInnerType;
import de.dhbwstuttgart.intermediate.types.IntermediateRefType;
import de.dhbwstuttgart.intermediate.types.IntermediateType;
import de.dhbwstuttgart.parser.scope.JavaClassName;
@ -24,10 +25,18 @@ import static org.objectweb.asm.Opcodes.*;
*/
public final class FunN extends IntermediateRefType {
private final String superFunNName;
private final String argumentGenericBase = "T";
private final String returnGeneric = "R";
private final String methodName = "apply";
private final int bytecodeVersion = V1_8;
private final String objectSuperType = Type.getInternalName(Object.class).replace('.','/');
private final String objectSignature = new IntermediateRefType(new JavaClassName(Type.getInternalName(Object.class))).getSignature();
/**
* Represents the super interface of this specialized function.
*/
private final IntermediateRefType superFunN;
/**
* Caches the superBytecode after first computation.
@ -39,9 +48,10 @@ public final class FunN extends IntermediateRefType {
*/
private byte[] bytecode;
public FunN(IntermediateType returnType){ this(Collections.emptyList(), returnType); }
public FunN(IntermediateInnerType returnType){ this(Collections.emptyList(), returnType); }
public FunN(List<IntermediateType> typArguments, IntermediateType returnType) {
public FunN(List<IntermediateInnerType> typArguments, IntermediateInnerType returnType) {
//using stream-API for single line processing of relevant data in the super()-call
super(new JavaClassName(
String.format("Fun%d$$%s%s",
typArguments.size(),
@ -53,7 +63,8 @@ public final class FunN extends IntermediateRefType {
.replace('/', '$')
.replace(";", "$_$")),
Stream.concat(typArguments.stream(), Stream.of(returnType)).collect(Collectors.toList()));
superFunNName = String.format("Fun%d$$", typArguments.size());
superFunN = new IntermediateRefType(new JavaClassName(String.format("Fun%d$$", typArguments.size())),
Stream.concat(typArguments.stream(), Stream.of(returnType)).collect(Collectors.toList()));
}
/**
@ -62,9 +73,6 @@ public final class FunN extends IntermediateRefType {
public byte[] getSuperBytecode(){
byte[] superBytecode = this.superBytecode;
if (superBytecode == null){
String superType = Type.getInternalName(Object.class).replace('.','/');
String objectSignature = new IntermediateRefType(new JavaClassName(Type.getInternalName(Object.class))).getSignature();
String superFunNClassSignature = "<";
String superFunNMethodSignature = "(";
String superFunNMethodDescriptor = "(";
@ -81,7 +89,7 @@ public final class FunN extends IntermediateRefType {
ClassWriter classWriter = new ClassWriter(0);
MethodVisitor methodVisitor;
classWriter.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, superFunNName, superFunNClassSignature, superType, null);
classWriter.visit(bytecodeVersion, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, superFunN.getClassName(), superFunNClassSignature, objectSuperType, null);
methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, methodName, superFunNMethodDescriptor, superFunNMethodSignature , null);
methodVisitor.visitEnd();
classWriter.visitEnd();
@ -99,7 +107,26 @@ public final class FunN extends IntermediateRefType {
public byte[] getBytecode(){
byte[] bytecode = this.bytecode;
if (bytecode == null){
//ToDo
String funNClassSignature = objectSignature + superFunN.getSignature();
boolean containsGeneric = false;
String genericSignature = "<";
for (int currentTypArgumentIndex = 0; currentTypArgumentIndex < getTypArgumentSize(); currentTypArgumentIndex++) {
IntermediateType typArgument = getTypArgument(currentTypArgumentIndex);
if (typArgument == null) continue;
if (typArgument instanceof IntermediateGenericType){
IntermediateGenericType generic = (IntermediateGenericType) typArgument;
genericSignature += String.format("%s:%s", generic.getGenericName(), generic.getDescriptor());
containsGeneric = true;
}
}
genericSignature += ">";
if (containsGeneric) funNClassSignature = genericSignature + funNClassSignature;
ClassWriter classWriter = new ClassWriter(0);
classWriter.visit(bytecodeVersion, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, getClassName(), funNClassSignature, objectSuperType, new String[]{superFunN.getClassName()});
classWriter.visitEnd();
bytecode = classWriter.toByteArray();
this.bytecode = bytecode;
}
return bytecode;

View File

@ -26,8 +26,6 @@ public class FunNTest {
private static FunN fun2IntIntString;
//ToDo mehr Tests und Bytecode Tests
@BeforeClass
public static void SetUp(){
IntermediateRefType integer = new IntermediateRefType(new JavaClassName(Type.getInternalName(Integer.class)));
@ -51,12 +49,21 @@ public class FunNTest {
@Test
public void BytecodeTest_Super0(){ assertArrayEquals(generatedASMFun0(), fun0T.getSuperBytecode()) ;}
@Test
public void BytecodeTest_Fun0T(){ assertArrayEquals(generatedASMFun0T(), fun0T.getBytecode()) ;}
@Test
public void BytecodeTest_Super1(){ assertArrayEquals(generatedASMFun1(), fun1IntInt.getSuperBytecode()) ;}
@Test
public void BytecodeTest_Fun1IntInt(){ assertArrayEquals(generatedASMFun1IntInt(), fun1IntInt.getBytecode()) ;}
@Test
public void BytecodeTest_Super2(){ assertArrayEquals(generatedASMFun2(), fun2IntIntString.getSuperBytecode()) ;}
@Test
public void BytecodeTest_Fun2IntIntString(){ assertArrayEquals(generatedASMFun2IntIntString(), fun2IntIntString.getBytecode()) ;}
private byte[] generatedASMFun0() {
ClassWriter classWriter = new ClassWriter(0);
MethodVisitor methodVisitor;
@ -67,6 +74,13 @@ public class FunNTest {
return classWriter.toByteArray();
}
private byte[] generatedASMFun0T() {
ClassWriter classWriter = new ClassWriter(0);
classWriter.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, "Fun0$$TT$_$", "<T:Ljava/lang/Object;>Ljava/lang/Object;LFun0$$<TT;>;", "java/lang/Object", new String[]{"Fun0$$"});
classWriter.visitEnd();
return classWriter.toByteArray();
}
private byte[] generatedASMFun1() {
ClassWriter classWriter = new ClassWriter(0);
MethodVisitor methodVisitor;
@ -77,6 +91,13 @@ public class FunNTest {
return classWriter.toByteArray();
}
private byte[] generatedASMFun1IntInt() {
ClassWriter classWriter = new ClassWriter(0);
classWriter.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, "Fun1$$Ljava$lang$Integer$_$Ljava$lang$Integer$_$", "Ljava/lang/Object;LFun1$$<Ljava/lang/Integer;Ljava/lang/Integer;>;", "java/lang/Object", new String[]{"Fun1$$"});
classWriter.visitEnd();
return classWriter.toByteArray();
}
private byte[] generatedASMFun2() {
ClassWriter classWriter = new ClassWriter(0);
MethodVisitor methodVisitor;
@ -86,4 +107,11 @@ public class FunNTest {
classWriter.visitEnd();
return classWriter.toByteArray();
}
private byte[] generatedASMFun2IntIntString() {
ClassWriter classWriter = new ClassWriter(0);
classWriter.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, "Fun2$$Ljava$lang$Integer$_$Ljava$lang$Integer$_$Ljava$lang$String$_$", "Ljava/lang/Object;LFun2$$<Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/String;>;", "java/lang/Object", new String[]{"Fun2$$"});
classWriter.visitEnd();
return classWriter.toByteArray();
}
}