Erweitern des Bytecode Gen.

This commit is contained in:
JanUlrich 2015-09-22 18:43:36 +02:00
parent 296ffbe297
commit 86e06a6e7a
41 changed files with 852 additions and 82 deletions

View File

@ -0,0 +1,3 @@
interface Fun0<A>{
A apply();
}

View File

@ -0,0 +1,7 @@
interface Fun1<A,B>{
A apply(B p);
}
class TestFun1<A>{
A apply(A a){return a;}
}

View File

@ -0,0 +1,5 @@
class GenericTest<A,B>{
GenericTest<? super String, ? extends String> field;
void methode(A a, B b){
}
}

View File

@ -0,0 +1,5 @@
class Identity<A>{
Fun1<A,A> op = (x)->x;
}

View File

@ -0,0 +1,10 @@
class InnerClass{
private class TestKlasse{
void methode(){}
}
void methode(){
new TestKlasse().methode();
}
}

View File

@ -0,0 +1,106 @@
Classfile /home/janulrich/Development/eclipseworkspace/JavaCompilerCore/notizen/stan/lambdaBytecode/Lambda3.class
Last modified 20.08.2015; size 903 bytes
MD5 checksum acb53c553588f3c919f2b0e6359bbd94
class Lambda3
InnerClasses:
public static final #46= #45 of #49; //Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
BootstrapMethods:
0: #18 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
Method arguments:
#19 ()V
#20 invokestatic Lambda3.lambda$methode$0:()V
#19 ()V
minor version: 0
major version: 52
flags: ACC_SUPER
Constant pool:
#1 = Methodref #8.#16 // java/lang/Object."<init>":()V
#2 = InvokeDynamic #0:#21 // #0:run:()Ljava/lang/Runnable;
#3 = Methodref #7.#22 // Lambda3.methode:()Ljava/lang/Runnable;
#4 = InterfaceMethodref #23.#24 // java/lang/Runnable.run:()V
#5 = Fieldref #25.#26 // java/lang/System.out:Ljava/io/PrintStream;
#6 = Methodref #27.#28 // java/io/PrintStream.println:()V
#7 = Class #29 // Lambda3
#8 = Class #30 // java/lang/Object
#9 = Utf8 <init>
#10 = Utf8 ()V
#11 = Utf8 Code
#12 = Utf8 methode
#13 = Utf8 ()Ljava/lang/Runnable;
#14 = Utf8 methode2
#15 = Utf8 lambda$methode$0
#16 = NameAndType #9:#10 // "<init>":()V
#17 = Utf8 BootstrapMethods
#18 = MethodHandle #6:#31 // invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#19 = MethodType #10 // ()V
#20 = MethodHandle #6:#32 // invokestatic Lambda3.lambda$methode$0:()V
#21 = NameAndType #33:#13 // run:()Ljava/lang/Runnable;
#22 = NameAndType #12:#13 // methode:()Ljava/lang/Runnable;
#23 = Class #34 // java/lang/Runnable
#24 = NameAndType #33:#10 // run:()V
#25 = Class #35 // java/lang/System
#26 = NameAndType #36:#37 // out:Ljava/io/PrintStream;
#27 = Class #38 // java/io/PrintStream
#28 = NameAndType #39:#10 // println:()V
#29 = Utf8 Lambda3
#30 = Utf8 java/lang/Object
#31 = Methodref #40.#41 // java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#32 = Methodref #7.#42 // Lambda3.lambda$methode$0:()V
#33 = Utf8 run
#34 = Utf8 java/lang/Runnable
#35 = Utf8 java/lang/System
#36 = Utf8 out
#37 = Utf8 Ljava/io/PrintStream;
#38 = Utf8 java/io/PrintStream
#39 = Utf8 println
#40 = Class #43 // java/lang/invoke/LambdaMetafactory
#41 = NameAndType #44:#48 // metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#42 = NameAndType #15:#10 // lambda$methode$0:()V
#43 = Utf8 java/lang/invoke/LambdaMetafactory
#44 = Utf8 metafactory
#45 = Class #50 // java/lang/invoke/MethodHandles$Lookup
#46 = Utf8 Lookup
#47 = Utf8 InnerClasses
#48 = Utf8 (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#49 = Class #51 // java/lang/invoke/MethodHandles
#50 = Utf8 java/lang/invoke/MethodHandles$Lookup
#51 = Utf8 java/lang/invoke/MethodHandles
{
Lambda3();
Signature: ()V
flags:
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
java.lang.Runnable methode();
Signature: ()Ljava/lang/Runnable;
flags:
Code:
stack=1, locals=1, args_size=1
0: invokedynamic #2, 0 // InvokeDynamic #0:run:()Ljava/lang/Runnable;
5: areturn
void methode2();
Signature: ()V
flags:
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokevirtual #3 // Method methode:()Ljava/lang/Runnable;
4: invokeinterface #4, 1 // InterfaceMethod java/lang/Runnable.run:()V
9: return
private static void lambda$methode$0();
Signature: ()V
flags: ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
Code:
stack=1, locals=0, args_size=0
0: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
3: invokevirtual #6 // Method java/io/PrintStream.println:()V
6: return
}

View File

@ -0,0 +1,12 @@
class Lambda1{
Runnable methode(){
return ()-> System.out.println();
}
void methode2(){
methode().run();
}
}

View File

