forked from JavaTX/JavaCompilerCore
Implementierung in FunN von getSuperBytecode() und Hinzufügen entsprechender Test.
Umbenennung in IntermediateRefType: getTypParameter() -> getTypArgument() und getTypParameterSize() -> getTypArgumentSize().
This commit is contained in:
parent
ac1e0340c3
commit
918a2cc04d
@ -1,13 +1,20 @@
|
|||||||
package de.dhbwstuttgart.intermediate.generation;
|
package de.dhbwstuttgart.intermediate.generation;
|
||||||
|
|
||||||
|
import de.dhbwstuttgart.intermediate.types.IntermediateGenericType;
|
||||||
import de.dhbwstuttgart.intermediate.types.IntermediateRefType;
|
import de.dhbwstuttgart.intermediate.types.IntermediateRefType;
|
||||||
import de.dhbwstuttgart.intermediate.types.IntermediateType;
|
import de.dhbwstuttgart.intermediate.types.IntermediateType;
|
||||||
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||||
|
import org.objectweb.asm.ClassWriter;
|
||||||
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
import org.objectweb.asm.Type;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import static org.objectweb.asm.Opcodes.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class which represents a function type.
|
* Class which represents a function type.
|
||||||
* Offers different methods to generate or interact with this real function type.
|
* Offers different methods to generate or interact with this real function type.
|
||||||
@ -17,16 +24,23 @@ import java.util.stream.Stream;
|
|||||||
*/
|
*/
|
||||||
public final class FunN extends IntermediateRefType {
|
public final class FunN extends IntermediateRefType {
|
||||||
|
|
||||||
/**
|
private final String superFunNName;
|
||||||
* Caches the bytecode after first computation.
|
private final String argumentGenericBase = "T";
|
||||||
*/
|
private final String returnGeneric = "R";
|
||||||
private byte[] bytecode;
|
private final String methodName = "apply";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Caches the superBytecode after first computation.
|
* Caches the superBytecode after first computation.
|
||||||
*/
|
*/
|
||||||
private byte[] superBytecode;
|
private byte[] superBytecode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Caches the bytecode after first computation.
|
||||||
|
*/
|
||||||
|
private byte[] bytecode;
|
||||||
|
|
||||||
|
public FunN(IntermediateType returnType){ this(Collections.emptyList(), returnType); }
|
||||||
|
|
||||||
public FunN(List<IntermediateType> typArguments, IntermediateType returnType) {
|
public FunN(List<IntermediateType> typArguments, IntermediateType returnType) {
|
||||||
super(new JavaClassName(
|
super(new JavaClassName(
|
||||||
String.format("Fun%d$$%s%s",
|
String.format("Fun%d$$%s%s",
|
||||||
@ -39,6 +53,7 @@ public final class FunN extends IntermediateRefType {
|
|||||||
.replace('/', '$')
|
.replace('/', '$')
|
||||||
.replace(";", "$_$")),
|
.replace(";", "$_$")),
|
||||||
Stream.concat(typArguments.stream(), Stream.of(returnType)).collect(Collectors.toList()));
|
Stream.concat(typArguments.stream(), Stream.of(returnType)).collect(Collectors.toList()));
|
||||||
|
superFunNName = String.format("Fun%d$$", typArguments.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -47,7 +62,30 @@ public final class FunN extends IntermediateRefType {
|
|||||||
public byte[] getSuperBytecode(){
|
public byte[] getSuperBytecode(){
|
||||||
byte[] superBytecode = this.superBytecode;
|
byte[] superBytecode = this.superBytecode;
|
||||||
if (superBytecode == null){
|
if (superBytecode == null){
|
||||||
//ToDo
|
String superType = Type.getInternalName(Object.class).replace('.','/');
|
||||||
|
String objectSignature = new IntermediateRefType(new JavaClassName(Type.getInternalName(Object.class))).getSignature();
|
||||||
|
|
||||||
|
String superFunNClassSignature = "<";
|
||||||
|
String superFunNMethodSignature = "(";
|
||||||
|
String superFunNMethodDescriptor = "(";
|
||||||
|
|
||||||
|
//currentParameter < getTypArgumentSize() because the return type is stored in the typArguments as well
|
||||||
|
for (int currentParameter = 1; currentParameter < getTypArgumentSize(); currentParameter++){
|
||||||
|
superFunNClassSignature += String.format("%s%d:%s",argumentGenericBase, currentParameter, objectSignature);
|
||||||
|
superFunNMethodSignature += new IntermediateGenericType(argumentGenericBase + currentParameter).getSignature();
|
||||||
|
superFunNMethodDescriptor += objectSignature;
|
||||||
|
}
|
||||||
|
superFunNClassSignature += String.format("%s:%s>%s", returnGeneric, objectSignature, objectSignature);
|
||||||
|
superFunNMethodSignature += String.format(")%s", new IntermediateGenericType(returnGeneric).getSignature());
|
||||||
|
superFunNMethodDescriptor += String.format(")%s", objectSignature);
|
||||||
|
|
||||||
|
ClassWriter classWriter = new ClassWriter(0);
|
||||||
|
MethodVisitor methodVisitor;
|
||||||
|
classWriter.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, superFunNName, superFunNClassSignature, superType, null);
|
||||||
|
methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, methodName, superFunNMethodDescriptor, superFunNMethodSignature , null);
|
||||||
|
methodVisitor.visitEnd();
|
||||||
|
classWriter.visitEnd();
|
||||||
|
superBytecode = classWriter.toByteArray();
|
||||||
this.superBytecode = superBytecode;
|
this.superBytecode = superBytecode;
|
||||||
}
|
}
|
||||||
return superBytecode;
|
return superBytecode;
|
||||||
|
@ -31,9 +31,7 @@ public class IntermediateRefType extends IntermediateInnerType{
|
|||||||
*/
|
*/
|
||||||
private String descriptor = "";
|
private String descriptor = "";
|
||||||
|
|
||||||
public IntermediateRefType(JavaClassName className) {
|
public IntermediateRefType(JavaClassName className) { this(className, Collections.emptyList()); }
|
||||||
this(className, new ArrayList<>());
|
|
||||||
}
|
|
||||||
|
|
||||||
public IntermediateRefType(JavaClassName className, List<IntermediateType> typArguments){
|
public IntermediateRefType(JavaClassName className, List<IntermediateType> typArguments){
|
||||||
this.className = className;
|
this.className = className;
|
||||||
@ -100,16 +98,18 @@ public class IntermediateRefType extends IntermediateInnerType{
|
|||||||
|
|
||||||
public boolean isParametrized() { return typArguments.size() > 0; }
|
public boolean isParametrized() { return typArguments.size() > 0; }
|
||||||
|
|
||||||
public int getTypParameterSize(){ return typArguments.size(); }
|
public int getTypArgumentSize(){ return typArguments.size(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param index
|
* @param index
|
||||||
* @return the typ parameter at {@code index} or {@code null}, iff {@code |typ parameters| < index}
|
* @return the typ parameter at {@code index} or {@code null}, iff {@code |typ parameters| < index}
|
||||||
*/
|
*/
|
||||||
public IntermediateType getTypParameter(int index) {
|
public IntermediateType getTypArgument(int index) {
|
||||||
if(typArguments.size() < index) return null;
|
if(typArguments.size() < index) return null;
|
||||||
return typArguments.get(index);
|
return typArguments.get(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getFullyQualifiedName(){ return className.toString(); }
|
public String getClassName(){ return className.getClassName(); }
|
||||||
|
public String getPackageName(){ return className.getPackageName(); }
|
||||||
|
public String getFullyQualifiedName(){ return className.toString(); }
|
||||||
}
|
}
|
||||||
|
@ -1,30 +1,45 @@
|
|||||||
package intermediate.generation;
|
package intermediate.generation;
|
||||||
|
|
||||||
import de.dhbwstuttgart.intermediate.generation.FunN;
|
import de.dhbwstuttgart.intermediate.generation.FunN;
|
||||||
|
import de.dhbwstuttgart.intermediate.types.IntermediateGenericType;
|
||||||
import de.dhbwstuttgart.intermediate.types.IntermediateRefType;
|
import de.dhbwstuttgart.intermediate.types.IntermediateRefType;
|
||||||
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
import de.dhbwstuttgart.parser.scope.JavaClassName;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.objectweb.asm.ClassWriter;
|
||||||
|
import org.objectweb.asm.MethodVisitor;
|
||||||
import org.objectweb.asm.Type;
|
import org.objectweb.asm.Type;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.objectweb.asm.Opcodes.*;
|
||||||
|
|
||||||
public class FunNTest {
|
public class FunNTest {
|
||||||
|
|
||||||
|
private static FunN fun0T;
|
||||||
|
|
||||||
private static String fun1IntIntSignature;
|
private static String fun1IntIntSignature;
|
||||||
private static String fun1IntIntDescriptor;
|
private static String fun1IntIntDescriptor;
|
||||||
private static FunN fun1IntInt;
|
private static FunN fun1IntInt;
|
||||||
|
|
||||||
|
private static FunN fun2IntIntString;
|
||||||
|
|
||||||
//ToDo mehr Tests und Bytecode Tests
|
//ToDo mehr Tests und Bytecode Tests
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void SetUp(){
|
public static void SetUp(){
|
||||||
IntermediateRefType integer = new IntermediateRefType(new JavaClassName(Type.getInternalName(Integer.class)));
|
IntermediateRefType integer = new IntermediateRefType(new JavaClassName(Type.getInternalName(Integer.class)));
|
||||||
|
IntermediateRefType string = new IntermediateRefType(new JavaClassName(Type.getInternalName(String.class)));
|
||||||
|
|
||||||
|
fun0T = new FunN(new IntermediateGenericType("T"));
|
||||||
|
|
||||||
fun1IntIntSignature = "LFun1$$Ljava$lang$Integer$_$Ljava$lang$Integer$_$<Ljava/lang/Integer;Ljava/lang/Integer;>;";
|
fun1IntIntSignature = "LFun1$$Ljava$lang$Integer$_$Ljava$lang$Integer$_$<Ljava/lang/Integer;Ljava/lang/Integer;>;";
|
||||||
fun1IntIntDescriptor = "LFun1$$Ljava$lang$Integer$_$Ljava$lang$Integer$_$;";
|
fun1IntIntDescriptor = "LFun1$$Ljava$lang$Integer$_$Ljava$lang$Integer$_$;";
|
||||||
fun1IntInt = new FunN(Arrays.asList(integer), integer);
|
fun1IntInt = new FunN(Arrays.asList(integer), integer);
|
||||||
|
|
||||||
|
fun2IntIntString = new FunN(Arrays.asList(integer, integer), string);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -32,4 +47,43 @@ public class FunNTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void DescriptorTest_Fun1IntegerInteger(){ assertEquals(fun1IntIntDescriptor, fun1IntInt.getDescriptor()); }
|
public void DescriptorTest_Fun1IntegerInteger(){ assertEquals(fun1IntIntDescriptor, fun1IntInt.getDescriptor()); }
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void BytecodeTest_Super0(){ assertArrayEquals(generatedASMFun0(), fun0T.getSuperBytecode()) ;}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void BytecodeTest_Super1(){ assertArrayEquals(generatedASMFun1(), fun1IntInt.getSuperBytecode()) ;}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void BytecodeTest_Super2(){ assertArrayEquals(generatedASMFun2(), fun2IntIntString.getSuperBytecode()) ;}
|
||||||
|
|
||||||
|
private byte[] generatedASMFun0() {
|
||||||
|
ClassWriter classWriter = new ClassWriter(0);
|
||||||
|
MethodVisitor methodVisitor;
|
||||||
|
classWriter.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, "Fun0$$", "<R:Ljava/lang/Object;>Ljava/lang/Object;", "java/lang/Object", null);
|
||||||
|
methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, "apply", "()Ljava/lang/Object;", "()TR;", null);
|
||||||
|
methodVisitor.visitEnd();
|
||||||
|
classWriter.visitEnd();
|
||||||
|
return classWriter.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] generatedASMFun1() {
|
||||||
|
ClassWriter classWriter = new ClassWriter(0);
|
||||||
|
MethodVisitor methodVisitor;
|
||||||
|
classWriter.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, "Fun1$$", "<T1:Ljava/lang/Object;R:Ljava/lang/Object;>Ljava/lang/Object;", "java/lang/Object", null);
|
||||||
|
methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, "apply", "(Ljava/lang/Object;)Ljava/lang/Object;", "(TT1;)TR;", null);
|
||||||
|
methodVisitor.visitEnd();
|
||||||
|
classWriter.visitEnd();
|
||||||
|
return classWriter.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] generatedASMFun2() {
|
||||||
|
ClassWriter classWriter = new ClassWriter(0);
|
||||||
|
MethodVisitor methodVisitor;
|
||||||
|
classWriter.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, "Fun2$$", "<T1:Ljava/lang/Object;T2:Ljava/lang/Object;R:Ljava/lang/Object;>Ljava/lang/Object;", "java/lang/Object", null);
|
||||||
|
methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, "apply", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", "(TT1;TT2;)TR;", null);
|
||||||
|
methodVisitor.visitEnd();
|
||||||
|
classWriter.visitEnd();
|
||||||
|
return classWriter.toByteArray();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user