@ -0,0 +1,110 @@
Classfile /home/janulrich/Development/eclipseworkspace/JavaCompilerCore/notizen/stan/lambdaBytecode/Lambda3.class
Last modified 20.08.2015; size 963 bytes
MD5 checksum 11b76982e895a4f22c01832b3da258ef
class Lambda3
InnerClasses:
public static final #48= #47 of #51; //Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
BootstrapMethods:
0: #18 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
Method arguments:
#19 ()V
#20 invokespecial Lambda3.lambda$methode$0:()V
#19 ()V
minor version: 0
major version: 52
flags: ACC_SUPER
Constant pool:
#1 = Methodref #8.#16 // java/lang/Object."<init>":()V
#2 = InvokeDynamic #0:#21 // #0:run:(LLambda3;)Ljava/lang/Runnable;
#3 = Methodref #7.#22 // Lambda3.methode:()Ljava/lang/Runnable;
#4 = InterfaceMethodref #23.#24 // java/lang/Runnable.run:()V
#5 = Fieldref #25.#26 // java/lang/System.out:Ljava/io/PrintStream;
#6 = Methodref #27.#28 // java/io/PrintStream.println:(Ljava/lang/Object;)V
#7 = Class #29 // Lambda3
#8 = Class #30 // java/lang/Object
#9 = Utf8 <init>
#10 = Utf8 ()V
#11 = Utf8 Code
#12 = Utf8 methode
#13 = Utf8 ()Ljava/lang/Runnable;
#14 = Utf8 methode2
#15 = Utf8 lambda$methode$0
#16 = NameAndType #9:#10 // "<init>":()V
#17 = Utf8 BootstrapMethods
#18 = MethodHandle #6:#31 // invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#19 = MethodType #10 // ()V
#20 = MethodHandle #7:#32 // invokespecial Lambda3.lambda$methode$0:()V
#21 = NameAndType #33:#34 // run:(LLambda3;)Ljava/lang/Runnable;
#22 = NameAndType #12:#13 // methode:()Ljava/lang/Runnable;
#23 = Class #35 // java/lang/Runnable
#24 = NameAndType #33:#10 // run:()V
#25 = Class #36 // java/lang/System
#26 = NameAndType #37:#38 // out:Ljava/io/PrintStream;
#27 = Class #39 // java/io/PrintStream
#28 = NameAndType #40:#41 // println:(Ljava/lang/Object;)V
#29 = Utf8 Lambda3
#30 = Utf8 java/lang/Object
#31 = Methodref #42.#43 // java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#32 = Methodref #7.#44 // Lambda3.lambda$methode$0:()V
#33 = Utf8 run
#34 = Utf8 (LLambda3;)Ljava/lang/Runnable;
#35 = Utf8 java/lang/Runnable
#36 = Utf8 java/lang/System
#37 = Utf8 out
#38 = Utf8 Ljava/io/PrintStream;
#39 = Utf8 java/io/PrintStream
#40 = Utf8 println
#41 = Utf8 (Ljava/lang/Object;)V
#42 = Class #45 // java/lang/invoke/LambdaMetafactory
#43 = NameAndType #46:#50 // metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#44 = NameAndType #15:#10 // lambda$methode$0:()V
#45 = Utf8 java/lang/invoke/LambdaMetafactory
#46 = Utf8 metafactory
#47 = Class #52 // java/lang/invoke/MethodHandles$Lookup
#48 = Utf8 Lookup
#49 = Utf8 InnerClasses
#50 = Utf8 (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#51 = Class #53 // java/lang/invoke/MethodHandles
#52 = Utf8 java/lang/invoke/MethodHandles$Lookup
#53 = Utf8 java/lang/invoke/MethodHandles
{
Lambda3();
Signature: ()V
flags:
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
java.lang.Runnable methode();
Signature: ()Ljava/lang/Runnable;
flags:
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokedynamic #2, 0 // InvokeDynamic #0:run:(LLambda3;)Ljava/lang/Runnable;
6: areturn
void methode2();
Signature: ()V
flags:
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokevirtual #3 // Method methode:()Ljava/lang/Runnable;
4: invokeinterface #4, 1 // InterfaceMethod java/lang/Runnable.run:()V
9: return
private void lambda$methode$0();
Signature: ()V
flags: ACC_PRIVATE, ACC_SYNTHETIC
Code:
stack=2, locals=1, args_size=1
0: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
3: aload_0
4: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
7: return
}

View File

@ -0,0 +1,12 @@
class Lambda3{
Runnable methode(){
return ()-> System.out.println(this);
}
void methode2(){
methode().run();
}
}

View File

@ -0,0 +1,104 @@
Classfile /home/janulrich/Development/eclipseworkspace/JavaCompilerCore/notizen/stan/lambdaBytecode/Lambda4.class
Last modified 03.09.2015; size 979 bytes
MD5 checksum f24040561dd183d0d75c91dbdd93f59c
Compiled from "Lambda4.java"
class Lambda4
SourceFile: "Lambda4.java"
InnerClasses:
public static final #45= #44 of #48; //Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
BootstrapMethods:
0: #19 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
Method arguments:
#20 (Ljava/lang/Integer;)Ljava/lang/Integer;
#21 invokespecial Lambda4.lambda$methode$0:(Ljava/lang/Integer;)Ljava/lang/Integer;
#20 (Ljava/lang/Integer;)Ljava/lang/Integer;
minor version: 0
major version: 52
flags: ACC_SUPER
Constant pool:
#1 = Methodref #6.#17 // java/lang/Object."<init>":()V
#2 = InvokeDynamic #0:#22 // #0:test:(LLambda4;)LTest;
#3 = Fieldref #23.#24 // java/lang/System.out:Ljava/io/PrintStream;
#4 = Methodref #25.#26 // java/io/PrintStream.println:(Ljava/lang/Object;)V
#5 = Class #27 // Lambda4
#6 = Class #28 // java/lang/Object
#7 = Utf8 <init>
#8 = Utf8 ()V
#9 = Utf8 Code
#10 = Utf8 LineNumberTable
#11 = Utf8 methode
#12 = Utf8 ()LTest;
#13 = Utf8 lambda$methode$0
#14 = Utf8 (Ljava/lang/Integer;)Ljava/lang/Integer;
#15 = Utf8 SourceFile
#16 = Utf8 Lambda4.java
#17 = NameAndType #7:#8 // "<init>":()V
#18 = Utf8 BootstrapMethods
#19 = MethodHandle #6:#29 // invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#20 = MethodType #14 // (Ljava/lang/Integer;)Ljava/lang/Integer;
#21 = MethodHandle #7:#30 // invokespecial Lambda4.lambda$methode$0:(Ljava/lang/Integer;)Ljava/lang/Integer;
#22 = NameAndType #31:#32 // test:(LLambda4;)LTest;
#23 = Class #33 // java/lang/System
#24 = NameAndType #34:#35 // out:Ljava/io/PrintStream;
#25 = Class #36 // java/io/PrintStream
#26 = NameAndType #37:#38 // println:(Ljava/lang/Object;)V
#27 = Utf8 Lambda4
#28 = Utf8 java/lang/Object
#29 = Methodref #39.#40 // java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#30 = Methodref #5.#41 // Lambda4.lambda$methode$0:(Ljava/lang/Integer;)Ljava/lang/Integer;
#31 = Utf8 test
#32 = Utf8 (LLambda4;)LTest;
#33 = Utf8 java/lang/System
#34 = Utf8 out
#35 = Utf8 Ljava/io/PrintStream;
#36 = Utf8 java/io/PrintStream
#37 = Utf8 println
#38 = Utf8 (Ljava/lang/Object;)V
#39 = Class #42 // java/lang/invoke/LambdaMetafactory
#40 = NameAndType #43:#47 // metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#41 = NameAndType #13:#14 // lambda$methode$0:(Ljava/lang/Integer;)Ljava/lang/Integer;
#42 = Utf8 java/lang/invoke/LambdaMetafactory
#43 = Utf8 metafactory
#44 = Class #49 // java/lang/invoke/MethodHandles$Lookup
#45 = Utf8 Lookup
#46 = Utf8 InnerClasses
#47 = Utf8 (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#48 = Class #50 // java/lang/invoke/MethodHandles
#49 = Utf8 java/lang/invoke/MethodHandles$Lookup
#50 = Utf8 java/lang/invoke/MethodHandles
{
Lambda4();
Signature: ()V
flags:
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 4: 0
Test methode();
Signature: ()LTest;
flags:
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokedynamic #2, 0 // InvokeDynamic #0:test:(LLambda4;)LTest;
6: areturn
LineNumberTable:
line 6: 0
private java.lang.Integer lambda$methode$0(java.lang.Integer);
Signature: (Ljava/lang/Integer;)Ljava/lang/Integer;
flags: ACC_PRIVATE, ACC_SYNTHETIC
Code:
stack=2, locals=2, args_size=2
0: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
3: aload_0
4: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
7: aload_1
8: areturn
LineNumberTable:
line 6: 0
}

View File

@ -0,0 +1,8 @@
interface Test{
Integer test(Integer i);
}
class Lambda4{
Test methode(){
return (i)->{System.out.println(this); return i;};
}
}

View File

@ -0,0 +1,8 @@
interface TestParam<A>{
A test(A i);
}
class Lambda5{
TestParam<Integer> methode(){
return (i)->{System.out.println(this); return i;};
}
}

View File

@ -0,0 +1,5 @@
class Lambda5Test{
public static void main(String[] args){
Integer i = new Lambda5().methode().test(2);
}
}

View File

@ -0,0 +1,37 @@
# Quellen
* http://cr.openjdk.java.net/~briangoetz/lambda/lambda-translation.html
* http://blog.takipi.com/erstellen-von-lambda-ausdrucken-scala-vs-java-8/
# Decompiler
* Es wird javap verwendet. Die Datei ~/bin/javap leitet den javap Befehl um. Muss angepasst werden, wenn man andere Version verwenden will.
#Quellen
* Brian Götz zu Lambdas: http://wiki.jvmlangsummit.com/images/1/1e/2011_Goetz_Lambda.pdf
# Doku
* 2 Möglichkeiten Lambda Ausdrücke zu kompilieren: Anonymous inner class, Invokedynamic
## Invokedynamic
* Hat Argumente auf dem Stack liegen
* Indexbytes zeigen auf eine InvokeDynamic_Info structure, welche beinhaltet:
* Methodenname der bootstrap-Methode (Symbolic Reference)
* Mehrere Symbolic References auf statische Argumente der Bootstrap Methode
* Einen Methodenname und Deskriptor.
* Ausführung:
* Nach dem auflösen dieser Struktur stehen die Informationen des InvokeDynamic_Info zur Verfügung
* Anschließend wird ein invokevirtual auf die Bootstrap Methode ausgeführt
* Die Index Referenz für InvokeVirtual hat bestimmte Werte: https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.invokedynamic
* Die Rückgabe der Bootstrap-Methode (CallSite) wird mittels invokevirtual ausgeführt.
## Bootstrap Methods
* Ein Attribut im Classfile
* Gibt die Bootstrap Methoden an
* Die Angabe erfolgt durch Zeiger auf Method_Handle_info Strukturen im Konstantenpool
* Rückgabe der Bootstrap-Methode ist ein CallSite Objekt: https://docs.oracle.com/javase/7/docs/api/java/lang/invoke/CallSite.html
## LambdaMetaFactory
* Stellt eine mögliche Bootstrap Methode dar
# TODO:
* Matrix Beispiel muss funktionieren (verschachtelter Lambda Ausdruck)
* Automatisch Bytecode generieren, wenn alle Typen eingesetzt sind

View File

@ -0,0 +1,5 @@
class Runnable{
Fun0<Runnable> method() { return ()-> this; }
}

View File

@ -0,0 +1,8 @@
/**
* Diese Klasse testet die generierte EmptyClass.class-Datei
*/
class Test{
public static void main(String[] args){
System.out.println(new Runnable().method().apply());
}
}

View File

@ -0,0 +1,104 @@
Classfile /home/janulrich/Development/eclipseworkspace/JavaCompilerCore/notizen/stan/lambdaBytecode/Lambda1.class
Last modified 20.08.2015; size 903 bytes
MD5 checksum acb53c553588f3c919f2b0e6359bbd94
class Lambda1
InnerClasses:
public static final #46= #45 of #49; //Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
BootstrapMethods:
0: #18 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
Method arguments:
#19 ()V
#20 invokestatic Lambda1.lambda$methode$0:()V
#19 ()V
minor version: 0
major version: 52
flags: ACC_SUPER
Constant pool:
#1 = Methodref #8.#16 // java/lang/Object."<init>":()V
#2 = InvokeDynamic #0:#21 // #0:run:()Ljava/lang/Runnable;
#3 = Methodref #7.#22 // Lambda1.methode:()Ljava/lang/Runnable;
#4 = InterfaceMethodref #23.#24 // java/lang/Runnable.run:()V
#5 = Fieldref #25.#26 // java/lang/System.out:Ljava/io/PrintStream;
#6 = Methodref #27.#28 // java/io/PrintStream.println:()V
#7 = Class #29 // Lambda1
#8 = Class #30 // java/lang/Object
#9 = Utf8 <init>
#10 = Utf8 ()V
#11 = Utf8 Code
#12 = Utf8 methode
#13 = Utf8 ()Ljava/lang/Runnable;
#14 = Utf8 methode2
#15 = Utf8 lambda$methode$0
#16 = NameAndType #9:#10 // "<init>":()V
#17 = Utf8 BootstrapMethods
#18 = MethodHandle #6:#31 // invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#19 = MethodType #10 // ()V
#20 = MethodHandle #6:#32 // invokestatic Lambda1.lambda$methode$0:()V
#21 = NameAndType #33:#13 // run:()Ljava/lang/Runnable;
#22 = NameAndType #12:#13 // methode:()Ljava/lang/Runnable;
#23 = Class #34 // java/lang/Runnable
#24 = NameAndType #33:#10 // run:()V
#25 = Class #35 // java/lang/System
#26 = NameAndType #36:#37 // out:Ljava/io/PrintStream;
#27 = Class #38 // java/io/PrintStream
#28 = NameAndType #39:#10 // println:()V
#29 = Utf8 Lambda1
#30 = Utf8 java/lang/Object
#31 = Methodref #40.#41 // java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#32 = Methodref #7.#42 // Lambda1.lambda$methode$0:()V
#33 = Utf8 run
#34 = Utf8 java/lang/Runnable
#35 = Utf8 java/lang/System
#36 = Utf8 out
#37 = Utf8 Ljava/io/PrintStream;
#38 = Utf8 java/io/PrintStream
#39 = Utf8 println
#40 = Class #43 // java/lang/invoke/LambdaMetafactory
#41 = NameAndType #44:#48 // metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#42 = NameAndType #15:#10 // lambda$methode$0:()V
#43 = Utf8 java/lang/invoke/LambdaMetafactory
#44 = Utf8 metafactory
#45 = Class #50 // java/lang/invoke/MethodHandles$Lookup
#46 = Utf8 Lookup
#47 = Utf8 InnerClasses
#48 = Utf8 (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#49 = Class #51 // java/lang/invoke/MethodHandles
#50 = Utf8 java/lang/invoke/MethodHandles$Lookup
#51 = Utf8 java/lang/invoke/MethodHandles
{
Lambda1();
Signature: ()V
flags:
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
java.lang.Runnable methode();
Signature: ()Ljava/lang/Runnable;
flags:
Code:
stack=1, locals=1, args_size=1
0: invokedynamic #2, 0 // InvokeDynamic #0:run:()Ljava/lang/Runnable;
5: areturn
void methode2();
Signature: ()V
flags:
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokevirtual #3 // Method methode:()Ljava/lang/Runnable;
4: invokeinterface #4, 1 // InterfaceMethod java/lang/Runnable.run:()V
9: return
private static void lambda$methode$0();
Signature: ()V
flags: ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
Code:
stack=1, locals=0, args_size=0
0: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
3: invokevirtual #6 // Method java/io/PrintStream.println:()V
6: return
}

View File

@ -1,15 +1,21 @@
package de.dhbwstuttgart.bytecode;
import java.util.Iterator;
import org.apache.commons.bcel6.classfile.BootstrapMethod;
import org.apache.commons.bcel6.classfile.BootstrapMethods;
import org.apache.commons.bcel6.classfile.ConstantPool;
import org.apache.commons.bcel6.classfile.InnerClass;
import org.apache.commons.bcel6.classfile.InnerClasses;
import org.apache.commons.bcel6.classfile.JavaClass;
import org.apache.commons.bcel6.classfile.Signature;
import org.apache.commons.bcel6.generic.ClassGen;
import org.apache.commons.bcel6.generic.ConstantPoolGen;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.typeinference.ResultSet;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
import de.dhbwstuttgart.typeinference.exceptions.DebugException;
@ -20,11 +26,15 @@ public class ClassGenerator extends ClassGen{
private DHBWInstructionFactory factory;
private TypeinferenceResultSet tiResult;
private int lambdaMethodeNr = 0;
private Type superClass;
public ClassGenerator(String name, String get_Name, String string,
private Menge<TypePlaceholder> usedTPHs = new Menge<>();
public ClassGenerator(String name, Type superClass, String string,
short accPublic, String[] strings, TypeinferenceResultSet resultSet) {
super(name,get_Name,string,accPublic,strings, new DHBWConstantPoolGen());
super(name,superClass.get_Name(),string,accPublic,strings, new DHBWConstantPoolGen());
this.tiResult = resultSet;
this.superClass = superClass;
cp = (DHBWConstantPoolGen) super.getConstantPool();
factory = new DHBWInstructionFactory(this, cp);
@ -36,6 +46,23 @@ public class ClassGenerator extends ClassGen{
return factory ;
}
/**
* Versucht einen Type zu finden von dem dieser TPH ein Subtyp sein muss.
* @param toTPH
* @return Es gilt dann "toTPH extends Type"
*/
public org.apache.commons.bcel6.generic.Type getNearestType(TypePlaceholder toTPH){
Type t = resolveTPH(toTPH);
if(t == null){
return this.getInstructionFactory().createObjectType();
}else if(t instanceof TypePlaceholder){ //Es muss sich in diesem Fall um einen TPH handeln:
//return getNearestType((TypePlaceholder) t);
return new TypePlaceholderType((TypePlaceholder) t);
}else{
return t.getBytecodeType(this);
}
}
public Type resolveTPH(TypePlaceholder typePlaceholder) {
return tiResult.getTypeOfPlaceholder(typePlaceholder);
}
@ -77,4 +104,49 @@ public class ClassGenerator extends ClassGen{
this.addAttribute(bootstrapAttribute);
return numberOfBootstrapMethods-1;
}
public void addUsedTPH(TypePlaceholder tph){
if(! this.getUsedTPH().contains(tph, (a, b)->{
return a.get_Name().equals(b.get_Name()); //Vergleich auf Namensgleichheit. Was anderes zählt im Bytecode nicht
}))
{ //Nur wenn noch nicht vorhanden anfügen:
this.usedTPHs.add(tph);
}
}
public Menge<TypePlaceholder> getUsedTPH() {
return usedTPHs;
}
@Override
public JavaClass getJavaClass() {
//Hier werden die letzten Schritte vor der Klassengenerierung ausgeführt:
//Signatur setzen:
String typeParameters = this.generateParameterSignature();
String superClassSignature = this.superClass.getBytecodeSignature(this);
String classSignature = typeParameters + superClassSignature;
if(classSignature.length()>0){
this.addAttribute(new Signature(cp.addUtf8("Signature"),2,cp.addUtf8(classSignature),cp.getConstantPool()));
}
return super.getJavaClass();
}
private String generateParameterSignature(){
String ret = "";
if(this.getUsedTPH().size()>0){
ret += "<";
Iterator<TypePlaceholder> it = ((Menge<TypePlaceholder>)this.getUsedTPH().clone()).iterator();
while(it.hasNext()){
TypePlaceholder tph = it.next();
//ret += tph.getBytecodeMethodSignature(this);
//ret += ":";
ret += tph.getClassSignature(this);
}
ret += ">";
}
return ret;
}
}

View File

@ -10,6 +10,7 @@ import org.apache.commons.bcel6.classfile.ConstantMethodHandle;
import org.apache.commons.bcel6.classfile.ConstantMethodType;
import org.apache.commons.bcel6.classfile.InnerClass;
import org.apache.commons.bcel6.classfile.Method;
import org.apache.commons.bcel6.classfile.Signature;
import org.apache.commons.bcel6.generic.ClassGen;
import org.apache.commons.bcel6.generic.ConstantPoolGen;
import org.apache.commons.bcel6.generic.INVOKEDYNAMIC;
@ -19,6 +20,12 @@ import org.apache.commons.bcel6.generic.LocalVariableInstruction;
import org.apache.commons.bcel6.generic.MethodGen;
import org.apache.commons.bcel6.generic.Type;
import de.dhbwstuttgart.syntaxtree.FormalParameter;
import de.dhbwstuttgart.syntaxtree.ParameterList;
import de.dhbwstuttgart.syntaxtree.statement.Block;
import de.dhbwstuttgart.syntaxtree.statement.Return;
import de.dhbwstuttgart.syntaxtree.type.FunN;
public class DHBWInstructionFactory extends InstructionFactory{
private DHBWConstantPoolGen cp;
@ -30,7 +37,15 @@ public class DHBWInstructionFactory extends InstructionFactory{
this.cg = cg;
}
public INVOKEDYNAMIC createInvokeDynamic( String interfaceMethodName, String lambdaTypeSignature, MethodGen lambdaMethod ) {
/**
*
* @param interfaceMethodName - Momentan immer "apply"
* @param invokeDynamicMethodType - Der Methodentyp
* @param interfaceMethodType
* @param lambdaMethod
* @return
*/
public INVOKEDYNAMIC createInvokeDynamic( String interfaceMethodName, String invokeDynamicMethodType, FunN interfaceMethodType, MethodGen lambdaMethod ) {
//Zuerst die Bootstrap-Methode erstellen: Diese müssen dann in ein BootstrapMethods-Attribut zusammengefasst und dem Classfile hinzugefügt werden
//this.cp.addMethodref(lambdaMethod);
@ -50,8 +65,8 @@ public class DHBWInstructionFactory extends InstructionFactory{
*/
String lambdaTypeParameterList = "()";
ConstantMethodType lambdaMethodType = new ConstantMethodType(this.cp.addUtf8("()LRunnable;"));
ConstantMethodType lambdaMethodType1 = new ConstantMethodType(this.cp.addUtf8("()Ljava/lang/Object;"));
ConstantMethodType lambdaMethodType1 = new ConstantMethodType(this.cp.addUtf8("()Ljava/lang/Object;")); //TODO: Hier den Grund finden, warum Object stehen muss.
ConstantMethodType lambdaMethodType = new ConstantMethodType(this.cp.addUtf8(interfaceMethodType.getBytecodeInvokeDynamicSignature(cg)));
int implMethodKind = 7; // 7 = InvokeSpecial @see https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html#jvms-5.4.3.5
ConstantMethodHandle implMethod = new ConstantMethodHandle(implMethodKind,cg.getConstantPool().addMethodref(lambdaMethod)); //Das zweite Argument ist der MethodRef zur LambdaMethode
@ -82,7 +97,6 @@ public class DHBWInstructionFactory extends InstructionFactory{
}
BootstrapMethod bMethod = new BootstrapMethod(lambdaMetafactoryHandle, arguments.size(), argumentsArray);
int index;
/*
@ -111,9 +125,9 @@ public class DHBWInstructionFactory extends InstructionFactory{
int bootstrap_method_attr_index = cg.addBootstrapMethod(bMethod);
//TODO: der Typ der Lambda Methode muss den Typ von this als erstes Argument enthalten, damit this innerhalb der Lambda Methode verwendet werden kann
int name_and_type_index = cp.addNameAndType(interfaceMethodName, lambdaTypeSignature);
int invokeDynamicFunktionstyp = cp.addNameAndType(interfaceMethodName, invokeDynamicMethodType);
ConstantInvokeDynamic cInvokeDynamic = new ConstantInvokeDynamic(bootstrap_method_attr_index, name_and_type_index);
ConstantInvokeDynamic cInvokeDynamic = new ConstantInvokeDynamic(bootstrap_method_attr_index, invokeDynamicFunktionstyp);
index = cp.addConstant(cInvokeDynamic);
@ -125,4 +139,7 @@ public class DHBWInstructionFactory extends InstructionFactory{
return InstructionFactory.createLoad(bytecodeType, index);
}
public Type createObjectType() {
return new org.apache.commons.bcel6.generic.ObjectType("java.lang.Object");
}
}

View File

@ -1,10 +1,17 @@
package de.dhbwstuttgart.bytecode;
import org.apache.commons.bcel6.classfile.Method;
import org.apache.commons.bcel6.classfile.Signature;
import org.apache.commons.bcel6.generic.ConstantPoolGen;
import org.apache.commons.bcel6.generic.InstructionList;
import org.apache.commons.bcel6.generic.MethodGen;
import org.apache.commons.bcel6.generic.Type;
import de.dhbwstuttgart.syntaxtree.FormalParameter;
import de.dhbwstuttgart.syntaxtree.ParameterList;
import de.dhbwstuttgart.syntaxtree.statement.Block;
import de.dhbwstuttgart.syntaxtree.statement.Return;
public class MethodGenerator extends MethodGen{
public MethodGenerator(int access_flags, Type return_type, Type[] arg_types, String[] arg_names, String method_name,
@ -12,5 +19,33 @@ public class MethodGenerator extends MethodGen{
super(access_flags, return_type, arg_types, arg_names, method_name, class_name, il, cp);
}
public Method createMethod(ClassGenerator cg, ParameterList parameter, de.dhbwstuttgart.syntaxtree.type.Type retType, Block block){
MethodGen method = this;
DHBWInstructionFactory factory = cg.getInstructionFactory();
InstructionList blockInstructions = block.genByteCode(cg);
InstructionList il = this.getInstructionList();
il.append(blockInstructions);//Die vom Block generierten Instructions an die InstructionList der Methode anfügen
//Ein return Statement anfügen, falls nicht vorhanden:
if (block.get_Statement().size() == 0) { il.append(factory.createReturn( org.apache.commons.bcel6.generic.Type.VOID)); }
else {
if (!(block.get_Statement().lastElement() instanceof Return)) { il.append(factory.createReturn( org.apache.commons.bcel6.generic.Type.VOID)); }
}
method.stripAttributes(true);
method.setMaxStack(); //Die Stack Größe automatisch berechnen lassen (erst nach dem alle Instructions angehängt wurden)
method.setMaxLocals();
//Die korrekte Signatur für die Methode anhängen. Hier sind dann auch die Parameter von RefTypes enthalten:
String paramTypesSig = "(";
for(FormalParameter p : parameter){
paramTypesSig += p.getType().getBytecodeMethodSignature(cg);
}
paramTypesSig += ")";
String retTypeSig = retType.getBytecodeMethodSignature(cg);
method.addAttribute(new Signature(cp.addUtf8("Signature"),2,cp.addUtf8(paramTypesSig+retTypeSig),cp.getConstantPool()));
return method.getMethod();
}
}

View File

@ -3,10 +3,20 @@ package de.dhbwstuttgart.bytecode;
import org.apache.commons.bcel6.Constants;
import org.apache.commons.bcel6.generic.ReferenceType;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
public class TypePlaceholderType extends ReferenceType{
public TypePlaceholderType(String name) {
super(Constants.T_REFERENCE, "T" + name + ";");
private final TypePlaceholder tph;
public TypePlaceholderType(TypePlaceholder tph) {
super(Constants.T_REFERENCE, "T" + tph.get_Name() + ";");
this.tph = tph;
if(this.tph == null)throw new NullPointerException();
}
public TypePlaceholder getTPH() {
return tph;
}
}

View File

@ -84,7 +84,7 @@ public class Class extends GTVDeclarationContext implements AClassOrInterface, I
logger.debug("Test");
if(pkgName != null)throw new NotImplementedException();
_cg = new ClassGenerator(name, superClass.get_Name(), name + ".java", Constants.ACC_PUBLIC , new String[] { }, resultSet); //letzter Parameter sind implementierte Interfaces
_cg = new ClassGenerator(name, this.getSuperClass(), name + ".java", Constants.ACC_PUBLIC , new String[] { }, resultSet); //letzter Parameter sind implementierte Interfaces
_cp = _cg.getConstantPool();
_factory = new DHBWInstructionFactory(_cg, _cp);
@ -111,20 +111,6 @@ public class Class extends GTVDeclarationContext implements AClassOrInterface, I
c.genByteCode(_cg, fieldInitializations);
}
String typeAttributeSignature = "";
if(this.getGenericParameter() != null && this.getGenericParameter().size()>0){
typeAttributeSignature = "<";
for(GenericTypeVar gp : this.getGenericParameter()){
typeAttributeSignature+=gp.getBytecodeSignature(_cg);
}
typeAttributeSignature+=">";
}
String superClassSignature = this.getSuperClass().getBytecodeSignature(_cg);
String classSignature = typeAttributeSignature + superClassSignature;
if(classSignature.length()>0){
_cg.addAttribute(new Signature(_cp.addUtf8("Signature"),2,_cp.addUtf8(classSignature),_cp.getConstantPool()));
}
ByteCodeResult code = new ByteCodeResult(_cg);
return code;
}

View File

@ -766,32 +766,10 @@ public class Method extends Field implements IItemWithOffset, TypeInsertable
}
//Methode generieren:
MethodGen method = new MethodGenerator(Constants.ACC_PUBLIC, this.getType().getBytecodeType(cg), argumentTypes , argumentNames, this.get_Method_Name(), parentClass.name, il, _cp);
method.stripAttributes(true);
MethodGenerator method = new MethodGenerator(Constants.ACC_PUBLIC, this.getType().getBytecodeType(cg), argumentTypes , argumentNames, this.get_Method_Name(), parentClass.name, il, _cp);
Block block = this.get_Block();
InstructionList blockInstructions = block.genByteCode(cg);
il.append(blockInstructions);//Die vom Block generierten Instructions an die InstructionList der Methode anfügen
if (block.get_Statement().size() == 0) { il.append(_factory.createReturn( org.apache.commons.bcel6.generic.Type.VOID)); }
else {
if (!(block.get_Statement().lastElement() instanceof Return)) { il.append(_factory.createReturn( org.apache.commons.bcel6.generic.Type.VOID)); }
}
method.setMaxStack(); //Die Stack Größe automatisch berechnen lassen (erst nach dem alle Instructions angehängt wurden)
method.setMaxLocals();
//Die korrekte Signatur für die Methode anhängen. Hier sind dann auch die Parameter von RefTypes enthalten:
String paramTypesSig = "(";
for(FormalParameter p : this.parameterlist){
paramTypesSig += p.getType().getBytecodeSignature(cg);
}
paramTypesSig += ")";
String retTypeSig = this.getType().getBytecodeSignature(cg);
method.addAttribute(new Signature(_cp.addUtf8("Signature"),2,_cp.addUtf8(paramTypesSig+retTypeSig),_cp.getConstantPool()));
cg.addMethod(method.getMethod());
//Methode generieren und anfügen:
cg.addMethod(method.createMethod(cg, getParameterList(), getType(), get_Block()));
}

View File

@ -27,6 +27,7 @@ import de.dhbwstuttgart.syntaxtree.misc.DeclId;
import de.dhbwstuttgart.syntaxtree.misc.UsedId;
import de.dhbwstuttgart.syntaxtree.modifier.Modifiers;
import de.dhbwstuttgart.syntaxtree.modifier.Public;
import de.dhbwstuttgart.syntaxtree.type.FunN;
import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.Type;
@ -34,7 +35,6 @@ import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.syntaxtree.type.Void;
import de.dhbwstuttgart.typeinference.ByteCodeResult;
import de.dhbwstuttgart.typeinference.ConstraintsSet;
import de.dhbwstuttgart.typeinference.FunN;
import de.dhbwstuttgart.typeinference.FunNInterface;
import de.dhbwstuttgart.typeinference.FunNMethod;
import de.dhbwstuttgart.typeinference.Pair;

View File

@ -15,6 +15,8 @@ import org.apache.commons.bcel6.generic.INVOKEDYNAMIC;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.bytecode.MethodGenerator;
import de.dhbwstuttgart.bytecode.TypePlaceholderType;
import de.dhbwstuttgart.myexception.CTypeReconstructionException;
import de.dhbwstuttgart.myexception.JVMCodeException;
import de.dhbwstuttgart.myexception.SCStatementException;
@ -26,6 +28,7 @@ import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.ParameterList;
import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode;
import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType;
import de.dhbwstuttgart.syntaxtree.type.FunN;
import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.type.ObjectType;
import de.dhbwstuttgart.syntaxtree.type.RefType;
@ -34,7 +37,6 @@ import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.syntaxtree.type.WildcardType;
import de.dhbwstuttgart.typeinference.ConstraintsSet;
import de.dhbwstuttgart.typeinference.FunN;
import de.dhbwstuttgart.typeinference.FunVoidN;
import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.OderConstraint;
@ -55,6 +57,12 @@ import de.dhbwstuttgart.typeinference.unify.CSubstitutionSet;
*/
public class LambdaExpression extends Expr{
/**
* Wird bei der TYPE Methode gesetzt. Speichert den errechneten Typ des LambdaAusdrucks
*/
private FunN lambdaType;
private Block method_body;
private ParameterList params;
@ -186,10 +194,12 @@ public class LambdaExpression extends Expr{
}
}
if(typeIsVoid(retType)){//In diesem Fall, muss der Typ des LambdaAusdrucks FunVoid sein
ret.add(new SingleConstraint(new FunVoidN(modifiedParamTypes).TYPE(assumptions, this),this.getType().TYPE(assumptions, this)));
this.lambdaType = new FunVoidN(modifiedParamTypes);
}else{
ret.add(new SingleConstraint(new FunN(retType, modifiedParamTypes).TYPE(assumptions, this),this.getType().TYPE(assumptions, this)));
this.lambdaType = new FunN(retType, modifiedParamTypes);
}
ret.add(new SingleConstraint(lambdaType.TYPE(assumptions, this),this.getType().TYPE(assumptions, this)));
return ret;
}
private boolean typeIsVoid(Type type){
@ -232,28 +242,44 @@ public class LambdaExpression extends Expr{
ConstantPoolGen cp = cg.getConstantPool();
InstructionList il = new InstructionList();
MethodGen lambdaMethod = new MethodGen(0, method_body.getType().getBytecodeType(cg),
params.getBytecodeTypeList(cg), params.getParameterNameArray(), cg.createLambdaMethodName(),
org.apache.commons.bcel6.generic.Type[] paramTypes = params.getBytecodeTypeList(cg);
org.apache.commons.bcel6.generic.Type[] paramTypesTemp = new org.apache.commons.bcel6.generic.Type[paramTypes.length];
for(int i = 0; i < paramTypes.length ; i++) {
if(paramTypes[i] instanceof TypePlaceholderType){
//TODO: Das kann auch ein spezifischer Typ als Object sein
paramTypesTemp[i] = cg.getNearestType(((TypePlaceholderType)paramTypes[i]).getTPH());
}else{
paramTypesTemp[i] = paramTypes[i];
}
}
paramTypes = paramTypesTemp;
org.apache.commons.bcel6.generic.Type retType = method_body.getType().getBytecodeType(cg);
if(retType instanceof TypePlaceholderType){
//Die TypePlaceholderTypen aussortieren. Sie werden nur in der Signatur erwähnt. Kommen im Bytecode sonst eigentlich nicht vor
retType = cg.getNearestType(((TypePlaceholderType) retType).getTPH());
}
MethodGenerator lambdaMethod = new MethodGenerator(0, retType,
paramTypes, params.getParameterNameArray(), cg.createLambdaMethodName(),
this.getParentClass().getName().toString(), new InstructionList(), cg.getConstantPool());
lambdaMethod.stripAttributes(true);
lambdaMethod.getInstructionList().append(this.method_body.genByteCode(cg));
//lambdaMethod.stripAttributes(true);
//lambdaMethod.getInstructionList().append(this.method_body.genByteCode(cg));
lambdaMethod.setAccessFlags(Constants.ACC_PRIVATE+Constants.ACC_SYNTHETIC);
String interfaceMethodName = "apply"; //Das ist ein Hack, funktioniert momentan, da nur FunN Interfaces für LambdaAusdrücke funktionieren
il.append(InstructionFactory.createLoad( org.apache.commons.bcel6.generic.Type.OBJECT, 0));
il.append(cg.getInstructionFactory().createInvokeDynamic(interfaceMethodName,this.getSAMSignature(cg),lambdaMethod));
il.append(cg.getInstructionFactory().createInvokeDynamic(interfaceMethodName,this.getLambdaSignature(cg),lambdaType,lambdaMethod));
lambdaMethod.setMaxLocals();
lambdaMethod.setMaxStack();
cg.addMethod(lambdaMethod.getMethod());
cg.addMethod(lambdaMethod.createMethod(cg, params, method_body.getType(), method_body));
return il;
}
private String getSAMSignature(ClassGenerator cg){
private String getLambdaSignature(ClassGenerator cg){
String typeSignature = "(";
return "(LRunnable;)LFun0;";
typeSignature+=this.getParentClass().getType().getBytecodeSignature(cg);
typeSignature += ")";
typeSignature += this.lambdaType.getBytecodeSignature(cg);
return typeSignature;
}
}

View File

@ -17,13 +17,13 @@ import de.dhbwstuttgart.myexception.SCStatementException;
import de.dhbwstuttgart.syntaxtree.Class;
import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode;
import de.dhbwstuttgart.syntaxtree.misc.UsedId;
import de.dhbwstuttgart.syntaxtree.type.FunN;
import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.syntaxtree.type.Void;
import de.dhbwstuttgart.typeinference.ConstraintsSet;
import de.dhbwstuttgart.typeinference.FunN;
import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.ResultSet;
import de.dhbwstuttgart.typeinference.SingleConstraint;

View File

@ -1,16 +1,12 @@
package de.dhbwstuttgart.typeinference;
package de.dhbwstuttgart.syntaxtree.type;
import java.util.Iterator;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.parser.JavaClassName;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.ParameterList;
import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.assumptions.MethodAssumption;
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
@ -120,6 +116,17 @@ public class FunN extends RefType {
return 0;
}
public String getBytecodeInvokeDynamicSignature(ClassGenerator cg) {
String ret = "(";
for(Type t : T){
ret+=t.getBytecodeMethodSignature(cg);
}
ret +=")";
ret+= R.getBytecodeMethodSignature(cg);
return ret;
}
/*
public CMethodTypeAssumption toCMethodTypeAssumption() {
//CMethodTypeAssumption ret = new CMethodTypeAssumption(this, "apply", R, this.T.size(), 0,this.getOffset(),new Menge<Integer>(),null);

View File

@ -818,24 +818,29 @@ public class RefType extends ObjectType implements IMatchable
}
@Override
public String getBytecodeSignature(ClassGenerator cg) {
public String getBytecodeMethodSignature(ClassGenerator cg) {
String paramString = "";
if(this.parameter != null && this.parameter.size()>0){
paramString+="<";
Iterator<Type> it = this.parameter.iterator();
while(it.hasNext()){
Type param = it.next();
paramString+=param.getBytecodeType(cg).getSignature();
paramString+=param.getBytecodeMethodSignature(cg);
//if(it.hasNext())
//paramString+=";"; //kein Delimiter zwischen den Typen
}
paramString+=">";
}
String typeSignature = this.getBytecodeType(cg).getSignature();
String typeSignature = this.getBytecodeSignature(cg);
typeSignature = typeSignature.substring(0, typeSignature.length()-1);
return typeSignature+paramString+";";
}
@Override
public String getBytecodeSignature(ClassGenerator cg) {
return this.getBytecodeType(cg).getSignature();
}
}
// ino.end

View File

@ -159,4 +159,14 @@ public class SuperWildcardType extends WildcardType implements ITypeContainer, I
return new de.dhbwstuttgart.bytecode.WildcardType(this.innerType.get_Name(), "-");
}
@Override
public String getBytecodeSignature(ClassGenerator cg) {
return this.innerType.getBytecodeSignature(cg);
}
@Override
public String getBytecodeMethodSignature(ClassGenerator cg) {
return "-" + this.innerType.getBytecodeMethodSignature(cg);
}
}

View File

@ -310,5 +310,13 @@ public abstract class Type extends SyntaxTreeNode implements IItemWithOffset
public String getBytecodeSignature(ClassGenerator cg) {
return this.getBytecodeType(cg).getSignature();
}
public String getBytecodeMethodSignature(ClassGenerator cg) {
return this.getBytecodeSignature(cg);
}
public String getClassSignature(ClassGenerator cg) {
return this.getBytecodeMethodSignature(cg);
}
}
// ino.end

View File

@ -434,10 +434,34 @@ public class TypePlaceholder extends ObjectType
public org.apache.commons.bcel6.generic.Type getBytecodeType(ClassGenerator cg) {
Type resolvedType = cg.resolveTPH(this);
if(resolvedType instanceof TypePlaceholder){
return new TypePlaceholderType(resolvedType.get_Name());
cg.addUsedTPH((TypePlaceholder)resolvedType);
return new TypePlaceholderType((TypePlaceholder)resolvedType);
}
return resolvedType.getBytecodeType(cg);
}
@Override
public String getBytecodeSignature(ClassGenerator cg) {
return cg.resolveTPH(this).getBytecodeMethodSignature(cg);
}
public String getBytecodeMethodSignature(ClassGenerator cg) {
return super.getBytecodeSignature(cg);
}
@Override
public String getClassSignature(ClassGenerator cg) {
//Die Signaturen in der Klasse bauen sich für Generische Variabeln (also TPHs) folgendermaßen auf: "GVAR:SuperClass"
String ret = this.getBytecodeMethodSignature(cg);
ret = ret.substring(0, ret.length()-1) + ":"; //";" mit ":" ersetzen
org.apache.commons.bcel6.generic.Type nearestType = cg.getNearestType(this);
if(nearestType instanceof TypePlaceholderType){ //Handelt es sich um einen weiteren TPH als nächsten Typ, so ist es ein allgemeiner Typ und wir nehmen Object als Superklasse
ret += cg.getInstructionFactory().createObjectType().getSignature();
}else{
ret += nearestType.getSignature();
}
return ret;
}
}
// ino.end

View File

@ -85,5 +85,12 @@ public class Void extends RefType
return org.apache.commons.bcel6.generic.Type.VOID;
}
public String getBytecodeSignature(ClassGenerator cg) {
return this.getBytecodeType(cg).getSignature();
}
public String getBytecodeMethodSignature(ClassGenerator cg) {
return this.getBytecodeSignature(cg);
}
}
// ino.end

View File

@ -105,6 +105,17 @@ public class WildcardType extends Type{
return this.innerType.getBytecodeType(cg);
}
@Override
public String getBytecodeSignature(ClassGenerator cg) {
return this.innerType.getBytecodeMethodSignature(cg);
}
@Override
public String getBytecodeMethodSignature(ClassGenerator cg) {
return this.innerType.getBytecodeMethodSignature(cg);
}
}

View File

@ -1,5 +1,8 @@
package de.dhbwstuttgart.typeinference;
import java.io.File;
import java.io.IOException;
import org.apache.commons.bcel6.generic.ClassGen;
import de.dhbwstuttgart.typeinference.Menge;
@ -47,4 +50,11 @@ public class ByteCodeResult{
return true;
}
/**
* Schreibt den Bytecode in die übergebene .class Datei
* @throws IOException
*/
public void writeClassToFile(File output) throws IOException{
this.getByteCode().getJavaClass().dump(output);
}
}

View File

@ -7,6 +7,7 @@ import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.parser.JavaClassName;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.ParameterList;
import de.dhbwstuttgart.syntaxtree.type.FunN;
import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.Type;

View File

@ -3,7 +3,20 @@ package de.dhbwstuttgart.typeinference;
import java.util.Set;
import java.util.Vector;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
public class Menge<A> extends Vector<A> implements Set<A>{
public interface Equal<A>{
boolean equal(A a, A b);
}
public boolean contains(A item, Equal<A> eq) {
for(A test : this){
if(eq.equal(item, test))return true;
}
return false;
}
}

View File

@ -115,8 +115,9 @@ public class TypeinferenceResultSet
* Startet die Bytecodegenerierung dieser sung.
* Dabei wird die codegen-Methode der inferierten Klasse mit diesem ResultSet aufgerufen.
*/
public void codegen(){
//TODO: Alles!
public ByteCodeResult codegen(){
ByteCodeResult res = this.ownerOfResultSet.genByteCode(this);
return res;
}
}

View File

@ -10,12 +10,12 @@ import de.dhbwstuttgart.parser.JavaClassName;
import de.dhbwstuttgart.syntaxtree.Class;
import de.dhbwstuttgart.syntaxtree.GTVDeclarationContext;
import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode;
import de.dhbwstuttgart.syntaxtree.type.FunN;
import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.syntaxtree.type.WildcardType;
import de.dhbwstuttgart.typeinference.FunN;
import de.dhbwstuttgart.typeinference.FunNInterface;
import de.dhbwstuttgart.typeinference.FunNMethod;
import de.dhbwstuttgart.typeinference.exceptions.DebugException;

View File

@ -1,5 +1,4 @@
class Identity{
op = (x)->x;
}

View File

@ -1,7 +1,7 @@
class Return{
Integer method() {
return 5;
return 6;
}

View File

@ -10,5 +10,6 @@ public static void main(String[] args){
System.out.println(new FieldDeclaration().field);
System.out.println(new Runnable().method().apply());
Runnable r = new Runnable().method().apply();
//Test t = new Identity().op.apply(this);
}
}