commit 2edb23f2d89ebbea89e6316ac72dca1eebc0d030 Author: JanUlrich Date: Tue Jan 10 14:22:05 2023 +0100 Change BigRefactoring to Gradle build diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..097f9f98 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,9 @@ +# +# https://help.github.com/articles/dealing-with-line-endings/ +# +# Linux start script should use lf +/gradlew text eol=lf + +# These are Windows script files and should use crlf +*.bat text eol=crlf + diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..05825b00 --- /dev/null +++ b/.gitignore @@ -0,0 +1,40 @@ +CVS +bin +*.class +*.log + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.ear + +# IDEs +.classpath +*.iml +.idea/ +/target/ +.DS_Store +.project +.settings/ +/target/ + +# +manually/ + +logFiles/** +!logFiles/.gitkeep + +src/main/java/de/dhbwstuttgart/parser/antlr/ +src/main/java/de/dhbwstuttgart/sat/asp/parser/antlr/ + +#GRADLE +# Ignore Gradle project-specific cache directory +.gradle + +# Ignore Gradle build output directory +build + + diff --git a/app/.build.gradle.kts.swp b/app/.build.gradle.kts.swp new file mode 100644 index 00000000..012d1593 Binary files /dev/null and b/app/.build.gradle.kts.swp differ diff --git a/app/build.gradle.kts b/app/build.gradle.kts new file mode 100644 index 00000000..003960bc --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,53 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * This generated file contains a sample Java application project to get you started. + * For more details take a look at the 'Building Java & JVM projects' chapter in the Gradle + * User Manual available at https://docs.gradle.org/7.6/userguide/building_java_projects.html + */ + +plugins { + // Apply the application plugin to add support for building a CLI application in Java. + antlr + application +} + +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(19)) + } +} + +repositories { + // Use Maven Central for resolving dependencies. + mavenCentral() +} + +dependencies { + // Use JUnit test framework. + testImplementation("junit:junit:4.13.2") + + // This dependency is used by the application. + implementation("com.google.guava:guava:31.1-jre") + implementation("commons-io:commons-io:2.6") + implementation("org.reflections:reflections:0.9.11") + implementation("org.ow2.asm:asm:7.0") + //implementation("org.antlr:antlr4:4.11.1") + antlr("org.antlr:antlr4:4.8-1") +} + + +tasks.withType { + options.compilerArgs.add("--enable-preview") +} +tasks.withType { + jvmArgs("--enable-preview") +} +tasks.withType { + jvmArgs("--enable-preview") +} + +application { + // Define the main class for the application. + mainClass.set("de.dhbwstuttgart.App") +} diff --git a/app/resources/AllgemeinTest/Box.jav b/app/resources/AllgemeinTest/Box.jav new file mode 100644 index 00000000..411f0551 --- /dev/null +++ b/app/resources/AllgemeinTest/Box.jav @@ -0,0 +1,13 @@ +class Box{ +void m(A a){} +} + +class B { } + +class Box_Main extends B { + + m(b) { + b.m(new Box_Main()); + b.m(new B()); + } +} diff --git a/app/resources/AllgemeinTest/Box_Main.jav b/app/resources/AllgemeinTest/Box_Main.jav new file mode 100644 index 00000000..0ba86f19 --- /dev/null +++ b/app/resources/AllgemeinTest/Box_Main.jav @@ -0,0 +1,13 @@ +class Box{ + A f; +} + +class B { } + +class Box_Main extends B {//Fehler Bugzilla Bug 230 + + m(b) { + b.f = new Box_Main(); + b.f = new B(); + } +} diff --git a/app/resources/AllgemeinTest/FCTest1.jav b/app/resources/AllgemeinTest/FCTest1.jav new file mode 100644 index 00000000..98647278 --- /dev/null +++ b/app/resources/AllgemeinTest/FCTest1.jav @@ -0,0 +1,12 @@ +import java.util.Vector; +import java.util.List; +import java.lang.Integer; + +class FCTest1 extends Vector> { + fc1() { + var y; + var z; + y.add(z); + return y; + } +} \ No newline at end of file diff --git a/app/resources/AllgemeinTest/FCTest2.jav b/app/resources/AllgemeinTest/FCTest2.jav new file mode 100644 index 00000000..c3f892dd --- /dev/null +++ b/app/resources/AllgemeinTest/FCTest2.jav @@ -0,0 +1,11 @@ +import java.util.Vector; +import java.util.List; +import java.lang.Integer; + +class FCTest2 extends Vector> { + fc2(y) { + var z; + y.add(z); + return y; + } +} \ No newline at end of file diff --git a/app/resources/AllgemeinTest/FCTest3.jav b/app/resources/AllgemeinTest/FCTest3.jav new file mode 100644 index 00000000..e862c4b8 --- /dev/null +++ b/app/resources/AllgemeinTest/FCTest3.jav @@ -0,0 +1,19 @@ +import java.util.Vector; +import java.lang.Integer; + +class FCTest3 extends Pair, Vector> { + + + fc2(x) { + x.snd().addElement(2); + } + + + + fc2a() { + var y; + y.snd().addElement(2); + return y; + } + +} \ No newline at end of file diff --git a/app/resources/AllgemeinTest/GenTest.jav b/app/resources/AllgemeinTest/GenTest.jav new file mode 100644 index 00000000..409838ae --- /dev/null +++ b/app/resources/AllgemeinTest/GenTest.jav @@ -0,0 +1,10 @@ +import java.lang.Integer; +import java.util.Vector; + +public class GenTest { + + main(x) { + var v = new Vector(); + return 1 + v.elementAt(0); + } +} diff --git a/app/resources/AllgemeinTest/Generics.jav b/app/resources/AllgemeinTest/Generics.jav new file mode 100644 index 00000000..efed04f0 --- /dev/null +++ b/app/resources/AllgemeinTest/Generics.jav @@ -0,0 +1,9 @@ +class Generics { + a; + id(b) { return b; } + setA(x) { + a = x; + return a; + } + m(x,y) { x = id(y); } +} diff --git a/app/resources/AllgemeinTest/M.jav b/app/resources/AllgemeinTest/M.jav new file mode 100755 index 00000000..39e6d482 --- /dev/null +++ b/app/resources/AllgemeinTest/M.jav @@ -0,0 +1,7 @@ +import java.util.List; +class M { +void m(p, p2){ + + new addList().addLists(p, p2); +} +} diff --git a/app/resources/AllgemeinTest/OverloadingMain.jav b/app/resources/AllgemeinTest/OverloadingMain.jav new file mode 100644 index 00000000..960f01db --- /dev/null +++ b/app/resources/AllgemeinTest/OverloadingMain.jav @@ -0,0 +1,9 @@ +import java.util.Stack; +import java.util.Vector; + +class OverloadingMain { + + mmMain(x) { var y; return new O1().mm(y); } + +} + diff --git a/app/resources/AllgemeinTest/Overloading_Generics.jav b/app/resources/AllgemeinTest/Overloading_Generics.jav new file mode 100644 index 00000000..d5691152 --- /dev/null +++ b/app/resources/AllgemeinTest/Overloading_Generics.jav @@ -0,0 +1,20 @@ +import java.lang.Integer; + + +public class Overloading_Generics { + + id1 (x) { return x; } + + //Integer id (Integer x) { return x; } +} + + +class Overloading_Generics1 { + main(x) { + var olg = new Overloading_Generics(); + return olg.id1(1); + } +} + + + diff --git a/app/resources/AllgemeinTest/OverrideMain.jav b/app/resources/AllgemeinTest/OverrideMain.jav new file mode 100644 index 00000000..0ede39ae --- /dev/null +++ b/app/resources/AllgemeinTest/OverrideMain.jav @@ -0,0 +1,25 @@ +import java.util.Vector; +import java.util.Stack; + +class OverrideMain { + ovrMain(x) { + var overide; + overide.ovr(x); + } +} + +/* + [ + [(TPH L = java.util.Stack), (TPH N = java.lang.String), (TPH M = ? extends Override2), (TPH FTN, TPH FTM), (TPH K = void)], +[(TPH FTO, TPH FTP), (TPH M = ? extends Override2), (TPH N = java.lang.String), (TPH L = java.util.Stack), (TPH K = void)], +[(TPH M = ? extends Override2), (TPH N = java.lang.String), (TPH K = void), (TPH FTR, TPH FTQ), (TPH L = java.util.Vector)], +[(TPH FTT, TPH FTS), (TPH M = ? extends Override2), (TPH L = java.util.Vector), (TPH K = void), (TPH N = java.lang.String)], +[(TPH L = java.util.Vector), (TPH M = ? extends Override2), (TPH N = java.lang.String), (TPH FTU, TPH FTV), (TPH K = void)], +[(TPH FTX, TPH FTW), (TPH M = ? extends Override2), (TPH L = java.util.Vector), (TPH K = void), (TPH N = java.lang.String)], +[(TPH M = ? extends Override2), (TPH L = java.util.Stack), (TPH K = void), (TPH FTY, TPH FTZ), (TPH N = java.lang.String)], +[(TPH FUB, TPH FUA), (TPH K = void), (TPH M = ? extends Override2), (TPH N = java.lang.String), (TPH L = java.util.Vector)], +[(TPH N = java.lang.String), (TPH L = java.util.Vector), (TPH FUD, TPH FUC), (TPH M = ? extends Override2), (TPH K = void)], +[(TPH N = java.lang.String), (TPH FUF, TPH FUE), (TPH M = ? extends Override2), (TPH K = void), (TPH L = java.util.Vector)]] + + [[(TPH M = ? extends Override2), (TPH MNX, TPH MNY), (TPH N = java.lang.String), (TPH K = void), (TPH L = java.util.Stack)], [(TPH L = java.util.Stack), (TPH N = java.lang.String), (TPH M = ? extends Override2), (TPH K = void), (TPH MOB, TPH MOC)], [(TPH M = ? extends Override2), (TPH N = java.lang.String), (TPH MNZ, TPH MOA), (TPH L = java.util.Vector), (TPH K = void)], [(TPH L = java.util.Vector), (TPH K = void), (TPH M = ? extends Override2), (TPH MOD, TPH MOE), (TPH N = java.lang.String)], [(TPH M = ? extends Override2), (TPH K = void), (TPH N = java.lang.String), (TPH MOF, TPH MOG), (TPH L = java.util.Stack)], [(TPH L = java.util.Vector), (TPH K = void), (TPH MOH, TPH MOI), (TPH M = ? extends Override2), (TPH N = java.lang.String)], [(TPH L = java.util.Vector), (TPH MOJ, TPH MOK), (TPH K = void), (TPH M = ? extends Override2), (TPH N = java.lang.String)], [(TPH MOL, TPH MOM), (TPH L = java.util.Stack), (TPH M = ? extends Override2), (TPH K = void), (TPH N = java.lang.String)], [(TPH L = java.util.Vector), (TPH MON, TPH MOO), (TPH N = java.lang.String), (TPH K = void), (TPH M = ? extends Override2)], [(TPH L = java.util.Stack), (TPH N = java.lang.String), (TPH M = ? extends Override2), (TPH MOQ, TPH MOP), (TPH K = void)]] +*/ diff --git a/app/resources/AllgemeinTest/OverrideMainRet.jav b/app/resources/AllgemeinTest/OverrideMainRet.jav new file mode 100644 index 00000000..44759c81 --- /dev/null +++ b/app/resources/AllgemeinTest/OverrideMainRet.jav @@ -0,0 +1,11 @@ +import java.util.Vector; +import java.util.Stack; + +class OverrideMainRet { + ovrMain() { + var overide; + var x; + overide.ovr(x); + return x; + } +} \ No newline at end of file diff --git a/app/resources/AllgemeinTest/Pair.java b/app/resources/AllgemeinTest/Pair.java new file mode 100644 index 00000000..b47b1d84 --- /dev/null +++ b/app/resources/AllgemeinTest/Pair.java @@ -0,0 +1,18 @@ +class Pair { + T x; + U y; + + public Pair() { } + public Pair(T x, U y) { + this.x = x; + this.y = y; + } + + public T fst () { + return x; + } + + public U snd () { + return y; + } +} diff --git a/app/resources/AllgemeinTest/Put.jav b/app/resources/AllgemeinTest/Put.jav new file mode 100644 index 00000000..b22977c6 --- /dev/null +++ b/app/resources/AllgemeinTest/Put.jav @@ -0,0 +1,19 @@ +import java.util.Vector; +import java.util.Stack; + +class Put { + + putElement(ele, v) { + v.addElement(ele); + } + + putElement(ele, s) { + s.push(ele); + } + + + main(ele, x) { + putElement(ele, x); + } + +} \ No newline at end of file diff --git a/app/resources/AllgemeinTest/Test.jav b/app/resources/AllgemeinTest/Test.jav new file mode 100644 index 00000000..3d505a85 --- /dev/null +++ b/app/resources/AllgemeinTest/Test.jav @@ -0,0 +1,4 @@ +class Test { + a; + Test b; +} \ No newline at end of file diff --git a/app/resources/AllgemeinTest/TestSubTypless.jav b/app/resources/AllgemeinTest/TestSubTypless.jav new file mode 100644 index 00000000..667fe6e7 --- /dev/null +++ b/app/resources/AllgemeinTest/TestSubTypless.jav @@ -0,0 +1,12 @@ +import java.util.ArrayList; + +class TestSubTypless { + m(a){ + var l = new ArrayList<>(); + l.add(a); + return m2(l).get(0); + } + m2(a){ + return m(a); + } +} \ No newline at end of file diff --git a/app/resources/AllgemeinTest/Twice.jav b/app/resources/AllgemeinTest/Twice.jav new file mode 100644 index 00000000..396bc5e2 --- /dev/null +++ b/app/resources/AllgemeinTest/Twice.jav @@ -0,0 +1,3 @@ +class Twice { + twice = f -> x -> f.apply(f.apply(x)); +} diff --git a/app/resources/AllgemeinTest/Var.jav b/app/resources/AllgemeinTest/Var.jav new file mode 100644 index 00000000..b95b3667 --- /dev/null +++ b/app/resources/AllgemeinTest/Var.jav @@ -0,0 +1,5 @@ +class Var { + + var(x) { var y; } + +} \ No newline at end of file diff --git a/app/resources/AllgemeinTest/VectorConstAdd.jav b/app/resources/AllgemeinTest/VectorConstAdd.jav new file mode 100644 index 00000000..b179bdcc --- /dev/null +++ b/app/resources/AllgemeinTest/VectorConstAdd.jav @@ -0,0 +1,15 @@ +import java.util.Vector; +import java.lang.Integer; + + +public class VectorConstAdd { + vectorAdd(v1) { + var i = 0; + var erg = new Vector<>(); + while (i < v1.size()) { + erg.addElement(v1.elementAt(i) + 1); + i++; + } + return erg; + } +} diff --git a/app/resources/AllgemeinTest/Wildcard_Andi.jav b/app/resources/AllgemeinTest/Wildcard_Andi.jav new file mode 100644 index 00000000..e6160437 --- /dev/null +++ b/app/resources/AllgemeinTest/Wildcard_Andi.jav @@ -0,0 +1,8 @@ +class Wildcard_Andi { + + Test ex = new Test<>(); + + Test sup = new Test<>(); +} + + diff --git a/app/resources/AllgemeinTest/addList.jav b/app/resources/AllgemeinTest/addList.jav new file mode 100755 index 00000000..a72023ea --- /dev/null +++ b/app/resources/AllgemeinTest/addList.jav @@ -0,0 +1,8 @@ +import java.util.List; + +class addList { + addLists(a, b){ +a.add(b.get(0)); +b.add(a.get(0)); +} +} diff --git a/app/resources/AllgemeinTest/wildcardPair.jav b/app/resources/AllgemeinTest/wildcardPair.jav new file mode 100644 index 00000000..73f310f4 --- /dev/null +++ b/app/resources/AllgemeinTest/wildcardPair.jav @@ -0,0 +1,22 @@ +import java.util.List; +import java.lang.Integer; +import java.lang.Object; +import java.lang.Boolean; + +class wildcardPair { + + make(l) { + var p = new Pair(l.get(0), l.get(1)); + return p; + } + //Boolean compare(Pair x) { return true; } + void m(l) { + Object o = l.get(0); + + //Pair p; + //List b; + //this.compare(p); //1, type incorrect + make(l); + //this.compare(this.make(b)); //2, OK + } +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/AA.jav b/app/resources/bytecode/javFiles/AA.jav new file mode 100644 index 00000000..3f8f172d --- /dev/null +++ b/app/resources/bytecode/javFiles/AA.jav @@ -0,0 +1,8 @@ +import java.lang.Integer; +import java.lang.String; + +public class AA { + m(Integer i) { return "AA"; } + + m2(AA x) { return "AA"; } +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/AssignToLit.jav b/app/resources/bytecode/javFiles/AssignToLit.jav new file mode 100644 index 00000000..873828ed --- /dev/null +++ b/app/resources/bytecode/javFiles/AssignToLit.jav @@ -0,0 +1,30 @@ +import java.lang.Integer; +import java.lang.Boolean; +import java.lang.String; +import java.lang.Byte; +import java.lang.Short; +import java.lang.Long; +import java.lang.Float; +import java.lang.Double; +import java.lang.Character; + +class AssignToLit { + void m(){ +// String s = "Test"; +// Boolean b = false; +// Byte byte1 = 5; +// Byte byte2 = 55; +// Short short1 = 5; +// Short short2 = 55; +// Integer int1 = 5; +// Integer int2 = 8888888; +// Long long1 = 1; +// Long long2 = 5; +// Long long3 = 89989898; +// Float float1 = 1; +// Float float2 = 55; +// Double d1 = 1; +// Double d2 = 55; + Character c = 'A'; + } +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/BB.jav b/app/resources/bytecode/javFiles/BB.jav new file mode 100644 index 00000000..27856c42 --- /dev/null +++ b/app/resources/bytecode/javFiles/BB.jav @@ -0,0 +1,3 @@ +import java.lang.Integer; + +public class BB extends AA { } \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/BinaryInMeth.jav b/app/resources/bytecode/javFiles/BinaryInMeth.jav new file mode 100644 index 00000000..3b5fa77b --- /dev/null +++ b/app/resources/bytecode/javFiles/BinaryInMeth.jav @@ -0,0 +1,17 @@ +import java.lang.Integer; +import java.lang.Double; + +public class BinaryInMeth { + + m(a){ + return ++a; + } + + m2(a,b){ + return m(a+b); + } + + m3(a) { + return m(++a); + } +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/CC.jav b/app/resources/bytecode/javFiles/CC.jav new file mode 100644 index 00000000..d7d5c967 --- /dev/null +++ b/app/resources/bytecode/javFiles/CC.jav @@ -0,0 +1,11 @@ +import java.lang.Integer; +import java.lang.String; + + +public class CC extends BB { + m(Integer i) { + return "CC"; + } + + m2(CC x) { return "CC"; } +} diff --git a/app/resources/bytecode/javFiles/ClassGenLam.jav b/app/resources/bytecode/javFiles/ClassGenLam.jav new file mode 100644 index 00000000..0e9cf050 --- /dev/null +++ b/app/resources/bytecode/javFiles/ClassGenLam.jav @@ -0,0 +1,8 @@ +import java.lang.Integer; + +public class ClassGenLam { + lam = x-> x; +// public ClassGenLam() { +// lam = x->x; +// } +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/Cycle.jav b/app/resources/bytecode/javFiles/Cycle.jav new file mode 100644 index 00000000..85f2ba9a --- /dev/null +++ b/app/resources/bytecode/javFiles/Cycle.jav @@ -0,0 +1,6 @@ +class Cycle { + m(x, y) { + y = x; + x = y; + } +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/DD.jav b/app/resources/bytecode/javFiles/DD.jav new file mode 100644 index 00000000..6d49f4c7 --- /dev/null +++ b/app/resources/bytecode/javFiles/DD.jav @@ -0,0 +1,4 @@ +import java.lang.Integer; + +public class DD extends CC { } + diff --git a/app/resources/bytecode/javFiles/DuMethod.jav b/app/resources/bytecode/javFiles/DuMethod.jav new file mode 100644 index 00000000..3898a7ba --- /dev/null +++ b/app/resources/bytecode/javFiles/DuMethod.jav @@ -0,0 +1,11 @@ +public class DuMethod{ + + method(a){ + return a+a; + } + + method(a){ + return a; + } + +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/EmptyMethod.jav b/app/resources/bytecode/javFiles/EmptyMethod.jav new file mode 100644 index 00000000..961989df --- /dev/null +++ b/app/resources/bytecode/javFiles/EmptyMethod.jav @@ -0,0 +1,8 @@ +public class EmptyMethod{ + + public void m1(){ + System.out.println("test"); + } + + public void m2(){} +} diff --git a/app/resources/bytecode/javFiles/Example.jav b/app/resources/bytecode/javFiles/Example.jav new file mode 100644 index 00000000..b7455a3f --- /dev/null +++ b/app/resources/bytecode/javFiles/Example.jav @@ -0,0 +1,9 @@ +import java.lang.String; + +public class Example { + + public m() { + String x = "X"; + return x; + } +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/Exceptions.jav b/app/resources/bytecode/javFiles/Exceptions.jav new file mode 100644 index 00000000..9903511c --- /dev/null +++ b/app/resources/bytecode/javFiles/Exceptions.jav @@ -0,0 +1,3 @@ +public class Exceptions { +// m(Integer i) throws +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/Fac.jav b/app/resources/bytecode/javFiles/Fac.jav new file mode 100644 index 00000000..28650b45 --- /dev/null +++ b/app/resources/bytecode/javFiles/Fac.jav @@ -0,0 +1,15 @@ +import java.lang.Integer; +//import java.lang.Double; + +public class Fac { + + getFac(n){ + var res = 1; + var i = 1; + while(i<=n) { + res = res * i; + i++; + } + return res; + } +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/Faculty.jav b/app/resources/bytecode/javFiles/Faculty.jav new file mode 100644 index 00000000..14007ece --- /dev/null +++ b/app/resources/bytecode/javFiles/Faculty.jav @@ -0,0 +1,52 @@ +import java.lang.Integer; +//import java.lang.Long; +//import java.lang.Short; + +public class Faculty { + public fact; + Faculty() { + fact = (x) -> { + if (x == 1) { + return 1; + } + else { + return x * (fact.apply(x-1)); + } + }; + } + + + + public getFact(x) { + return fact.apply(x); + } +} +// m (x) { +// +//// var fact = (x) -> { +//// if (x == 1) { +//// return x; +//// } +//// else { +//// return x * (fact.apply(x-1)); +//// } +//// }; +//// return fact; +//// var x = 13; +//// if(x>22) { +//// return 0; +//// }else if(x <1){ +//// return x; +//// }else { +//// return 1; +//// } +// +// if (x < 0) { +// return 0; +// }else if(x<2) { +// return x; +// } else { +// return x * m(x-1); +// } +// } +//} diff --git a/app/resources/bytecode/javFiles/Faculty2.jav b/app/resources/bytecode/javFiles/Faculty2.jav new file mode 100644 index 00000000..828f06f5 --- /dev/null +++ b/app/resources/bytecode/javFiles/Faculty2.jav @@ -0,0 +1,10 @@ +class Faculty2 { + + m () { + + var fact = (Integer x) -> { + return x; + }; + return fact; + } +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/Field.jav b/app/resources/bytecode/javFiles/Field.jav new file mode 100644 index 00000000..0fd1133f --- /dev/null +++ b/app/resources/bytecode/javFiles/Field.jav @@ -0,0 +1,9 @@ +import java.lang.Integer; + +public class Field { + public x = 5; + + m(){ + return x; + } +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/FieldTph.jav b/app/resources/bytecode/javFiles/FieldTph.jav new file mode 100644 index 00000000..fc74e539 --- /dev/null +++ b/app/resources/bytecode/javFiles/FieldTph.jav @@ -0,0 +1,4 @@ +public class FieldTph { + a; + +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/FieldTph2.jav b/app/resources/bytecode/javFiles/FieldTph2.jav new file mode 100644 index 00000000..7d60b683 --- /dev/null +++ b/app/resources/bytecode/javFiles/FieldTph2.jav @@ -0,0 +1,12 @@ +public class FieldTph2 { + a; + + m(b){ + b = a; + return b; + } + + m2(c){ + a = c; + } +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/FieldTphConsMeth.jav b/app/resources/bytecode/javFiles/FieldTphConsMeth.jav new file mode 100644 index 00000000..cf195bd2 --- /dev/null +++ b/app/resources/bytecode/javFiles/FieldTphConsMeth.jav @@ -0,0 +1,26 @@ +public class FieldTphConsMeth { + + a; + public FieldTphConsMeth(c) { + a = id(c); + } + + id(b) { + return b; + } + + setA(x) { + a = x; + return a; + } + + m(x,y) { + x = id(y); + } + + /*m2(x,y) { + x = setA(y); + return x; + }*/ + +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/FieldTphMMeth.jav b/app/resources/bytecode/javFiles/FieldTphMMeth.jav new file mode 100644 index 00000000..ad97edc4 --- /dev/null +++ b/app/resources/bytecode/javFiles/FieldTphMMeth.jav @@ -0,0 +1,27 @@ +import java.lang.Boolean; + +public class FieldTphMMeth { + a; + + public FieldTphMMeth(c,d,e) { + a = m(c,d,e); + } + + m(b,d,e) { + if(e) { + return m3(b); + } else{ + return m3(d); + } + + } + + m2(b) { + a = m3(b); + } + + m3(b){ + return b; + } + +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/For.jav b/app/resources/bytecode/javFiles/For.jav new file mode 100644 index 00000000..c4bd6677 --- /dev/null +++ b/app/resources/bytecode/javFiles/For.jav @@ -0,0 +1,30 @@ +import java.lang.Integer; +import java.lang.Boolean; + +class For{ + Integer m(Integer x){ + var c = x + 2; +// Boolean b = true; +// c = 5; +// c++; +// ++c; +// c--; +// --c; +// while(x<2){ +// x = x +1; +// b = false; +// } + return c; +// for(int i = 0;i<10;i++) { +// x = x + 5; +// } + } + +// m2(Integer x){ +// if(x<2) { +// return 1; +// }else { +// return 2; +// } +// } +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/FunOL.jav b/app/resources/bytecode/javFiles/FunOL.jav new file mode 100644 index 00000000..60736e1f --- /dev/null +++ b/app/resources/bytecode/javFiles/FunOL.jav @@ -0,0 +1,12 @@ +import java.util.Vector; +import java.lang.Integer; +import java.lang.String; +//import java.lang.Byte; +//import java.lang.Boolean; + +public class FunOL { + + add(f, y) { + return f.apply() + y; + } +} diff --git a/app/resources/bytecode/javFiles/Gen.jav b/app/resources/bytecode/javFiles/Gen.jav new file mode 100644 index 00000000..3b58b188 --- /dev/null +++ b/app/resources/bytecode/javFiles/Gen.jav @@ -0,0 +1,8 @@ +import java.lang.Integer; +import java.util.Vector; + +public class Gen{ + Vector m(Vector v){ + return v; + } +} diff --git a/app/resources/bytecode/javFiles/Generics.jav b/app/resources/bytecode/javFiles/Generics.jav new file mode 100644 index 00000000..bb7b2af5 --- /dev/null +++ b/app/resources/bytecode/javFiles/Generics.jav @@ -0,0 +1,17 @@ + +class Generics { + Generics(B b){ + } + B mt1(B b){ + return mt1(b); + } +} + + +/* +Problem: +auto test = new List(); +auto test2 = new List(); +... //code, welcher möglicherweise test und test2 vertauscht +test.add("hallo"); +*/ \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/Generics2.jav b/app/resources/bytecode/javFiles/Generics2.jav new file mode 100644 index 00000000..52d5caa2 --- /dev/null +++ b/app/resources/bytecode/javFiles/Generics2.jav @@ -0,0 +1,6 @@ +class Generics2{ + B m1(B b){ + return b; + } + +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/GreaterEqual.jav b/app/resources/bytecode/javFiles/GreaterEqual.jav new file mode 100644 index 00000000..3ec69e8a --- /dev/null +++ b/app/resources/bytecode/javFiles/GreaterEqual.jav @@ -0,0 +1,57 @@ +import java.lang.Integer; +import java.lang.Long; +import java.lang.Float; +import java.lang.Double; + +public class GreaterEqual { + + gE(Integer a, Integer b){ + var c = a>=b; + return c; + } + + gE(Long a, Long b){ + var c = a>=b; + return c; + } + + gE(Float a, Float b){ + var c = a>=b; + return c; + } + + gE(Double a, Double b){ + var c = a>=b; + return c; + } + + gE(Long a, Integer b){ + var c = a>=b; + return c; + } + + gE(Float a, Integer b){ + var c = a>=b; + return c; + } + + gE(Double a, Integer b){ + var c = a>=b; + return c; + } + + gE(Float a, Long b){ + var c = a>=b; + return c; + } + + gE(Double a, Long b){ + var c = a>=b; + return c; + } + + gE(Double a, Float b){ + var c = a>=b; + return c; + } +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/GreaterThan.jav b/app/resources/bytecode/javFiles/GreaterThan.jav new file mode 100644 index 00000000..9077f5b1 --- /dev/null +++ b/app/resources/bytecode/javFiles/GreaterThan.jav @@ -0,0 +1,56 @@ +import java.lang.Integer; +import java.lang.Long; +import java.lang.Float; +import java.lang.Double; + +public class GreaterThan { + gT(Integer a, Integer b){ + var c = a>b; + return c; + } + + gT(Long a, Long b){ + var c = a>b; + return c; + } + + gT(Float a, Float b){ + var c = a>b; + return c; + } + + gT(Double a, Double b){ + var c = a>b; + return c; + } + + gT(Long a, Integer b){ + var c = a>b; + return c; + } + + gT(Float a, Integer b){ + var c = a>b; + return c; + } + + gT(Double a, Integer b){ + var c = a>b; + return c; + } + + gT(Float a, Long b){ + var c = a>b; + return c; + } + + gT(Double a, Long b){ + var c = a>b; + return c; + } + + gT(Double a, Float b){ + var c = a>b; + return c; + } +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/Id.jav b/app/resources/bytecode/javFiles/Id.jav new file mode 100644 index 00000000..03cf2a09 --- /dev/null +++ b/app/resources/bytecode/javFiles/Id.jav @@ -0,0 +1,20 @@ +public class Id { +// a; +// id(b){ +// return b; +// } + id2 = x -> x; +// id2 = () -> { +// var x = m(a); +// var y = x; +// var z = y; +// }; +// +// m(a){ +// return a; +// } + id3 (x) { + return id2.apply(x); + } +} + diff --git a/app/resources/bytecode/javFiles/IfTest.jav b/app/resources/bytecode/javFiles/IfTest.jav new file mode 100644 index 00000000..bbcda96c --- /dev/null +++ b/app/resources/bytecode/javFiles/IfTest.jav @@ -0,0 +1,15 @@ +import java.lang.Integer; +import java.lang.Boolean; +import java.lang.String; + +public class IfTest{ + Integer m1(Boolean b) { + Integer i; + String b; + if(b) { + return i; + }else{ + return b; + } + } +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/Import.jav b/app/resources/bytecode/javFiles/Import.jav new file mode 100644 index 00000000..c658568f --- /dev/null +++ b/app/resources/bytecode/javFiles/Import.jav @@ -0,0 +1,8 @@ +import java.util.Vector; + +class Import { + void methode(){ + Vector v = new Vector<>(); + v.add("X"); + } +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/Inf.jav b/app/resources/bytecode/javFiles/Inf.jav new file mode 100644 index 00000000..788fca8d --- /dev/null +++ b/app/resources/bytecode/javFiles/Inf.jav @@ -0,0 +1,55 @@ +public class Inf { + m(x,y,a){ + var z; + var v; + var w; + var b; + y=x; + z=x; + v=y; + w=y; + y=a; + b=a; + } +} + +/* +TPH M m(TPH N x, TPH O y, TPH P a)({ + TPH Q z; + TPH R v; + TPH S w; + TPH T b; + (y)::TPH O = (x)::TPH N; + (z)::TPH Q = (x)::TPH N; + (v)::TPH R = (y)::TPH O; + (w)::TPH S = (y)::TPH O; + (y)::TPH O = (a)::TPH P; + (b)::TPH T = (a)::TPH P; + return; + })::TPH U + + Inf()({ + super(()); + })::TPH X + +} +// v::R w::S +// \ / +// z::Q y::O b::T +// \ / \ / +// x::N a::P + +RESULT Final: [[(TPH O < TPH S), (TPH P < TPH O), (TPH O < TPH R), (TPH P < TPH T), (TPH M = void), (TPH N < TPH O), (TPH N < TPH Q)]] +Simplified constraints: [(TPH O < TPH S), (TPH P < TPH O), (TPH O < TPH R), (TPH P < TPH T), (TPH N < TPH O), (TPH N < TPH Q)] +m: [(TPH DDV = java.lang.Object), (TPH DDX = java.lang.Object), (TPH DDX < TPH DDV), (TPH N < TPH DDX), (TPH P < TPH DDX)] +Class Inf: [] +Inf: [] + +Unify nach Oder-Constraints-Anpassung: +UND:[(void =. M, , -1 WC: false, IT: false), (N <. O, 1 WC: false, IT: false, 1 WC: false, IT: false), (P <. O, 1 WC: false, IT: false, 1 WC: false, IT: false), (N <. Q, 1 WC: false, IT: false, 0 WC: true, IT: false), (O <. S, 1 WC: false, IT: false, 0 WC: true, IT: false), (O <. R, 1 WC: false, IT: false, 0 WC: true, IT: false), (P <. T, 1 WC: false, IT: false, 0 WC: true, IT: false)] +isInherited = false +isStatement = false + +ODER: +*/ + diff --git a/app/resources/bytecode/javFiles/Infimum.jav b/app/resources/bytecode/javFiles/Infimum.jav new file mode 100644 index 00000000..7c475394 --- /dev/null +++ b/app/resources/bytecode/javFiles/Infimum.jav @@ -0,0 +1,6 @@ +class Infimum { + m(x, y, z) { + y = x; + z = x; + } +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/Inherit.jav b/app/resources/bytecode/javFiles/Inherit.jav new file mode 100644 index 00000000..7b5927d2 --- /dev/null +++ b/app/resources/bytecode/javFiles/Inherit.jav @@ -0,0 +1,18 @@ +import java.util.Vector; + +import java.lang.Integer; +import java.lang.String; + + +public class Inherit { + + main(d, i) { + return d.m(i); + } + + main(v, i) { + var aa = v.elementAt(0); + return aa.m(i); + } + +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/Inherit2.jav b/app/resources/bytecode/javFiles/Inherit2.jav new file mode 100644 index 00000000..fe4c5062 --- /dev/null +++ b/app/resources/bytecode/javFiles/Inherit2.jav @@ -0,0 +1,17 @@ +import java.util.Vector; + +import java.lang.Integer; +import java.lang.String; + + +public class Inherit2 { + + main(d) { + return d.m2(d); + } + + main(v) { + var aa = v.elementAt(0); + return aa.m2(aa); + } +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/Interface1.jav b/app/resources/bytecode/javFiles/Interface1.jav new file mode 100644 index 00000000..b741819c --- /dev/null +++ b/app/resources/bytecode/javFiles/Interface1.jav @@ -0,0 +1,3 @@ +public interface Interface1{ + public void test(); +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/KompTph.jav b/app/resources/bytecode/javFiles/KompTph.jav new file mode 100644 index 00000000..ec34e154 --- /dev/null +++ b/app/resources/bytecode/javFiles/KompTph.jav @@ -0,0 +1,13 @@ +public class KompTph { + public m(a, b, c) { + var d = a; + var e = a; + a = b; + c = b; + m2(a,c); + } + + public m2(a,b){ + m(a,a,b); + } +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/LamRunnable.jav b/app/resources/bytecode/javFiles/LamRunnable.jav new file mode 100644 index 00000000..451858f2 --- /dev/null +++ b/app/resources/bytecode/javFiles/LamRunnable.jav @@ -0,0 +1,9 @@ +public class LamRunnable{ + + public LamRunnable(){ + + Runnable lam = () -> {System.out.println("lambda");}; + lam.run(); + } +} + \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/Lambda.jav b/app/resources/bytecode/javFiles/Lambda.jav new file mode 100644 index 00000000..ba466b18 --- /dev/null +++ b/app/resources/bytecode/javFiles/Lambda.jav @@ -0,0 +1,11 @@ +import java.lang.Integer; + +public class Lambda { + + m () { + var lam1 = (x) -> { + return x; + }; + return lam1; + } +} diff --git a/app/resources/bytecode/javFiles/Lambda2.jav b/app/resources/bytecode/javFiles/Lambda2.jav new file mode 100644 index 00000000..92f32b71 --- /dev/null +++ b/app/resources/bytecode/javFiles/Lambda2.jav @@ -0,0 +1,35 @@ +import java.lang.String; + +public class Lambda2 +{ + public static void main(List args){ + var listOfStrings = new List(); + var listOfObjects; + listOfObjects = map(listOfStrings, (a) -> a); +} + +public map(a , b){ + b.apply(a); + return a; +} + +/* +public static List map(List input, Function func) { + List output; + output = new List(); + output.add(func.apply(input.get())); + return output; +} +*/ +} + +class List{ + /* A get(); + void add(A); + */ +} +/* +class Function{ + B apply(A a); +} +*/ \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/Lambda3.jav b/app/resources/bytecode/javFiles/Lambda3.jav new file mode 100644 index 00000000..9c4e960c --- /dev/null +++ b/app/resources/bytecode/javFiles/Lambda3.jav @@ -0,0 +1,23 @@ + +public class Lambda2 +{ + /* + public static List map(List input, + Function func){ + input.add(func.apply(input.get())); + } + */ + public map(input,func){ + input.add(func.apply(input.get())); + return map(new List(), func); + } +} + +class List{ + A get(); + void add(A); +} + +class Function{ + B apply(A a); +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/Lambda4.jav b/app/resources/bytecode/javFiles/Lambda4.jav new file mode 100644 index 00000000..378eb4d3 --- /dev/null +++ b/app/resources/bytecode/javFiles/Lambda4.jav @@ -0,0 +1,18 @@ +class Lambda{ + +methode(){ + return ((f) -> f); +} +} +/* +interface Fun0{ + A apply(); +} + +interface Fun1{ + A apply(B b); +} +*/ +interface Fun2{ + A apply(B b, C c); +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/LambdaCapture.jav b/app/resources/bytecode/javFiles/LambdaCapture.jav new file mode 100644 index 00000000..ab1751f4 --- /dev/null +++ b/app/resources/bytecode/javFiles/LambdaCapture.jav @@ -0,0 +1,12 @@ +import java.lang.Integer; +public class LambdaCapture { + Integer i = 8; + f; + public LambdaCapture(){ + Integer w = 7; + f = j ->{ + return w+i;}; + + } + +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/LambdaVoid.jav b/app/resources/bytecode/javFiles/LambdaVoid.jav new file mode 100644 index 00000000..dc16fcbf --- /dev/null +++ b/app/resources/bytecode/javFiles/LambdaVoid.jav @@ -0,0 +1,9 @@ +import java.lang.Integer; + +public class Lambda { + + m () { + var lam1 = (x) -> { }; + return lam1; + } +} diff --git a/app/resources/bytecode/javFiles/LessEqual.jav b/app/resources/bytecode/javFiles/LessEqual.jav new file mode 100644 index 00000000..2e3b7024 --- /dev/null +++ b/app/resources/bytecode/javFiles/LessEqual.jav @@ -0,0 +1,56 @@ +import java.lang.Integer; +import java.lang.Long; +import java.lang.Float; +import java.lang.Double; + +public class LessEqual { + lessEqual(Integer a, Integer b){ + var c = a<=b; + return c; + } + + lessEqual(Long a, Long b){ + var c = a<=b; + return c; + } + + lessEqual(Float a, Float b){ + var c = a<=b; + return c; + } + + lessEqual(Double a, Double b){ + var c = a<=b; + return c; + } + + lessEqual(Long a, Integer b){ + var c = a<=b; + return c; + } + + lessEqual(Float a, Integer b){ + var c = a<=b; + return c; + } + + lessEqual(Double a, Integer b){ + var c = a<=b; + return c; + } + + lessEqual(Float a, Long b){ + var c = a<=b; + return c; + } + + lessEqual(Double a, Long b){ + var c = a<=b; + return c; + } + + lessEqual(Double a, Float b){ + var c = a<=b; + return c; + } +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/LessThan.jav b/app/resources/bytecode/javFiles/LessThan.jav new file mode 100644 index 00000000..04e1e83e --- /dev/null +++ b/app/resources/bytecode/javFiles/LessThan.jav @@ -0,0 +1,57 @@ +import java.lang.Integer; +import java.lang.Long; +import java.lang.Float; +import java.lang.Double; + +public class LessThan { + + lessThan(Integer a, Integer b){ + var c = a> { + + Matrix () { + } + + Matrix(vv) { + Integer i; + i = 0; + while(i < vv.size()) { +// Boolean a = this.add(vv.elementAt(i)); + this.add(vv.elementAt(i)); + i=i+1; + } + } + + mul(m) { + var ret = new Matrix(); + var i = 0; + while(i < size()) { + var v1 = this.elementAt(i); + var v2 = new Vector(); + var j = 0; + while(j < v1.size()) { + var erg = 0; + var k = 0; + while(k < v1.size()) { + erg = erg + v1.elementAt(k) + * m.elementAt(k).elementAt(j); + k++; } +// v2.addElement(new Integer(erg)); + v2.addElement(erg); + j++; } + ret.addElement(v2); + i++; + } + return ret; + } +} diff --git a/app/resources/bytecode/javFiles/MatrixOP.jav b/app/resources/bytecode/javFiles/MatrixOP.jav new file mode 100644 index 00000000..21d37347 --- /dev/null +++ b/app/resources/bytecode/javFiles/MatrixOP.jav @@ -0,0 +1,43 @@ +import java.util.Vector; +import java.lang.Integer; +//import java.lang.Byte; +import java.lang.Boolean; + +public class MatrixOP extends Vector> { + + MatrixOP () { + } + + MatrixOP(vv) { + Integer i; + i = 0; + while(i < vv.size()) { +// Boolean a = this.add(vv.elementAt(i)); + this.add(vv.elementAt(i)); + i=i+1; + } + } + + public mul = (m1, m2) -> { + var ret = new MatrixOP(); + var i = 0; + while(i < m1.size()) { + var v1 = m1.elementAt(i); + var v2 = new Vector(); + var j = 0; + while(j < v1.size()) { + var erg = 0; + var k = 0; + while(k < v1.size()) { + erg = erg + v1.elementAt(k) + * m2.elementAt(k).elementAt(j); + k++; } +// v2.addElement(new Integer(erg)); + v2.addElement(erg); + j++; } + ret.addElement(v2); + i++; + } + return ret; + }; +} diff --git a/app/resources/bytecode/javFiles/Merge.jav b/app/resources/bytecode/javFiles/Merge.jav new file mode 100644 index 00000000..ad5e103e --- /dev/null +++ b/app/resources/bytecode/javFiles/Merge.jav @@ -0,0 +1,20 @@ +import java.util.List; +import java.lang.Integer; +//import java.util.Collection; + +class Merge { + + merge(a, b) { + a.addAll(b); + return a; + } + + + + sort(in){ + var firstHalf = in.subList(1,2); + var secondHalf = in.subList(1,2); + return merge(sort(firstHalf), sort(secondHalf)); + } + +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/Methods.jav b/app/resources/bytecode/javFiles/Methods.jav new file mode 100644 index 00000000..3c46739d --- /dev/null +++ b/app/resources/bytecode/javFiles/Methods.jav @@ -0,0 +1,14 @@ +import java.lang.Integer; + +class Methods { + + m(a,b){ + var c=a+b; + return c; + } + + method2(x){ + Integer i = this.m(x,2); + return i; + } +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/OL.jav b/app/resources/bytecode/javFiles/OL.jav new file mode 100644 index 00000000..4eab848f --- /dev/null +++ b/app/resources/bytecode/javFiles/OL.jav @@ -0,0 +1,32 @@ +import java.lang.String; +import java.lang.Integer; +import java.lang.Double; +import java.lang.Boolean; +//import java.util.Vector; + + +public class OL { + + java.lang.Double m(java.lang.Double x) { return x + x; } + java.lang.Integer m(java.lang.Integer x) { return x + x; } + java.lang.String m(java.lang.String x) { return x + x; } + java.lang.Boolean m(Boolean x) { return x; } + +// if the class contains just this method, then correct BC will be generated. +// But if another methods are contained then the generated BC is not correct +// m(x) { +// //x.add(1); +// x.addAll(x); +// return x; +// } + +} + +public class OLMain { + + main(x) { + var ol; + ol = new OL(); + return ol.m(x); + } +} diff --git a/app/resources/bytecode/javFiles/OLFun.jav b/app/resources/bytecode/javFiles/OLFun.jav new file mode 100644 index 00000000..adf8c6a8 --- /dev/null +++ b/app/resources/bytecode/javFiles/OLFun.jav @@ -0,0 +1,13 @@ +import java.lang.String; +import java.lang.Integer; +import java.lang.Double; +import java.util.Vector; +import java.lang.Boolean; + +public class OLFun { + + //f = x -> {return x + x;}; + m(f, x) { + x = f.apply(x+x); + } +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/OLFun2.jav b/app/resources/bytecode/javFiles/OLFun2.jav new file mode 100644 index 00000000..406c0d98 --- /dev/null +++ b/app/resources/bytecode/javFiles/OLFun2.jav @@ -0,0 +1,13 @@ +import java.lang.String; +import java.lang.Integer; +import java.lang.Double; +import java.util.Vector; +import java.lang.Boolean; + +public class OLFun2 { + + x; + m(f){ + x = f.apply(x + x) + } +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/Op.jav b/app/resources/bytecode/javFiles/Op.jav new file mode 100644 index 00000000..082f48d8 --- /dev/null +++ b/app/resources/bytecode/javFiles/Op.jav @@ -0,0 +1,16 @@ +import java.lang.Integer; +import java.lang.String; +import java.lang.Long; +import java.lang.Float; +import java.lang.Double; +import java.lang.Boolean; +import java.lang.Short; +import java.lang.Byte; + +public class Op { + + m(a, b) { + //var c = a+b; + return a+b; + } +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/Op2.jav b/app/resources/bytecode/javFiles/Op2.jav new file mode 100644 index 00000000..9d446eb2 --- /dev/null +++ b/app/resources/bytecode/javFiles/Op2.jav @@ -0,0 +1,11 @@ +import java.lang.Integer; +import java.lang.String; + +public class Op2 { + m(){ + var x = ""; + var a = 5+x; + + return a; + } +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/OverlaodGen.jav b/app/resources/bytecode/javFiles/OverlaodGen.jav new file mode 100644 index 00000000..d5946496 --- /dev/null +++ b/app/resources/bytecode/javFiles/OverlaodGen.jav @@ -0,0 +1,11 @@ +import java.util.Vector; + +class OverlaodGen { + void method(Vector v) { +// Integer i = v.get(0); + } + + void method(Vector v) { +// String s = v.get(0); + } +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/Overloading.jav b/app/resources/bytecode/javFiles/Overloading.jav new file mode 100644 index 00000000..fb48fe0f --- /dev/null +++ b/app/resources/bytecode/javFiles/Overloading.jav @@ -0,0 +1,18 @@ +import java.lang.String; + +public class Overloading{ + + test(x){ + return x.methode(); + } + + methode(){ + return "Overloading"; + } +} + +public class Overloading2{ + methode(){ + return "Overloading2"; + } +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/Plus.jav b/app/resources/bytecode/javFiles/Plus.jav new file mode 100644 index 00000000..1cdecc8c --- /dev/null +++ b/app/resources/bytecode/javFiles/Plus.jav @@ -0,0 +1,9 @@ +import java.lang.Integer; +import java.lang.String; + +public class Plus { + + m(a,b) { + return a+b; + } +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/PostIncDec.jav b/app/resources/bytecode/javFiles/PostIncDec.jav new file mode 100644 index 00000000..29c2ef17 --- /dev/null +++ b/app/resources/bytecode/javFiles/PostIncDec.jav @@ -0,0 +1,27 @@ +import java.lang.Integer; + +public class PostIncDec { + m() { + var i = 0; + i++; + return i; + } + + m2() { + var i = 0; + var j = i++; + return j; + } + + d() { + var i = 0; + i--; + return i; + } + + d2() { + var i = 0; + var j = i--; + return j; + } +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/PreInc.jav b/app/resources/bytecode/javFiles/PreInc.jav new file mode 100644 index 00000000..011501f1 --- /dev/null +++ b/app/resources/bytecode/javFiles/PreInc.jav @@ -0,0 +1,28 @@ +import java.lang.Integer; + +public class PreInc { + m() { + var i = 0; + ++i; + return i; + } + + m2() { + var i = 0; + var j = ++i; + return j; + } + + d() { + var i = 0; + --i; + return i; + } + + d2() { + var i = 0; + var j = --i; + return j; + } + +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/Put.jav b/app/resources/bytecode/javFiles/Put.jav new file mode 100644 index 00000000..79a1cfa1 --- /dev/null +++ b/app/resources/bytecode/javFiles/Put.jav @@ -0,0 +1,19 @@ +import java.util.Vector; +import java.util.Stack; + +public class Put { + + putElement(ele, v) { + v.addElement(ele); + } + + putElement(ele, s) { + s.push(ele); + } + + + main(ele, x) { + putElement(ele, x); + } + +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/RecursiveMeth.jav b/app/resources/bytecode/javFiles/RecursiveMeth.jav new file mode 100644 index 00000000..be35a43c --- /dev/null +++ b/app/resources/bytecode/javFiles/RecursiveMeth.jav @@ -0,0 +1,5 @@ +public class RecursiveMeth{ + public Integer test(){ + return this.test(); + } +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/RelOps.jav b/app/resources/bytecode/javFiles/RelOps.jav new file mode 100644 index 00000000..0fdd2cff --- /dev/null +++ b/app/resources/bytecode/javFiles/RelOps.jav @@ -0,0 +1,8 @@ +import java.lang.Integer; +import java.lang.Boolean; + +public class RelOps { + m(a,b){ + return a { + +} + +public class SubMatrix extends Matrix2 { + m(){ + Vector v = new Vector(); + v.add(1); + } +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/Tph.jav b/app/resources/bytecode/javFiles/Tph.jav new file mode 100644 index 00000000..3f9d0aab --- /dev/null +++ b/app/resources/bytecode/javFiles/Tph.jav @@ -0,0 +1,11 @@ +public class Tph { + + m(a,b){ + var c = m2(b); + return a; + } + + m2(b){ + return b; + } +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/Tph2.jav b/app/resources/bytecode/javFiles/Tph2.jav new file mode 100644 index 00000000..2f9c53e6 --- /dev/null +++ b/app/resources/bytecode/javFiles/Tph2.jav @@ -0,0 +1,18 @@ +public class Tph2 { + id = x->x; + id3 (x) { + return id.apply(x); + } + +/* + m(a,b){ + var c = m2(a,b); + //m2(a,b); + return a; + } + + m2(a,b){ + return b; + } +*/ +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/Tph3.jav b/app/resources/bytecode/javFiles/Tph3.jav new file mode 100644 index 00000000..553e2745 --- /dev/null +++ b/app/resources/bytecode/javFiles/Tph3.jav @@ -0,0 +1,14 @@ +public class Tph3 { +// m(a,b){ +// var c = m2(a,b); +// return c; +// } +// +// m2(a,b){ +// return m(a,b); +// } + m1(x, y) { m2(x); x = y; + } + + m2(y) { m1(y, y); } +} diff --git a/app/resources/bytecode/javFiles/Tph4.jav b/app/resources/bytecode/javFiles/Tph4.jav new file mode 100644 index 00000000..58fe1d16 --- /dev/null +++ b/app/resources/bytecode/javFiles/Tph4.jav @@ -0,0 +1,12 @@ +public class Tph4{ + m(a,b){ + var c = m2(b); + var d = m2(c); + return d; + } + + m2(b){ + return b; + } + +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/Tph5.jav b/app/resources/bytecode/javFiles/Tph5.jav new file mode 100644 index 00000000..e73cfa2c --- /dev/null +++ b/app/resources/bytecode/javFiles/Tph5.jav @@ -0,0 +1,13 @@ +public class Tph5 { +// m(a,b,c){ +// a = c; +// b = c; +// return a; +// } + + m(x,y){ + x = m2(y); + } + + m2(y) { return y; } +} diff --git a/app/resources/bytecode/javFiles/Tph6.jav b/app/resources/bytecode/javFiles/Tph6.jav new file mode 100644 index 00000000..2f9e4294 --- /dev/null +++ b/app/resources/bytecode/javFiles/Tph6.jav @@ -0,0 +1,14 @@ +public class Tph6 { +// m(a,b,c){ +// a = c; +// b = c; +// return a; +// } + + m(x,y){ + var c = m2(y); + c = m2(x); + } + + m2(y) { return y; } +} diff --git a/app/resources/bytecode/javFiles/Tph7.jav b/app/resources/bytecode/javFiles/Tph7.jav new file mode 100644 index 00000000..cc55afb5 --- /dev/null +++ b/app/resources/bytecode/javFiles/Tph7.jav @@ -0,0 +1,11 @@ +public class Tph7 { + + m(a,b){ + var c = m2(b); + return m2(b); + } + + m2(b){ + return b; + } +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/TypedID.jav b/app/resources/bytecode/javFiles/TypedID.jav new file mode 100644 index 00000000..aa885831 --- /dev/null +++ b/app/resources/bytecode/javFiles/TypedID.jav @@ -0,0 +1,12 @@ +public class TypedID/* */ { + + lam = x-> x; + + id(b){ + return b; + } + + m(){ + return lam; + } +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/VectorAdd.jav b/app/resources/bytecode/javFiles/VectorAdd.jav new file mode 100644 index 00000000..d5e50157 --- /dev/null +++ b/app/resources/bytecode/javFiles/VectorAdd.jav @@ -0,0 +1,16 @@ +import java.util.Vector; +import java.lang.Integer; + + +public class VectorAdd { + vectorAdd(v1, v2) { + var i = 0; + v1 = new Vector(); + var erg = new Vector<>(); + while (i < v1.size()) { + erg.addElement(v1.elementAt(i) + v2.elementAt(i)); + i++; + } + return erg; + } +} diff --git a/app/resources/bytecode/javFiles/VectorSuper.jav b/app/resources/bytecode/javFiles/VectorSuper.jav new file mode 100644 index 00000000..fbadafb2 --- /dev/null +++ b/app/resources/bytecode/javFiles/VectorSuper.jav @@ -0,0 +1,11 @@ +import java.util.Vector; +import java.lang.Integer; + +public class VectorSuper { + + m(x){ + Integer y = 1; + x.addElement(y); + //return x; + } +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/VoidMeth.jav b/app/resources/bytecode/javFiles/VoidMeth.jav new file mode 100644 index 00000000..6b3ab212 --- /dev/null +++ b/app/resources/bytecode/javFiles/VoidMeth.jav @@ -0,0 +1,4 @@ +public class VoidMeth{ + public void test(){ + } +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/WC.jav b/app/resources/bytecode/javFiles/WC.jav new file mode 100644 index 00000000..389a4fcd --- /dev/null +++ b/app/resources/bytecode/javFiles/WC.jav @@ -0,0 +1,8 @@ +import java.lang.Integer; +import java.util.List; +public class WC { + + void m (List a, List b) { + + } +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/While.jav b/app/resources/bytecode/javFiles/While.jav new file mode 100644 index 00000000..cd2139a6 --- /dev/null +++ b/app/resources/bytecode/javFiles/While.jav @@ -0,0 +1,12 @@ +import java.lang.Integer; +import java.lang.Long; +import java.lang.Double; + +public class While { + m(x) { + while(x < 2) { + x = x+1; + } + return x; + } +} \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/Y.jav b/app/resources/bytecode/javFiles/Y.jav new file mode 100644 index 00000000..a97360d4 --- /dev/null +++ b/app/resources/bytecode/javFiles/Y.jav @@ -0,0 +1,42 @@ +import java.lang.Integer; + +class Y { + y; + //factorial; + + Y() { + y = f -> t -> f.apply(y.apply(f)).apply(t); + //factorial = y.apply(f -> n -> { if (n == 0) return 1; else return n * f.apply(n - 1); }); + } + /* + getY() { + return y; + } + */ +} +/* +class fac1 { + factorial; + + fac1() { + var y; + y = new Y().getY(); + factorial = y.apply(f -> n -> { if (n == 0) return 1; else return n * f.apply(n - 1); }); + } +} + +ergibt Parse-Error +class fac1 { + factorial; + + fac1() { + var y; + y = new Y<>().y; + factorial = y.apply(f -> n -> { if (n == 0) return 1; else return n * f.apply(n - 1); }); + } + public static void main(String args[]) { + System.out.println(new fac1().factorial.apply(3)); + } + +} +*/ \ No newline at end of file diff --git a/app/resources/bytecode/javFiles/applyLambda.jav b/app/resources/bytecode/javFiles/applyLambda.jav new file mode 100644 index 00000000..331bfbfe --- /dev/null +++ b/app/resources/bytecode/javFiles/applyLambda.jav @@ -0,0 +1,16 @@ +import java.util.Vector; +class Apply { } + +public class applyLambda { + + m () { + var lam1 = (x) -> { + return x; + }; + + return lam1.apply(new Apply()); + //return lam1; + //return new Vector(); + } +} + diff --git a/app/resources/bytecode/javFiles/mathStruc.jav b/app/resources/bytecode/javFiles/mathStruc.jav new file mode 100644 index 00000000..171881b1 --- /dev/null +++ b/app/resources/bytecode/javFiles/mathStruc.jav @@ -0,0 +1,15 @@ +import java.util.Vector; +import java.lang.Integer; + +public class mathStruc { + model; + + //Fun1*, Fun1*,MathStruc >> + innerOp = (o) -> (ms) -> new mathStruc<>(o.apply(model,ms.model)); + + public mathStruc(m) { + model =m; + //innerOp = (o) -> (ms) -> new mathStruc<>(o.apply(this.model,ms.model)); + } +} + diff --git a/app/resources/bytecode/javFiles/mathStrucInteger.jav b/app/resources/bytecode/javFiles/mathStrucInteger.jav new file mode 100644 index 00000000..f1f67553 --- /dev/null +++ b/app/resources/bytecode/javFiles/mathStrucInteger.jav @@ -0,0 +1,23 @@ +import java.util.Vector; +import java.lang.Integer; + +public class mathStrucInteger { + model; + + innerOp = (o) -> (ms) -> new mathStrucInteger<>(o.apply(model,ms.model)); + + public mathStrucInteger(m) { + model =m; + } +} + +class mathStrucIntegerUse { + + main() { + var ms; + ms = new mathStrucInteger<>(2); + var ms2; + ms2 = ms.innerOp.apply((x,y) -> x+y).apply(ms); + return ms2; + } +} diff --git a/app/resources/bytecode/javFiles/mathStrucMatrixOP.jav b/app/resources/bytecode/javFiles/mathStrucMatrixOP.jav new file mode 100644 index 00000000..2b24f037 --- /dev/null +++ b/app/resources/bytecode/javFiles/mathStrucMatrixOP.jav @@ -0,0 +1,91 @@ +//PL 2019-10-24: laeuft nicht durch, zu gross +import java.util.Vector; +import java.lang.Integer; +import java.lang.Boolean; + +public class mathStrucMatrixOP { + model; + + innerOp = (o) -> (ms) -> new mathStrucMatrixOP<>(o.apply(model,ms.model)); + + public mathStrucMatrixOP(m) { + model =m; + } +} + +public class MatrixOP extends Vector> { + + MatrixOP () { + } + + MatrixOP(vv) { + Integer i; + i = 0; + while(i < vv.size()) { +// Boolean a = this.add(vv.elementAt(i)); + this.add(vv.elementAt(i)); + i=i+1; + } + } + + public mul = (m1, m2) -> { + var ret = new MatrixOP(); + var i = 0; + while(i < m1.size()) { + var v1 = m1.elementAt(i); + var v2 = new Vector(); + var j = 0; + while(j < v1.size()) { + var erg = 0; + var k = 0; + while(k < v1.size()) { + erg = erg + v1.elementAt(k) + * m2.elementAt(k).elementAt(j); + k++; } +// v2.addElement(new Integer(erg)); + v2.addElement(erg); + j++; } + ret.addElement(v2); + i++; + } + return ret; + }; +} + + +class mathStrucUseMatrixOP { + + main() { + Vector> vv = new Vector>(); + Vector v1 = new Vector(); + v1.addElement(2); + v1.addElement(2); + Vector v2 = new Vector(); + v2.addElement(3); + v2.addElement(3); + vv.addElement(v1); + vv.addElement(v2); + + MatrixOP m1 = new MatrixOP(vv); + + Vector> vv1 = new Vector>(); + Vector v3 = new Vector(); + v3.addElement(2); + v3.addElement(2); + Vector v4 = new Vector(); + v4.addElement(3); + v4.addElement(3); + vv1.addElement(v3); + vv1.addElement(v4); + + MatrixOP m2 = new MatrixOP(vv1); + + var mms; + mms = new mathStrucMatrixOP<>(m1); + var mms2; + mms2 = new mathStrucMatrixOP<>(m2); + var mms3; + mms3 = mms.innerOp.apply(m1.mul).apply(mms2); + return mms3; + } +} diff --git a/app/resources/insertGenericsJav/TestAny.jav b/app/resources/insertGenericsJav/TestAny.jav new file mode 100644 index 00000000..86c0ceb1 --- /dev/null +++ b/app/resources/insertGenericsJav/TestAny.jav @@ -0,0 +1,13 @@ +class TestAny { + a; + b = a; + anyMethod() { + var f; + return f; + } + otherMethod(e) { + b = e; + e = a; + return e; + } +} \ No newline at end of file diff --git a/app/resources/insertGenericsJav/TestClassField.jav b/app/resources/insertGenericsJav/TestClassField.jav new file mode 100644 index 00000000..f3d24e51 --- /dev/null +++ b/app/resources/insertGenericsJav/TestClassField.jav @@ -0,0 +1,6 @@ +class Example{ + f; + fReturn(){ + return f; + } +} \ No newline at end of file diff --git a/app/resources/insertGenericsJav/TestContraVariant.jav b/app/resources/insertGenericsJav/TestContraVariant.jav new file mode 100644 index 00000000..9349e620 --- /dev/null +++ b/app/resources/insertGenericsJav/TestContraVariant.jav @@ -0,0 +1,12 @@ +public class TestContraVariant { + + m(x) { + var y; + x = y; + return y; + } + + main(x) { + return m(x); + } +} \ No newline at end of file diff --git a/app/resources/insertGenericsJav/TestGGFinder.jav b/app/resources/insertGenericsJav/TestGGFinder.jav new file mode 100644 index 00000000..cc94cad5 --- /dev/null +++ b/app/resources/insertGenericsJav/TestGGFinder.jav @@ -0,0 +1,17 @@ +public class TestGGFinder { + a; + + id(b) { + var c = b; + return c; + } + + setA(x) { + a = x; + return a; + } + + m(x,y) { + x = id(y); + } +} \ No newline at end of file diff --git a/app/resources/insertGenericsJav/TestLocalVarLambda.jav b/app/resources/insertGenericsJav/TestLocalVarLambda.jav new file mode 100644 index 00000000..ab4455c7 --- /dev/null +++ b/app/resources/insertGenericsJav/TestLocalVarLambda.jav @@ -0,0 +1,7 @@ +public class TestLocalVarLambda { + +m(x) { + var id = z -> z; + return id.apply(x); + } +} \ No newline at end of file diff --git a/app/resources/insertGenericsJav/TestMutualRecursion.jav b/app/resources/insertGenericsJav/TestMutualRecursion.jav new file mode 100644 index 00000000..60ce72ca --- /dev/null +++ b/app/resources/insertGenericsJav/TestMutualRecursion.jav @@ -0,0 +1,17 @@ +public class TestMutualRecursion { + a; + + id(b) { + var c = b; + return main(b,c); + } + + m(x,y) { + x = id(y); + return x; + } + + main(x,y) { + return m(id(x),y); + } +} \ No newline at end of file diff --git a/app/resources/insertGenericsJav/TestMutualRecursionWithField.jav b/app/resources/insertGenericsJav/TestMutualRecursionWithField.jav new file mode 100644 index 00000000..82dc42d2 --- /dev/null +++ b/app/resources/insertGenericsJav/TestMutualRecursionWithField.jav @@ -0,0 +1,22 @@ +public class TestMutualRecursionWithField { + a; + + id(b) { + var c = b; + return main(b,c); + } + + setA(x) { + a = x; + return a; + } + + m(x,y) { + x = id(y); + return x; + } + + main(x,y) { + return m(id(x),setA(y)); + } +} \ No newline at end of file diff --git a/app/resources/insertGenericsJav/TestMutualRecursionWithField2.jav b/app/resources/insertGenericsJav/TestMutualRecursionWithField2.jav new file mode 100644 index 00000000..727e6031 --- /dev/null +++ b/app/resources/insertGenericsJav/TestMutualRecursionWithField2.jav @@ -0,0 +1,22 @@ +public class TestMutualRecursionWithField2 { + a; + + id(b) { + var c = b; + return main(b,c); + } + + setA(x) { + a = x; + return a; + } + + m(x,y) { + x = id(y); + return x; + } + + main(x,y) { + return m(setA(x),id(y)); + } +} \ No newline at end of file diff --git a/app/resources/insertGenericsJav/TestMutualRecursionWithField3.jav b/app/resources/insertGenericsJav/TestMutualRecursionWithField3.jav new file mode 100644 index 00000000..24e09890 --- /dev/null +++ b/app/resources/insertGenericsJav/TestMutualRecursionWithField3.jav @@ -0,0 +1,23 @@ +public class TestMutualRecursionWithField3 { + a; + + id(b) { + var c = b; + return main(b,c); + } + + setA(x) { + a = x; + return a; + } + + m(x,y) { + x = id(y); + return x; + } + + main(x,y) { + var z = m(setA(x),id(y)); + return z; + } +} \ No newline at end of file diff --git a/app/resources/insertGenericsJav/TestReturnVar.jav b/app/resources/insertGenericsJav/TestReturnVar.jav new file mode 100644 index 00000000..0688e5b8 --- /dev/null +++ b/app/resources/insertGenericsJav/TestReturnVar.jav @@ -0,0 +1,6 @@ +class VarReturn { + anyMethod() { + var f; + return f; + } +} \ No newline at end of file diff --git a/app/resources/insertGenericsJav/TestSecondLineOfClassConstraints.jav b/app/resources/insertGenericsJav/TestSecondLineOfClassConstraints.jav new file mode 100644 index 00000000..16275a50 --- /dev/null +++ b/app/resources/insertGenericsJav/TestSecondLineOfClassConstraints.jav @@ -0,0 +1,12 @@ +class Example { + a; + b = a; + anyMethod() { + var f; + return f; + } + otherMethod(e) { + e = a; + return e; + } +} \ No newline at end of file diff --git a/app/resources/insertGenericsJav/TestTPHsAndGenerics.jav b/app/resources/insertGenericsJav/TestTPHsAndGenerics.jav new file mode 100644 index 00000000..33a79e51 --- /dev/null +++ b/app/resources/insertGenericsJav/TestTPHsAndGenerics.jav @@ -0,0 +1,13 @@ +class TPHsAndGenerics { + id = x -> x; + id2 (x) { + return id.apply(x); + } + m(a, b){ + var c = m2(a,b); + return a; + } + m2(a, b){ + return b; + } +} \ No newline at end of file diff --git a/app/resources/insertGenericsJav/TestTPHsAndGenerics2.jav b/app/resources/insertGenericsJav/TestTPHsAndGenerics2.jav new file mode 100644 index 00000000..9cdc21f7 --- /dev/null +++ b/app/resources/insertGenericsJav/TestTPHsAndGenerics2.jav @@ -0,0 +1,13 @@ +class TPHsAndGenerics2 { + id = x -> x; + id2 (x) { + return id.apply(x); + } + m(a, b){ + var c = m2(a,b); + return a; + } + m2(a, b){ + return b; + } +} \ No newline at end of file diff --git a/app/resources/insertGenericsJav/TestThreeArgs.jav b/app/resources/insertGenericsJav/TestThreeArgs.jav new file mode 100644 index 00000000..fe22dd3c --- /dev/null +++ b/app/resources/insertGenericsJav/TestThreeArgs.jav @@ -0,0 +1,15 @@ +public class TestThreeArgs { + a; + + id(b) { + var a /* = null */; + var c = b; + m(a,a,b); + return c; + } + + m(x,y, z) { + x = id(y); + return x; + } +} \ No newline at end of file diff --git a/app/resources/insertGenericsJav/TestTwoArgs.jav b/app/resources/insertGenericsJav/TestTwoArgs.jav new file mode 100644 index 00000000..84631151 --- /dev/null +++ b/app/resources/insertGenericsJav/TestTwoArgs.jav @@ -0,0 +1,22 @@ +public class TestTwoArgs { + a; + + id(b) { + var c = b; + return c; + } + + setA(x) { + a = x; + return a; + } + + m(x,y) { + x = id(y); + return x; + } + + main(x,y) { + return m(id(x),setA(y)); + } +} \ No newline at end of file diff --git a/app/resources/insertGenericsJav/TestTwoArgs2.jav b/app/resources/insertGenericsJav/TestTwoArgs2.jav new file mode 100644 index 00000000..f8c270a7 --- /dev/null +++ b/app/resources/insertGenericsJav/TestTwoArgs2.jav @@ -0,0 +1,17 @@ +public class TestTwoArgs2 { + a; + + id(b) { + var c = b; + return c; + } + + m(x,y) { + x = id(y); + return x; + } + + main(x,y) { + return m(id(x),m(x,y)); + } +} \ No newline at end of file diff --git a/app/resources/insertGenericsJav/TestTwoCalls.jav b/app/resources/insertGenericsJav/TestTwoCalls.jav new file mode 100644 index 00000000..be3137f0 --- /dev/null +++ b/app/resources/insertGenericsJav/TestTwoCalls.jav @@ -0,0 +1,12 @@ +public class TestTwoCalls { + + id(b) { + var c = b; + return c; + } + + main(x,y) { + id(x); + return id(y); + } +} \ No newline at end of file diff --git a/app/resources/insertGenericsJav/TestVector.jav b/app/resources/insertGenericsJav/TestVector.jav new file mode 100644 index 00000000..1519afb7 --- /dev/null +++ b/app/resources/insertGenericsJav/TestVector.jav @@ -0,0 +1,12 @@ +import java.util.Vector; + +public class TestVector { + + m(v, w) { + w.addElement(id(v.elementAt(0))); + } + + id(x) { + return x; + } +} \ No newline at end of file diff --git a/app/resources/insertGenericsJav/TestVectorArg.jav b/app/resources/insertGenericsJav/TestVectorArg.jav new file mode 100644 index 00000000..ca29f820 --- /dev/null +++ b/app/resources/insertGenericsJav/TestVectorArg.jav @@ -0,0 +1,12 @@ +import java.util.Vector; + +public class TestVectorArg { + + add(v, e) { + v.addElement(e); + } + + main(v, e) { + add(v, e); + } +} \ No newline at end of file diff --git a/app/resources/insertGenericsJav/TestVoidMeth.jav b/app/resources/insertGenericsJav/TestVoidMeth.jav new file mode 100644 index 00000000..50ee7206 --- /dev/null +++ b/app/resources/insertGenericsJav/TestVoidMeth.jav @@ -0,0 +1,4 @@ +class VoidMeth { + anyMethod() { + } +} \ No newline at end of file diff --git a/app/resources/javFiles/AddLong.jav b/app/resources/javFiles/AddLong.jav new file mode 100644 index 00000000..d6d47e9f --- /dev/null +++ b/app/resources/javFiles/AddLong.jav @@ -0,0 +1,9 @@ +import java.lang.Integer; +import java.lang.Long; + +public class AddLong{ + Long add(Integer a, Long b) { + Long c = a+b; + return c; + } +} \ No newline at end of file diff --git a/app/resources/javFiles/EmptyClass.jav b/app/resources/javFiles/EmptyClass.jav new file mode 100644 index 00000000..8160d7da --- /dev/null +++ b/app/resources/javFiles/EmptyClass.jav @@ -0,0 +1,3 @@ +public class EmptyClass{ + +} \ No newline at end of file diff --git a/app/resources/javFiles/EmptyMethod.jav b/app/resources/javFiles/EmptyMethod.jav new file mode 100644 index 00000000..dd28fc69 --- /dev/null +++ b/app/resources/javFiles/EmptyMethod.jav @@ -0,0 +1,37 @@ +public class EmptyMethod{ + static String s1 =""; + String s2; + public void m1(){ + //String s = ""; + System.out.println("test"); + //Integer ab = Math.abs(1); + //Math.abs(1); + //String lV = "local"; + //s1 = "1"; + //s1.concat("2"); + s2 = s1; + //m2(); + Clazz i = new Clazz(); + Integer i = new Integer(1); + } + + public void m2(){} +} + +class Clazz{} +/* +public class EmptyMethod2{ + public static test = "5"; + public void m1(Integer i, String j, Boolean b){ + //String s = ""; + EmptyMethod em = new EmptyMethod(); + em.m1(); + em.s1 = ""; + //Integer ab = Math.abs(1); + //Math.abs(1); + //String lV = "local"; + //s1 = "1"; + //s1.concat("2"); + //s2 = s1; + } +}*/ \ No newline at end of file diff --git a/app/resources/javFiles/Expressions.jav b/app/resources/javFiles/Expressions.jav new file mode 100644 index 00000000..e2e992a1 --- /dev/null +++ b/app/resources/javFiles/Expressions.jav @@ -0,0 +1,8 @@ +class Expressions{ + +void test(){ + var x = 2; + x = x + 2; +} + +} \ No newline at end of file diff --git a/app/resources/javFiles/FC_Matrix.jav b/app/resources/javFiles/FC_Matrix.jav new file mode 100644 index 00000000..75ead472 --- /dev/null +++ b/app/resources/javFiles/FC_Matrix.jav @@ -0,0 +1,10 @@ +import java.util.Vector; + +class Matrix extends Vector> { + + methode(m) { + m.add(1); + Matrix i; + methode(i); + } + } diff --git a/app/resources/javFiles/Faculty.jav b/app/resources/javFiles/Faculty.jav new file mode 100644 index 00000000..ed201ff9 --- /dev/null +++ b/app/resources/javFiles/Faculty.jav @@ -0,0 +1,16 @@ +import java.lang.Integer; + +class Faculty { + //fact; + + Integer mul(Integer x, Integer y) { + return x; + } + + m () { + var fact = (Integer x) -> { + return mul(x, fact.apply(x)); + }; + return fact; + } +} \ No newline at end of file diff --git a/app/resources/javFiles/FacultyIf.jav b/app/resources/javFiles/FacultyIf.jav new file mode 100644 index 00000000..3c368923 --- /dev/null +++ b/app/resources/javFiles/FacultyIf.jav @@ -0,0 +1,17 @@ +import java.lang.Integer; + +class Faculty { + + m () { + + var fact = (Integer x) -> { + if (x == 1) { + return x; + } + else { + return x * (fact.apply(x-1)); + } + }; + return fact; + } +} diff --git a/app/resources/javFiles/FacultyTyped.jav b/app/resources/javFiles/FacultyTyped.jav new file mode 100644 index 00000000..089d2f33 --- /dev/null +++ b/app/resources/javFiles/FacultyTyped.jav @@ -0,0 +1,19 @@ +import java.lang.Integer; + +class Faculty { + + Integer mul(Integer x, Integer y) { + return x; + } + + Fun1 m () { + var fact = (Integer x) -> { + return mul(x, fact.apply(x)); + }; + return fact; + } +} + +interface Fun1{ + B apply(A a); +} \ No newline at end of file diff --git a/app/resources/javFiles/FieldAccess.jav b/app/resources/javFiles/FieldAccess.jav new file mode 100644 index 00000000..894bb6e1 --- /dev/null +++ b/app/resources/javFiles/FieldAccess.jav @@ -0,0 +1,13 @@ +class Box { +A f; +} +class B { + } + +class Box_Main extends B { + + m(b) { + b.f = new Box_Main(); + b.f = new B(); + } +} \ No newline at end of file diff --git a/app/resources/javFiles/Fields.jav b/app/resources/javFiles/Fields.jav new file mode 100644 index 00000000..cd2add71 --- /dev/null +++ b/app/resources/javFiles/Fields.jav @@ -0,0 +1,11 @@ +import java.lang.String; + +class Fields{ +test2 = "test"; +test; +m(){ + var test3; + return test; +} + +} \ No newline at end of file diff --git a/app/resources/javFiles/Generics.jav b/app/resources/javFiles/Generics.jav new file mode 100644 index 00000000..dd7b4eba --- /dev/null +++ b/app/resources/javFiles/Generics.jav @@ -0,0 +1,22 @@ +import java.lang.String; + +class Generics { + // A mt1(A a, B b){ + B mt1(B a, B b){ + return mt1(a, a); + } +} + +class Test { + methode(String s){ + return new Generics().mt1(s,s); + } +} + +/* +Problem: +auto test = new List(); +auto test2 = new List(); +... //code, welcher möglicherweise test und test2 vertauscht +test.add("hallo"); +*/ \ No newline at end of file diff --git a/app/resources/javFiles/IfTest.jav b/app/resources/javFiles/IfTest.jav new file mode 100644 index 00000000..88885561 --- /dev/null +++ b/app/resources/javFiles/IfTest.jav @@ -0,0 +1,14 @@ +import java.lang.Integer; +import java.lang.Boolean; +import java.lang.Object; + +public class IfTest { + Object m1(b) { + Integer i; + if(b) { + return i; + }else{ + return b; + } + } +} \ No newline at end of file diff --git a/app/resources/javFiles/Import.jav b/app/resources/javFiles/Import.jav new file mode 100644 index 00000000..2fc3a8b3 --- /dev/null +++ b/app/resources/javFiles/Import.jav @@ -0,0 +1,8 @@ +import java.util.Vector; + +class Import { + void methode(){ + var v; + v.add(v); + } +} \ No newline at end of file diff --git a/app/resources/javFiles/Lambda.jav b/app/resources/javFiles/Lambda.jav new file mode 100644 index 00000000..5bd67a0b --- /dev/null +++ b/app/resources/javFiles/Lambda.jav @@ -0,0 +1,13 @@ + +class Apply { } + +public class Lambda { + + m () { + var lam1 = (x) -> { + return x; + }; + return lam1.apply(new Apply()); + } +} + diff --git a/app/resources/javFiles/Lambda2.jav b/app/resources/javFiles/Lambda2.jav new file mode 100644 index 00000000..cf1e910b --- /dev/null +++ b/app/resources/javFiles/Lambda2.jav @@ -0,0 +1,33 @@ +import java.lang.String; + +public class Lambda2 +{ + public static void main(List args){ + var listOfStrings = new List(); + var listOfObjects; + listOfObjects = map(listOfStrings, (a) -> a); +} + +public map(a , b){ + b.apply(a); + return a; +} + +/* +public static List map(List input, Function func) { + List output; + output = new List(); + output.add(func.apply(input.get())); + return output; +} +*/ +} + +class List{ + A get(); + void add(A); +} + +class Function{ + B apply(A a); +} \ No newline at end of file diff --git a/app/resources/javFiles/Lambda3.jav b/app/resources/javFiles/Lambda3.jav new file mode 100644 index 00000000..9e22f302 --- /dev/null +++ b/app/resources/javFiles/Lambda3.jav @@ -0,0 +1,24 @@ +import java.lang.String; + +public class Lambda2 +{ + /* + public static List map(List input, + Function func){ + input.add(func.apply(input.get())); + } + */ + public map(input,func){ + input.add(func.apply(input.get())); + return map(new List(), func); + } +} + +class List{ + A get(); + void add(A); +} + +class Function{ + B apply(A a); +} \ No newline at end of file diff --git a/app/resources/javFiles/LambdaField.jav b/app/resources/javFiles/LambdaField.jav new file mode 100644 index 00000000..4eb53738 --- /dev/null +++ b/app/resources/javFiles/LambdaField.jav @@ -0,0 +1,6 @@ +public class LambdaField { + + f = x -> x; + +} + diff --git a/app/resources/javFiles/LambdaRunnable.jav b/app/resources/javFiles/LambdaRunnable.jav new file mode 100644 index 00000000..37924ea2 --- /dev/null +++ b/app/resources/javFiles/LambdaRunnable.jav @@ -0,0 +1,14 @@ +import java.lang.Runnable; +import java.lang.String; +import java.lang.System; + +public class LamRunnable{ + + public LamRunnable(){ + + + Runnable lam = () -> {System.out.println("lambda");}; + lam.run(); + } +} + diff --git a/app/resources/javFiles/ListenerOverload.jav b/app/resources/javFiles/ListenerOverload.jav new file mode 100644 index 00000000..00a5e605 --- /dev/null +++ b/app/resources/javFiles/ListenerOverload.jav @@ -0,0 +1,20 @@ +import java.lang.Integer; +import java.lang.String; + +class ListenerOverload{ + +call(p){ + call(p.left); + call(p.right); +} + +call(Integer i){} + +call(String s){} + +} + +class Pair{ + left; + right; +} \ No newline at end of file diff --git a/app/resources/javFiles/Matrix.jav b/app/resources/javFiles/Matrix.jav new file mode 100644 index 00000000..5e1eac08 --- /dev/null +++ b/app/resources/javFiles/Matrix.jav @@ -0,0 +1,28 @@ +import java.util.Vector; +import java.lang.Integer; + +class Matrix extends Vector> { + Integer mul1(Integer x, Integer y) { return x;} + Integer add1(Integer x, Integer y) { return x;} + mul(m) { + var ret = new Matrix(); + var i = 0; + while(i < size()) { + var v1 = this.elementAt(i); + var v2 = new Vector(); + var j = 0; + while(j < v1.size()) { + var erg = 0; + var k = 0; + while(k < v1.size()) { + erg = erg + v1.elementAt(k) * m.elementAt(k).elementAt(j); + //erg = add1(erg, mul1(v1.elementAt(k), + // m.elementAt(k).elementAt(j))); + k++; } + v2.addElement(new Integer(erg)); + j++; } + ret.addElement(v2); + i++; } + return ret; + } +} diff --git a/app/resources/javFiles/Meth_Gen.jav b/app/resources/javFiles/Meth_Gen.jav new file mode 100644 index 00000000..056dd82f --- /dev/null +++ b/app/resources/javFiles/Meth_Gen.jav @@ -0,0 +1,11 @@ +class Meth_Gen { + + m1(x, y) { + m2(x); + x = y; + } + + m2(y) { + m1(y, y); + } +} \ No newline at end of file diff --git a/app/resources/javFiles/MethodCallGenerics.jav b/app/resources/javFiles/MethodCallGenerics.jav new file mode 100644 index 00000000..0d02509b --- /dev/null +++ b/app/resources/javFiles/MethodCallGenerics.jav @@ -0,0 +1,14 @@ +import java.lang.String; + +class Generics { + // A mt1(A a, B b){ + B mt1(B a, B b){ + return mt1(a, a); + } +} + +class Test { + methode(String s){ + return new Generics().mt1(s,s); + } +} diff --git a/app/resources/javFiles/MethodWildcardGen.jav b/app/resources/javFiles/MethodWildcardGen.jav new file mode 100644 index 00000000..c982c442 --- /dev/null +++ b/app/resources/javFiles/MethodWildcardGen.jav @@ -0,0 +1,21 @@ +/* +class C{ + A f; + m(b, c){ + c.f = b; + c.m(b, c); + } +} +*/ +class C{ + X f; + m(b, c, d){ + this.f = b; + this.f = c.f; + c.m2(d); + } + + m2(a){ + a.f = this.f; + } +} diff --git a/app/resources/javFiles/Methods.jav b/app/resources/javFiles/Methods.jav new file mode 100644 index 00000000..e45d9830 --- /dev/null +++ b/app/resources/javFiles/Methods.jav @@ -0,0 +1,17 @@ + +class Methods { + mt4(a,b,c) { return a.add(b).sub(c) ; } + + mt1(a) {return a;} + + mt2(a) {return a.f; } + + mt3(a) {return a.add(); } +} + +class Test { + java.lang.Object f; + add(){} + add(b){return b;} + sub(b){} +} \ No newline at end of file diff --git a/app/resources/javFiles/MethodsEasy.jav b/app/resources/javFiles/MethodsEasy.jav new file mode 100644 index 00000000..ee6f9daf --- /dev/null +++ b/app/resources/javFiles/MethodsEasy.jav @@ -0,0 +1,7 @@ + +class Methods { + mt4(a,b,c) { return a.mt3(b).mt3(c) ; } + + mt3(a) {return a.mt3(a); } +} + diff --git a/app/resources/javFiles/Op1.jav b/app/resources/javFiles/Op1.jav new file mode 100644 index 00000000..800f58b8 --- /dev/null +++ b/app/resources/javFiles/Op1.jav @@ -0,0 +1,11 @@ +public class Op1{ + public Op1() { + + Runnable lam = () -> { + String test = ""; + String b = "b"; + test = b; + System.out.println(test);}; + //lam.run(); + } +} \ No newline at end of file diff --git a/app/resources/javFiles/Package.jav b/app/resources/javFiles/Package.jav new file mode 100644 index 00000000..bbc1e51d --- /dev/null +++ b/app/resources/javFiles/Package.jav @@ -0,0 +1,5 @@ +package strucType.input; + +class Neu +{ +} \ No newline at end of file diff --git a/app/resources/javFiles/Sorting.jav b/app/resources/javFiles/Sorting.jav new file mode 100644 index 00000000..e5897914 --- /dev/null +++ b/app/resources/javFiles/Sorting.jav @@ -0,0 +1,15 @@ +import java.util.List; +import java.util.Collection; + +class Sorting{ + void merge(a, b){ + a.addAll(b); + return a; + } + + sort(in){ + var firstHalf = in; + var secondHalf = in; + return merge(sort(firstHalf), sort(secondHalf)); + } +} \ No newline at end of file diff --git a/app/resources/javFiles/Subclass.jav b/app/resources/javFiles/Subclass.jav new file mode 100644 index 00000000..fe6e9208 --- /dev/null +++ b/app/resources/javFiles/Subclass.jav @@ -0,0 +1,6 @@ +public class Subclass extends Superclass { + + public void printMethod() { + super.printMethod(); + } +} \ No newline at end of file diff --git a/app/resources/javFiles/Superclass.jav b/app/resources/javFiles/Superclass.jav new file mode 100644 index 00000000..d58089de --- /dev/null +++ b/app/resources/javFiles/Superclass.jav @@ -0,0 +1,6 @@ +public class Superclass { + + public void printMethod() { + System.out.println("Printed in Superclass."); + } +} diff --git a/app/resources/javFiles/Vector.jav b/app/resources/javFiles/Vector.jav new file mode 100644 index 00000000..5c21cfff --- /dev/null +++ b/app/resources/javFiles/Vector.jav @@ -0,0 +1,23 @@ +import java.util.ArrayList; +import java.util.Vector; +import java.lang.Object; + +class MyVector{ + +id(x){ + Object i; + x.add(i); + x.add(i); + x.add(i); + x.add(i); + x.add(i); + x.add(i); + x.add(i); + x.add(i); + x.add(i); + x.add(i); + x.add(i); + x.add(i); + return x; +} +} \ No newline at end of file diff --git a/app/resources/javFiles/fc.jav b/app/resources/javFiles/fc.jav new file mode 100644 index 00000000..b387cb91 --- /dev/null +++ b/app/resources/javFiles/fc.jav @@ -0,0 +1,18 @@ +import java.util.List; + +class Test{ + methode(param1, param2, param3) { + param2.add(param3); + return param1.meth(param2); + } +} + +interface Klasse1{ + Klasse1 meth(p); + Klasse1 meth(Klasse2 p); +} + +interface Klasse2{ + Klasse1 meth(Klasse1 p); + Klasse2 meth(Klasse2 p); +} \ No newline at end of file diff --git a/app/resources/javFiles/mathStruc.jav b/app/resources/javFiles/mathStruc.jav new file mode 100644 index 00000000..c8518e5d --- /dev/null +++ b/app/resources/javFiles/mathStruc.jav @@ -0,0 +1,8 @@ +class MathStruc { + + A model; + + innerOp = o -> ms -> new MathStruc(o.apply(this.model, ms.model)); + + MathStruc(A m) { model=m; } + } \ No newline at end of file diff --git a/app/resources/javFiles/packageTest/Gen.jav b/app/resources/javFiles/packageTest/Gen.jav new file mode 100644 index 00000000..3b58b188 --- /dev/null +++ b/app/resources/javFiles/packageTest/Gen.jav @@ -0,0 +1,8 @@ +import java.lang.Integer; +import java.util.Vector; + +public class Gen{ + Vector m(Vector v){ + return v; + } +} diff --git a/app/resources/javFiles/packageTest/OLMain.jav b/app/resources/javFiles/packageTest/OLMain.jav new file mode 100644 index 00000000..0cdb0b4f --- /dev/null +++ b/app/resources/javFiles/packageTest/OLMain.jav @@ -0,0 +1,12 @@ +import java.lang.String; +import java.lang.Integer; +import java.lang.Double; + +public class OLMain { + + main(x) { + var ol; + ol = new OLextends(); + return ol.m(x); + } +} diff --git a/app/resources/javFiles/packageTest/OLOneFile.jav b/app/resources/javFiles/packageTest/OLOneFile.jav new file mode 100644 index 00000000..eb865d61 --- /dev/null +++ b/app/resources/javFiles/packageTest/OLOneFile.jav @@ -0,0 +1,22 @@ +import java.lang.String; +import java.lang.Integer; +import java.lang.Double; +import java.lang.Boolean; + + +public class OLOneFile { + + m2(x) { return x + x; } + +} + +public class OLextendsOneFile extends OLOneFile { } + +public class OLMainOneFile { + + main(x) { + var ol; + ol = new OLextendsOneFile(); + return ol.m2(x); + } +} diff --git a/app/resources/javFiles/packageTest/OLTest.txt b/app/resources/javFiles/packageTest/OLTest.txt new file mode 100644 index 00000000..d91b58d7 --- /dev/null +++ b/app/resources/javFiles/packageTest/OLTest.txt @@ -0,0 +1,6 @@ +java -jar ~/eclipse-workspace/JavaCompilerCore/target/JavaTXcompiler-0.2-jar-with-dependencies.jar de/test/OL.jav -d de/test/output +java -jar ~/eclipse-workspace/JavaCompilerCore/target/JavaTXcompiler-0.2-jar-with-dependencies.jar OLextends.jav -cp de/test/output +java -jar ~/eclipse-workspace/JavaCompilerCore/target/JavaTXcompiler-0.2-jar-with-dependencies.jar OLMain.jav -cp .:de/test/output +javac UseOLMain.java +java -cp .:de/test/output UseOLMain +rm -f UseOLMain.class diff --git a/app/resources/javFiles/packageTest/OLextends.jav b/app/resources/javFiles/packageTest/OLextends.jav new file mode 100644 index 00000000..b3c055df --- /dev/null +++ b/app/resources/javFiles/packageTest/OLextends.jav @@ -0,0 +1,7 @@ +import de.test.OL; + + +public class OLextends extends OL { + + +} diff --git a/app/resources/javFiles/packageTest/Pair2.jav b/app/resources/javFiles/packageTest/Pair2.jav new file mode 100644 index 00000000..d62474ea --- /dev/null +++ b/app/resources/javFiles/packageTest/Pair2.jav @@ -0,0 +1,14 @@ +import de.test.Pair; + +class Pairs { + setfst(fst) { + return new Pair<>(snd, fst); + } + + swap () { + return new Pair<> (snd, fst); } + + polyrec(p) { + return polyrec (p.swap()); + } +} \ No newline at end of file diff --git a/app/resources/javFiles/packageTest/Test.jav b/app/resources/javFiles/packageTest/Test.jav new file mode 100644 index 00000000..2f6429a1 --- /dev/null +++ b/app/resources/javFiles/packageTest/Test.jav @@ -0,0 +1,3 @@ + +public class Test{ +} diff --git a/app/resources/javFiles/packageTest/UseOLMain.java b/app/resources/javFiles/packageTest/UseOLMain.java new file mode 100644 index 00000000..2d7d6fd8 --- /dev/null +++ b/app/resources/javFiles/packageTest/UseOLMain.java @@ -0,0 +1,5 @@ +class UseOLMain { + public static void main(String[] arg) { + System.out.println(new OLMain().main(1+1)); + } +} diff --git a/app/resources/javFiles/packageTest/de/test/ImportTest.jav b/app/resources/javFiles/packageTest/de/test/ImportTest.jav new file mode 100644 index 00000000..58b6fc0b --- /dev/null +++ b/app/resources/javFiles/packageTest/de/test/ImportTest.jav @@ -0,0 +1,9 @@ +package de.test; + +import de.test.ToImport; + +class ImportTest{ + void methode(){ + new ToImport(); + } +} \ No newline at end of file diff --git a/app/resources/javFiles/packageTest/de/test/ImportTest2.jav b/app/resources/javFiles/packageTest/de/test/ImportTest2.jav new file mode 100644 index 00000000..3526abc8 --- /dev/null +++ b/app/resources/javFiles/packageTest/de/test/ImportTest2.jav @@ -0,0 +1,11 @@ +package de.test; + +import de.test.subpackage1.ToImport2; +import de.test.subpackage2.ToImport3; + +class ImportTest2{ + void methode(){ + new ToImport2().m1(); + new ToImport3().m2(); + } +} \ No newline at end of file diff --git a/app/resources/javFiles/packageTest/de/test/ImportTestDefault.jav b/app/resources/javFiles/packageTest/de/test/ImportTestDefault.jav new file mode 100644 index 00000000..ecd8d7c5 --- /dev/null +++ b/app/resources/javFiles/packageTest/de/test/ImportTestDefault.jav @@ -0,0 +1,7 @@ +package de.test; + +class ImportTestDefault{ + void methode(){ + new ToImport(); + } +} \ No newline at end of file diff --git a/app/resources/javFiles/packageTest/de/test/OL.jav b/app/resources/javFiles/packageTest/de/test/OL.jav new file mode 100644 index 00000000..7f1ba512 --- /dev/null +++ b/app/resources/javFiles/packageTest/de/test/OL.jav @@ -0,0 +1,13 @@ +package de.test; +import java.lang.String; +import java.lang.Integer; +import java.lang.Double; +import java.lang.Boolean; +//import java.util.Vector; + + +public class OL { + + public m(x) { return x + x; } + +} diff --git a/app/resources/javFiles/packageTest/de/test/Pair.jav b/app/resources/javFiles/packageTest/de/test/Pair.jav new file mode 100644 index 00000000..dbde6636 --- /dev/null +++ b/app/resources/javFiles/packageTest/de/test/Pair.jav @@ -0,0 +1,12 @@ +package de.test; + +class Pair { + fst; + snd; + + Pair(fst, snd) { + this.fst = fst; + this.snd = snd; + } +} + diff --git a/app/resources/javFiles/packageTest/de/test/TestClass.jav b/app/resources/javFiles/packageTest/de/test/TestClass.jav new file mode 100644 index 00000000..6681b36a --- /dev/null +++ b/app/resources/javFiles/packageTest/de/test/TestClass.jav @@ -0,0 +1,3 @@ +package de.test; + +public class TestClass{} \ No newline at end of file diff --git a/app/resources/javFiles/packageTest/de/test/ToImport.jav b/app/resources/javFiles/packageTest/de/test/ToImport.jav new file mode 100644 index 00000000..3afdba54 --- /dev/null +++ b/app/resources/javFiles/packageTest/de/test/ToImport.jav @@ -0,0 +1,4 @@ +package de.test; + +class ToImport{ +} \ No newline at end of file diff --git a/app/resources/javFiles/packageTest/de/test/mathStruc.jav b/app/resources/javFiles/packageTest/de/test/mathStruc.jav new file mode 100644 index 00000000..28db5db8 --- /dev/null +++ b/app/resources/javFiles/packageTest/de/test/mathStruc.jav @@ -0,0 +1,18 @@ +package de.test; + + +import java.util.Vector; +import java.lang.Integer; + +public class mathStruc { + model; + + //Fun1*, Fun1*,MathStruc >> + innerOp = (o) -> (ms) -> new mathStruc<>(o.apply(model,ms.model)); + + public mathStruc(m) { + model =m; + //innerOp = (o) -> (ms) -> new mathStruc<>(o.apply(this.model,ms.model)); + } +} + diff --git a/app/resources/javFiles/packageTest/de/test/mathStrucVector.jav b/app/resources/javFiles/packageTest/de/test/mathStrucVector.jav new file mode 100644 index 00000000..fe6d6055 --- /dev/null +++ b/app/resources/javFiles/packageTest/de/test/mathStrucVector.jav @@ -0,0 +1,33 @@ +package de.test; + +import java.util.Vector; +import java.lang.Integer; +import java.lang.Boolean; + +import de.test.mathStruc; +import de.test.vectorAdd; + + +public class mathStrucVector { + + public main() { + Vector v1 = new Vector(); + v1.addElement(2); + v1.addElement(2); + Vector v2 = new Vector(); + v2.addElement(3); + v2.addElement(3); + + vectorAdd va = new vectorAdd(); + + var ms; + ms = new mathStruc<>(v1); + var ms2; + ms2 = new mathStruc<>(v2); + var ms3; + + ms3 = ms.innerOp.apply(va.add).apply(ms2); + return ms3; + + } +} diff --git a/app/resources/javFiles/packageTest/de/test/output/de/test/mathStrucVectoruse.java b/app/resources/javFiles/packageTest/de/test/output/de/test/mathStrucVectoruse.java new file mode 100644 index 00000000..54b9e45b --- /dev/null +++ b/app/resources/javFiles/packageTest/de/test/output/de/test/mathStrucVectoruse.java @@ -0,0 +1,10 @@ +package de.test; +import de.test.mathStrucVector; + + +class mathStrucVectorUse { + + public static void main(String[] args) { + new mathStrucVector().main(); + } +} diff --git a/app/resources/javFiles/packageTest/de/test/output/mathStrucVectoruse.java b/app/resources/javFiles/packageTest/de/test/output/mathStrucVectoruse.java new file mode 100644 index 00000000..9a9b2e75 --- /dev/null +++ b/app/resources/javFiles/packageTest/de/test/output/mathStrucVectoruse.java @@ -0,0 +1,8 @@ + + +class mathStrucVectorUse { + + public static void main(String[] args) { + new mathStrucVector().main(); + } +} diff --git a/app/resources/javFiles/packageTest/de/test/packageNameTestWrongPackage.jav b/app/resources/javFiles/packageTest/de/test/packageNameTestWrongPackage.jav new file mode 100644 index 00000000..a86d22aa --- /dev/null +++ b/app/resources/javFiles/packageTest/de/test/packageNameTestWrongPackage.jav @@ -0,0 +1,3 @@ +package de.tesst; + +class TestClass{} \ No newline at end of file diff --git a/app/resources/javFiles/packageTest/de/test/subpackage1/Test1.jav b/app/resources/javFiles/packageTest/de/test/subpackage1/Test1.jav new file mode 100644 index 00000000..a7011169 --- /dev/null +++ b/app/resources/javFiles/packageTest/de/test/subpackage1/Test1.jav @@ -0,0 +1,4 @@ +package de.test.subpackage1; + +class Test1{ +} \ No newline at end of file diff --git a/app/resources/javFiles/packageTest/de/test/subpackage1/ToImport2.jav b/app/resources/javFiles/packageTest/de/test/subpackage1/ToImport2.jav new file mode 100644 index 00000000..bcc67b95 --- /dev/null +++ b/app/resources/javFiles/packageTest/de/test/subpackage1/ToImport2.jav @@ -0,0 +1,5 @@ +package de.test.subpackage1; + +class ToImport2{ +void m1(){} +} \ No newline at end of file diff --git a/app/resources/javFiles/packageTest/de/test/subpackage2/Test2.jav b/app/resources/javFiles/packageTest/de/test/subpackage2/Test2.jav new file mode 100644 index 00000000..750f7612 --- /dev/null +++ b/app/resources/javFiles/packageTest/de/test/subpackage2/Test2.jav @@ -0,0 +1,4 @@ +package de.test.subpackage2; + +class Test2{ +} \ No newline at end of file diff --git a/app/resources/javFiles/packageTest/de/test/subpackage2/ToImport3.jav b/app/resources/javFiles/packageTest/de/test/subpackage2/ToImport3.jav new file mode 100644 index 00000000..3efd8fff --- /dev/null +++ b/app/resources/javFiles/packageTest/de/test/subpackage2/ToImport3.jav @@ -0,0 +1,5 @@ +package de.test.subpackage2; + +class ToImport3{ +void m2(){} +} \ No newline at end of file diff --git a/app/resources/javFiles/packageTest/de/test/vectorAdd.jav b/app/resources/javFiles/packageTest/de/test/vectorAdd.jav new file mode 100644 index 00000000..727a83a9 --- /dev/null +++ b/app/resources/javFiles/packageTest/de/test/vectorAdd.jav @@ -0,0 +1,20 @@ +package de.test; + +import java.util.Vector; +import java.lang.Integer; +import java.lang.Boolean; + + +public class vectorAdd { + + public add = (v1, v2) -> { + var ret = new Vector(); + var i = 0; + while(i < v1.size()) { + //if (i < v2.size()) { + ret.addElement(v1.elementAt(i) + v2.elementAt(i)); + //} + } + return ret; + }; +} diff --git a/app/resources/javFiles/test.jav b/app/resources/javFiles/test.jav new file mode 100644 index 00000000..303d167a --- /dev/null +++ b/app/resources/javFiles/test.jav @@ -0,0 +1,15 @@ +class Test{ + methode(param1, param2, param3) { + return param1.meth(param2.meth(param3)); + } +} + +interface Klasse1{ + Klasse1 meth(Klasse1 p); + Klasse1 meth(Klasse2 p); +} + +interface Klasse2{ + Klasse1 meth(Klasse1 p); + Klasse2 meth(Klasse2 p); +} \ No newline at end of file diff --git a/app/resources/javFiles/test1.jav b/app/resources/javFiles/test1.jav new file mode 100644 index 00000000..4b34948e --- /dev/null +++ b/app/resources/javFiles/test1.jav @@ -0,0 +1,7 @@ +class Faculty { + + int a; + m (int x) { + return a+x; + } +} diff --git a/app/resources/log4jTesting.xml b/app/resources/log4jTesting.xml new file mode 100755 index 00000000..dc30c245 --- /dev/null +++ b/app/resources/log4jTesting.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/resources/testBytecode/generatedBC/.gitignore b/app/resources/testBytecode/generatedBC/.gitignore new file mode 100644 index 00000000..5e7d2734 --- /dev/null +++ b/app/resources/testBytecode/generatedBC/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore diff --git a/app/resources/testBytecode/public b/app/resources/testBytecode/public new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/app/resources/testBytecode/public @@ -0,0 +1 @@ + diff --git a/app/src/main/antlr/de/dhbwstuttgart/parser/antlr/Java8.g4 b/app/src/main/antlr/de/dhbwstuttgart/parser/antlr/Java8.g4 new file mode 100644 index 00000000..aca30251 --- /dev/null +++ b/app/src/main/antlr/de/dhbwstuttgart/parser/antlr/Java8.g4 @@ -0,0 +1,1787 @@ +/* + * [The "BSD license"] + * Copyright (c) 2014 Terence Parr + * Copyright (c) 2014 Sam Harwell + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * A Java 8 grammar for ANTLR 4 derived from the Java Language Specification + * chapter 19. + * + * NOTE: This grammar results in a generated parser that is much slower + * than the Java 7 grammar in the grammars-v4/java directory. This + * one is, however, extremely close to the spec. + * + * You can test with + * + * $ antlr4 Java8.g4 + * $ javac *.java + * $ grun Java8 compilationUnit *.java + * + * Or, +~/antlr/code/grammars-v4/java8 $ java Test . +/Users/parrt/antlr/code/grammars-v4/java8/./Java8BaseListener.java +/Users/parrt/antlr/code/grammars-v4/java8/./Java8Lexer.java +/Users/parrt/antlr/code/grammars-v4/java8/./Java8Listener.java +/Users/parrt/antlr/code/grammars-v4/java8/./Java8Parser.java +/Users/parrt/antlr/code/grammars-v4/java8/./Test.java +Total lexer+parser time 30844ms. + */ +grammar Java8; + +@header { + package de.dhbwstuttgart.parser.antlr; +} +/* + * Productions from §3 (Lexical Structure) + */ + +literal + : IntegerLiteral + | FloatingPointLiteral + | BooleanLiteral + | CharacterLiteral + | StringLiteral + | NullLiteral + ; + +/* + * Productions from §4 (Types, Values, and Variables) + */ + +type + : primitiveType + | referenceType + ; + +primitiveType + : annotation* numericType + | annotation* 'boolean' + ; + +numericType + : integralType + | floatingPointType + ; + +integralType + : 'byte' + | 'short' + | 'int' + | 'long' + | 'char' + ; + +floatingPointType + : 'float' + | 'double' + ; + +referenceType + : classOrInterfaceType + | typeVariable + | arrayType + ; + +classOrInterfaceType + : ( classType_lfno_classOrInterfaceType + | interfaceType_lfno_classOrInterfaceType + ) + ( classType_lf_classOrInterfaceType + )* + ; + +classType + : annotation* Identifier typeArguments? + | classOrInterfaceType '.' annotation* Identifier typeArguments? + ; + +classType_lf_classOrInterfaceType + : '.' annotation* Identifier typeArguments? + ; + +classType_lfno_classOrInterfaceType + : annotation* Identifier typeArguments? + ; + +interfaceType + : classType + ; + +interfaceType_lf_classOrInterfaceType + : classType_lf_classOrInterfaceType + ; + +interfaceType_lfno_classOrInterfaceType + : classType_lfno_classOrInterfaceType + ; + +typeVariable + : annotation* Identifier + ; + +arrayType + : primitiveType dims + | classOrInterfaceType dims + | typeVariable dims + ; + +dims + : annotation* '[' ']' (annotation* '[' ']')* + ; + +typeParameter + : typeParameterModifier* Identifier typeBound? + ; + +typeParameterModifier + : annotation + ; + +typeBound + : 'extends' typeVariable + | 'extends' classOrInterfaceType additionalBound* + ; + +additionalBound + : '&' interfaceType + ; + +typeArguments + : '<' typeArgumentList '>' + ; + +typeArgumentList + : typeArgument (',' typeArgument)* + ; + +typeArgument + : referenceType + | wildcard + ; + +wildcard + : annotation* '?' wildcardBounds? + ; + +wildcardBounds + : 'extends' referenceType + | 'super' referenceType + ; + +/* + * Productions from §6 (Names) + */ + +packageName + : Identifier + | packageName '.' Identifier + ; + +typeName + : Identifier + | packageOrTypeName '.' Identifier + ; + +packageOrTypeName + : Identifier + | packageOrTypeName '.' Identifier + ; + +expressionName + : Identifier + | ambiguousName '.' Identifier + ; + +methodName + : Identifier + ; + +ambiguousName + : Identifier + | ambiguousName '.' Identifier + ; + +/* + * Productions from §7 (Packages) + */ + +compilationUnit + : packageDeclaration? importDeclaration* typeDeclaration* EOF + ; + +packageDeclaration + : packageModifier* 'package' Identifier ('.' Identifier)* ';' + ; + +packageModifier + : annotation + ; + +importDeclaration + : singleTypeImportDeclaration + | typeImportOnDemandDeclaration + | singleStaticImportDeclaration + | staticImportOnDemandDeclaration + ; + +singleTypeImportDeclaration + : 'import' typeName ';' + ; + +typeImportOnDemandDeclaration + : 'import' packageOrTypeName '.' '*' ';' + ; + +singleStaticImportDeclaration + : 'import' 'static' typeName '.' Identifier ';' + ; + +staticImportOnDemandDeclaration + : 'import' 'static' typeName '.' '*' ';' + ; + +typeDeclaration + : classDeclaration + | interfaceDeclaration + | ';' + ; + +/* + * Productions from §8 (Classes) + */ + +classDeclaration + : normalClassDeclaration + | enumDeclaration + ; + +normalClassDeclaration + : classModifier* 'class' Identifier typeParameters? superclass? superinterfaces? classBody + ; + +classModifier + : annotation + | 'public' + | 'protected' + | 'private' + | 'abstract' + | 'static' + | 'final' + | 'strictfp' + ; + +typeParameters + : '<' typeParameterList '>' + ; + +typeParameterList + : typeParameter (',' typeParameter)* + ; + +superclass + : 'extends' classType + ; + +superinterfaces + : 'implements' interfaceTypeList + ; + +interfaceTypeList + : interfaceType (',' interfaceType)* + ; + +classBody + : '{' classBodyDeclaration* '}' + ; + +classBodyDeclaration + : classMemberDeclaration + | instanceInitializer + | staticInitializer +// | constructorDeclaration + ; + +classMemberDeclaration + : fieldDeclaration + | methodDeclaration + | classDeclaration + | interfaceDeclaration + | ';' + ; + +fieldDeclaration + : fieldModifier* unannTypeOrAuto? variableDeclaratorList ';' + ; + +fieldModifier + : annotation + | 'public' + | 'protected' + | 'private' + | 'static' + | 'final' + | 'transient' + | 'volatile' + ; + +variableDeclaratorList + : variableDeclarator (',' variableDeclarator)* + ; + +variableDeclarator + : variableDeclaratorId ('=' variableInitializer)? //auskommentiert, weil variablenDecklaration sonst nicht eindeutig + ; + +variableDeclaratorId + : Identifier dims? + ; + +variableInitializer + : expression + | arrayInitializer + ; + +unannType + : unannPrimitiveType + | unannReferenceType + ; + +unannPrimitiveType + : numericType + | 'boolean' + ; + +unannReferenceType + : unannClassOrInterfaceType + | unannTypeVariable + | unannArrayType + ; + +unannClassOrInterfaceType + : ( unannClassType_lfno_unannClassOrInterfaceType + | unannInterfaceType_lfno_unannClassOrInterfaceType + ) + ( unannClassType_lf_unannClassOrInterfaceType + | unannInterfaceType_lf_unannClassOrInterfaceType + )* + ; + +unannClassType + : Identifier typeArguments? + | unannClassOrInterfaceType '.' annotation* Identifier typeArguments? + ; + +unannClassType_lf_unannClassOrInterfaceType + : '.' annotation* Identifier typeArguments? + ; + +unannClassType_lfno_unannClassOrInterfaceType + : Identifier typeArguments? + ; + +unannInterfaceType + : unannClassType + ; + +unannInterfaceType_lf_unannClassOrInterfaceType + : unannClassType_lf_unannClassOrInterfaceType + ; + +unannInterfaceType_lfno_unannClassOrInterfaceType + : unannClassType_lfno_unannClassOrInterfaceType + ; + +unannTypeVariable + : Identifier + ; + +unannArrayType + : unannPrimitiveType dims + | unannClassOrInterfaceType dims + | unannTypeVariable dims + ; + +methodDeclaration + : methodModifier* methodHeader methodBody + ; + +methodModifier + : annotation + | 'public' + | 'protected' + | 'private' + | 'abstract' + | 'static' + | 'final' + | 'synchronized' + | 'native' + | 'strictfp' + ; + +methodHeader + : result? methodDeclarator throws_? + | typeParameters annotation* result? methodDeclarator throws_? + ; + +result + : unannType + | 'void' + ; + +methodDeclarator + : Identifier '(' formalParameterList? ')' dims? + ; + +formalParameterList + : formalParameters ',' lastFormalParameter + | lastFormalParameter + ; + +formalParameters + : formalParameter (',' formalParameter)* + | receiverParameter (',' formalParameter)* + ; + +formalParameter + : variableModifier* unannType? variableDeclaratorId + ; + +variableModifier + : annotation + | 'final' + ; + +lastFormalParameter + : variableModifier* unannType annotation* '...' variableDeclaratorId + | formalParameter + ; + +receiverParameter + : annotation* unannType (Identifier '.')? 'this' + ; + +throws_ + : 'throws' exceptionTypeList + ; + +exceptionTypeList + : exceptionType (',' exceptionType)* + ; + +exceptionType + : classType + | typeVariable + ; + +methodBody + : block + | ';' + ; + +instanceInitializer + : block + ; + +staticInitializer + : 'static' block + ; + +constructorDeclaration + : constructorModifier* constructorDeclarator throws_? constructorBody + ; + +constructorModifier + : annotation + | 'public' + | 'protected' + | 'private' + ; + +constructorDeclarator + : typeParameters? simpleTypeName '(' formalParameterList? ')' + ; + +simpleTypeName + : Identifier + ; + +constructorBody + : '{' explicitConstructorInvocation? blockStatements? '}' + ; + +explicitConstructorInvocation + : typeArguments? 'this' '(' argumentList? ')' ';' + | typeArguments? 'super' '(' argumentList? ')' ';' + | expressionName '.' typeArguments? 'super' '(' argumentList? ')' ';' + | primary '.' typeArguments? 'super' '(' argumentList? ')' ';' + ; + +enumDeclaration + : classModifier* 'enum' Identifier superinterfaces? enumBody + ; + +enumBody + : '{' enumConstantList? ','? enumBodyDeclarations? '}' + ; + +enumConstantList + : enumConstant (',' enumConstant)* + ; + +enumConstant + : enumConstantModifier* Identifier ('(' argumentList? ')')? classBody? + ; + +enumConstantModifier + : annotation + ; + +enumBodyDeclarations + : ';' classBodyDeclaration* + ; + +/* + * Productions from §9 (Interfaces) + */ + +interfaceDeclaration + : normalInterfaceDeclaration + | annotationTypeDeclaration + ; + +normalInterfaceDeclaration + : interfaceModifier* 'interface' Identifier typeParameters? extendsInterfaces? interfaceBody + ; + +interfaceModifier + : annotation + | 'public' + | 'protected' + | 'private' + | 'abstract' + | 'static' + | 'strictfp' + ; + +extendsInterfaces + : 'extends' interfaceTypeList + ; + +interfaceBody + : '{' interfaceMemberDeclaration* '}' + ; + +interfaceMemberDeclaration + : constantDeclaration + | interfaceMethodDeclaration + | classDeclaration + | interfaceDeclaration + | ';' + ; + +constantDeclaration + : constantModifier* unannType variableDeclaratorList ';' + ; + +constantModifier + : annotation + | 'public' + | 'static' + | 'final' + ; + +interfaceMethodDeclaration + : interfaceMethodModifier* methodHeader methodBody + ; + +interfaceMethodModifier + : annotation + | 'public' + | 'abstract' + | 'default' + | 'static' + | 'strictfp' + ; + +annotationTypeDeclaration + : interfaceModifier* '@' 'interface' Identifier annotationTypeBody + ; + +annotationTypeBody + : '{' annotationTypeMemberDeclaration* '}' + ; + +annotationTypeMemberDeclaration + : annotationTypeElementDeclaration + | constantDeclaration + | classDeclaration + | interfaceDeclaration + | ';' + ; + +annotationTypeElementDeclaration + : annotationTypeElementModifier* unannType Identifier '(' ')' dims? defaultValue? ';' + ; + +annotationTypeElementModifier + : annotation + | 'public' + | 'abstract' + ; + +defaultValue + : 'default' elementValue + ; + +annotation + : normalAnnotation + | markerAnnotation + | singleElementAnnotation + ; + +normalAnnotation + : '@' typeName '(' elementValuePairList? ')' + ; + +elementValuePairList + : elementValuePair (',' elementValuePair)* + ; + +elementValuePair + : Identifier '=' elementValue + ; + +elementValue + : conditionalExpression + | elementValueArrayInitializer + | annotation + ; + +elementValueArrayInitializer + : '{' elementValueList? ','? '}' + ; + +elementValueList + : elementValue (',' elementValue)* + ; + +markerAnnotation + : '@' typeName + ; + +singleElementAnnotation + : '@' typeName '(' elementValue ')' + ; + +/* + * Productions from §10 (Arrays) + */ + +arrayInitializer + : '{' variableInitializerList? ','? '}' + ; + +variableInitializerList + : variableInitializer (',' variableInitializer)* + ; + +/* + * Productions from §14 (Blocks and Statements) + */ + +block + : '{' blockStatements? '}' + ; + +blockStatements + : blockStatement blockStatement* + ; + +blockStatement + : localVariableDeclarationStatement + | classDeclaration + | statement + ; + +localVariableDeclarationStatement + : localVariableDeclaration ';' + ; + +unannTypeOrAuto + : unannType + | 'var' + ; + +localVariableDeclaration + : variableModifier* unannTypeOrAuto variableDeclaratorList + ; + +statement + : statementWithoutTrailingSubstatement + | labeledStatement + | ifThenStatement + | ifThenElseStatement + | whileStatement + | forStatement + ; + +statementNoShortIf + : statementWithoutTrailingSubstatement + | labeledStatementNoShortIf + | ifThenElseStatementNoShortIf + | whileStatementNoShortIf + | forStatementNoShortIf + ; + +statementWithoutTrailingSubstatement + : block + | emptyStatement + | expressionStatement + | assertStatement + | switchStatement + | doStatement + | breakStatement + | continueStatement + | returnStatement + | synchronizedStatement + | throwStatement + | tryStatement + ; + +emptyStatement + : ';' + ; + +labeledStatement + : Identifier ':' statement + ; + +labeledStatementNoShortIf + : Identifier ':' statementNoShortIf + ; + +expressionStatement + : statementExpression ';' + ; + +statementExpression + : assignment + | preIncrementExpression + | preDecrementExpression + | postIncrementExpression + | postDecrementExpression + | methodInvocation + | classInstanceCreationExpression + ; + +ifThenStatement + : 'if' '(' expression ')' statement + ; + +ifThenElseStatement + : 'if' '(' expression ')' statementNoShortIf 'else' statement + ; + +ifThenElseStatementNoShortIf + : 'if' '(' expression ')' statementNoShortIf 'else' statementNoShortIf + ; + +assertStatement + : 'assert' expression ';' + | 'assert' expression ':' expression ';' + ; + +switchStatement + : 'switch' '(' expression ')' switchBlock + ; + +switchBlock + : '{' switchBlockStatementGroup* switchLabel* '}' + ; + +switchBlockStatementGroup + : switchLabels blockStatements + ; + +switchLabels + : switchLabel switchLabel* + ; + +switchLabel + : 'case' constantExpression ':' + | 'case' enumConstantName ':' + | 'default' ':' + ; + +enumConstantName + : Identifier + ; + +whileStatement + : 'while' '(' expression ')' statement + ; + +whileStatementNoShortIf + : 'while' '(' expression ')' statementNoShortIf + ; + +doStatement + : 'do' statement 'while' '(' expression ')' ';' + ; + +forStatement + : basicForStatement + | enhancedForStatement + ; + +forStatementNoShortIf + : basicForStatementNoShortIf + | enhancedForStatementNoShortIf + ; + +basicForStatement + : 'for' '(' forInit? ';' expression? ';' forUpdate? ')' statement + ; + +basicForStatementNoShortIf + : 'for' '(' forInit? ';' expression? ';' forUpdate? ')' statementNoShortIf + ; + +forInit + : statementExpressionList + | localVariableDeclaration + ; + +forUpdate + : statementExpressionList + ; + +statementExpressionList + : statementExpression (',' statementExpression)* + ; + +enhancedForStatement + : 'for' '(' variableModifier* unannType variableDeclaratorId ':' expression ')' statement + ; + +enhancedForStatementNoShortIf + : 'for' '(' variableModifier* unannType variableDeclaratorId ':' expression ')' statementNoShortIf + ; + +breakStatement + : 'break' Identifier? ';' + ; + +continueStatement + : 'continue' Identifier? ';' + ; + +returnStatement + : 'return' expression? ';' + ; + +throwStatement + : 'throw' expression ';' + ; + +synchronizedStatement + : 'synchronized' '(' expression ')' block + ; + +tryStatement + : 'try' block catches + | 'try' block catches? finally_ + | tryWithResourcesStatement + ; + +catches + : catchClause catchClause* + ; + +catchClause + : 'catch' '(' catchFormalParameter ')' block + ; + +catchFormalParameter + : variableModifier* catchType variableDeclaratorId + ; + +catchType + : unannClassType ('|' classType)* + ; + +finally_ + : 'finally' block + ; + +tryWithResourcesStatement + : 'try' resourceSpecification block catches? finally_? + ; + +resourceSpecification + : '(' resourceList ';'? ')' + ; + +resourceList + : resource (';' resource)* + ; + +resource + : variableModifier* unannType variableDeclaratorId '=' expression + ; + +/* + * Productions from §15 (Expressions) + */ + +primary + : ( primaryNoNewArray_lfno_primary + | arrayCreationExpression + ) + ( primaryNoNewArray_lf_primary + )* + ; + +primaryNoNewArray + : literal + | typeName ('[' ']')* '.' 'class' + | 'void' '.' 'class' + | 'this' + | typeName '.' 'this' + | '(' expression ')' + | classInstanceCreationExpression + | fieldAccess + | arrayAccess + | methodInvocation + | methodReference + ; + +primaryNoNewArray_lf_arrayAccess + : + ; + +primaryNoNewArray_lfno_arrayAccess + : literal + | typeName ('[' ']')* '.' 'class' + | 'void' '.' 'class' + | 'this' + | typeName '.' 'this' + | '(' expression ')' + | classInstanceCreationExpression + | fieldAccess + | methodInvocation + | methodReference + ; + +primaryNoNewArray_lf_primary + : classInstanceCreationExpression_lf_primary + | fieldAccess_lf_primary + | arrayAccess_lf_primary + | methodInvocation_lf_primary + | methodReference_lf_primary + ; + +primaryNoNewArray_lf_primary_lf_arrayAccess_lf_primary + : + ; + +primaryNoNewArray_lf_primary_lfno_arrayAccess_lf_primary + : classInstanceCreationExpression_lf_primary + | fieldAccess_lf_primary + | methodInvocation_lf_primary + | methodReference_lf_primary + ; + +primaryNoNewArray_lfno_primary + : literal //done + | typeName ('[' ']')* '.' 'class' + | unannPrimitiveType ('[' ']')* '.' 'class' + | 'void' '.' 'class' + | 'this' + | typeName '.' 'this' + | '(' expression ')' //done + | classInstanceCreationExpression_lfno_primary //done + | fieldAccess_lfno_primary + | arrayAccess_lfno_primary + | methodInvocation_lfno_primary //done + | methodReference_lfno_primary + ; + +primaryNoNewArray_lfno_primary_lf_arrayAccess_lfno_primary + : + ; + +primaryNoNewArray_lfno_primary_lfno_arrayAccess_lfno_primary + : literal + | typeName ('[' ']')* '.' 'class' + | unannPrimitiveType ('[' ']')* '.' 'class' + | 'void' '.' 'class' + | 'this' + | typeName '.' 'this' + | '(' expression ')' + | classInstanceCreationExpression_lfno_primary + | fieldAccess_lfno_primary + | methodInvocation_lfno_primary + | methodReference_lfno_primary + ; + +classInstanceCreationExpression + : 'new' typeArguments? annotation* Identifier ('.' annotation* Identifier)* typeArgumentsOrDiamond? '(' argumentList? ')' classBody? + | expressionName '.' 'new' typeArguments? annotation* Identifier typeArgumentsOrDiamond? '(' argumentList? ')' classBody? + | primary '.' 'new' typeArguments? annotation* Identifier typeArgumentsOrDiamond? '(' argumentList? ')' classBody? + ; + +classInstanceCreationExpression_lf_primary + : '.' 'new' typeArguments? annotation* Identifier typeArgumentsOrDiamond? '(' argumentList? ')' classBody? + ; + +classInstanceCreationExpression_lfno_primary + : 'new' typeArguments? annotation* Identifier ('.' annotation* Identifier)* typeArgumentsOrDiamond? '(' argumentList? ')' classBody? + | expressionName '.' 'new' typeArguments? annotation* Identifier typeArgumentsOrDiamond? '(' argumentList? ')' classBody? + ; + +typeArgumentsOrDiamond + : typeArguments + | '<' '>' + ; + +fieldAccess + : primary '.' Identifier + | 'super' '.' Identifier + | typeName '.' 'super' '.' Identifier + ; + +fieldAccess_lf_primary + : '.' Identifier + ; + +fieldAccess_lfno_primary + : 'super' '.' Identifier + | typeName '.' 'super' '.' Identifier + ; + +arrayAccess + : ( expressionName '[' expression ']' + | primaryNoNewArray_lfno_arrayAccess '[' expression ']' + ) + ( primaryNoNewArray_lf_arrayAccess '[' expression ']' + )* + ; + +arrayAccess_lf_primary + : ( primaryNoNewArray_lf_primary_lfno_arrayAccess_lf_primary '[' expression ']' + ) + ( primaryNoNewArray_lf_primary_lf_arrayAccess_lf_primary '[' expression ']' + )* + ; + +arrayAccess_lfno_primary + : ( expressionName '[' expression ']' + | primaryNoNewArray_lfno_primary_lfno_arrayAccess_lfno_primary '[' expression ']' + ) + ( primaryNoNewArray_lfno_primary_lf_arrayAccess_lfno_primary '[' expression ']' + )* + ; + +methodInvocation + : methodName '(' argumentList? ')' + | typeName '.' typeArguments? Identifier '(' argumentList? ')' + | expressionName '.' typeArguments? Identifier '(' argumentList? ')' + | primary '.' typeArguments? Identifier '(' argumentList? ')' + | 'super' '.' typeArguments? Identifier '(' argumentList? ')' + | typeName '.' 'super' '.' typeArguments? Identifier '(' argumentList? ')' + ; + +methodInvocation_lf_primary + : '.' typeArguments? Identifier '(' argumentList? ')' + ; + +methodInvocation_lfno_primary + : methodName '(' argumentList? ')' + | typeName '.' typeArguments? Identifier '(' argumentList? ')' + | expressionName '.' typeArguments? Identifier '(' argumentList? ')' + | 'super' '.' typeArguments? Identifier '(' argumentList? ')' + | typeName '.' 'super' '.' typeArguments? Identifier '(' argumentList? ')' + ; + +argumentList + : expression (',' expression)* + ; + +methodReference + : expressionName '::' typeArguments? Identifier + | referenceType '::' typeArguments? Identifier + | primary '::' typeArguments? Identifier + | 'super' '::' typeArguments? Identifier + | typeName '.' 'super' '::' typeArguments? Identifier + | classType '::' typeArguments? 'new' + | arrayType '::' 'new' + ; + +methodReference_lf_primary + : '::' typeArguments? Identifier + ; + +methodReference_lfno_primary + : expressionName '::' typeArguments? Identifier + | referenceType '::' typeArguments? Identifier + | 'super' '::' typeArguments? Identifier + | typeName '.' 'super' '::' typeArguments? Identifier + | classType '::' typeArguments? 'new' + | arrayType '::' 'new' + ; + +arrayCreationExpression + : 'new' primitiveType dimExprs dims? + | 'new' classOrInterfaceType dimExprs dims? + | 'new' primitiveType dims arrayInitializer + | 'new' classOrInterfaceType dims arrayInitializer + ; + +dimExprs + : dimExpr dimExpr* + ; + +dimExpr + : annotation* '[' expression ']' + ; + +constantExpression + : expression + ; + +expression + : lambdaExpression + | assignmentExpression + ; + +lambdaExpression + : lambdaParameters '->' lambdaBody + ; + +lambdaParameters + : Identifier + | '(' formalParameterList? ')' + //| '(' inferredFormalParameterList ')' + ; + +inferredFormalParameterList + : Identifier (',' Identifier)* + ; + +lambdaBody + : expression + | block + ; + +assignmentExpression + : conditionalExpression + | assignment + ; + +assignment + : leftHandSide assignmentOperator expression + ; + +leftHandSide + : expressionName + | fieldAccess + | arrayAccess + ; + +assignmentOperator + : '=' + | '*=' + | '/=' + | '%=' + | '+=' + | '-=' + | '<<=' + | '>>=' + | '>>>=' + | '&=' + | '^=' + | '|=' + ; + +conditionalExpression + : conditionalOrExpression + | conditionalOrExpression '?' expression ':' conditionalExpression + ; + +conditionalOrExpression + : conditionalAndExpression + | conditionalOrExpression '||' conditionalAndExpression + ; + +conditionalAndExpression + : inclusiveOrExpression + | conditionalAndExpression '&&' inclusiveOrExpression + ; + +inclusiveOrExpression + : exclusiveOrExpression + | inclusiveOrExpression '|' exclusiveOrExpression + ; + +exclusiveOrExpression + : andExpression + | exclusiveOrExpression '^' andExpression + ; + +andExpression + : equalityExpression + | andExpression '&' equalityExpression + ; + +equalityExpression + : relationalExpression + | equalityExpression '==' relationalExpression + | equalityExpression '!=' relationalExpression + ; + +relationalExpression + : shiftExpression + | relationalExpression '<' shiftExpression + | relationalExpression '>' shiftExpression + | relationalExpression '<=' shiftExpression + | relationalExpression '>=' shiftExpression + | relationalExpression 'instanceof' referenceType + ; + +shiftExpression + : additiveExpression + | shiftExpression '<' '<' additiveExpression + | shiftExpression '>' '>' additiveExpression + | shiftExpression '>' '>' '>' additiveExpression + ; + +additiveExpression + : multiplicativeExpression + | additiveExpression '+' multiplicativeExpression + | additiveExpression '-' multiplicativeExpression + ; + +multiplicativeExpression + : unaryExpression + | multiplicativeExpression '*' unaryExpression + | multiplicativeExpression '/' unaryExpression + | multiplicativeExpression '%' unaryExpression + ; + +unaryExpression + : preIncrementExpression + | preDecrementExpression + | '+' unaryExpression + | '-' unaryExpression + | unaryExpressionNotPlusMinus + ; + +preIncrementExpression + : '++' unaryExpression + ; + +preDecrementExpression + : '--' unaryExpression + ; + +unaryExpressionNotPlusMinus + : postfixExpression + | '~' unaryExpression + | '!' unaryExpression + | castExpression + ; + +postfixExpression + : ( primary + | expressionName + ) + ( postIncrementExpression_lf_postfixExpression + | postDecrementExpression_lf_postfixExpression + )* + ; + +postIncrementExpression + : postfixExpression '++' + ; + +postIncrementExpression_lf_postfixExpression + : '++' + ; + +postDecrementExpression + : postfixExpression '--' + ; + +postDecrementExpression_lf_postfixExpression + : '--' + ; + +castExpression + : '(' primitiveType ')' unaryExpression + | '(' referenceType additionalBound* ')' unaryExpressionNotPlusMinus + | '(' referenceType additionalBound* ')' lambdaExpression + ; + +// LEXER + +// §3.9 Keywords + +ABSTRACT : 'abstract'; +ASSERT : 'assert'; +BOOLEAN : 'boolean'; +BREAK : 'break'; +BYTE : 'byte'; +CASE : 'case'; +CATCH : 'catch'; +CHAR : 'char'; +CLASS : 'class'; +CONST : 'const'; +CONTINUE : 'continue'; +DEFAULT : 'default'; +DO : 'do'; +DOUBLE : 'double'; +ELSE : 'else'; +ENUM : 'enum'; +EXTENDS : 'extends'; +FINAL : 'final'; +FINALLY : 'finally'; +FLOAT : 'float'; +FOR : 'for'; +IF : 'if'; +GOTO : 'goto'; +IMPLEMENTS : 'implements'; +IMPORT : 'import'; +INSTANCEOF : 'instanceof'; +INT : 'int'; +INTERFACE : 'interface'; +LONG : 'long'; +NATIVE : 'native'; +NEW : 'new'; +PACKAGE : 'package'; +PRIVATE : 'private'; +PROTECTED : 'protected'; +PUBLIC : 'public'; +RETURN : 'return'; +SHORT : 'short'; +STATIC : 'static'; +STRICTFP : 'strictfp'; +SUPER : 'super'; +SWITCH : 'switch'; +SYNCHRONIZED : 'synchronized'; +THIS : 'this'; +THROW : 'throw'; +THROWS : 'throws'; +TRANSIENT : 'transient'; +TRY : 'try'; +VOID : 'void'; +VOLATILE : 'volatile'; +WHILE : 'while'; + +// §3.10.1 Integer Literals + +IntegerLiteral + : DecimalIntegerLiteral + | HexIntegerLiteral + | OctalIntegerLiteral + | BinaryIntegerLiteral + ; + +fragment +DecimalIntegerLiteral + : DecimalNumeral IntegerTypeSuffix? + ; + +fragment +HexIntegerLiteral + : HexNumeral IntegerTypeSuffix? + ; + +fragment +OctalIntegerLiteral + : OctalNumeral IntegerTypeSuffix? + ; + +fragment +BinaryIntegerLiteral + : BinaryNumeral IntegerTypeSuffix? + ; + +fragment +IntegerTypeSuffix + : [lL] + ; + +fragment +DecimalNumeral + : '0' + | NonZeroDigit (Digits? | Underscores Digits) + ; + +fragment +Digits + : Digit (DigitsAndUnderscores? Digit)? + ; + +fragment +Digit + : '0' + | NonZeroDigit + ; + +fragment +NonZeroDigit + : [1-9] + ; + +fragment +DigitsAndUnderscores + : DigitOrUnderscore+ + ; + +fragment +DigitOrUnderscore + : Digit + | '_' + ; + +fragment +Underscores + : '_'+ + ; + +fragment +HexNumeral + : '0' [xX] HexDigits + ; + +fragment +HexDigits + : HexDigit (HexDigitsAndUnderscores? HexDigit)? + ; + +fragment +HexDigit + : [0-9a-fA-F] + ; + +fragment +HexDigitsAndUnderscores + : HexDigitOrUnderscore+ + ; + +fragment +HexDigitOrUnderscore + : HexDigit + | '_' + ; + +fragment +OctalNumeral + : '0' Underscores? OctalDigits + ; + +fragment +OctalDigits + : OctalDigit (OctalDigitsAndUnderscores? OctalDigit)? + ; + +fragment +OctalDigit + : [0-7] + ; + +fragment +OctalDigitsAndUnderscores + : OctalDigitOrUnderscore+ + ; + +fragment +OctalDigitOrUnderscore + : OctalDigit + | '_' + ; + +fragment +BinaryNumeral + : '0' [bB] BinaryDigits + ; + +fragment +BinaryDigits + : BinaryDigit (BinaryDigitsAndUnderscores? BinaryDigit)? + ; + +fragment +BinaryDigit + : [01] + ; + +fragment +BinaryDigitsAndUnderscores + : BinaryDigitOrUnderscore+ + ; + +fragment +BinaryDigitOrUnderscore + : BinaryDigit + | '_' + ; + +// §3.10.2 Floating-Point Literals + +FloatingPointLiteral + : DecimalFloatingPointLiteral + | HexadecimalFloatingPointLiteral + ; + +fragment +DecimalFloatingPointLiteral + : Digits '.' Digits? ExponentPart? FloatTypeSuffix? + | '.' Digits ExponentPart? FloatTypeSuffix? + | Digits ExponentPart FloatTypeSuffix? + | Digits FloatTypeSuffix + ; + +fragment +ExponentPart + : ExponentIndicator SignedInteger + ; + +fragment +ExponentIndicator + : [eE] + ; + +fragment +SignedInteger + : Sign? Digits + ; + +fragment +Sign + : [+-] + ; + +fragment +FloatTypeSuffix + : [fFdD] + ; + +fragment +HexadecimalFloatingPointLiteral + : HexSignificand BinaryExponent FloatTypeSuffix? + ; + +fragment +HexSignificand + : HexNumeral '.'? + | '0' [xX] HexDigits? '.' HexDigits + ; + +fragment +BinaryExponent + : BinaryExponentIndicator SignedInteger + ; + +fragment +BinaryExponentIndicator + : [pP] + ; + +// §3.10.3 Boolean Literals + +BooleanLiteral + : 'true' + | 'false' + ; + +// §3.10.4 Character Literals + +CharacterLiteral + : '\'' SingleCharacter '\'' + | '\'' EscapeSequence '\'' + ; + +fragment +SingleCharacter + : ~['\\] + ; + +// §3.10.5 String Literals + +StringLiteral + : '"' StringCharacters? '"' + ; + +fragment +StringCharacters + : StringCharacter+ + ; + +fragment +StringCharacter + : ~["\\] + | EscapeSequence + ; + +// §3.10.6 Escape Sequences for Character and String Literals + +fragment +EscapeSequence + : '\\' [btnfr"'\\] + | OctalEscape + | UnicodeEscape // This is not in the spec but prevents having to preprocess the input + ; + +fragment +OctalEscape + : '\\' OctalDigit + | '\\' OctalDigit OctalDigit + | '\\' ZeroToThree OctalDigit OctalDigit + ; + +fragment +ZeroToThree + : [0-3] + ; + +// This is not in the spec but prevents having to preprocess the input +fragment +UnicodeEscape + : '\\' 'u' HexDigit HexDigit HexDigit HexDigit + ; + +// §3.10.7 The Null Literal + +NullLiteral + : 'null' + ; + +// §3.11 Separators + +LPAREN : '('; +RPAREN : ')'; +LBRACE : '{'; +RBRACE : '}'; +LBRACK : '['; +RBRACK : ']'; +SEMI : ';'; +COMMA : ','; +DOT : '.'; + +// §3.12 Operators + +ASSIGN : '='; +GT : '>'; +LT : '<'; +BANG : '!'; +TILDE : '~'; +QUESTION : '?'; +COLON : ':'; +EQUAL : '=='; +LE : '<='; +GE : '>='; +NOTEQUAL : '!='; +AND : '&&'; +OR : '||'; +INC : '++'; +DEC : '--'; +ADD : '+'; +SUB : '-'; +MUL : '*'; +DIV : '/'; +BITAND : '&'; +BITOR : '|'; +CARET : '^'; +MOD : '%'; +ARROW : '->'; +COLONCOLON : '::'; + +ADD_ASSIGN : '+='; +SUB_ASSIGN : '-='; +MUL_ASSIGN : '*='; +DIV_ASSIGN : '/='; +AND_ASSIGN : '&='; +OR_ASSIGN : '|='; +XOR_ASSIGN : '^='; +MOD_ASSIGN : '%='; +LSHIFT_ASSIGN : '<<='; +RSHIFT_ASSIGN : '>>='; +URSHIFT_ASSIGN : '>>>='; + +// §3.8 Identifiers (must appear after all keywords in the grammar) + +Identifier + : JavaLetter JavaLetterOrDigit* + ; + + +fragment +JavaLetter + : [a-zA-Z$_] // these are the "java letters" below 0x7F + | // covers all characters above 0x7F which are not a surrogate + ~[\u0000-\u007F\uD800-\uDBFF] + {Character.isJavaIdentifierStart(_input.LA(-1))}? + | // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF + [\uD800-\uDBFF] [\uDC00-\uDFFF] + {Character.isJavaIdentifierStart(Character.toCodePoint((char)_input.LA(-2), (char)_input.LA(-1)))}? + ; + +fragment +JavaLetterOrDigit + : [a-zA-Z0-9$_] // these are the "java letters or digits" below 0x7F + | // covers all characters above 0x7F which are not a surrogate + ~[\u0000-\u007F\uD800-\uDBFF] + {Character.isJavaIdentifierPart(_input.LA(-1))}? + | // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF + [\uD800-\uDBFF] [\uDC00-\uDFFF] + {Character.isJavaIdentifierPart(Character.toCodePoint((char)_input.LA(-2), (char)_input.LA(-1)))}? + ; + +// +// Additional symbols not defined in the lexical specification +// + +AT : '@'; +ELLIPSIS : '...'; + +// +// Whitespace and comments +// + +WS : [ \t\r\n\u000C]+ -> skip + ; + +COMMENT + : '/*' .*? '*/' -> skip + ; + +LINE_COMMENT + : '//' ~[\r\n]* -> skip + ; diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/AStatement.java b/app/src/main/java/de/dhbwstuttgart/bytecode/AStatement.java new file mode 100644 index 00000000..5c28bf43 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/AStatement.java @@ -0,0 +1,30 @@ +package de.dhbwstuttgart.bytecode; + +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +import de.dhbwstuttgart.syntaxtree.statement.BinaryExpr; +import de.dhbwstuttgart.syntaxtree.statement.Expression; + +public abstract class AStatement implements IStatement { + protected Expression expr; + + public AStatement(Expression expr) { + this.expr = expr; + } + + @Override + public boolean isExprBinary() { + return (expr instanceof BinaryExpr); + } + + @Override + public void genBCForRelOp(MethodVisitor mv,Label branchLabel, Label endLabel, BytecodeGenMethod bytecodeGenMethod) { + mv.visitInsn(Opcodes.ICONST_1); + mv.visitJumpInsn(Opcodes.GOTO, endLabel); + mv.visitLabel(branchLabel); + mv.visitInsn(Opcodes.ICONST_0); + mv.visitLabel(endLabel); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/ArgumentExpr.java b/app/src/main/java/de/dhbwstuttgart/bytecode/ArgumentExpr.java new file mode 100644 index 00000000..b396e8d1 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/ArgumentExpr.java @@ -0,0 +1,11 @@ +package de.dhbwstuttgart.bytecode; + +import de.dhbwstuttgart.syntaxtree.statement.Expression; + +public class ArgumentExpr extends AStatement { + + public ArgumentExpr(Expression expr) { + super(expr); + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/ArgumentVisitor.java b/app/src/main/java/de/dhbwstuttgart/bytecode/ArgumentVisitor.java new file mode 100644 index 00000000..268e53b5 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/ArgumentVisitor.java @@ -0,0 +1,258 @@ +package de.dhbwstuttgart.bytecode; + +import java.util.List; + +import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.statement.ArgumentList; +import de.dhbwstuttgart.syntaxtree.statement.Assign; +import de.dhbwstuttgart.syntaxtree.statement.AssignToField; +import de.dhbwstuttgart.syntaxtree.statement.BinaryExpr; +import de.dhbwstuttgart.syntaxtree.statement.Block; +import de.dhbwstuttgart.syntaxtree.statement.CastExpr; +import de.dhbwstuttgart.syntaxtree.statement.DoStmt; +import de.dhbwstuttgart.syntaxtree.statement.EmptyStmt; +import de.dhbwstuttgart.syntaxtree.statement.ExpressionReceiver; +import de.dhbwstuttgart.syntaxtree.statement.FieldVar; +import de.dhbwstuttgart.syntaxtree.statement.ForStmt; +import de.dhbwstuttgart.syntaxtree.statement.IfStmt; +import de.dhbwstuttgart.syntaxtree.statement.InstanceOf; +import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression; +import de.dhbwstuttgart.syntaxtree.statement.Literal; +import de.dhbwstuttgart.syntaxtree.statement.LocalVar; +import de.dhbwstuttgart.syntaxtree.statement.LocalVarDecl; +import de.dhbwstuttgart.syntaxtree.statement.MethodCall; +import de.dhbwstuttgart.syntaxtree.statement.NewArray; +import de.dhbwstuttgart.syntaxtree.statement.NewClass; +import de.dhbwstuttgart.syntaxtree.statement.Return; +import de.dhbwstuttgart.syntaxtree.statement.ReturnVoid; +import de.dhbwstuttgart.syntaxtree.statement.StaticClassName; +import de.dhbwstuttgart.syntaxtree.statement.Super; +import de.dhbwstuttgart.syntaxtree.statement.SuperCall; +import de.dhbwstuttgart.syntaxtree.statement.This; +import de.dhbwstuttgart.syntaxtree.statement.UnaryExpr; +import de.dhbwstuttgart.syntaxtree.statement.WhileStmt; + +public class ArgumentVisitor implements StatementVisitor { + private List argListMethCall; + private BytecodeGenMethod bytecodeGenMethod; + + public ArgumentVisitor(List argListMethCall, BytecodeGenMethod bytecodeGenMethod) { + this.argListMethCall = argListMethCall; + this.bytecodeGenMethod = bytecodeGenMethod; + } + + @Override + public void visit(ArgumentList argumentList) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(LambdaExpression lambdaExpression) { + lambdaExpression.accept(bytecodeGenMethod); + // Zieltype des Lambas ist Funktionale Interface + // kann nie primitiv sein => un-/boxing wird hier nicht gebraucht + argListMethCall.remove(0); + } + + @Override + public void visit(Assign assign) { + assign.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolver().getResolvedType(assign.getType())); + argListMethCall.remove(0); + } + + @Override + public void visit(BinaryExpr binary) { + binary.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) { + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolver().getResolvedType(binary.getType())); + } else { + bytecodeGenMethod.doBoxing(bytecodeGenMethod.getResolver().getResolvedType(binary.getType())); + } + argListMethCall.remove(0); + } + + @Override + public void visit(Block block) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(CastExpr castExpr) { + castExpr.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolver().getResolvedType(castExpr.getType())); + argListMethCall.remove(0); + } + + @Override + public void visit(EmptyStmt emptyStmt) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(FieldVar fieldVar) { + fieldVar.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolver().getResolvedType(fieldVar.getType())); + argListMethCall.remove(0); + } + + @Override + public void visit(ForStmt forStmt) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(IfStmt ifStmt) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(InstanceOf instanceOf) { + instanceOf.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolver().getResolvedType(instanceOf.getType())); + argListMethCall.remove(0); + } + + @Override + public void visit(LocalVar localVar) { + localVar.accept(bytecodeGenMethod); + if(!bytecodeGenMethod.isBinaryExp) { + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolver().getResolvedType(localVar.getType())); + } + argListMethCall.remove(0); + } + + @Override + public void visit(LocalVarDecl localVarDecl) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(MethodCall methodCall) { + methodCall.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolver().getResolvedType(methodCall.getType())); + argListMethCall.remove(0); + } + + @Override + public void visit(NewClass methodCall) { + methodCall.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolver().getResolvedType(methodCall.getType())); + argListMethCall.remove(0); + } + + @Override + public void visit(NewArray newArray) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(Return aReturn) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(ReturnVoid aReturn) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(StaticClassName staticClassName) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(Super aSuper) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(This aThis) { + aThis.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolver().getResolvedType(aThis.getType())); + argListMethCall.remove(0); + } + + @Override + public void visit(WhileStmt whileStmt) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(DoStmt whileStmt) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(AssignToField assignLeftSide) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(AssignToLocal assignLeftSide) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(SuperCall superCall) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(ExpressionReceiver expressionReceiver) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(UnaryExpr unaryExpr) { + unaryExpr.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolver().getResolvedType(unaryExpr.getType())); + argListMethCall.remove(0); + } + + @Override + public void visit(Literal literal) { + literal.accept(bytecodeGenMethod); + + if(argListMethCall.get(0)) + bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolver().getResolvedType(literal.getType())); + argListMethCall.remove(0); + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/AssignStmt.java b/app/src/main/java/de/dhbwstuttgart/bytecode/AssignStmt.java new file mode 100644 index 00000000..366c450a --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/AssignStmt.java @@ -0,0 +1,11 @@ +package de.dhbwstuttgart.bytecode; + +import de.dhbwstuttgart.syntaxtree.statement.Expression; + +public class AssignStmt extends AStatement { + + public AssignStmt(Expression rightSide) { + super(rightSide); + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java b/app/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java new file mode 100644 index 00000000..04f408af --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGen.java @@ -0,0 +1,630 @@ +package de.dhbwstuttgart.bytecode; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Optional; + +import de.dhbwstuttgart.parser.scope.JavaClassName; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; + +import de.dhbwstuttgart.bytecode.Exception.BytecodeGeneratorError; +import de.dhbwstuttgart.bytecode.descriptor.DescriptorToString; +import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor; +import de.dhbwstuttgart.bytecode.signature.Signature; +import de.dhbwstuttgart.bytecode.signature.TypeToSignature; +import de.dhbwstuttgart.bytecode.signature.TypeToString; +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericGenratorResultForSourceFile; +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericsGeneratorResult; +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericsGeneratorResultForClass; +import de.dhbwstuttgart.bytecode.utilities.MethodUtility; +import de.dhbwstuttgart.bytecode.utilities.NormalConstructor; +import de.dhbwstuttgart.bytecode.utilities.NormalMethod; +import de.dhbwstuttgart.bytecode.utilities.Resolver; +import de.dhbwstuttgart.exceptions.NotImplementedException; +import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; +import de.dhbwstuttgart.syntaxtree.ASTVisitor; +import de.dhbwstuttgart.syntaxtree.ClassOrInterface; +import de.dhbwstuttgart.syntaxtree.Constructor; +import de.dhbwstuttgart.syntaxtree.Field; +import de.dhbwstuttgart.syntaxtree.FormalParameter; +import de.dhbwstuttgart.syntaxtree.GenericDeclarationList; +import de.dhbwstuttgart.syntaxtree.GenericTypeVar; +import de.dhbwstuttgart.syntaxtree.Method; +import de.dhbwstuttgart.syntaxtree.ParameterList; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.syntaxtree.statement.ArgumentList; +import de.dhbwstuttgart.syntaxtree.statement.Assign; +import de.dhbwstuttgart.syntaxtree.statement.AssignToField; +import de.dhbwstuttgart.syntaxtree.statement.BinaryExpr; +import de.dhbwstuttgart.syntaxtree.statement.Block; +import de.dhbwstuttgart.syntaxtree.statement.CastExpr; +import de.dhbwstuttgart.syntaxtree.statement.DoStmt; +import de.dhbwstuttgart.syntaxtree.statement.EmptyStmt; +import de.dhbwstuttgart.syntaxtree.statement.ExpressionReceiver; +import de.dhbwstuttgart.syntaxtree.statement.FieldVar; +import de.dhbwstuttgart.syntaxtree.statement.ForStmt; +import de.dhbwstuttgart.syntaxtree.statement.IfStmt; +import de.dhbwstuttgart.syntaxtree.statement.InstanceOf; +import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression; +import de.dhbwstuttgart.syntaxtree.statement.Literal; +import de.dhbwstuttgart.syntaxtree.statement.LocalVar; +import de.dhbwstuttgart.syntaxtree.statement.LocalVarDecl; +import de.dhbwstuttgart.syntaxtree.statement.MethodCall; +import de.dhbwstuttgart.syntaxtree.statement.NewArray; +import de.dhbwstuttgart.syntaxtree.statement.NewClass; +import de.dhbwstuttgart.syntaxtree.statement.Return; +import de.dhbwstuttgart.syntaxtree.statement.ReturnVoid; +import de.dhbwstuttgart.syntaxtree.statement.StaticClassName; +import de.dhbwstuttgart.syntaxtree.statement.Super; +import de.dhbwstuttgart.syntaxtree.statement.SuperCall; +import de.dhbwstuttgart.syntaxtree.statement.This; +import de.dhbwstuttgart.syntaxtree.statement.UnaryExpr; +import de.dhbwstuttgart.syntaxtree.statement.WhileStmt; +import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType; +import de.dhbwstuttgart.syntaxtree.type.GenericRefType; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.result.ResultSet; + +public class BytecodeGen implements ASTVisitor { + + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); + + String type; + + public static RefTypeOrTPHOrWildcardOrGeneric THISTYPE = null; + private JavaClassName className; + private String pkgName; + private boolean isInterface; + private Collection listOfResultSets; + private ResultSet resultSet; + private SourceFile sf; + private File path; + + private Optional fieldInitializations; + + private int indexOfFirstParam = 0; + + private String superClass; + + private List tphsClass; + + // stores parameter, local vars and the next index on the local variable table, + // which use for aload_i, astore_i,... + HashMap paramsAndLocals = new HashMap<>(); + // stores generics and their bounds of class + HashMap genericsAndBounds = new HashMap<>(); + + private int constructorPos = 0; + + HashMap methodParamsAndTypes = new HashMap<>(); + byte[] bytecode; + HashMap classFiles; + + private final ArrayList methodNameAndParamsT = new ArrayList<>(); + private final ArrayList fieldNameAndParamsT = new ArrayList<>(); + + private final ArrayList fieldNameSignature = new ArrayList<>(); + + private List simplifyResultsForAllSourceFiles; + private GenericsGeneratorResultForClass generatedGenerics; + + private Resolver resolver; + private final ClassLoader classLoader; + + public BytecodeGen(HashMap classFiles, Collection listOfResultSets, List simplifyResultsForAllSourceFiles, SourceFile sf, + File path, ClassLoader classLoader) { + this.classFiles = classFiles; + this.listOfResultSets = listOfResultSets; + this.simplifyResultsForAllSourceFiles = simplifyResultsForAllSourceFiles; + this.sf = sf; + this.path = path; + this.pkgName = sf.getPkgName(); + this.classLoader = classLoader; + } + + @Override + public void visit(SourceFile sourceFile) { + for (ClassOrInterface cl : sourceFile.getClasses()) { + System.out.println("in Class: " + cl.getClassName().toString()); + BytecodeGen classGen = new BytecodeGen(classFiles, listOfResultSets, simplifyResultsForAllSourceFiles, sf, path, classLoader); + cl.accept(classGen); + classGen.writeClass(cl.getClassName()); + } + } + + /** + * Associates the bytecode of the class that was build with the classWriter + * {@link #cw} with the class name in the map {@link #classFiles} + * + * @param name name of the class with which the bytecode is to be associated + */ + private void writeClass(JavaClassName name) { + bytecode = cw.toByteArray(); + classFiles.put(name, bytecode); + + } + + public HashMap getClassFiles() { + return classFiles; + } + + @Override + public void visit(ClassOrInterface classOrInterface) { + + className = classOrInterface.getClassName(); + + cw.visitSource(className.getClassName() + ".jav", null); + + isInterface = (classOrInterface.getModifiers() & 512) == 512; + + int acc = isInterface ? classOrInterface.getModifiers() + Opcodes.ACC_ABSTRACT + : classOrInterface.getModifiers() + Opcodes.ACC_SUPER; + + fieldInitializations = classOrInterface.getfieldInitializations(); + +// resultSet = listOfResultSets.get(0); + boolean isVisited = false; + List listOfResultSetsList = new ArrayList<>(listOfResultSets); + generatedGenerics = simplifyResultsForAllSourceFiles.stream().map(sr->sr.getSimplifyResultsByName(className)).findFirst().get(); + for (int i = 0; i < listOfResultSetsList.size(); i++) { + //for (ResultSet rs : listOfResultSets) { + superClass = classOrInterface.getSuperClass().acceptTV(new TypeToDescriptor()); + resultSet = listOfResultSetsList.get(i); + resolver = new Resolver(resultSet); +// tphExtractor.setResultSet(resultSet); + + + // Nur einmal ausführen!! + if (!isVisited) { + + String sig = null; + /* + * if class has generics then creates signature Signature looks like: + * Superclass + */ + if (classOrInterface.getGenerics().iterator().hasNext() || classOrInterface.getSuperClass().acceptTV(new TypeToSignature()).contains("<") + || !generatedGenerics.getClassConstraints().isEmpty()) { + + List consClass = generatedGenerics.getClassConstraints(); +// + Signature signature = new Signature(classOrInterface, genericsAndBounds, consClass); + sig = signature.createSignatureForClassOrInterface(); + System.out.println("Signature: => " + sig); + } + + cw.visit(Opcodes.V1_8, acc, classOrInterface.getClassName().toString().replace(".", "/"), sig, + classOrInterface.getSuperClass().acceptTV(new TypeToDescriptor()), null); + + isVisited = true; + } + + for (Field f : classOrInterface.getFieldDecl()) { + f.accept(this); + } + + for (Constructor c : classOrInterface.getConstructors()) { + c.accept(this); + } + + for (Method m : classOrInterface.getMethods()) { + m.accept(this); + } + + } + + } + + @Override + public void visit(Constructor field) { + // stores generics and their bounds of method + HashMap genericsAndBoundsMethod = new HashMap<>(); + + field.getParameterList().accept(this); + + String id = MethodUtility.createID(resolver, field); + + if (methodNameAndParamsT.contains(id)) { + return; + } + methodNameAndParamsT.add(id); + System.out.println("Constructor: " + field.name + " , paramsType: " + id); + + String desc = null; + boolean hasGen = false; + + for (String paramName : methodParamsAndTypes.keySet()) { + String typeOfParam = methodParamsAndTypes.get(paramName).acceptTV(new TypeToSignature()); + System.out.println(typeOfParam); + if (genericsAndBounds.containsKey(typeOfParam) || typeOfParam.contains("$") || typeOfParam.contains("<")) { + hasGen = true; + break; + } + } + String sig = null; + if (hasGen) { + List constraints = generatedGenerics.getClassConstraints(); + Signature signature = new Signature(genericsAndBounds, + methodParamsAndTypes, resultSet, constraints); + + sig = signature.createSignatureForConstructor(field); + } + if (field.getParameterList().iterator().hasNext()) + System.out.println(field.getParameterList().iterator().next().getType().acceptTV(new TypeToDescriptor())); + + NormalConstructor constructor = new NormalConstructor(field, genericsAndBounds, hasGen); + desc = constructor.accept(new DescriptorToString(resultSet)); + System.out.println("Constructor: " + field.getName() + " Sig: " + sig + " Desc: " + desc); + MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "", desc, sig, null); + mv.visitCode(); + + Block block = fieldInitializations.get().block; + + constructorPos += 1; + + BytecodeGenMethod gen = new BytecodeGenMethod(className, superClass, resultSet, field, mv, paramsAndLocals, cw, + genericsAndBoundsMethod, genericsAndBounds, isInterface, classFiles, sf, path, block, constructorPos, classLoader); + if (!field.getParameterList().iterator().hasNext() + && !(field.block.statements.get(field.block.statements.size() - 1) instanceof ReturnVoid)) { + mv.visitInsn(Opcodes.RETURN); + } + mv.visitMaxs(0, 0); + mv.visitEnd(); + } + + @Override + public void visit(Method method) { + // TODO: check if the method is static => if static then the first param will be + // stored in pos 0 + // else it will be stored in pos 1 and this will be stored in pos 0 + String retType = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor()); + + String id = MethodUtility.createID(resolver, method); + + if (methodNameAndParamsT.contains(id)) { + return; + } + methodNameAndParamsT.add(id); + System.out.println("Method: " + method.name + " , paramsType: " + id); + // stores generics and their bounds of method + HashMap genericsAndBoundsMethod = new HashMap<>(); + + method.getParameterList().accept(this); + + String methDesc = null; + + // Method getModifiers() ? + int acc = isInterface ? Opcodes.ACC_ABSTRACT : method.modifier; + System.out.println(acc); + + /* Prüfe, ob die Rückgabe-Type der Methode eine Type-Variable ist */ + boolean hasGenInParameterList = genericsAndBounds.containsKey(retType) || retType.contains("TPH ") + || resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToSignature()) + .contains("<"); + /* + * Wenn die Rückgabe-Type eine Typ-variable ist, erzeuge direkt die Signature, + * wenn nicht, prüfe, ob einer der Parameter Typ-Variable als Typ hat + */ + if (!hasGenInParameterList) { + for (String paramName : methodParamsAndTypes.keySet()) { + String typeOfParam = methodParamsAndTypes.get(paramName).acceptTV(new TypeToDescriptor()); + String sigOfParam = methodParamsAndTypes.get(paramName).acceptTV(new TypeToSignature()); + if (genericsAndBounds.containsKey(typeOfParam) || typeOfParam.contains("TPH ") + || sigOfParam.contains("<")) { + hasGenInParameterList = true; + break; + } + } + } + // TODO: Test if the return-type or any of the parameter is a parameterized + // type. (VP) + // then create the descriptor with the new syntax. + + String sig = null; + /* + * method.getGenerics: <....> RT method(..) + */ + boolean hasGen = method.getGenerics().iterator().hasNext() || hasGenInParameterList; + /* if method has generics or return type is TPH, create signature */ + // zwite operand muss weggelassen werden + if (hasGen || resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToString()) + .equals("TPH")) { + + List constraints = generatedGenerics.getMethodConstraintsByID(id); + List classConstraints = generatedGenerics.getClassConstraints(); + Signature signature = new Signature(genericsAndBoundsMethod, genericsAndBounds, + methodParamsAndTypes, resultSet, constraints,classConstraints); + sig = signature.createSignatureForMethod(method); + } + System.out.println(method.getName() + " ==> " + sig); + NormalMethod meth = new NormalMethod(method, genericsAndBounds, genericsAndBoundsMethod, hasGen); + methDesc = meth.accept(new DescriptorToString(resultSet)); + + MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC + acc, method.getName(), methDesc, sig, null); + + mv.visitCode(); + BytecodeGenMethod gen = new BytecodeGenMethod(className, superClass, resultSet, method, mv, paramsAndLocals, cw, + genericsAndBoundsMethod, genericsAndBounds, isInterface, classFiles, sf, path, classLoader); + + mv.visitMaxs(0, 0); + mv.visitEnd(); + } + + @Override + public void visit(ParameterList formalParameters) { + paramsAndLocals = new HashMap<>(); + methodParamsAndTypes = new HashMap<>(); + Iterator itr = formalParameters.iterator(); + int i = 1; + while (itr.hasNext()) { + FormalParameter fp = itr.next(); + paramsAndLocals.put(fp.getName(), i); + methodParamsAndTypes.put(fp.getName(), resultSet.resolveType(fp.getType()).resolvedType); + fp.accept(this); + i++; + } + } + + @Override + public void visit(FormalParameter formalParameter) { + formalParameter.getType().accept(this); + } + + @Override + public void visit(RefType refType) { + type = "L" + refType.toString() + ";"; + } + + @Override + public void visit(SuperWildcardType superWildcardType) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(TypePlaceholder typePlaceholder) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(ExtendsWildcardType extendsWildcardType) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(GenericRefType genericRefType) { + // TODO Auto-generated method stub + + } + + // ?? + @Override + public void visit(FieldVar fieldVar) { + System.out.println("In FieldVar ---"); +// cw.newField(fieldVar.receiver.toString(), fieldVar.fieldVarName.toString(), fieldVar.getType().toString()); + FieldVisitor fv = cw.visitField(Opcodes.ACC_PRIVATE, fieldVar.fieldVarName, "L" + fieldVar.getType() + ";", + null, null); + fv.visitEnd(); + } + + @Override + public void visit(Field field) { + System.out.println("In Field ---"); + String des = "L"; + if (resultSet.resolveType(field.getType()).resolvedType instanceof TypePlaceholder) { + des += Type.getInternalName(Object.class); + } else { + des += resultSet.resolveType(field.getType()).resolvedType.acceptTV(new TypeToDescriptor()); + } + des += ";"; + System.out.println(des); + String sig = resultSet.resolveType(field.getType()).resolvedType.acceptTV(new TypeToSignature(generatedGenerics.getClassConstraints())); + System.out.println(sig); + if (sig.charAt(sig.length() - 1) != (";").charAt(0)) { + sig += ";"; + } + String nameAndDesc = field.getName() + "%%" + des; + String nameAndSig = field.getName() + "%%" + sig; + if (fieldNameAndParamsT.contains(nameAndDesc)) { + if (fieldNameSignature.contains(nameAndSig)) { + return; + } + throw new BytecodeGeneratorError("Bytecode generation aborted due to duplicate field name&signature"); + } + fieldNameAndParamsT.add(nameAndDesc); + fieldNameSignature.add(nameAndSig); + + cw.visitField(field.modifier, field.getName(), des, sig, null); + } + + @Override + public void visit(LambdaExpression lambdaExpression) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(Assign assign) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(BinaryExpr binary) { + + } + + @Override + public void visit(Block block) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(CastExpr castExpr) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(EmptyStmt emptyStmt) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(ForStmt forStmt) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(IfStmt ifStmt) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(InstanceOf instanceOf) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(LocalVar localVar) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(LocalVarDecl localVarDecl) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(MethodCall methodCall) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(NewClass methodCall) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(NewArray newArray) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(Return aReturn) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(ReturnVoid aReturn) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(StaticClassName staticClassName) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(Super aSuper) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(This aThis) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(WhileStmt whileStmt) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(DoStmt whileStmt) { + // TODO Auto-generated method stub + + } + + // ??? + @Override + public void visit(Literal literal) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(ArgumentList argumentList) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(GenericTypeVar genericTypeVar) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(GenericDeclarationList genericTypeVars) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(AssignToField assignLeftSide) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(AssignToLocal assignLeftSide) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(SuperCall superCall) { + + } + + @Override + public void visit(ExpressionReceiver expressionReceiver) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(UnaryExpr unaryExpr) { + throw new NotImplementedException(); + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java b/app/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java new file mode 100644 index 00000000..5cbcfca9 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java @@ -0,0 +1,1527 @@ +package de.dhbwstuttgart.bytecode; + +import java.io.File; +import java.lang.invoke.CallSite; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.reflect.Parameter; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.stream.Collectors; + +import de.dhbwstuttgart.bytecode.funN.FunNGenerator; +import de.dhbwstuttgart.bytecode.funN.FunNUtilities; +import de.dhbwstuttgart.bytecode.utilities.*; +import de.dhbwstuttgart.environment.DirectoryClassLoader; +import de.dhbwstuttgart.exceptions.NotImplementedException; +import de.dhbwstuttgart.parser.scope.JavaClassName; +import de.dhbwstuttgart.syntaxtree.statement.*; +import de.dhbwstuttgart.syntaxtree.statement.BinaryExpr.Operator; +import de.dhbwstuttgart.syntaxtree.statement.UnaryExpr.Operation; + +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Handle; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; + +import de.dhbwstuttgart.bytecode.Exception.NotInCurrentPackageException; +import de.dhbwstuttgart.bytecode.descriptor.DescriptorToString; +import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor; +import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; +import de.dhbwstuttgart.syntaxtree.FormalParameter; +import de.dhbwstuttgart.syntaxtree.Method; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.result.ResultSet; +import javassist.NotFoundException; + +public class BytecodeGenMethod implements StatementVisitor { + + private Resolver resolver; + private Method m; + private MethodVisitor mv; + private HashMap paramsAndLocals = new HashMap<>(); + private JavaClassName className; + private int lamCounter; + private ClassWriter cw; + private ResultSet resultSet; + private boolean isInterface; + private HashMap genericsAndBoundsMethod; + private HashMap genericsAndBounds; + public boolean isBinaryExp = false; + private String superClass; + private File path; + private SourceFile sf; + private IStatement statement = null; + private boolean isReturnStmt = false; + private boolean isParentBinary = false; + + private boolean needDUP = false; + + private Block blockFieldInit = null; + private boolean isBlockFieldInitVisited = false; + // for tests ** + private String fieldName; + private String fieldDesc; + private Expression rightSideTemp; + + private boolean isRightSideALambda = false; + private KindOfLambda kindOfLambda; + private HashMap classFiles; + + private int constructorPos = 0; + + private ArrayList varsFunInterface = new ArrayList<>();; + private final ClassLoader classLoader; + + // generate bytecode for constructor + public BytecodeGenMethod(JavaClassName className, String superClass, ResultSet resultSet, Method m, MethodVisitor mv, + HashMap paramsAndLocals, ClassWriter cw, HashMap genericsAndBoundsMethod, + HashMap genericsAndBounds, boolean isInterface, HashMap classFiles, + SourceFile sf, File path, Block block, int constructorPos, ClassLoader classLoader) { + + this.className = className; + this.superClass = superClass; + this.resultSet = resultSet; + this.resolver = new Resolver(resultSet); + this.m = m; + this.mv = mv; + this.paramsAndLocals = paramsAndLocals; + this.cw = cw; + this.genericsAndBoundsMethod = genericsAndBoundsMethod; + this.genericsAndBounds = genericsAndBounds; + this.isInterface = isInterface; + this.classFiles = classFiles; + this.sf = sf; + this.path = path; + this.lamCounter = -1; + this.constructorPos = constructorPos; + this.classLoader = classLoader; + if(block != null) + this.blockFieldInit = block; + this.m.block.accept(this); + } + + public BytecodeGenMethod(JavaClassName className, String superClass,ResultSet resultSet, Method m, MethodVisitor mv, + HashMap paramsAndLocals, ClassWriter cw, HashMap genericsAndBoundsMethod, + HashMap genericsAndBounds, boolean isInterface, HashMap classFiles, SourceFile sf,File path, ClassLoader classLoader) { + + this.className = className; + this.superClass = superClass; + this.resultSet = resultSet; + this.resolver = new Resolver(resultSet); + this.m = m; + this.mv = mv; + this.paramsAndLocals = paramsAndLocals; + this.cw = cw; + this.genericsAndBoundsMethod = genericsAndBoundsMethod; + this.genericsAndBounds = genericsAndBounds; + this.isInterface = isInterface; + this.classFiles = classFiles; + this.sf = sf; + this.path = path; + this.lamCounter = -1; + this.classLoader = classLoader; + if (!isInterface) + this.m.block.accept(this); + } + + public BytecodeGenMethod(JavaClassName className, ClassWriter cw, LambdaExpression lambdaExpression, ArrayList usedVars, ResultSet resultSet, MethodVisitor mv, + int indexOfFirstParamLam, boolean isInterface, HashMap classFiles, File path, int lamCounter, SourceFile sf,HashMap genericsAndBoundsMethod, + HashMap genericsAndBounds, ClassLoader classLoader) { + this.className = className; + this.cw = cw; + this.resultSet = resultSet; + this.resolver = new Resolver(resultSet); + this.mv = mv; + this.isInterface = isInterface; + this.classFiles = classFiles; + this.path = path; + this.lamCounter = lamCounter; + this.sf = sf; + this.genericsAndBoundsMethod = genericsAndBoundsMethod; + this.genericsAndBounds = genericsAndBounds; + this.classLoader = classLoader; + + Iterator itr = lambdaExpression.params.iterator(); + int i = indexOfFirstParamLam; + + for(String var : usedVars) { + this.paramsAndLocals.put(var, i); + i++; + } + + while (itr.hasNext()) { + FormalParameter fp = itr.next(); + this.paramsAndLocals.put(fp.getName(), i); + i++; + } + lambdaExpression.methodBody.accept(this); + } + + public Resolver getResolver() { + return resolver; + } + + public void isBinary(boolean isBinary) { + this.isBinaryExp =isBinary; + } + + + @Override + public void visit(Block block) { + HashMap paramsAndLocalsOld = new HashMap<>(paramsAndLocals); + for (Statement stmt : block.getStatements()) { + stmt.accept(this); + if(stmt instanceof MethodCall) { + String ret = resolver.getResolvedType(((MethodCall) stmt).getType()); + if(!ret.equals(CONSTANTS.VOID)) + mv.visitInsn(Opcodes.POP); + } + } + paramsAndLocals = paramsAndLocalsOld; + } + + @Override + public void visit(SuperCall superCall) { + superCall.receiver.accept(this); + superCall.arglist.accept(this); + mv.visitMethodInsn(Opcodes.INVOKESPECIAL, this.superClass, superCall.name, "()V", + isInterface); + + if(blockFieldInit!=null && !isBlockFieldInitVisited) { + isBlockFieldInitVisited =true; + //blockFieldInit.accept(this); + for(Statement stmt : blockFieldInit.statements) { + if(stmt instanceof SuperCall) + continue; + + stmt.accept(this); + } + } + } + + // ?? + @Override + public void visit(LocalVar localVar) { + // wenn String + String zuerst wird ein StringBuilder initialisiert dann + // wird die lokale Var geladen. Sonst wird zuerst die lokale Var geladen. + System.out.println(localVar.name); + mv.visitVarInsn(Opcodes.ALOAD, paramsAndLocals.get(localVar.name)); + + if (isBinaryExp) { + doUnboxing(resolver.getResolvedType(localVar.getType())); + } + } + + // ?? + @Override + public void visit(LocalVarDecl localVarDecl) { + paramsAndLocals.put(localVarDecl.getName(), paramsAndLocals.size()+1); + } + + @Override + public void visit(Assign assign) { + statement = new AssignStmt(assign.rightSide); + // if the right side is a lambda => the left side must be a functional interface + if (assign.rightSide instanceof LambdaExpression) { + isRightSideALambda = true; + } else { + isRightSideALambda = false; + } + + isBinaryExp = statement.isExprBinary(); + + if (assign.lefSide instanceof AssignToField) { + // load_0, ldc or .. then putfield + this.rightSideTemp = assign.rightSide; + } else { + assign.rightSide.accept(this); + } + + statement = new AssignStmt(assign.rightSide); + isBinaryExp = statement.isExprBinary(); + + if (isBinaryExp) { + BinaryExpr binary = (BinaryExpr) assign.rightSide; + String binaryType = resolver.getResolvedType(binary.getType()); + doBoxing(binaryType); + isBinaryExp = false; + } + + System.out.println("ASSIGN TYPE R: " + resolver.getResolvedType(assign.rightSide.getType())); + String typeOfRightSide = resolver.getResolvedType(assign.rightSide.getType()); + if(typeOfRightSide.contains(CONSTANTS.ANGLEBRACKET)) { + mv.visitTypeInsn(Opcodes.CHECKCAST, typeOfRightSide.substring(0, typeOfRightSide.indexOf('<'))); + } + assign.lefSide.accept(this); + + statement = null; + } + + @Override + public void visit(BinaryExpr binary) { + isParentBinary = true; + String lexpType = resolver.getResolvedType(binary.lexpr.getType()); + String rexpType = resolver.getResolvedType(binary.rexpr.getType()); + + String largerType = getLargerType(lexpType, rexpType); + String typeOfBinary = resolver.getResolvedType(binary.getType()); + + if (typeOfBinary.equals(Type.getInternalName(String.class))) { + mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(StringBuilder.class)); + mv.visitInsn(Opcodes.DUP); + mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(StringBuilder.class), "", "()V", + false); + } + + Label endLabel = new Label(); + // this case for while loops and If statements + if (statement instanceof LoopStmt) + mv.visitLabel(endLabel); + + if(binary.lexpr instanceof UnaryExpr) + needDUP = true; + + binary.lexpr.accept(this); + + if(lexpType.equals(Type.getInternalName(String.class))) { + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(StringBuilder.class), "append", + "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false); + } + + if (!lexpType.equals(rexpType) && !lexpType.equals(largerType)) + doCast(lexpType, largerType); + + if(binary.rexpr instanceof UnaryExpr) + needDUP = true; + + binary.rexpr.accept(this); + if(rexpType.equals(Type.getInternalName(String.class))) { + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(StringBuilder.class), "append", + "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false); + } + isParentBinary = false; + + if (!lexpType.equals(rexpType) && !rexpType.equals(largerType)) + doCast(rexpType, largerType); + + Operator op = binary.operation; + + switch (op) { + case ADD: + doVisitAddOpInsn(largerType); + break; + + case SUB: + doVisitSubOpInsn(typeOfBinary); + break; + + case MUL: + doVisitMulOpInsn(typeOfBinary); + break; + + case DIV: + doVisitDivOpInsn(typeOfBinary); + break; + + case MOD: + doVisitModOpInsn(typeOfBinary); + break; + + case LESSTHAN: + case LESSEQUAL: + case BIGGERTHAN: + case BIGGEREQUAL: + case EQUAL: + case NOTEQUAL: + Label branchLabel = new Label(); + doVisitRelOpInsn(op, largerType, branchLabel, endLabel); + break; + + default: + break; + } + } + + private String getLargerType(String lexpType, String rexpType) { + if (lexpType.equals(Type.getInternalName(String.class)) + || rexpType.equals(Type.getInternalName(String.class))) { + return Type.getInternalName(String.class); + } else if (lexpType.equals(Type.getInternalName(Double.class)) + || rexpType.equals(Type.getInternalName(Double.class))) { + return Type.getInternalName(Double.class); + } else if (lexpType.equals(Type.getInternalName(Float.class)) + || rexpType.equals(Type.getInternalName(Float.class))) { + return Type.getInternalName(Float.class); + } else if (lexpType.equals(Type.getInternalName(Long.class)) + || rexpType.equals(Type.getInternalName(Long.class))) { + return Type.getInternalName(Long.class); + } else { + return Type.getInternalName(Integer.class); + } + } + + private void doCast(String sourceType, String dest) { + switch (dest) { + case CONSTANTS.REFTYPE_LONG: + mv.visitInsn(Opcodes.I2L); + break; + + case CONSTANTS.REFTYPE_DOUBLE: + if (sourceType.equals(Type.getInternalName(Long.class))) { + mv.visitInsn(Opcodes.L2D); + } else if (sourceType.equals(Type.getInternalName(Float.class))) { + mv.visitInsn(Opcodes.F2D); + } else { + mv.visitInsn(Opcodes.I2D); + } + break; + + case CONSTANTS.REFTYPE_FLOAT: + if (sourceType.equals(Type.getInternalName(Long.class))) { + mv.visitInsn(Opcodes.L2F); + } else { + mv.visitInsn(Opcodes.I2F); + } + break; + // braucht man eigentlich nicht, muss getestet werden + case CONSTANTS.REFTYPE_STRING: + if (sourceType.equals(Type.getInternalName(Double.class))) { + mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "valueOf", + "(D)Ljava/lang/String;", false); + } else if (sourceType.equals(Type.getInternalName(Long.class))) { + mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "valueOf", + "(J)Ljava/lang/String;", false); + } else if (sourceType.equals(Type.getInternalName(Float.class))) { + mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "valueOf", + "(F)Ljava/lang/String;", false); + } else { + mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "valueOf", + "(I)Ljava/lang/String;", false); + } + break; + default: + break; + } + } + + private void doVisitRelOpInsn(Operator op, String typeOfBinary, Label branchLabel, Label endLabel) { + System.out.println("TypeOfBinary: " + typeOfBinary); + switch (typeOfBinary) { + case CONSTANTS.REFTYPE_LONG: + mv.visitInsn(Opcodes.LCMP); + doVisitIfInRelOp(op, branchLabel, endLabel); + break; + case CONSTANTS.REFTYPE_DOUBLE: + mv.visitInsn(Opcodes.DCMPG); + doVisitIfInRelOp(op, branchLabel, endLabel); + break; + case CONSTANTS.REFTYPE_FLOAT: + mv.visitInsn(Opcodes.FCMPG); + doVisitIfInRelOp(op, branchLabel, endLabel); + break; + default: + switch (op) { + case LESSTHAN: + mv.visitJumpInsn(Opcodes.IF_ICMPGE, branchLabel); + break; + case LESSEQUAL: + mv.visitJumpInsn(Opcodes.IF_ICMPGT, branchLabel); + break; + case BIGGERTHAN: + mv.visitJumpInsn(Opcodes.IF_ICMPLE, branchLabel); + break; + case BIGGEREQUAL: + mv.visitJumpInsn(Opcodes.IF_ICMPLT, branchLabel); + break; + case EQUAL: + mv.visitJumpInsn(Opcodes.IF_ICMPNE, branchLabel); + break; + case NOTEQUAL: + mv.visitJumpInsn(Opcodes.IFEQ, branchLabel); + break; + default: + break; + } + + statement.genBCForRelOp(mv, branchLabel, endLabel, this); + + break; + } + } + + private void doVisitIfInRelOp(Operator op, Label branchLabel, Label endLabel) { + + switch (op) { + case LESSTHAN: + mv.visitJumpInsn(Opcodes.IFGE, branchLabel); + break; + case LESSEQUAL: + mv.visitJumpInsn(Opcodes.IFGT, branchLabel); + break; + case BIGGERTHAN: + mv.visitJumpInsn(Opcodes.IFLE, branchLabel); + break; + case BIGGEREQUAL: + mv.visitJumpInsn(Opcodes.IFLT, branchLabel); + break; + case EQUAL: + mv.visitJumpInsn(Opcodes.IFNE, branchLabel); + break; + case NOTEQUAL: + mv.visitJumpInsn(Opcodes.IFEQ, branchLabel); + break; + default: + break; + } + + statement.genBCForRelOp(mv, branchLabel, endLabel, this); + } + + private void doVisitModOpInsn(String typeOfBinary) { + switch (typeOfBinary) { + case CONSTANTS.REFTYPE_LONG: + mv.visitInsn(Opcodes.LREM); + break; + case CONSTANTS.REFTYPE_DOUBLE: + mv.visitInsn(Opcodes.DREM); + break; + case CONSTANTS.REFTYPE_FLOAT: + mv.visitInsn(Opcodes.FREM); + break; + default: + mv.visitInsn(Opcodes.IREM); + break; + } + } + + private void doVisitDivOpInsn(String typeOfBinary) { + switch (typeOfBinary) { + case CONSTANTS.REFTYPE_LONG: + mv.visitInsn(Opcodes.LDIV); + break; + case CONSTANTS.REFTYPE_DOUBLE: + mv.visitInsn(Opcodes.DDIV); + break; + case CONSTANTS.REFTYPE_FLOAT: + mv.visitInsn(Opcodes.FDIV); + break; + default: + mv.visitInsn(Opcodes.IDIV); + break; + } + } + + private void doVisitMulOpInsn(String typeOfBinary) { + switch (typeOfBinary) { + case CONSTANTS.REFTYPE_LONG: + mv.visitInsn(Opcodes.LMUL); + break; + case CONSTANTS.REFTYPE_DOUBLE: + mv.visitInsn(Opcodes.DMUL); + break; + case CONSTANTS.REFTYPE_FLOAT: + mv.visitInsn(Opcodes.FMUL); + break; + default: + mv.visitInsn(Opcodes.IMUL); + break; + } + } + + private void doVisitSubOpInsn(String typeOfBinary) { + switch (typeOfBinary) { + case CONSTANTS.REFTYPE_LONG: + mv.visitInsn(Opcodes.LSUB); + break; + case CONSTANTS.REFTYPE_DOUBLE: + mv.visitInsn(Opcodes.DSUB); + break; + case CONSTANTS.REFTYPE_FLOAT: + mv.visitInsn(Opcodes.FSUB); + break; + default: + mv.visitInsn(Opcodes.ISUB); + break; + } + + } + + private void doVisitAddOpInsn(String typeOfBinary) { + switch (typeOfBinary) { + case CONSTANTS.REFTYPE_BYTE: + mv.visitInsn(Opcodes.IADD); + break; + case CONSTANTS.REFTYPE_SHORT: + mv.visitInsn(Opcodes.IADD); + break; + case CONSTANTS.REFTYPE_INTEGER: + mv.visitInsn(Opcodes.IADD); + break; + case CONSTANTS.REFTYPE_LONG: + mv.visitInsn(Opcodes.LADD); + break; + case CONSTANTS.REFTYPE_DOUBLE: + mv.visitInsn(Opcodes.DADD); + break; + case CONSTANTS.REFTYPE_FLOAT: + mv.visitInsn(Opcodes.FADD); + break; + case CONSTANTS.REFTYPE_STRING: + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", CONSTANTS.TO_STRING, "()Ljava/lang/String;", + false); + break; + default: + break; + } + } + + @Override + public void visit(LambdaExpression lambdaExpression) { + this.lamCounter++; + + String typeErasure = createDescriptorWithTypeErasure(lambdaExpression); + //ToDo Etienne: Double Check + RefTypeOrTPHOrWildcardOrGeneric returnType = resolver.resolve(lambdaExpression.getReturnType()); + List argumentTypes = lambdaExpression + .params + .getFormalparalist() + .stream() + .map(FormalParameter::getType) + .map(resolver::resolve) + .collect(Collectors.toList()); + FunNUtilities funNUtilities = FunNGenerator.getInstance(); + FunNUtilities.writeClassFile(funNUtilities.getSuperClassName(argumentTypes.size()), + funNUtilities.generateSuperBytecode(argumentTypes.size()), path); + FunNUtilities.writeClassFile(funNUtilities.getSpecializedClassName(argumentTypes, returnType), + funNUtilities.generateSpecializedBytecode(argumentTypes, returnType), path); + + Lambda lam = new Lambda(lambdaExpression); + String lamDesc = lam.accept(new DescriptorToString(resultSet)); + // Call site, which, when invoked, returns an instance of the functional + // interface to which + // the lambda is being converted + MethodType mt = MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class, + MethodType.class, MethodType.class, MethodHandle.class, MethodType.class); + + Handle bootstrap = new Handle(Opcodes.H_INVOKESTATIC, "java/lang/invoke/LambdaMetafactory", "metafactory", + mt.toMethodDescriptorString(), false); + String desugaredMethodName = CONSTANTS.DESUGAREDMETHODNAME + this.lamCounter; + + // Für die Parameter-Typen und Return-Typ braucht man die Bounds (für die + // Typlöschung) + + // Type erasure + Type arg1 = Type.getMethodType(typeErasure); + // Type arg1 = Type.getMethodType(lamDesc); + // real Type + Type arg3 = Type.getMethodType(lamDesc); + + int staticOrSpecial, staticOrInstance = 0, indexOfFirstParamLam = 0; + + this.kindOfLambda = new KindOfLambda(lambdaExpression); + + if (kindOfLambda.isInstanceCapturingLambda()) { + mv.visitVarInsn(Opcodes.ALOAD, 0); + loadUsedVarsInLambda(); + staticOrSpecial = Opcodes.H_INVOKESPECIAL; + indexOfFirstParamLam = 1; + } else { + staticOrSpecial = Opcodes.H_INVOKESTATIC; + staticOrInstance = Opcodes.ACC_STATIC; + } + String newDesc = addUsedVarsToDesugaredMethodDescriptor(lamDesc); + // first check if capturing lambda then invokestatic or invokespecial + Handle arg2 = new Handle(staticOrSpecial, this.className.getClassName(), desugaredMethodName, newDesc, false); + // Descriptor of functional interface methode + SamMethod samMethod = new SamMethod(kindOfLambda.getArgumentList(), lambdaExpression.getType()); + // Desc: (this/nothing)TargetType + String fiMethodDesc = samMethod.accept(new DescriptorToString(resultSet)); + mv.visitInvokeDynamicInsn("apply", fiMethodDesc, bootstrap, arg1, arg2, arg3); + if(constructorPos<2) { + MethodVisitor mvLambdaBody = cw.visitMethod(Opcodes.ACC_PRIVATE + staticOrInstance + Opcodes.ACC_SYNTHETIC, + desugaredMethodName, newDesc, null, null); + + ArrayList usedVars = kindOfLambda.getUsedVars(); + + new BytecodeGenMethod(className, cw,lambdaExpression, usedVars,this.resultSet, mvLambdaBody, indexOfFirstParamLam, isInterface, + classFiles,this.path, lamCounter, sf, genericsAndBoundsMethod, + genericsAndBounds, classLoader); + + mvLambdaBody.visitMaxs(0, 0); + mvLambdaBody.visitEnd(); + cw.visitInnerClass("java/lang/invoke/MethodHandles$Lookup", "java/lang/invoke/MethodHandles", "Lookup", + Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC + Opcodes.ACC_FINAL); + } +// generateBCForFunN(lambdaExpression, typeErasure); + } + + private String addUsedVarsToDesugaredMethodDescriptor(String lamDesc) { + String newDesc = "("; + int pos = 0; + if(kindOfLambda.isThisUsed()) { + pos = 1; + } + + for(int i=pos;i itr = lambdaExpression.params.iterator(); + while (itr.hasNext()) { + itr.next(); + typeErasure += "L" + Type.getInternalName(Object.class) + ";"; + } + + typeErasure += ")L" + Type.getInternalName(Object.class) + ";"; + return typeErasure; + } + + + + @Override + public void visit(CastExpr castExpr) { + + } + + @Override + public void visit(EmptyStmt emptyStmt) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(FieldVar fieldVar) { + fieldName = fieldVar.fieldVarName; + fieldDesc = "L"; + if(resultSet.resolveType(fieldVar.getType()).resolvedType instanceof TypePlaceholder) { + fieldDesc += Type.getInternalName(Object.class); + } else { + fieldDesc += resultSet.resolveType(fieldVar.getType()).resolvedType.acceptTV(new TypeToDescriptor()); + } + fieldDesc +=";"; + + fieldVar.receiver.accept(this); + // test (if) + if (!fieldVar.receiver.getClass().equals(StaticClassName.class)) { + mv.visitFieldInsn(Opcodes.GETFIELD, resolver.getResolvedType(fieldVar.receiver.getType()), fieldName, fieldDesc); + } + + if (isBinaryExp) { + doUnboxing(resolver.getResolvedType(fieldVar.getType())); + } + // mv.visitFieldInsn(Opcodes.GETSTATIC, + // fieldVar.receiver.getType().toString().replace(".", "/"), + // fieldVar.fieldVarName, fieldVar.getType().toString()); + } + + @Override + public void visit(ForStmt forStmt) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(IfStmt ifStmt) { + statement = new IfStatement(ifStmt.expr, ifStmt.then_block, ifStmt.else_block); + isBinaryExp = statement.isExprBinary(); + ifStmt.expr.accept(this); + if(!(ifStmt.expr instanceof BinaryExpr)) { + doUnboxing(resolver.getResolvedType(ifStmt.expr.getType())); + Label branchLabel = new Label(); + Label endLabel = new Label(); + mv.visitJumpInsn(Opcodes.IFEQ, branchLabel); + statement.genBCForRelOp(mv, branchLabel, endLabel, this); + } + statement = null; + } + + @Override + public void visit(InstanceOf instanceOf) { + + } + + @Override + public void visit(MethodCall methodCall) { + boolean parentBinary = isParentBinary; + System.out.println("In MethodCall = " + methodCall.name); + String receiverName = resolver.getResolvedType(methodCall.receiver.getType()); + System.out.println("Methods of " + receiverName + " "); + java.lang.reflect.Method methodRefl = null; + String clazz = receiverName.replace("/", "."); + + String mDesc = ""; + + MethodCallHelper helper = new MethodCallHelper(methodCall, sf, resultSet, path); + + ClassLoader cLoader = this.classLoader; + // This will be used if the class is not standard class (not in API) + ClassLoader cLoader2; + + String methCallType = resultSet.resolveType(methodCall.getType()).resolvedType.acceptTV(new TypeToDescriptor()); + String[] typesOfParams = getTypes(methodCall.arglist.getArguments()); + try { + clazz = getRawClassName(receiverName, clazz); + + java.lang.reflect.Method[] methods = cLoader.loadClass(clazz).getMethods(); + System.out.println("Methods of " + receiverName + " "); + methodRefl = getMethod(methodCall.name, methodCall.arglist.getArguments().size(),methCallType, typesOfParams, methods); + + } catch (Exception e) { + String superClass = ""; + while(true) { + try { + superClass = helper.getSuperClass(receiverName.replace("/", ".")); + + try { + String superClazz = superClass.replace("/", "."); + superClazz = getRawClassName(superClass, superClazz); + java.lang.reflect.Method[] methods = cLoader.loadClass(superClazz).getMethods(); + System.out.println("Methods of " + superClass + " "); + + methodRefl = getMethod(methodCall.name, methodCall.arglist.getArguments().size(), methCallType, typesOfParams, methods); + + break; + } catch (Exception e3) { + receiverName = superClass; + continue; + } + } catch (NotInCurrentPackageException e2) { + break; + } + + } + + } + + if(methodRefl == null) { + boolean toCreate = !receiverName.equals(className.getClassName()) && helper.isInCurrPkg(clazz); + if(toCreate) { + try { + mDesc = helper.getDesc(clazz); + } catch (NotInCurrentPackageException | NotFoundException e) { + e.printStackTrace(); + } + } else if(!helper.isInCurrPkg(clazz)){ + if(clazz.contains(CONSTANTS.$$)) { + mDesc = helper.getDescriptorOfApplyMethod(methCallType); + //ToDo Etienne: Double Check + RefTypeOrTPHOrWildcardOrGeneric returnType = resolver.resolve(methodCall.getType()); + List argumentTypes = methodCall + .arglist + .getArguments() + .stream() + .map(TypableStatement::getType) + .map(resolver::resolve) + .collect(Collectors.toList()); + FunNUtilities funNUtilities = FunNGenerator.getInstance(); + FunNUtilities.writeClassFile(funNUtilities.getSuperClassName(argumentTypes.size()), + funNUtilities.generateSuperBytecode(argumentTypes.size()), path); + FunNUtilities.writeClassFile(funNUtilities.getSpecializedClassName(argumentTypes, returnType), + funNUtilities.generateSpecializedBytecode(argumentTypes, returnType), path); + }else { + try { + cLoader2 = new DirectoryClassLoader(path, classLoader); + java.lang.reflect.Method[] methods = cLoader2.loadClass(clazz).getMethods(); + System.out.println("Methods of " + receiverName + " "); + for(int i = 0; i argListMethCall = new LinkedList<>(); + String receiverRefl=""; + if(methodRefl == null && receiverName.equals(className.getClassName())) { + MethodFromMethodCall method = new MethodFromMethodCall(methodCall.arglist, methodCall.getType(), + receiverName, genericsAndBoundsMethod, genericsAndBounds); + mDesc = method.accept(new DescriptorToString(resultSet)); + methodCall.arglist.accept(this); + } else if(methodRefl != null) { + System.out.println(methodCall.name + " -> Refl != null"); + receiverRefl = methodRefl.getAnnotatedReceiverType().getType().toString(); + getBoolListOfType(methodRefl, argListMethCall); + System.out.println("Receiver = " + methodRefl.getAnnotatedReceiverType().getType().toString()); + mDesc = getMethodDesc(methodRefl); + visitArgumentListOfMethodCallFromStandardAPI(methodCall, argListMethCall); + } else { + methodCall.arglist.accept(this); + } + + System.out.println("Methodcall ("+ methodCall.name +") Desc : " + mDesc); + + +// methodCall.arglist.accept(this); + visitInvokeInsn(methodCall, receiverName, methodRefl, clazz, mDesc, receiverRefl); + + + if(methodRefl != null && !methodRefl.getReturnType().isPrimitive()) { + if(methodRefl.getReturnType().equals(Object.class)) { + helper.createCheckCast(methodCall,mv); + } + /*if(isBinaryExp) { + doUnboxing(resolver.getResolvedType(methodCall.getType())); + }*/ + if(parentBinary || isBinaryExp) { + doUnboxing(resolver.getResolvedType(methodCall.getType())); + } + } else if(receiverName.contains(CONSTANTS.$$) && !methCallType.equals(Type.getInternalName(Object.class))) { + helper.createCheckCast(methodCall,mv); + } + System.out.println("ISParent Binary = "+isParentBinary +" -> " + parentBinary); + if(methodRefl == null && (parentBinary || !isReturnStmt)) { + if(isBinaryExp) + doUnboxing(resolver.getResolvedType(methodCall.getType())); + } + + } + + private void getBoolListOfType(java.lang.reflect.Method methodRefl, List argListMethCall) { + for(Parameter p:methodRefl.getParameters()) { + System.out.println(p.getName() + " und is Primitive = " + p.getType().isPrimitive()); + argListMethCall.add(p.getType().isPrimitive()); + } + } + + private void visitArgumentListOfMethodCallFromStandardAPI(MethodCall methodCall, List argListMethCall) { + for (Expression al : methodCall.arglist.getArguments()) { + statement = new ArgumentExpr(al); + ArgumentVisitor argV = new ArgumentVisitor(argListMethCall,this); + al.accept(argV); + statement = null; + } + } + + private void visitInvokeInsn(MethodCall methodCall, String receiverName, java.lang.reflect.Method methodRefl, String clazz, String mDesc, String receiverRefl) { + // is methodCall.receiver functional Interface)? + if (varsFunInterface.contains(methodCall.receiver.getType()) || (methodRefl!= null && receiverRefl.contains("interface")) || + receiverName.contains(CONSTANTS.$$)) { + mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, clazz.replace(".", "/"), methodCall.name, + mDesc, true); + } else { + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, clazz.replace(".", "/"), methodCall.name, + mDesc, isInterface); + } + } + + private String getRawClassName(String receiverName, String clazz) { + if (receiverName.contains(CONSTANTS.ANGLEBRACKET)) { + clazz = clazz.substring(0, receiverName.indexOf(CONSTANTS.ANGLEBRACKET)); + } + return clazz; + } + + private String[] getTypes(List arguments) { + String[] types = new String[arguments.size()]; + for(int i = 0; i[] pTypes = m.getParameterTypes(); + for(int j = 0; j", d, isInterface); + } + + private String createDescriptorForInitMethod(NewClass methodCall) { + String d = "("; + for (Expression e : methodCall.arglist.getArguments()) { + String type = resolver.getResolvedType(e.getType()); + if(type.contains("TPH ")){ + type = Type.getInternalName(Object.class); + } + d = d + "L" + type + ";"; + } + d += ")V"; + return d; + } + + @Override + public void visit(NewArray newArray) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(ExpressionReceiver receiver) { + receiver.expr.accept(this); + } + + @Override + public void visit(UnaryExpr unaryExpr) { + unaryExpr.expr.accept(this); + Operation op = unaryExpr.operation; + + String typeOfUnary = resolver.getResolvedType(unaryExpr.getType()); + + boolean isIncOrDec = false; + + switch (op) { + case POSTDECREMENT: + case POSTINCREMENT: + if (statement instanceof AssignStmt) + mv.visitInsn(Opcodes.DUP); + genBCForIncAndDec(op, typeOfUnary); + doBoxing(typeOfUnary); + isIncOrDec = true; + break; + case PREDECREMENT: + case PREINCREMENT: + genBCForIncAndDec(op, typeOfUnary); + doBoxing(typeOfUnary); + if (statement instanceof AssignStmt) + mv.visitInsn(Opcodes.DUP); + isIncOrDec = true; + break; + + case MINUS: + doVisitNegIns(typeOfUnary); + break; + default: + break; + } + + // Für Byte und Short muss noch einen Cast geben i2b, i2s + // das wird später gemacht, da bytecode für cast noch nicht erzeugt wird + + if (isIncOrDec && (unaryExpr.expr instanceof LocalVar)) { + if(needDUP) { + mv.visitInsn(Opcodes.DUP); + needDUP = false; + } + LocalVar local = (LocalVar) unaryExpr.expr; + mv.visitVarInsn(Opcodes.ASTORE, paramsAndLocals.get(local.name)); + } + } + + private void doVisitNegIns(String typeOfUnary) { + switch (typeOfUnary) { + case CONSTANTS.REFTYPE_LONG: + mv.visitInsn(Opcodes.LNEG); + break; + case CONSTANTS.REFTYPE_DOUBLE: + mv.visitInsn(Opcodes.DNEG); + break; + case CONSTANTS.REFTYPE_FLOAT: + mv.visitInsn(Opcodes.FNEG); + break; + default: + mv.visitInsn(Opcodes.INEG); + break; + } + + } + + private void genBCForIncAndDec(Operation op, String typeOfUnary) { + + doUnboxing(typeOfUnary); + loadValue(typeOfUnary, 1.0, true); + + switch (op) { + case POSTDECREMENT: + case PREDECREMENT: + doVisitSubOpInsn(typeOfUnary); + break; + + case POSTINCREMENT: + case PREINCREMENT: + doVisitAddOpInsn(typeOfUnary); + break; + + default: + break; + } + } + + @Override + public void visit(Return aReturn) { + statement = new ReturnStmt(aReturn.retexpr); + isReturnStmt = true; + isBinaryExp = statement.isExprBinary(); + boolean isBinary = isBinaryExp; + if(aReturn.retexpr instanceof UnaryExpr) + needDUP = true; + + aReturn.retexpr.accept(this); + + if (isBinary) { + BinaryExpr binary = (BinaryExpr) aReturn.retexpr; + doBoxing(resolver.getResolvedType(binary.getType())); +// isBinaryExp = false; + } + + mv.visitInsn(Opcodes.ARETURN); + isReturnStmt = false; + statement = null; + } + + @Override + public void visit(ReturnVoid aReturn) { + mv.visitInsn(Opcodes.RETURN); + } + + @Override + public void visit(StaticClassName staticClassName) { + // mv.visitMethodInsn(Opcodes.INVOKESTATIC, + // staticClassName.getType().toString().replace(".", "/"), + // staticClassName.toString(), staticClassName.getType().toString(), false); + // mv.visitFieldInsn(Opcodes.GETSTATIC, + // getResolvedType(staticClassName.getType()), fieldName, fieldDesc); + throw new NotImplementedException("Static noch nicht implementiert!"); + } + + @Override + public void visit(Super aSuper) { + + } + + @Override + public void visit(This aThis) { + + if(BytecodeGen.THISTYPE == null) + BytecodeGen.THISTYPE = aThis.getType(); + + mv.visitVarInsn(Opcodes.ALOAD, 0); + } + + @Override + public void visit(WhileStmt whileStmt) { + statement = new LoopStmt(whileStmt.expr, whileStmt.loopBlock); + isBinaryExp = statement.isExprBinary(); + whileStmt.expr.accept(this); +// isBinaryExp = false; + statement = null; + } + + @Override + public void visit(DoStmt whileStmt) { + whileStmt.expr.accept(this); + // TODO: + } + + @Override + public void visit(Literal literal) { + Object value = literal.value; + String typeOfLiteral = resolver.getResolvedType(literal.getType()); + System.out.println("typeOfLiteral :=> "+ typeOfLiteral); + // Der Wert des Literals wird auf den Stack geladen und + // geboxt, wenn es nötig ist. + loadValue(typeOfLiteral, value, false); + } + + // Unboxing: RefType -> prim + public void doUnboxing(String type) { + switch (type) { +// case "java/lang/String": +// mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(StringBuilder.class), "append", +// "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false); +// +// break; + case "java/lang/Boolean": + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false); + break; + case CONSTANTS.REFTYPE_BYTE: + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, CONSTANTS.REFTYPE_BYTE, "byteValue", "()B", false); + break; + case CONSTANTS.REFTYPE_SHORT: + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, CONSTANTS.REFTYPE_SHORT, "shortValue", "()S", false); + break; + case "java/lang/Integer": + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false); + break; + case CONSTANTS.REFTYPE_LONG: + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, CONSTANTS.REFTYPE_LONG, "longValue", "()J", false); + break; + case CONSTANTS.REFTYPE_FLOAT: + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, CONSTANTS.REFTYPE_FLOAT, "floatValue", "()F", false); + break; + case CONSTANTS.REFTYPE_DOUBLE: + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, CONSTANTS.REFTYPE_DOUBLE, "doubleValue", "()D", false); + break; + case "java/lang/Character": + break; + default: + // mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Integer", "intValue", + // "()I", false); + break; + } + } + + private void loadValue(String type, Object value, boolean isOperator) { + switch (type) { + case CONSTANTS.REFTYPE_STRING: + mv.visitLdcInsn(String.valueOf(value)); + break; + case "java/lang/Boolean": + visitBooleanLiteral((Boolean) value); + break; + case CONSTANTS.REFTYPE_BYTE: + if(value instanceof Double) + visitByteLiteral(((Double) value).byteValue(), false); + if(value instanceof Integer) + visitByteLiteral(((Integer) value).byteValue(), false); + break; + case CONSTANTS.REFTYPE_SHORT: + if(value instanceof Double) + visitShortLiteral(((Double) value).shortValue(), false); + if(value instanceof Integer) + visitShortLiteral(((Integer) value).shortValue(), false); + break; + case "java/lang/Integer": + // zweite Argument isLong +// visitIntegerLiteral(((Double) value).intValue(), false); + if(value instanceof Double) + visitIntegerLiteral(((Double) value).intValue(), false); + if(value instanceof Integer) + visitIntegerLiteral(((Integer) value).intValue(), false); + break; + case CONSTANTS.REFTYPE_LONG: + if(value instanceof Double) + visitLongLiteral(((Double) value).longValue(), true); + if(value instanceof Integer) + visitLongLiteral(((Integer) value).longValue(), true); + break; + case CONSTANTS.REFTYPE_FLOAT: + if(value instanceof Double) + visitFloatLiteral(((Double) value).floatValue()); + if(value instanceof Integer) + visitFloatLiteral(((Integer) value).floatValue()); + break; + case CONSTANTS.REFTYPE_DOUBLE: + if(value instanceof Double) + visitDoubleLiteral((Double) value); + if(value instanceof Integer) + visitDoubleLiteral(((Integer) value).doubleValue()); + break; + case "java/lang/Character": + visitCharLiteral((Character) value); + break; + default: + // wenn die Typ des Literals = Number ist, wird integer-value + // verwendet +// visitIntegerLiteral(((Double) value).intValue(), false); + break; + } + // Boxing + if (!type.equals(CONSTANTS.REFTYPE_STRING) && !type.equals("java/lang/Boolean")) { + if (!this.isBinaryExp && !isOperator) + doBoxing(type); + } + + } + + // Boxing: prim -> RefType + public void doBoxing(String type) { + switch (type) { +// case "java/lang/String": +// mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;", +// false); +// break; + case "java/lang/Boolean": + mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false); + break; + case CONSTANTS.REFTYPE_BYTE: + mv.visitMethodInsn(Opcodes.INVOKESTATIC, CONSTANTS.REFTYPE_BYTE, "valueOf", "(B)Ljava/lang/Byte;", false); + break; + case CONSTANTS.REFTYPE_SHORT: + mv.visitMethodInsn(Opcodes.INVOKESTATIC, CONSTANTS.REFTYPE_SHORT, "valueOf", "(S)Ljava/lang/Short;", false); + break; + case "java/lang/Integer": + mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false); + break; + case CONSTANTS.REFTYPE_LONG: + mv.visitMethodInsn(Opcodes.INVOKESTATIC, CONSTANTS.REFTYPE_LONG, "valueOf", "(J)Ljava/lang/Long;", false); + break; + case CONSTANTS.REFTYPE_FLOAT: + mv.visitMethodInsn(Opcodes.INVOKESTATIC, CONSTANTS.REFTYPE_FLOAT, "valueOf", "(F)Ljava/lang/Float;", false); + break; + case CONSTANTS.REFTYPE_DOUBLE: + mv.visitMethodInsn(Opcodes.INVOKESTATIC, CONSTANTS.REFTYPE_DOUBLE, "valueOf", "(D)Ljava/lang/Double;", false); + break; + case "java/lang/Character": + mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", + false); + break; + default: + break; + } + } + + private void visitCharLiteral(Character value) { + mv.visitIntInsn(Opcodes.BIPUSH, (int) value); + + } + + private void visitDoubleLiteral(Double value) { + if (value == 0) { + mv.visitInsn(Opcodes.DCONST_0); + } else if (value == 1) { + mv.visitInsn(Opcodes.DCONST_1); + } else { + mv.visitLdcInsn(value); + } + } + + private void visitFloatLiteral(Float value) { + if (value.intValue() > -1 && value.intValue() < 3) { + // Opcodes.FCONST_0 = 11, Opcodes.FCONST_1 = 12, usw + mv.visitInsn(value.intValue() + 11); + } else { + mv.visitLdcInsn(value); + } + } + + private void visitLongLiteral(Long value, boolean isLong) { + if (value == 0) { + mv.visitInsn(Opcodes.LCONST_0); + } else if (value == 1) { + mv.visitInsn(Opcodes.LCONST_1); + } else { + mv.visitLdcInsn(value); + } + } + + private void visitShortLiteral(Short value, boolean isLong) { + if (value < 128 || (value > -129 && value < -1)) { + visitByteLiteral(value.byteValue(), isLong); + } else if (value < Math.pow(2, 15) || (value >= -Math.pow(2, 15)) && value < -128) { + mv.visitIntInsn(Opcodes.SIPUSH, value); + } + } + + private void visitByteLiteral(Byte value, boolean isLong) { + + if (!isLong && value < 6 && value > -1) { + // Opcodes.ICONST_0 = 3, Opcodes.ICONST_1 = 4, usw + mv.visitInsn(value + 3); + } else if (isLong && value > -1 && value < 2) { + // Opcodes.LCONST_0 = 9, Opcodes.LCONST_1 = 10 + mv.visitInsn(value + 9); + } else { + mv.visitIntInsn(Opcodes.BIPUSH, value); + } + + } + + private void visitIntegerLiteral(Integer value, boolean isLong) { + + if (value < Math.pow(2, 15) || (value >= -Math.pow(2, 15)) && value < -128) { + visitShortLiteral(value.shortValue(), isLong); + } else { + mv.visitLdcInsn(value); + } + } + + private void visitBooleanLiteral(Boolean b) { + if (b) { + mv.visitInsn(Opcodes.ICONST_1); + } else { + mv.visitInsn(Opcodes.ICONST_0); + } + // muss noch getestet werden. + mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false); + } + + @Override + public void visit(ArgumentList argumentList) { + for (Expression al : argumentList.getArguments()) { + statement = new ArgumentExpr(al); + isBinaryExp = statement.isExprBinary(); + if(al instanceof UnaryExpr) + needDUP = true; + al.accept(this); + //TODO: teste, ob man das für unary braucht + if (isBinaryExp) { + BinaryExpr binary = (BinaryExpr) al; + String binaryType = resolver.getResolvedType(binary.getType()); + doBoxing(binaryType); + } + statement = null; + } + } + + @Override + public void visit(AssignToField assignLeftSide) { + // temporäre Lösung für testen, bis ich weiss wie man funktionale + // interfaces erkennt + if (isRightSideALambda) + varsFunInterface.add(assignLeftSide.field.getType()); + // Loads the an object reference from the local variable + // array slot onto the top of the operand stack. + assignLeftSide.field.receiver.accept(this); + this.rightSideTemp.accept(this); + String fDesc = "L"; + if(resultSet.resolveType(assignLeftSide.field.getType()).resolvedType instanceof TypePlaceholder) { + fDesc += Type.getInternalName(Object.class); + } else { + fDesc += resultSet.resolveType(assignLeftSide.field.getType()).resolvedType.acceptTV(new TypeToDescriptor()); + } + fDesc +=";"; + + + System.out.println("Receiver = " + resolver.getResolvedType(assignLeftSide.field.receiver.getType())); + mv.visitFieldInsn(Opcodes.PUTFIELD, resolver.getResolvedType(assignLeftSide.field.receiver.getType()), + assignLeftSide.field.fieldVarName, fDesc); + } + + @Override + public void visit(AssignToLocal assignLeftSide) { + if (isRightSideALambda) + varsFunInterface.add(assignLeftSide.localVar.getType()); + int index = paramsAndLocals.size(); + String var = assignLeftSide.localVar.name; + if (!paramsAndLocals.containsKey(var)) { + paramsAndLocals.put(var, index + 1); + } + + mv.visitVarInsn(Opcodes.ASTORE, paramsAndLocals.get(var)); + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/Exception/BytecodeGeneratorError.java b/app/src/main/java/de/dhbwstuttgart/bytecode/Exception/BytecodeGeneratorError.java new file mode 100644 index 00000000..7d26f66f --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/Exception/BytecodeGeneratorError.java @@ -0,0 +1,19 @@ +/** + * + */ +package de.dhbwstuttgart.bytecode.Exception; + +/** + * @author fayez + * + */ +public class BytecodeGeneratorError extends RuntimeException { + + /** + * @param message + */ + public BytecodeGeneratorError(String message) { + super(message); + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/Exception/NotFoundException.java b/app/src/main/java/de/dhbwstuttgart/bytecode/Exception/NotFoundException.java new file mode 100644 index 00000000..829d08a9 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/Exception/NotFoundException.java @@ -0,0 +1,25 @@ +/** + * + */ +package de.dhbwstuttgart.bytecode.Exception; + +/** + * @author fayez + * + */ +public class NotFoundException extends Exception { + + /** + * + */ + private static final long serialVersionUID = 1L; + + /** + * @param message + */ + public NotFoundException(String message) { + super(message); + } + + +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/Exception/NotInCurrentPackageException.java b/app/src/main/java/de/dhbwstuttgart/bytecode/Exception/NotInCurrentPackageException.java new file mode 100644 index 00000000..4c3293a6 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/Exception/NotInCurrentPackageException.java @@ -0,0 +1,26 @@ +/** + * + */ +package de.dhbwstuttgart.bytecode.Exception; + +/** + * @author fayez + * + */ +public class NotInCurrentPackageException extends Exception { + + /** + * + */ + private static final long serialVersionUID = 1L; + + /** + * @param message + */ + public NotInCurrentPackageException(String message) { + super(message); + } + + + +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/IStatement.java b/app/src/main/java/de/dhbwstuttgart/bytecode/IStatement.java new file mode 100644 index 00000000..f8d61097 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/IStatement.java @@ -0,0 +1,9 @@ +package de.dhbwstuttgart.bytecode; + +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; + +public interface IStatement { + public boolean isExprBinary(); + public void genBCForRelOp(MethodVisitor mv, Label branchLabel, Label endLabel, BytecodeGenMethod bytecodeGenMethod); +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/IfStatement.java b/app/src/main/java/de/dhbwstuttgart/bytecode/IfStatement.java new file mode 100644 index 00000000..dc548f01 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/IfStatement.java @@ -0,0 +1,29 @@ +package de.dhbwstuttgart.bytecode; + +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +import de.dhbwstuttgart.syntaxtree.statement.Expression; +import de.dhbwstuttgart.syntaxtree.statement.Statement; + +public class IfStatement extends AStatement{ + + private Statement then_block; + private Statement else_block; + + public IfStatement(Expression expr, Statement then_block, Statement else_block) { + super(expr); + this.then_block = then_block; + this.else_block = else_block; + } + + @Override + public void genBCForRelOp(MethodVisitor mv,Label branchLabel, Label endLabel, BytecodeGenMethod bytecodeGenMethod) { + bytecodeGenMethod.isBinary(false); + this.then_block.accept(bytecodeGenMethod); + + mv.visitLabel(branchLabel); + this.else_block.accept(bytecodeGenMethod); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/LoopStmt.java b/app/src/main/java/de/dhbwstuttgart/bytecode/LoopStmt.java new file mode 100644 index 00000000..0f7788d4 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/LoopStmt.java @@ -0,0 +1,26 @@ +package de.dhbwstuttgart.bytecode; + +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +import de.dhbwstuttgart.syntaxtree.statement.Expression; +import de.dhbwstuttgart.syntaxtree.statement.Statement; + +public class LoopStmt extends AStatement { + + private Statement loopBlock; + + public LoopStmt(Expression expr, Statement loopBlock) { + super(expr); + this.loopBlock = loopBlock; + } + + @Override + public void genBCForRelOp(MethodVisitor mv,Label branchLabel, Label endLabel, BytecodeGenMethod bytecodeGenMethod) { + bytecodeGenMethod.isBinary(false); + this.loopBlock.accept(bytecodeGenMethod); + mv.visitJumpInsn(Opcodes.GOTO, endLabel); + mv.visitLabel(branchLabel); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/ReturnStmt.java b/app/src/main/java/de/dhbwstuttgart/bytecode/ReturnStmt.java new file mode 100644 index 00000000..bd747720 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/ReturnStmt.java @@ -0,0 +1,14 @@ +package de.dhbwstuttgart.bytecode; + +import org.objectweb.asm.MethodVisitor; + +import de.dhbwstuttgart.syntaxtree.statement.BinaryExpr; +import de.dhbwstuttgart.syntaxtree.statement.Expression; + +public class ReturnStmt extends AStatement { + + public ReturnStmt(Expression retexpr) { + super(retexpr); + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/TPHExtractor.java b/app/src/main/java/de/dhbwstuttgart/bytecode/TPHExtractor.java new file mode 100644 index 00000000..6f443a47 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/TPHExtractor.java @@ -0,0 +1,269 @@ +/** + * + */ +package de.dhbwstuttgart.bytecode; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import de.dhbwstuttgart.bytecode.constraint.ExtendsConstraint; +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; +import de.dhbwstuttgart.bytecode.utilities.MethodAndTPH; +import de.dhbwstuttgart.bytecode.utilities.MethodUtility; +import de.dhbwstuttgart.bytecode.utilities.Resolver; +import de.dhbwstuttgart.syntaxtree.AbstractASTWalker; +import de.dhbwstuttgart.syntaxtree.ClassOrInterface; +import de.dhbwstuttgart.syntaxtree.Constructor; +import de.dhbwstuttgart.syntaxtree.Field; +import de.dhbwstuttgart.syntaxtree.FormalParameter; +import de.dhbwstuttgart.syntaxtree.Method; +import de.dhbwstuttgart.syntaxtree.ParameterList; +import de.dhbwstuttgart.syntaxtree.statement.LocalVar; +import de.dhbwstuttgart.syntaxtree.statement.LocalVarDecl; +import de.dhbwstuttgart.syntaxtree.type.GenericRefType; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.constraints.Constraint; +import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; +import de.dhbwstuttgart.typeinference.constraints.Pair; +import de.dhbwstuttgart.typeinference.result.GenericInsertPair; +import de.dhbwstuttgart.typeinference.result.ResultPair; +import de.dhbwstuttgart.typeinference.result.ResultSet; + +/** + * @author Fayez Abu Alia + * + */ +public class TPHExtractor extends AbstractASTWalker { + // Alle TPHs der Felder werden iKopf der Klasse definiert + // alle TPHs der Klasse: (TPH, is in Method?) + public final HashMap allTPHS = new HashMap<>(); + public final List tphsClass = new ArrayList<>(); + MethodAndTPH methodAndTph; + + Boolean inMethod = false; + boolean inLocalOrParamOrReturn = false; + + public final ArrayList ListOfMethodsAndTph = new ArrayList<>(); + + // Alle Constraints in einer Menge (Und- & Oder-Constraints) + public Set oldConstraints = new HashSet<>(); + + final ArrayList> allPairs = new ArrayList<>(); + public final ArrayList allCons = new ArrayList<>(); + private ResultSet resultSet; + private Resolver resolver; + + public TPHExtractor() { + + } + + public void setResultSet(ResultSet resultSet) { + this.resultSet = resultSet; + this.resolver = new Resolver(resultSet); + } + + public Resolver getResolver() { + return resolver; + } + +// @Override +// public void visit(ClassOrInterface classOrInterface) { +// inMethod = false; +// classOrInterface.getfieldInitializations().ifPresent(c->c.block.accept(this)); +// super.visit(classOrInterface); +// inMethod = true; +// } + @Override + public void visit(TypePlaceholder tph) { + if (resultSet.resolveType(tph).resolvedType instanceof TypePlaceholder) { + TypePlaceholder resolvedTPH = (TypePlaceholder) resultSet.resolveType(tph).resolvedType; + String tphName = resolvedTPH.getName(); + if (inMethod && !tphsClass.contains(tphName)) { + ArrayList tphs = null; + if (!(tphs = methodAndTph.getTphs()).contains(tphName)) { + methodAndTph.addTph(tphName); + } + if (inLocalOrParamOrReturn) { + if (!(tphs = methodAndTph.getLocalTphs()).contains(tphName)) { + tphs.add(tphName); + } + } + } else { + if (!tphsClass.contains(tphName)) { + tphsClass.add(tphName); + } + } + if (!allTPHS.containsKey(tphName)) { + allTPHS.put(tphName, inMethod); + } +// final List cons = new ArrayList<>(); +// resultSet.resolveType(tph).additionalGenerics.forEach(ag -> { +// TPHConstraint con = new ExtendsConstraint(ag.TA1.getName(), ag.TA2.getName(), Relation.EXTENDS); +// cons.add(con); +// }); +// +// Map visitMap = new HashMap<>(); +// for(TPHConstraint cc : cons) { +// visitMap.put(cc, false); +// } +// +// String left = resolvedTPH.getName(); +// for (TPHConstraint cc : visitMap.keySet()) { +// +// if(visitMap.get(cc)) +// continue; +// +// if (cc.getLeft().equals(left)) { +// allCons.add(cc); +// List toVisit = getToVisitCons(cons,cc.getRight(), visitMap); +// } +// } + + //resultSet.resolveType(tph).getAdditionalGenerics().forEach(ag -> { + resultSet.genIns.forEach(ag -> { + +// if (ag.contains(resolvedTPH) /* && ag.TA1.equals(resolvedTPH) */ && !contains(allPairs, ag)) { + if (inMethod) + methodAndTph.getPairs().add(ag); + allPairs.add(ag); + TPHConstraint con = new ExtendsConstraint(ag.getLeft().getName(), ag.getRight().getName()); + if(!containsConstraint(allCons,con)) + allCons.add(con); +// } + }); + } else if (resultSet.resolveType(tph).resolvedType instanceof RefType) { + RefType rt = (RefType) resultSet.resolveType(tph).resolvedType; + rt.accept(this); + } + } + + private static boolean containsConstraint(ArrayList allCons, TPHConstraint c) { + for(TPHConstraint con:allCons) { + if(c.getLeft().equals(con.getLeft()) && c.getRight().equals(con.getRight())) { + return true; + } + } + return false; + } + + private List getToVisitCons(List cons, String right, Map visitMap) { + List res = new ArrayList<>(); + for(TPHConstraint cc : cons) { + if(cc.getLeft().equals(right)) { + res.add(cc); + if(visitMap.get(cc)) + visitMap.replace(cc, false); + } + } + return res; + } + + @Override + public void visit(GenericRefType genericRefType) { + String name = genericRefType.getParsedName(); + if (inMethod) { + methodAndTph.addTph(name); + if (inLocalOrParamOrReturn) + methodAndTph.getLocalTphs().add(name); + }else { + tphsClass.add(name); + } + allTPHS.put(name, inMethod); + } + + private boolean contains(ArrayList pairs, GenericInsertPair genPair) { + for (int i = 0; i < pairs.size(); ++i) { + GenericInsertPair p = pairs.get(i); + if (p.TA1.equals(genPair.TA1) && p.TA2.equals(genPair.TA2)) + return true; + } + return false; + } + + @Override + public void visit(Method method) { + inMethod = true; + String id = MethodUtility.createID(resolver,method); + Predicate filterUndConstraints = cs -> ((cs.TA1 instanceof TypePlaceholder) && (cs.TA2 instanceof TypePlaceholder) && + (resultSet.resolveType((TypePlaceholder)(cs.TA1)).resolvedType instanceof TypePlaceholder) && + (resultSet.resolveType((TypePlaceholder)(cs.TA2)).resolvedType instanceof TypePlaceholder)); + + Function, ConstraintSet> filterConstrRemainingTVar = + csS -> { + ConstraintSet ret = new ConstraintSet<>(); + ret.addAllUndConstraint( + csS.getUndConstraints() + .stream().filter(filterUndConstraints) + .collect(Collectors.toCollection(Constraint::new))); + + csS.getOderConstraints() + .forEach(oConSSet -> { Set> setCons = new HashSet<>(); + oConSSet.forEach(OConS -> { Constraint newConsPair = new Constraint(); + newConsPair.isStatement = OConS.isStatement; + setCons.add( + OConS.stream() + .filter(filterUndConstraints) + .collect(Collectors.toCollection(() -> newConsPair)) ); + } ); + ret.addOderConstraint(setCons);} ); + return ret; + }; + ConstraintSet filteredConstraints = filterConstrRemainingTVar.apply(method.getConstraints()); + methodAndTph = new MethodAndTPH(id, filteredConstraints); + oldConstraints.addAll(filteredConstraints.getAll()); + + inLocalOrParamOrReturn = true; + method.getReturnType().accept(this); + method.getParameterList().accept(this); + inLocalOrParamOrReturn = false; + + if(method.block != null) + method.block.accept(this); + + inMethod = false; + ListOfMethodsAndTph.add(methodAndTph); + } + + @Override + public void visit(Constructor cons) { + inMethod = false; + //super.visit(cons); + cons.getParameterList().accept(this); + if(cons.block != null) + cons.block.accept(this); + inMethod = true; + } + + @Override + public void visit(LocalVarDecl localVarDecl) { +// inLocalOrParamOrReturn = inMethod; + super.visit(localVarDecl); +// inLocalOrParamOrReturn = false; + } + + @Override + public void visit(LocalVar localVar) { +// inLocalOrParamOrReturn = inMethod; + super.visit(localVar); +// inLocalOrParamOrReturn = false; + } + + @Override + public void visit(ParameterList formalParameters) { + inLocalOrParamOrReturn = inMethod; + super.visit(formalParameters); + inLocalOrParamOrReturn = false; + } + +} \ No newline at end of file diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/constraint/EqualConstraint.java b/app/src/main/java/de/dhbwstuttgart/bytecode/constraint/EqualConstraint.java new file mode 100644 index 00000000..69fb0b02 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/constraint/EqualConstraint.java @@ -0,0 +1,9 @@ +package de.dhbwstuttgart.bytecode.constraint; + +public class EqualConstraint extends TPHConstraint { + + public EqualConstraint(String left, String right) { + super(left, right, Relation.EQUAL); + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/constraint/ExtendsConstraint.java b/app/src/main/java/de/dhbwstuttgart/bytecode/constraint/ExtendsConstraint.java new file mode 100644 index 00000000..77007a3b --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/constraint/ExtendsConstraint.java @@ -0,0 +1,9 @@ +package de.dhbwstuttgart.bytecode.constraint; + +public class ExtendsConstraint extends TPHConstraint { + + public ExtendsConstraint(String left, String right) { + super(left, right, Relation.EXTENDS); + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/constraint/TPHConstraint.java b/app/src/main/java/de/dhbwstuttgart/bytecode/constraint/TPHConstraint.java new file mode 100644 index 00000000..0533a028 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/constraint/TPHConstraint.java @@ -0,0 +1,90 @@ +package de.dhbwstuttgart.bytecode.constraint; + +import de.dhbwstuttgart.typeinference.constraints.Pair; +import de.dhbwstuttgart.typeinference.unify.model.PairOperator; +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; + +public class TPHConstraint { + protected String left; + protected String right; + protected Relation rel; + protected int variance; //noch nicht benutzt + public enum Relation{ + EXTENDS, EQUAL + } + + public TPHConstraint(Pair p) { + this.left = ((TypePlaceholder)p.TA1).getName(); + this.right = ((TypePlaceholder)p.TA2).getName(); + this.rel = p.GetOperator().equals(PairOperator.SMALLERDOT) ? Relation.EXTENDS : Relation.EQUAL; + } + + public TPHConstraint(String left, String right, Relation rel) { + this.left = left; + this.right = right; + this.rel = rel; + } + + public String getLeft() { + return left; + } + + + public String getRight() { + return right; + } + + + public Relation getRel() { + return rel; + } + + public void setLeft(String left) { + this.left = left; + } + + public void setRight(String right) { + this.right = right; + } + + public void setRel(Relation rel) { + this.rel = rel; + } + + public boolean containTPH(String tph) { + return left.equals(tph)||right.equals(tph); + } + + public boolean equalConstraint(TPHConstraint constraint) { + return rel == constraint.getRel() && left.equals(constraint.getLeft()) && right.equals(constraint.getRight()); + } + + @Override + public int hashCode() { + return (left+right).hashCode(); + } + + @Override + public boolean equals (Object o) { + if (o instanceof TPHConstraint) { + TPHConstraint o_tphcons = (TPHConstraint)o; + return (this.left.equals(o_tphcons.getLeft()) + && this.right.equals(o_tphcons.getRight()) + && this.rel.equals(o_tphcons.rel)); + } + else { + return false; + } + } + + + @Override + public String toString() { + if(rel == Relation.EXTENDS) { + return left + " < " + right; + }else { + return left + " = " + right; + } + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/descriptor/DescriptorToString.java b/app/src/main/java/de/dhbwstuttgart/bytecode/descriptor/DescriptorToString.java new file mode 100644 index 00000000..c272c12f --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/descriptor/DescriptorToString.java @@ -0,0 +1,260 @@ +package de.dhbwstuttgart.bytecode.descriptor; + +import java.util.HashMap; +import java.util.Iterator; + +import de.dhbwstuttgart.bytecode.utilities.*; +import de.dhbwstuttgart.syntaxtree.statement.ArgumentList; +import org.objectweb.asm.Type; + +import de.dhbwstuttgart.syntaxtree.FormalParameter; +import de.dhbwstuttgart.syntaxtree.statement.Expression; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.typeinference.result.ResultSet; + +public class DescriptorToString implements DescriptorVisitor, CONSTANTS { + ResultSet resultSet; + + public DescriptorToString() { + } + + public DescriptorToString(ResultSet resultSet) { + this.resultSet = resultSet; + } + + private String addReturnType(String desc, RefTypeOrTPHOrWildcardOrGeneric returnType, ResultSet resultSet) { + if(resultSet.resolveType(returnType).resolvedType.toString().equals(CONSTANTS.VOID)){ + desc = desc + ")V"; + }else { + desc = desc + ")" + "L"+resultSet.resolveType(returnType).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; + } + return desc; + } + + @Override + public String visit(NormalMethod method) { + + String desc = "("; + Iterator itr = method.getParameterList().iterator(); + while(itr.hasNext()) { + FormalParameter fp = itr.next(); +// System.out.println(resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToSignature())); +// System.out.println("Parmetrisierte typ ? "+ ((RefType) fp.getType()).getParaList().size()); + if(method.hasGen()) { + String fpDesc = fp.getType().acceptTV(new TypeToDescriptor()); + if(method.getGenericsAndBoundsMethod().containsKey(fpDesc)) { + String bound = getBound(fpDesc, method.getGenericsAndBoundsMethod()); + desc += "L"+bound+ ";"; + }else if(method.getGenericsAndBounds().containsKey(fpDesc)){ + String bound = getBound(fpDesc, method.getGenericsAndBounds()); + desc += "L"+bound+ ";"; + }else { +// desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; + String resType = resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor()); + if(resType.contains(CONSTANTS.TPH)/*resType.subSequence(0, 4).equals("TPH ")*/) { + // Bound ist immer Object + desc += "L"+Type.getInternalName(Object.class)+ ";"; + } else { + // TODO:: + if(method.getGenericsAndBounds().containsKey(resType)) { + String bound = getBound(resType, method.getGenericsAndBounds()); + desc += "L"+bound+ ";"; + }else if(method.getGenericsAndBoundsMethod().containsKey(resType)) { + String bound = getBound(resType, method.getGenericsAndBoundsMethod()); + desc += "L"+bound+ ";"; + } else { + desc += "L"+resType+ ";"; + } + } + } + } + //TODO: generate a class java%% ... %% + else if(resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor()).contains(CONSTANTS.ANGLEBRACKET)){ + desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.toString().replace(".", "$$").replace(CONSTANTS.ANGLEBRACKET, "$$$").replace(">", "$$$")+ ";"; + } + else { + desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; + } + } + + if(resultSet.resolveType(method.getReturnType()).resolvedType.toString().equals(CONSTANTS.VOID)) { + desc += ")V"; + }else { + if(method.hasGen()) { + String ret = method.getReturnType().acceptTV(new TypeToDescriptor()); + if(method.getGenericsAndBoundsMethod().containsKey(ret)) { + desc += ")L"+method.getGenericsAndBoundsMethod().get(ret)+ ";"; + }else if(method.getGenericsAndBounds().containsKey(ret)){ + desc += ")L"+method.getGenericsAndBounds().get(ret)+ ";"; + }else { + String resType = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor()); + if(resType.contains(CONSTANTS.TPH)/*resType.subSequence(0, 4).equals("TPH ")*/) { +// desc += ")" + "L"+method.getGenericsAndBoundsMethod().get(resType.substring(4)+"$")+ ";"; + desc += ")" + "L"+Type.getInternalName(Object.class)+ ";"; + } else { + // TODO:: + if(method.getGenericsAndBounds().containsKey(resType)) { + String bound = getBound(resType, method.getGenericsAndBounds()); + desc += ")L"+bound+ ";"; + }else if(method.getGenericsAndBoundsMethod().containsKey(resType)) { + String bound = getBound(resType, method.getGenericsAndBoundsMethod()); + desc += ")L"+bound+ ";"; + } else { + desc += ")L"+resType+ ";"; + } +// desc += ")" + "L"+resType+ ";"; + } + } + }else { + desc += ")" + "L"+resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; + } + } +// desc = addReturnType(desc,method.getReturnType(), resultSet); + return desc; + } + + private String getBound(String fpDesc, HashMap genericsAndBounds) { + String start = genericsAndBounds.get(fpDesc); + while(genericsAndBounds.containsKey(start)) { + start = genericsAndBounds.get(start); + } + + return start; + } + + @Override + public String visit(NormalConstructor constructor) { + String desc = "("; + Iterator itr = constructor.getParameterList().iterator(); + while(itr.hasNext()) { + FormalParameter fp = itr.next(); + if(constructor.hasGen()) { +// System.out.println("Cons has Gens"); + String fpDesc = fp.getType().acceptTV(new TypeToDescriptor()); +// System.out.println(fpDesc); + if(constructor.getGenericsAndBounds().containsKey(fpDesc)){ + desc += "L"+constructor.getGenericsAndBounds().get(fpDesc)+ ";"; + }else { +// desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; + String resType = resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor()); + if(resType.subSequence(0, 4).equals(CONSTANTS.TPH)) { + // Bound ist immer Object + desc += "L"+Type.getInternalName(Object.class)+ ";"; + } else { + desc += "L"+resType+ ";"; + } + } + }else { +// System.out.println("Cons has NO Gens"); + desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; + } + } + desc = desc + ")V"; + return desc; + } + + //ToDo Etienne: ändern + @Override + public String visit(Lambda lambdaExpression) { + String desc = "("; + Iterator itr = lambdaExpression.getParams().iterator(); + while(itr.hasNext()) { + FormalParameter fp = itr.next(); + String d = resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor()); + if(d.contains(CONSTANTS.TPH) ||d.contains(CONSTANTS.ANGLEBRACKET)) { + desc += "L"+Type.getInternalName(Object.class)+ ";"; + }else { + desc = desc + "L"+ d + ";"; + } + } + + String retType = resultSet.resolveType(lambdaExpression.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor()); + + if(retType.contains(CONSTANTS.TPH)|| retType.contains(CONSTANTS.ANGLEBRACKET)){ + desc += ")L"+Type.getInternalName(Object.class)+ ";"; + }else { + desc = desc + ")"+"L"+retType+";"; + } + return desc; + } + + @Override + public String visit(SamMethod samMethod) { + String desc = "("; + Iterator itr = samMethod.getArgumentList().iterator(); + while(itr.hasNext()) { + RefTypeOrTPHOrWildcardOrGeneric rt = itr.next(); + String d = resultSet.resolveType(rt).resolvedType.acceptTV(new TypeToDescriptor()); + + if(d.contains(CONSTANTS.TPH) ||d.contains(CONSTANTS.ANGLEBRACKET)) { + desc += "L"+Type.getInternalName(Object.class)+ ";"; + }else { + desc += "L"+ d + ";"; + + } + } + String retType = resultSet.resolveType(samMethod.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor()); + + if(retType.contains(CONSTANTS.TPH)|| retType.contains(CONSTANTS.ANGLEBRACKET)){ + desc += ")L"+Type.getInternalName(Object.class)+ ";"; + }else { + desc = desc + ")"+"L"+retType+";"; + } + return desc; + } + + @Override + public String visit(MethodFromMethodCall methodFromMethodCall) { + String desc = "("; + for(Expression e : methodFromMethodCall.getArgList().getArguments()) { + String d = resultSet.resolveType(e.getType()).resolvedType.acceptTV(new TypeToDescriptor()); + + if(d.contains(CONSTANTS.TPH) ||d.contains(CONSTANTS.ANGLEBRACKET) || methodFromMethodCall.getReceiverName().contains("$$")) { + desc += "L"+Type.getInternalName(Object.class)+ ";"; + }else { + if(methodFromMethodCall.getGenericsAndBoundsMethod().containsKey(d)) { + desc += "L"+methodFromMethodCall.getGenericsAndBoundsMethod().get(d)+ ";"; + }else if(methodFromMethodCall.getGenericsAndBounds().containsKey(d)) { + desc += "L"+methodFromMethodCall.getGenericsAndBounds().get(d)+ ";"; + }else { + desc += "L"+resultSet.resolveType(e.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; + } + } + + } + String retType = resultSet.resolveType(methodFromMethodCall.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor()); + System.out.println("DescriptorToString retType = " + retType); + if(retType.equals(CONSTANTS.VOID)) { + desc += ")V"; + }else if(retType.contains(CONSTANTS.TPH)|| retType.contains(CONSTANTS.ANGLEBRACKET) || methodFromMethodCall.getReceiverName().contains("$$")){ + desc += ")L"+Type.getInternalName(Object.class)+ ";"; + }else { + if(methodFromMethodCall.getGenericsAndBoundsMethod().containsKey(retType)) { + desc += ")L"+methodFromMethodCall.getGenericsAndBoundsMethod().get(retType)+ ";"; + }else if(methodFromMethodCall.getGenericsAndBounds().containsKey(retType)){ + desc += ")L"+methodFromMethodCall.getGenericsAndBounds().get(retType)+ ";"; + }else { + desc += ")" + "L"+retType+ ";"; + } + } +// desc = addReturnType(desc, methodFromMethodCall.getReturnType(), resultSet); + return desc; + } + + @Override + public String createDescForFunN(ArgumentList argumentList, String returnType) { + Iterator itr1 = argumentList.getArguments().iterator(); + String methDesc = "("; + while(itr1.hasNext()) { + methDesc += "L" + Type.getInternalName(Object.class) + ";"; + itr1.next(); + } + if (returnType.equals(CONSTANTS.VOID)){ + methDesc += ")V"; + } else { + methDesc += ")L" + Type.getInternalName(Object.class) + ";"; + } + return methDesc; + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/descriptor/DescriptorVisitor.java b/app/src/main/java/de/dhbwstuttgart/bytecode/descriptor/DescriptorVisitor.java new file mode 100644 index 00000000..d1576c76 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/descriptor/DescriptorVisitor.java @@ -0,0 +1,17 @@ +package de.dhbwstuttgart.bytecode.descriptor; + +import de.dhbwstuttgart.bytecode.utilities.Lambda; +import de.dhbwstuttgart.bytecode.utilities.MethodFromMethodCall; +import de.dhbwstuttgart.bytecode.utilities.NormalConstructor; +import de.dhbwstuttgart.bytecode.utilities.NormalMethod; +import de.dhbwstuttgart.bytecode.utilities.SamMethod; +import de.dhbwstuttgart.syntaxtree.statement.ArgumentList; + +public interface DescriptorVisitor { + String visit(NormalMethod method); + String visit(NormalConstructor constructor); + String visit(Lambda lambdaExpression); + String visit(SamMethod samMethod); + String visit(MethodFromMethodCall methodFromMethodCall); + String createDescForFunN(ArgumentList argumentList, String returnType); +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java b/app/src/main/java/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java new file mode 100644 index 00000000..f10f8070 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/descriptor/TypeToDescriptor.java @@ -0,0 +1,52 @@ +package de.dhbwstuttgart.bytecode.descriptor; + +import de.dhbwstuttgart.bytecode.funN.FunNGenerator; +import de.dhbwstuttgart.bytecode.funN.FunNUtilities; +import de.dhbwstuttgart.syntaxtree.type.*; + +public class TypeToDescriptor implements TypeVisitor{ + + private final boolean specializedFunN; + + public TypeToDescriptor(){ this(true); } + + public TypeToDescriptor(boolean specializedFunN) { this.specializedFunN = specializedFunN; } + + @Override + public String visit(RefType refType) { + if (refType.getName().toString().matches("Fun\\d+\\$\\$") && specializedFunN) { + FunNUtilities funNUtilities = FunNGenerator.getInstance(); + return funNUtilities.getSpecializedDescriptor(funNUtilities.getArguments(refType.getParaList()), funNUtilities.getReturnType(refType.getParaList())); + } + + return refType.getName().toString().replace(".", "/"); +// String t = refType.getName().toString().replace(".", "/"); +// return t.equals("Fun1")?(t+"$$"):t; + } + + @Override + public String visit(SuperWildcardType superWildcardType) { + System.out.println("\nWILDCARD ="+superWildcardType.getInnerType().toString().replace(".", "/")); + //return superWildcardType.getInnerType().toString().replace(".", "/"); + return superWildcardType.getInnerType().acceptTV(new TypeToDescriptor()); + //throw new NotImplementedException(); + } + + @Override + public String visit(TypePlaceholder typePlaceholder) { + return typePlaceholder.toString().replace(".", "/"); + } + + @Override + public String visit(ExtendsWildcardType extendsWildcardType) { + System.out.println("\nWILDCARD extends ="+extendsWildcardType.getInnerType().toString().replace(".", "/")); + //return extendsWildcardType.getInnerType().toString().replace(".", "/"); + return extendsWildcardType.getInnerType().acceptTV(new TypeToDescriptor()); + //throw new NotImplementedException(); + } + + @Override + public String visit(GenericRefType genericRefType) { + return genericRefType.getParsedName().replace(".", "/"); + } +} \ No newline at end of file diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/funN/FunNGenerator.java b/app/src/main/java/de/dhbwstuttgart/bytecode/funN/FunNGenerator.java new file mode 100644 index 00000000..3a651c93 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/funN/FunNGenerator.java @@ -0,0 +1,149 @@ +package de.dhbwstuttgart.bytecode.funN; + +import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor; +import de.dhbwstuttgart.bytecode.signature.TypeToSignature; +import de.dhbwstuttgart.bytecode.utilities.CONSTANTS; +import de.dhbwstuttgart.parser.scope.JavaClassName; +import de.dhbwstuttgart.syntaxtree.type.GenericRefType; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Type; + +import java.io.File; +import java.io.FileOutputStream; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.objectweb.asm.Opcodes.*; + +/** + * //ToDo beschreiben + * + * @since Studienarbeit Type Erasure + * @author etiennezink + */ +public class FunNGenerator implements FunNUtilities{ + + private static FunNGenerator funNGenerator = new FunNGenerator(); + + public static FunNGenerator getInstance(){ + return funNGenerator; + } + + 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 RefType objectRefType = new RefType(new JavaClassName(objectSuperType), null); + private final String objectSignature = applySignature(objectRefType); + + private String applyDescriptor(RefTypeOrTPHOrWildcardOrGeneric a) { return a.acceptTV(new TypeToDescriptor(true)); } + private String applySignature(RefTypeOrTPHOrWildcardOrGeneric a) { return a.acceptTV(new TypeToSignature(true)); } + private String applyNameDescriptor(RefTypeOrTPHOrWildcardOrGeneric a){ return a instanceof TypePlaceholder ? "LTPH;" : String.format("L%s;", applyDescriptor(a)); } + + @Override + public byte[] generateSuperBytecode(int numberArguments) { + StringBuilder superFunNClassSignature = new StringBuilder("<"); + StringBuilder superFunNMethodSignature = new StringBuilder("("); + StringBuilder superFunNMethodDescriptor = new StringBuilder("("); + + for (int currentParameter = 1; currentParameter <= numberArguments; currentParameter++){ + superFunNClassSignature.append(String.format("%s%d:%s",argumentGenericBase, currentParameter, objectSignature)); + superFunNMethodSignature.append(String.format("T%s;", applySignature( new GenericRefType(argumentGenericBase + currentParameter, null)))); + superFunNMethodDescriptor.append(objectSignature); + } + superFunNClassSignature.append(String.format("%s:%s>%s", returnGeneric, objectSignature, objectSignature)); + superFunNMethodSignature.append(String.format(")T%s;", applySignature(new GenericRefType(returnGeneric, null)))); + superFunNMethodDescriptor.append(String.format(")%s", objectSignature)); + + ClassWriter classWriter = new ClassWriter(0); + MethodVisitor methodVisitor; + classWriter.visit(bytecodeVersion, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, getSuperClassName(numberArguments), superFunNClassSignature.toString(), objectSuperType, null); + methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, methodName, superFunNMethodDescriptor.toString(), superFunNMethodSignature.toString(), null); + methodVisitor.visitEnd(); + classWriter.visitEnd(); + return classWriter.toByteArray(); + } + + @Override + public String getSuperClassName(int numberArguments) { + return String.format("Fun%d$$", numberArguments); + } + + @Override + public byte[] generateSpecializedBytecode(List argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType) { + List parameters = Stream + .concat(argumentTypes.stream(), Stream.of(returnType)) + .collect(Collectors.toList()); + RefType superFunN = new RefType(new JavaClassName(getSuperClassName(argumentTypes.size())), parameters , null); + StringBuilder funNClassSignature = new StringBuilder(objectSignature + (superFunN.acceptTV(new TypeToSignature(false)))); + boolean containsGeneric = false; + + String genericSignature = "<"; + for (RefTypeOrTPHOrWildcardOrGeneric typeArgument : parameters) { + //ToDo Etienne: Refactor + if (typeArgument instanceof GenericRefType){ + GenericRefType generic = (GenericRefType) typeArgument; + if(genericSignature.contains(generic.getParsedName())) continue; + genericSignature += String.format("%s:%s", generic.getParsedName(), applyDescriptor(generic)); + containsGeneric = true; + } else if(typeArgument instanceof TypePlaceholder){ + TypePlaceholder placeholder = (TypePlaceholder) typeArgument; + if(genericSignature.contains(applySignature(placeholder).substring(1))) continue; + genericSignature += String.format("%s:%s", applySignature(placeholder).substring(1), objectSignature); + containsGeneric = true; + } + } + genericSignature += ">"; + if (containsGeneric) funNClassSignature.insert(0, genericSignature); + + ClassWriter classWriter = new ClassWriter(0); + classWriter.visit(bytecodeVersion, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, getSpecializedClassName(argumentTypes, returnType), funNClassSignature.toString(), objectSuperType, new String[]{getSuperClassName(argumentTypes.size())}); + classWriter.visitEnd(); + return classWriter.toByteArray(); + } + + @Override + public String getSpecializedClassName(List argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType) { + return String.format("Fun%d$$%s%s", + argumentTypes.size(), + argumentTypes + .stream() + .map(this::applyNameDescriptor) + .collect(Collectors.joining()), + applyNameDescriptor(returnType)) + .replace('/', '$') + .replace(";", "$_$"); + } + + @Override + public String getSpecializedDescriptor(List argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType) { + return applyDescriptor(new RefType(new JavaClassName(getSpecializedClassName(argumentTypes, returnType)), null)); + } + + @Override + public String getSpecializedSignature(List argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType) { + return applySignature(new RefType(new JavaClassName(getSpecializedClassName(argumentTypes, returnType)), null)); + } + + @Override + public List getArguments(List list) { + return list + .stream() + .limit(Math.max(0, list.size() - 1)) + .collect(Collectors.toList()); + } + + @Override + public RefTypeOrTPHOrWildcardOrGeneric getReturnType(List list) { + if(list.size() == 0) + throw new IndexOutOfBoundsException(); + return list.get(list.size() - 1); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/funN/FunNUtilities.java b/app/src/main/java/de/dhbwstuttgart/bytecode/funN/FunNUtilities.java new file mode 100644 index 00000000..7ae4da4d --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/funN/FunNUtilities.java @@ -0,0 +1,36 @@ +package de.dhbwstuttgart.bytecode.funN; + +import de.dhbwstuttgart.bytecode.utilities.CONSTANTS; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; + +import java.io.File; +import java.io.FileOutputStream; +import java.util.List; + +public interface FunNUtilities { + + byte[] generateSuperBytecode(int numberArguments); + String getSuperClassName(int numberArguments); + + byte[] generateSpecializedBytecode(List argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType); + String getSpecializedClassName(List argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType); + String getSpecializedDescriptor(List argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType); + String getSpecializedSignature(List argumentTypes, RefTypeOrTPHOrWildcardOrGeneric returnType); + + List getArguments(List list); + RefTypeOrTPHOrWildcardOrGeneric getReturnType(List list); + + @Deprecated + public static boolean writeClassFile(String className, byte[] bytecode, File directory) { + try (FileOutputStream output = new FileOutputStream(new File(directory , className + CONSTANTS.EXTENSIONCLASS))){ + output.write(bytecode); + output.flush(); + return true; + } catch (Exception e) { + e.printStackTrace(); + } + return false; + } + + +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/ConstraintsSimplierResult.java b/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/ConstraintsSimplierResult.java new file mode 100644 index 00000000..5ed0bd5e --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/ConstraintsSimplierResult.java @@ -0,0 +1,53 @@ +/** + * + */ +package de.dhbwstuttgart.bytecode.genericsGenerator; + +import java.util.List; + +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.NameReplacementResult; +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericsGeneratorResult; + +/** + * This class represents the result of the constraints simplifier. + * + * @author fayez + * + */ +public class ConstraintsSimplierResult { + private List genericsGenResults; + private List nameReplacementResults; + /** + * @param genericsGenResults + */ + public ConstraintsSimplierResult(List genericsGenResults, + List nameReplacementResults) { + this.genericsGenResults = genericsGenResults; + this.setNameReplacementResults(nameReplacementResults); + } + /** + * @return the genericsGenResults + */ + public List getGenericsGenResults() { + return genericsGenResults; + } + /** + * @param genericsGenResults the genericsGenResults to set + */ + public void setGenericsGenResults(List genericsGenResults) { + this.genericsGenResults = genericsGenResults; + } + /** + * @return the nameReplacementResults + */ + public List getNameReplacementResults() { + return nameReplacementResults; + } + /** + * @param nameReplacementResults the nameReplacementResults to set + */ + public void setNameReplacementResults(List nameReplacementResults) { + this.nameReplacementResults = nameReplacementResults; + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/ConstraintsSimplifier.java b/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/ConstraintsSimplifier.java new file mode 100644 index 00000000..b510c71b --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/ConstraintsSimplifier.java @@ -0,0 +1,137 @@ +/** + * + */ +package de.dhbwstuttgart.bytecode.genericsGenerator; + +import java.util.*; + +import de.dhbwstuttgart.bytecode.TPHExtractor; +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.*; + +/** + * @author fayez + * + */ +public class ConstraintsSimplifier { + public static ConstraintsSimplierResult simplifyConstraints(final TPHExtractor tphExtractor, final List genericsGeneratorResults, final List tphsClass) { + + List allCons = tphExtractor.allCons; + List equalCons = new ArrayList<>(); + + /* Step 1 */ + List foundCons = GenericsGeneratorUtility.findConstraintsWithLeftSameLeftSide(allCons); + if(!foundCons.isEmpty()) { + List equalCons2 = new ArrayList<>(); + GenericsGeneratorUtility.simplifyConstraintsWithSameLeftSide(foundCons,tphExtractor,tphsClass,equalCons2); + equalCons.addAll(equalCons2); + } + +// if(!simpleCycles.isEmpty()) { +// handleSimpleCycles(allCons, simpleCycles,tphExtractor); +// equalCons.addAll(GenericsGeneratorUtility.getEqualConstraints(allCons)); +// } +// + List cycles = findCycles(allCons); + + if(!cycles.isEmpty()) { + handleCycle(genericsGeneratorResults, allCons, cycles,tphExtractor); + } + /* The right hand side of equal constraint is the new name in name replacement result */ + List nameReplacementResults = GenericsGeneratorUtility.createNameReplacementResultsFromEqualConstraints(equalCons); + getEqualsFromNameReplacementResults(genericsGeneratorResults,nameReplacementResults); + ConstraintsSimplierResult result = new ConstraintsSimplierResult(genericsGeneratorResults, nameReplacementResults); + return result; + } + + private static void getEqualsFromNameReplacementResults(List genericsGeneratorResults, + List nameReplacementResults) { + genericsGeneratorResults.forEach(g->{ + String tph = g.getConstraint().getLeft(); + if (!nameReplacementResults.isEmpty()) { + collectAllEquals(nameReplacementResults, g, tph); + } + + if (!nameReplacementResults.isEmpty()) { + collectAllEquals(nameReplacementResults, g); + } + }); + + } + + private static void collectAllEquals(List nameReplacementResults, GenericsGeneratorResult g) { + Set equalsTPHs = g.getEqualsTPHs(); + Set tphsToAdd = getAllEqualTphs(equalsTPHs, nameReplacementResults); + while (!tphsToAdd.isEmpty()){ + equalsTPHs.addAll(tphsToAdd); + tphsToAdd = getAllEqualTphs(equalsTPHs, nameReplacementResults); + } + } + + private static Set getAllEqualTphs(Set equalsTPHs, List nameReplacementResults) { + Set tphsToAdd = new HashSet<>(); + equalsTPHs.forEach(e->{ + collectAllEquals(nameReplacementResults, tphsToAdd,e); + }); + return tphsToAdd; + } + + public static void collectAllEquals(List nameReplacementResults, Set tphsToAdd, + String tph) { + List toRemoveList = new ArrayList<>(); + Optional nameReplacementResult = nameReplacementResults.stream().filter(n->n.getName().equals(tph)).findFirst(); + nameReplacementResult.ifPresent(toRemove->{ + tphsToAdd.addAll(toRemove.getOldNames()); + toRemoveList.add(toRemove); + }); + if(!toRemoveList.isEmpty()){ + nameReplacementResults.remove(toRemoveList.get(0)); + toRemoveList.clear(); + } + } + + /** + * @param nameReplacementResults + * @param g + * @param tph + */ + public static void collectAllEquals(List nameReplacementResults, GenericsGeneratorResult g, + String tph) { + List toRemoveList = new ArrayList<>(); + Optional nameReplacementResult = nameReplacementResults.stream().filter(n->n.getName().equals(tph)).findFirst(); + nameReplacementResult.ifPresent(toRemove->{ + g.getEqualsTPHs().addAll(toRemove.getOldNames()); + toRemoveList.add(toRemove); + }); + if(!toRemoveList.isEmpty()){ + nameReplacementResults.remove(toRemoveList.get(0)); + toRemoveList.clear(); + } + } + + /** + * @param genericsGeneratorResults + * @param allCons + * @param cycles + * @param tphExtractor + */ + public static void handleCycle(List genericsGeneratorResults, + List allCons, List cycles, TPHExtractor tphExtractor) { + GenericsGeneratorUtility.modifyRelationForConstraintsInCycle(cycles); + List nameReplacementResults = GenericsGeneratorUtility.substituteTPHSFormCycle(allCons, cycles,tphExtractor); + GenericsGeneratorUtility.createResults(genericsGeneratorResults,nameReplacementResults); + GenericsGeneratorUtility.removeEqualConstraints(allCons); + } + + /** + * @param allCons + * @return + */ + public static List findCycles(List allCons) { + /* find all cycles */ + CyclesFinder cyclesFinder = new CyclesFinder(allCons); + List cycles = cyclesFinder.findCycles(); + return cycles; + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/CyclesFinder.java b/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/CyclesFinder.java new file mode 100644 index 00000000..9b0867f5 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/CyclesFinder.java @@ -0,0 +1,106 @@ +/** + * + */ +package de.dhbwstuttgart.bytecode.genericsGenerator; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; + +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.Cycle; + +/** + * @author fayez + * + */ +public class CyclesFinder { + private final List allCons; + + public CyclesFinder(List allCons) { + this.allCons = allCons; + } + + public List findCycles() { + List vistedConstraints = new ArrayList<>(allCons.size()); + List cycles = new ArrayList<>(); + for (TPHConstraint constraint : allCons) { + if(constraint.getRel()==Relation.EQUAL) + continue; + if (!vistedConstraints.contains(constraint)) { + vistedConstraints.add(constraint); + checkConstraint(constraint, vistedConstraints, cycles); + } + } + return cycles; + } + + private void checkConstraint(TPHConstraint constraint, List vistedConstraints, + List cycles) { + List tphsInRelation = new LinkedList<>(); + List maybeCycle = new ArrayList<>(); + maybeCycle.add(constraint); + tphsInRelation.add(constraint.getLeft()); + tphsInRelation.add(constraint.getRight()); + Optional nextConstraint = getConstraintInRelation(tphsInRelation, maybeCycle); + while (nextConstraint.isPresent()) { + if(containsInLongCycle(nextConstraint.get(), cycles)) { + break; + } + if (isCycle(tphsInRelation)) { + addAllToVisitedConstraints(vistedConstraints, maybeCycle); + Cycle cycle = new Cycle(maybeCycle); + cycles.add(cycle); + return; + } + nextConstraint = getConstraintInRelation(tphsInRelation, maybeCycle); + } + +// addAllToVisitedConstraints(vistedConstraints, maybeCycle); + } + + private boolean containsInLongCycle(TPHConstraint c, List cycles) { + for(Cycle cycle : cycles) { + if(cycle.containConstraint(c)) + return true; + } + return false; + } + + private void addAllToVisitedConstraints(List vistedConstraints, List maybeCycle) { + for (TPHConstraint con : maybeCycle) { + if (!vistedConstraints.contains(con)) + vistedConstraints.add(con); + } + } + + private Optional getConstraintInRelation(List tphsInRelation, + List maybeCycle) { + TPHConstraint constraint = getConstraintByLeftSide(tphsInRelation.get(tphsInRelation.size()-1),maybeCycle); + Optional nextConstraint = Optional.ofNullable(constraint); + if(nextConstraint.isPresent()) { + maybeCycle.add(constraint); + tphsInRelation.add(constraint.getRight()); + } + return nextConstraint; + } + + private TPHConstraint getConstraintByLeftSide(String left, List maybeCycle) { + for(TPHConstraint constraint : allCons) { + if(constraint.getRel()==Relation.EQUAL) + continue; + if(maybeCycle.contains(constraint)) + continue; + if(constraint.getLeft().equals(left)) + return constraint; + } + return null; + } + + private boolean isCycle(List tphsInRelation) { + return tphsInRelation.get(0).equals(tphsInRelation.get(tphsInRelation.size() - 1)); + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/GeneratedGenericsFinder.java b/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/GeneratedGenericsFinder.java new file mode 100644 index 00000000..e25958d1 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/GeneratedGenericsFinder.java @@ -0,0 +1,732 @@ +/** + * + */ +package de.dhbwstuttgart.bytecode.genericsGenerator; + +import java.util.*; + +import de.dhbwstuttgart.bytecode.TPHExtractor; +import de.dhbwstuttgart.bytecode.constraint.ExtendsConstraint; +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.*; +import de.dhbwstuttgart.bytecode.insertGenerics.ClassConstraint; +import de.dhbwstuttgart.bytecode.insertGenerics.FamilyOfGeneratedGenerics; +import de.dhbwstuttgart.bytecode.utilities.MethodAndTPH; +import de.dhbwstuttgart.bytecode.utilities.MethodUtility; +import de.dhbwstuttgart.bytecode.utilities.Resolver; +import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; +import de.dhbwstuttgart.parser.scope.JavaClassName; +import de.dhbwstuttgart.syntaxtree.ASTVisitor; +import de.dhbwstuttgart.syntaxtree.ClassOrInterface; +import de.dhbwstuttgart.syntaxtree.Constructor; +import de.dhbwstuttgart.syntaxtree.Field; +import de.dhbwstuttgart.syntaxtree.FormalParameter; +import de.dhbwstuttgart.syntaxtree.GenericDeclarationList; +import de.dhbwstuttgart.syntaxtree.GenericTypeVar; +import de.dhbwstuttgart.syntaxtree.Method; +import de.dhbwstuttgart.syntaxtree.ParameterList; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.syntaxtree.statement.ArgumentList; +import de.dhbwstuttgart.syntaxtree.statement.Assign; +import de.dhbwstuttgart.syntaxtree.statement.AssignToField; +import de.dhbwstuttgart.syntaxtree.statement.BinaryExpr; +import de.dhbwstuttgart.syntaxtree.statement.Block; +import de.dhbwstuttgart.syntaxtree.statement.CastExpr; +import de.dhbwstuttgart.syntaxtree.statement.DoStmt; +import de.dhbwstuttgart.syntaxtree.statement.EmptyStmt; +import de.dhbwstuttgart.syntaxtree.statement.ExpressionReceiver; +import de.dhbwstuttgart.syntaxtree.statement.FieldVar; +import de.dhbwstuttgart.syntaxtree.statement.ForStmt; +import de.dhbwstuttgart.syntaxtree.statement.IfStmt; +import de.dhbwstuttgart.syntaxtree.statement.InstanceOf; +import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression; +import de.dhbwstuttgart.syntaxtree.statement.Literal; +import de.dhbwstuttgart.syntaxtree.statement.LocalVar; +import de.dhbwstuttgart.syntaxtree.statement.LocalVarDecl; +import de.dhbwstuttgart.syntaxtree.statement.MethodCall; +import de.dhbwstuttgart.syntaxtree.statement.NewArray; +import de.dhbwstuttgart.syntaxtree.statement.NewClass; +import de.dhbwstuttgart.syntaxtree.statement.Return; +import de.dhbwstuttgart.syntaxtree.statement.ReturnVoid; +import de.dhbwstuttgart.syntaxtree.statement.StaticClassName; +import de.dhbwstuttgart.syntaxtree.statement.Super; +import de.dhbwstuttgart.syntaxtree.statement.SuperCall; +import de.dhbwstuttgart.syntaxtree.statement.This; +import de.dhbwstuttgart.syntaxtree.statement.UnaryExpr; +import de.dhbwstuttgart.syntaxtree.statement.WhileStmt; +import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType; +import de.dhbwstuttgart.syntaxtree.type.GenericRefType; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.result.ResultSet; + +/** + * @author fayez + * + */ +public class GeneratedGenericsFinder implements ASTVisitor { + private final TPHExtractor tphExtractor = new TPHExtractor(); + private Collection listOfResultSets; + private SourceFile sf; + private List tphsClass; + private GenericGenratorResultForSourceFile generatedGenericsForSF;//Ergebnis des GGenerics + private ResultSet resultSet; + private final List methodNameAndParamsT = new ArrayList<>(); + private FamilyOfGeneratedGenerics fogg; + + private String pkgName; + private JavaClassName className; + private Resolver resolver; + + + /** + * @param sf + * @param listOfResultSets + */ + public GeneratedGenericsFinder(SourceFile sf, Collection listOfResultSets) { + this.sf = sf; + this.listOfResultSets = listOfResultSets; + } + + public GenericGenratorResultForSourceFile findGeneratedGenerics() { + sf.accept(this); + return generatedGenericsForSF; + } + + /** + * returns the family of Generated Generics + * insbesondere fuer Testzwecke + */ + public FamilyOfGeneratedGenerics getFogg() { + return fogg; + } + + /* + * (non-Javadoc) + * + * @see + * de.dhbwstuttgart.syntaxtree.ASTVisitor#visit(de.dhbwstuttgart.syntaxtree. + * SourceFile) + */ + @Override + public void visit(SourceFile sourceFile) { + pkgName = sf.getPkgName(); + generatedGenericsForSF = new GenericGenratorResultForSourceFile(pkgName); + for (ClassOrInterface cl : sourceFile.getClasses()) { + cl.accept(this); + } + } + + /* + * (non-Javadoc) + * + * @see + * de.dhbwstuttgart.syntaxtree.ASTVisitor#visit(de.dhbwstuttgart.syntaxtree. + * ClassOrInterface) + */ + @Override + public void visit(ClassOrInterface classOrInterface) { + className = classOrInterface.getClassName(); + List listOfResultSetsList = new ArrayList<>(listOfResultSets); + + boolean isVisited = false; + + ConstraintsSimplierResult simplifiedConstraints = null; + GenericsGeneratorResultForClass ggResult = null; + GenericsGeneratorResultForClass ggResultAlternative = null; + + for (int i = 0; i < listOfResultSetsList.size(); i++) { + resultSet = listOfResultSetsList.get(i); + tphExtractor.setResultSet(resultSet); + resolver = new Resolver(resultSet); + classOrInterface.accept(tphExtractor); + //PL 2020-10-16: Ab hier GGenerics implementieren durch Ali + //Rueckgabe an generatedGenericsForSF + fogg = new FamilyOfGeneratedGenerics(tphExtractor, resultSet); + + System.out.println("fogg.allConstraints: "+ fogg.allConstraints); + System.out.println("fogg.posOfTPHs: "+ fogg.posOfTPHs); + System.out.println("fogg.classConstraints: "+ fogg.classConstraints); + System.out.println("fogg.methodConstraintsWithPosition: "+ fogg.methodConstraintsWithPosition); + System.out.println(fogg); + + ///* + //Fayez Ansatz Anfang + tphsClass = tphExtractor.tphsClass; + //PL 2020-01-15 + //Es muss ggResult aus fogg gebildet werden + simplifiedConstraints = GenericsGenerator.simplifyConstraints(tphExtractor, tphsClass); + if(!isVisited) { + ggResult = GenericsGenerator.generateConstraints(className, tphExtractor, tphsClass,simplifiedConstraints); + isVisited = true; + } + + for(Method m : classOrInterface.getMethods()) { + addMethodConstraints(simplifiedConstraints, ggResult, m); + + } + + + if(ggResult != null) { //Hinzufuegen von Fayez ggResult + generatedGenericsForSF.addGenericGeneratorResultClass(ggResult); + } + // Fayez Ansatz Ende + //*/ + + //Ali Ansatz Anfang + List listOfClassCons = new ArrayList<>(); + for(TPHConstraint clCons: fogg.classConstraints) { +// ExtendsConstraint ec = new ExtendsConstraint(clCons.getLeft(), clCons.getRight()); + GenericsGeneratorResult ggR = new GenericsGeneratorResult(clCons, new HashSet<>()); + listOfClassCons.add(ggR); + } + + GenericGeneratorResultsForAllMethods ggRfaM = null; + List listOfMethAndCons = new ArrayList<>(); + for(String methID: fogg.methodConstraintsWithPosition.keySet()) { + List listOfGGR = new ArrayList<>(); + for(TPHConstraint methCons: fogg.methodConstraintsWithPosition.get(methID)) { +// ExtendsConstraint ec = new ExtendsConstraint(methCons.getLeft(),methCons.getRight()); + GenericsGeneratorResult ggR = new GenericsGeneratorResult(methCons, new HashSet<>()); + listOfGGR.add(ggR); + } + MethodAndConstraints mac = new MethodAndConstraints(methID, listOfGGR); + listOfMethAndCons.add(mac); + } + ggRfaM = new GenericGeneratorResultsForAllMethods(listOfMethAndCons); + ggResultAlternative = new GenericsGeneratorResultForClass(className, listOfClassCons, ggRfaM); + + if(ggResultAlternative != null) {//hinzufuegen von Alis ggResult + //generatedGenericsForSF.addGenericGeneratorResultClass(ggResultAlternative); + System.out.println(generatedGenericsForSF); + } + System.out.println(ggResultAlternative); + //Ali Ansatz Ende + + } + + } + + /** + * @param simplifiedConstraints + * @param ggResult + * @param m + */ + public void addMethodConstraints(ConstraintsSimplierResult simplifiedConstraints, + GenericsGeneratorResultForClass ggResult, Method m) { + String id = MethodUtility.createID(resolver, m); + boolean isInGGResult = (ggResult != null) && ggResult.contains(id); + if(methodNameAndParamsT.contains(id) || isInGGResult) + return; + methodNameAndParamsT.add(id); + Optional methodAndTPH = GenericsGeneratorUtility.getMethodAndTphs(tphExtractor.ListOfMethodsAndTph,id); + methodAndTPH.ifPresent(mt->{ + MethodAndConstraints methodConstraints = GenericsGenerator.generateConstraintsForMethod(tphExtractor.allCons, mt , simplifiedConstraints, tphsClass); + ggResult.getMethodsAndTheirConstraints().getMethodsAndConstraints().add(methodConstraints); + }); + } + + /* + * (non-Javadoc) + * + * @see + * de.dhbwstuttgart.syntaxtree.ASTVisitor#visit(de.dhbwstuttgart.syntaxtree. + * Method) + */ + @Override + public void visit(Method method) { + + } + + /* + * (non-Javadoc) + * + * @see + * de.dhbwstuttgart.syntaxtree.ASTVisitor#visit(de.dhbwstuttgart.syntaxtree. + * ParameterList) + */ + @Override + public void visit(ParameterList formalParameters) { + + } + + /* + * (non-Javadoc) + * + * @see + * de.dhbwstuttgart.syntaxtree.ASTVisitor#visit(de.dhbwstuttgart.syntaxtree. + * Constructor) + */ + @Override + public void visit(Constructor field) { + + } + + /* + * (non-Javadoc) + * + * @see de.dhbwstuttgart.syntaxtree.StatementVisitor#visit(de.dhbwstuttgart. + * syntaxtree.statement.ArgumentList) + */ + @Override + public void visit(ArgumentList argumentList) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see de.dhbwstuttgart.syntaxtree.StatementVisitor#visit(de.dhbwstuttgart. + * syntaxtree.statement.LambdaExpression) + */ + @Override + public void visit(LambdaExpression lambdaExpression) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see de.dhbwstuttgart.syntaxtree.StatementVisitor#visit(de.dhbwstuttgart. + * syntaxtree.statement.Assign) + */ + @Override + public void visit(Assign assign) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see de.dhbwstuttgart.syntaxtree.StatementVisitor#visit(de.dhbwstuttgart. + * syntaxtree.statement.BinaryExpr) + */ + @Override + public void visit(BinaryExpr binary) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see de.dhbwstuttgart.syntaxtree.StatementVisitor#visit(de.dhbwstuttgart. + * syntaxtree.statement.Block) + */ + @Override + public void visit(Block block) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see de.dhbwstuttgart.syntaxtree.StatementVisitor#visit(de.dhbwstuttgart. + * syntaxtree.statement.CastExpr) + */ + @Override + public void visit(CastExpr castExpr) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see de.dhbwstuttgart.syntaxtree.StatementVisitor#visit(de.dhbwstuttgart. + * syntaxtree.statement.EmptyStmt) + */ + @Override + public void visit(EmptyStmt emptyStmt) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see de.dhbwstuttgart.syntaxtree.StatementVisitor#visit(de.dhbwstuttgart. + * syntaxtree.statement.FieldVar) + */ + @Override + public void visit(FieldVar fieldVar) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see de.dhbwstuttgart.syntaxtree.StatementVisitor#visit(de.dhbwstuttgart. + * syntaxtree.statement.ForStmt) + */ + @Override + public void visit(ForStmt forStmt) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see de.dhbwstuttgart.syntaxtree.StatementVisitor#visit(de.dhbwstuttgart. + * syntaxtree.statement.IfStmt) + */ + @Override + public void visit(IfStmt ifStmt) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see de.dhbwstuttgart.syntaxtree.StatementVisitor#visit(de.dhbwstuttgart. + * syntaxtree.statement.InstanceOf) + */ + @Override + public void visit(InstanceOf instanceOf) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see de.dhbwstuttgart.syntaxtree.StatementVisitor#visit(de.dhbwstuttgart. + * syntaxtree.statement.LocalVar) + */ + @Override + public void visit(LocalVar localVar) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see de.dhbwstuttgart.syntaxtree.StatementVisitor#visit(de.dhbwstuttgart. + * syntaxtree.statement.LocalVarDecl) + */ + @Override + public void visit(LocalVarDecl localVarDecl) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see de.dhbwstuttgart.syntaxtree.StatementVisitor#visit(de.dhbwstuttgart. + * syntaxtree.statement.MethodCall) + */ + @Override + public void visit(MethodCall methodCall) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see de.dhbwstuttgart.syntaxtree.StatementVisitor#visit(de.dhbwstuttgart. + * syntaxtree.statement.NewClass) + */ + @Override + public void visit(NewClass methodCall) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see de.dhbwstuttgart.syntaxtree.StatementVisitor#visit(de.dhbwstuttgart. + * syntaxtree.statement.NewArray) + */ + @Override + public void visit(NewArray newArray) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see de.dhbwstuttgart.syntaxtree.StatementVisitor#visit(de.dhbwstuttgart. + * syntaxtree.statement.Return) + */ + @Override + public void visit(Return aReturn) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see de.dhbwstuttgart.syntaxtree.StatementVisitor#visit(de.dhbwstuttgart. + * syntaxtree.statement.ReturnVoid) + */ + @Override + public void visit(ReturnVoid aReturn) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see de.dhbwstuttgart.syntaxtree.StatementVisitor#visit(de.dhbwstuttgart. + * syntaxtree.statement.StaticClassName) + */ + @Override + public void visit(StaticClassName staticClassName) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see de.dhbwstuttgart.syntaxtree.StatementVisitor#visit(de.dhbwstuttgart. + * syntaxtree.statement.Super) + */ + @Override + public void visit(Super aSuper) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see de.dhbwstuttgart.syntaxtree.StatementVisitor#visit(de.dhbwstuttgart. + * syntaxtree.statement.This) + */ + @Override + public void visit(This aThis) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see de.dhbwstuttgart.syntaxtree.StatementVisitor#visit(de.dhbwstuttgart. + * syntaxtree.statement.WhileStmt) + */ + @Override + public void visit(WhileStmt whileStmt) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see de.dhbwstuttgart.syntaxtree.StatementVisitor#visit(de.dhbwstuttgart. + * syntaxtree.statement.DoStmt) + */ + @Override + public void visit(DoStmt whileStmt) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see de.dhbwstuttgart.syntaxtree.StatementVisitor#visit(de.dhbwstuttgart. + * syntaxtree.statement.AssignToField) + */ + @Override + public void visit(AssignToField assignLeftSide) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see + * de.dhbwstuttgart.syntaxtree.StatementVisitor#visit(de.dhbwstuttgart.parser. + * SyntaxTreeGenerator.AssignToLocal) + */ + @Override + public void visit(AssignToLocal assignLeftSide) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see de.dhbwstuttgart.syntaxtree.StatementVisitor#visit(de.dhbwstuttgart. + * syntaxtree.statement.SuperCall) + */ + @Override + public void visit(SuperCall superCall) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see de.dhbwstuttgart.syntaxtree.StatementVisitor#visit(de.dhbwstuttgart. + * syntaxtree.statement.ExpressionReceiver) + */ + @Override + public void visit(ExpressionReceiver expressionReceiver) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see de.dhbwstuttgart.syntaxtree.StatementVisitor#visit(de.dhbwstuttgart. + * syntaxtree.statement.UnaryExpr) + */ + @Override + public void visit(UnaryExpr unaryExpr) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see de.dhbwstuttgart.syntaxtree.StatementVisitor#visit(de.dhbwstuttgart. + * syntaxtree.statement.Literal) + */ + @Override + public void visit(Literal literal) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see + * de.dhbwstuttgart.syntaxtree.ASTVisitor#visit(de.dhbwstuttgart.syntaxtree. + * GenericTypeVar) + */ + @Override + public void visit(GenericTypeVar genericTypeVar) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see + * de.dhbwstuttgart.syntaxtree.ASTVisitor#visit(de.dhbwstuttgart.syntaxtree. + * FormalParameter) + */ + @Override + public void visit(FormalParameter formalParameter) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see + * de.dhbwstuttgart.syntaxtree.ASTVisitor#visit(de.dhbwstuttgart.syntaxtree. + * GenericDeclarationList) + */ + @Override + public void visit(GenericDeclarationList genericTypeVars) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see + * de.dhbwstuttgart.syntaxtree.ASTVisitor#visit(de.dhbwstuttgart.syntaxtree. + * Field) + */ + @Override + public void visit(Field field) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see + * de.dhbwstuttgart.syntaxtree.ASTVisitor#visit(de.dhbwstuttgart.syntaxtree.type + * .RefType) + */ + @Override + public void visit(RefType refType) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see + * de.dhbwstuttgart.syntaxtree.ASTVisitor#visit(de.dhbwstuttgart.syntaxtree.type + * .SuperWildcardType) + */ + @Override + public void visit(SuperWildcardType superWildcardType) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see + * de.dhbwstuttgart.syntaxtree.ASTVisitor#visit(de.dhbwstuttgart.syntaxtree.type + * .TypePlaceholder) + */ + @Override + public void visit(TypePlaceholder typePlaceholder) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see + * de.dhbwstuttgart.syntaxtree.ASTVisitor#visit(de.dhbwstuttgart.syntaxtree.type + * .ExtendsWildcardType) + */ + @Override + public void visit(ExtendsWildcardType extendsWildcardType) { + // TODO Auto-generated method stub + + } + + /* + * (non-Javadoc) + * + * @see + * de.dhbwstuttgart.syntaxtree.ASTVisitor#visit(de.dhbwstuttgart.syntaxtree.type + * .GenericRefType) + */ + @Override + public void visit(GenericRefType genericRefType) { + // TODO Auto-generated method stub + + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/GenericsGenerator.java b/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/GenericsGenerator.java new file mode 100644 index 00000000..8e5bd481 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/GenericsGenerator.java @@ -0,0 +1,256 @@ +/** + * + */ +package de.dhbwstuttgart.bytecode.genericsGenerator; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.*; +import de.dhbwstuttgart.parser.scope.JavaClassName; +import org.objectweb.asm.Type; + +import de.dhbwstuttgart.bytecode.TPHExtractor; +import de.dhbwstuttgart.bytecode.constraint.ExtendsConstraint; +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; +import de.dhbwstuttgart.bytecode.utilities.MethodAndTPH; + +/** + * @author fayez + * + */ +public class GenericsGenerator { + /*TODO: When generating generics for a class if we have the following: + tphClass < tphMeth1 < tphMeth2 + then we have to convert tphMeth1, tphMeth2 to tph class and generate the following + class constraints: tphClass < tphMeth1, tphMeth1 < tphMeth2, tphMeth2 < Object + */ + + public static GenericsGeneratorResultForClass generateConstraints(final JavaClassName className, final TPHExtractor tphExtractor, + final List tphsClass, final ConstraintsSimplierResult simplifiedConstraints) { + + List classConstraints = generateConstraintsForClass(tphExtractor, + simplifiedConstraints, tphsClass); +// GenericGeneratorResultsForAllMethods methodsAndConstraints = generateConstraintsForAllMethods(tphExtractor, +// simplifiedConstraints, tphsClass); + GenericGeneratorResultsForAllMethods methodsAndConstraints = new GenericGeneratorResultsForAllMethods(new ArrayList<>()); + + return new GenericsGeneratorResultForClass(className, classConstraints, methodsAndConstraints); + } + + + /** + * @param tphExtractor + * @param tphsClass + * @return + */ + public static ConstraintsSimplierResult simplifyConstraints(final TPHExtractor tphExtractor, + final List tphsClass) { + final List genericsGeneratorResults = new ArrayList<>(); + + ConstraintsSimplierResult simplifiedConstraints = ConstraintsSimplifier.simplifyConstraints(tphExtractor, + genericsGeneratorResults, tphsClass); + return simplifiedConstraints; + } + + + private static List generateConstraintsForClass(final TPHExtractor tphExtractor, + final ConstraintsSimplierResult simplifiedConstraints, final List tphsClass) { + final List constraints = new ArrayList<>(); + + if (tphsClass.isEmpty()) + return constraints; + + final List allCons = tphExtractor.allCons; + + final Set visitedTPHs = new HashSet<>(); + + final List methodTPHs = tphExtractor.ListOfMethodsAndTph.stream().map(m -> m.getLocalTphs()) + .flatMap(l -> l.stream()).collect(Collectors.toList()); + + createConstraintsForClassTphs(simplifiedConstraints, tphsClass, constraints, allCons, visitedTPHs, methodTPHs); + + GenericsGeneratorUtility.addTPHsToClassTPHs(constraints, tphsClass); + GenericsGeneratorUtility.removeClassTPHsFromMethodTPHs(tphsClass, tphExtractor); + + generateGGConstraintsForTPH(tphsClass, constraints, simplifiedConstraints); + + return constraints; + } + + private static void createConstraintsForClassTphs(ConstraintsSimplierResult simplifiedConstraints, List tphsClass, List constraints, List allCons, Set visitedTPHs, List methodTPHs) { + List classAndMethodTphs = new ArrayList<>(tphsClass); + classAndMethodTphs.addAll(methodTPHs); + + for (String tph : tphsClass) { + + if (visitedTPHs.contains(tph)) + continue; + + final LinkedList tphsInRel = GenericsGeneratorUtility + .createLinkedListForTPHsInRelationClass(allCons, tphsClass, methodTPHs, visitedTPHs, tph); + + generateConstraintsForClassFromList(tphsInRel,simplifiedConstraints,classAndMethodTphs,constraints); + } + } + + private static void generateConstraintsForClassFromList(LinkedList tphsInRel, ConstraintsSimplierResult simplifiedConstraints, List classAndMethodTphs, List constraints) { + + if(tphsInRel.isEmpty()) + return; + + List resultConstraints = new ArrayList<>(); + String subType = tphsInRel.getFirst(); + String superType = GenericsGeneratorUtility.getNextClassTph(classAndMethodTphs, tphsInRel); + + int idxOfSuper = tphsInRel.indexOf(superType); + int size = tphsInRel.size(); + while (size > 2 && idxOfSuper < size-1){ + GenericsGeneratorResult genericsGeneratorResult = getGenericsGeneratorResultForClass(simplifiedConstraints, subType, superType); + constraints.add(genericsGeneratorResult); + + tphsInRel = new LinkedList<>(tphsInRel.subList(idxOfSuper, size)); + subType = tphsInRel.getFirst(); + superType = GenericsGeneratorUtility.getNextClassTph(classAndMethodTphs, tphsInRel); + + idxOfSuper = tphsInRel.indexOf(superType); + size = tphsInRel.size(); + } + GenericsGeneratorResult genericsGeneratorResult = getGenericsGeneratorResultForClass(simplifiedConstraints, subType, superType); + constraints.add(genericsGeneratorResult); + } + + private static GenericsGeneratorResult getGenericsGeneratorResultForClass(ConstraintsSimplierResult simplifiedConstraints, String subType, String superType) { + TPHConstraint constraint = new ExtendsConstraint(subType, superType); + + Set equalSet = GenericsGeneratorUtility + .createEqualSet(simplifiedConstraints.getNameReplacementResults(), subType); + + return new GenericsGeneratorResult(constraint, equalSet); + } + /* TODO Remove this methoda*/ + private static GenericsGeneratorResult generateGGResultForClass(LinkedList tphsInRel, + ConstraintsSimplierResult simplifiedConstraints, List tphsClass) { + String subType = tphsInRel.getFirst(); + + String superType = GenericsGeneratorUtility.getNextClassTph(tphsClass, tphsInRel); + + TPHConstraint constraint = new ExtendsConstraint(subType, superType); + + Set equalSet = GenericsGeneratorUtility + .createEqualSet(simplifiedConstraints.getNameReplacementResults(), subType); + + return new GenericsGeneratorResult(constraint, equalSet); + } + + private static GenericGeneratorResultsForAllMethods generateConstraintsForAllMethods( + final TPHExtractor tphExtractor, ConstraintsSimplierResult simplifiedConstraints, List tphsClass) { + + final List methodsAndConstraints = new ArrayList<>(); + final GenericGeneratorResultsForAllMethods results = new GenericGeneratorResultsForAllMethods( + methodsAndConstraints); + tphExtractor.ListOfMethodsAndTph.forEach(m -> { + MethodAndConstraints methAndCons = generateConstraintsForMethod(tphExtractor.allCons, m, + simplifiedConstraints, tphsClass); + methodsAndConstraints.add(methAndCons); + }); + + return results; + } + + public static MethodAndConstraints generateConstraintsForMethod(final List allCons, + final MethodAndTPH m, final ConstraintsSimplierResult simplifiedConstraints, List tphsClass) { + final List localTphs = m.getLocalTphs(); + + List constraints = new ArrayList<>(); + MethodAndConstraints result = new MethodAndConstraints(m.getId(), constraints); + + if (localTphs.isEmpty()) + return result; + + if (localTphs.size() == 1 && tphsClass.isEmpty()) { + generateGGConstraintsForTPH(localTphs, constraints, simplifiedConstraints); + return result; + } + + final Set visitedTPHs = new HashSet<>(); + + for (String tph : localTphs) { + + if (visitedTPHs.contains(tph)) + continue; + + final LinkedList tphsInRel = GenericsGeneratorUtility.createLinkedListForTPHsInRelation(allCons, + localTphs, tphsClass, visitedTPHs, tph); + if (!tphsInRel.isEmpty()) { + GenericsGeneratorUtility.removeNotLocalTphs(tphsInRel, localTphs, tphsClass); + if (!GenericsGeneratorUtility.isInResult(tphsInRel.getFirst(), constraints)) { + GenericsGeneratorResult constraint = generateGGResult(tphsInRel, simplifiedConstraints); + constraints.add(constraint); + } + } + } + + generateGGConstraintsForTPH(localTphs, constraints, simplifiedConstraints); + return result; + } + + private static void generateGGConstraintsForTPH(List localTphs, + final List constraints, final ConstraintsSimplierResult simplifiedConstraints) { + + localTphs.forEach(tph -> { + boolean isInSimplifiedConstraints = GenericsGeneratorUtility.isTPHInGenericGeneratorResult(simplifiedConstraints.getGenericsGenResults(), tph); + if (isInSimplifiedConstraints) { + GenericsGeneratorResult ggResult = GenericsGeneratorUtility.getGenericGeneratorResult(simplifiedConstraints.getGenericsGenResults(), tph).get(); +// GenericsGeneratorUtility.removeGenericGeneratorResult(simplifiedConstraints.getGenericsGenResults(),ggResult); + constraints.add(ggResult); + } else { + boolean isInConstraints = GenericsGeneratorUtility.isTPHInGenericGeneratorResult(constraints, tph); + + if (!isInConstraints) { + GenericsGeneratorResult ggResult = generateGGResult(tph, simplifiedConstraints.getNameReplacementResults()); + constraints.add(ggResult); + } + } + }); + + } + + private static GenericsGeneratorResult generateGGResult(String tph, + List nameReplacementResults) { + String superType = Type.getInternalName(Object.class); + TPHConstraint constraint = new ExtendsConstraint(tph, superType); + Set equalSet = GenericsGeneratorUtility.createEqualSet(nameReplacementResults, tph); + + return new GenericsGeneratorResult(constraint, equalSet); + } + + private static GenericsGeneratorResult generateGGResult(final LinkedList tphsInRel, + final ConstraintsSimplierResult simplifiedConstraints) { + + String subType = tphsInRel.getFirst(); + + if (tphsInRel.size() == 1) { + Optional constraintFromSimplifiedCon = simplifiedConstraints + .getGenericsGenResults().stream().filter(g -> g.getConstraint().getLeft().equals(subType)) + .findFirst(); + if (constraintFromSimplifiedCon.isPresent()) + return constraintFromSimplifiedCon.get(); + } + + String superType = tphsInRel.size() > 1 ? tphsInRel.getLast() : Type.getInternalName(Object.class); + + TPHConstraint constraint = new ExtendsConstraint(subType, superType); + + Set equalSet = GenericsGeneratorUtility + .createEqualSet(simplifiedConstraints.getNameReplacementResults(), subType); + + return new GenericsGeneratorResult(constraint, equalSet); + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/GenericsGeneratorUtility.java b/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/GenericsGeneratorUtility.java new file mode 100644 index 00000000..f909734f --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGenerator/GenericsGeneratorUtility.java @@ -0,0 +1,571 @@ +/** + * + */ +package de.dhbwstuttgart.bytecode.genericsGenerator; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.*; +import org.objectweb.asm.Type; + +import de.dhbwstuttgart.bytecode.TPHExtractor; +import de.dhbwstuttgart.bytecode.constraint.EqualConstraint; +import de.dhbwstuttgart.bytecode.constraint.ExtendsConstraint; +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; +import de.dhbwstuttgart.bytecode.utilities.ConstraintsFinder; +import de.dhbwstuttgart.bytecode.utilities.MethodAndTPH; +import de.dhbwstuttgart.bytecode.utilities.NameReplacer; + +/** + * @author fayez + * + */ +public class GenericsGeneratorUtility { + /** + * Returns a list of type placeholders names of a specified method + * + * @param methodID The id of the method ReturnTypeMethodName(ParameterTypes) + * @param listOfMethodsAndTph List of all methods + * @return a list of type placehoders names + */ + public static List getMethodTPHS(String methodID, ArrayList listOfMethodsAndTph) { + return listOfMethodsAndTph.stream().filter(mt->mt.getId().equals(methodID)).findAny().get().getTphs(); + } + + /** + * Returns a reverse constraint of a specified constraint which is given by its left and right + * side + * + * @param allCons List of all constraints + * @param left The left side of the given constraint + * @param right The right side of the given constraint + * @return An Optional object which contains the reverse constraint if it is exist + */ + public static Optional getReverseConstraint(List allCons, String left, String right) { + return allCons.stream().filter(c->{ + return c.getRight().equals(left) && c.getLeft().equals(right); + }).findAny(); + } + + /** + * Substitutes the old name by the new name in all constraints + * + * @param allCons List of all constraints + * @param oldName The name to be replaced + * @param newName The new name + */ + public static void substituteTPH(List allCons, String oldName, String newName) { + allCons.stream() + .filter(c->c.getRel()==Relation.EXTENDS) + .forEach(c->{ + if(c.getLeft().equals(oldName)) + c.setLeft(newName); + if(c.getRight().equals(oldName)) + c.setRight(newName); + }); + + } + + public static List findConstraintsWithLeftSameLeftSide(List allCons) { + // finder looks for constraints that have the same left hand side + // and put them in a list + ConstraintsFinder finder = new ConstraintsFinder(allCons); + List foundCons = finder.findConstraints(); + return foundCons; + } + + public static void simplifyConstraintsWithSameLeftSide(List consWithSameLeftSide, + List allCons, List methodTPHS) { + List eqCons = new ArrayList<>(); + + for (ConstraintsWithSameLeftSide list : consWithSameLeftSide) { + NameReplacementResult replRes = modifyNames(allCons, methodTPHS, list); + createEqualConstraintsForNames(replRes.getName(), replRes.getOldNames(),eqCons); + + for (TPHConstraint c : allCons) { + if (c.getRel() == Relation.EQUAL && replRes.getName().equals(c.getRight())) { + eqCons.add(c); + } + } + updateEqualCons(replRes, eqCons); + + TPHConstraint c = list.getConstraints().get(0); + allCons.removeAll(list.getConstraints()); + allCons.add(c); + } + + } + + public static void simplifyConstraintsWithSameLeftSide(List consWithSameLeftSide, + TPHExtractor tphExtractor, List tphsClass, List equalCons) { + List allCons = tphExtractor.allCons; + + for (ConstraintsWithSameLeftSide list : consWithSameLeftSide) { + if(!stillWithSameLeftSide(list)) + continue; + NameReplacementResult replRes = modifyNames(allCons, list, tphExtractor.ListOfMethodsAndTph,tphsClass); + createEqualConstraintsForNames(replRes.getName(), replRes.getOldNames(),equalCons); + + for (TPHConstraint c : allCons) { + if (c.getRel() == Relation.EQUAL && replRes.getName().equals(c.getRight())) { + equalCons.add(c); + } + } + updateEqualCons(replRes, equalCons); + + TPHConstraint c = list.getConstraints().get(0); + allCons.removeAll(list.getConstraints()); + removeConstraintsWithSameLeftAndRightSide(allCons); + allCons.add(c); + removeDuplicate(allCons); + } + consWithSameLeftSide.clear(); + consWithSameLeftSide = findConstraintsWithLeftSameLeftSide(allCons); + if(!consWithSameLeftSide.isEmpty()) + simplifyConstraintsWithSameLeftSide(consWithSameLeftSide,tphExtractor,tphsClass,equalCons); + + } + + private static void removeDuplicate(List allCons) { + List visited = new ArrayList<>(); + List toRemove = new ArrayList<>(); + checkForDuplicate(allCons, visited, toRemove); + removeConstraintsByIndex(allCons, toRemove); + } + + private static void removeConstraintsByIndex(List allCons, List toRemove) { + for(int index : toRemove) + allCons.remove(index); + } + + private static void checkForDuplicate(List allCons, List visited, List toRemove) { + for(int i = 0;i allCons, List visited, List toRemove, int i) { + TPHConstraint constraint = allCons.get(i); + if(containsInList(visited,constraint.getLeft(),constraint.getRight())){ + toRemove.add(i); + } else { + visited.add(constraint); + } + } + + private static boolean containsInList(List allConstraints, String left, String right) { + for(TPHConstraint constraint : allConstraints) + if(constraint.getLeft().equals(left) && constraint.getRight().equals(right)) + return true; + return false; + } + + private static void addNewConstraintsWithSameLeftSide(ConstraintsWithSameLeftSide constraintsWithSameLeftSide, List allCons) { + allCons.forEach(c->{ + if (constraintsWithSameLeftSide.getConstraints().get(0).getLeft().equals(c.getLeft())){ + if(!constraintsWithSameLeftSide.getConstraints().contains(c)) + constraintsWithSameLeftSide.getConstraints().add(c); + } + }); + } + + private static void checkForNewConstraintsWithSameLeftSide(List consWithSameLeftSide, List allCons) { + allCons.forEach(c->{ + Optional constraintsWithSameLeftSide = getConstraintsWithSameLeftSide(consWithSameLeftSide, c.getLeft()); + constraintsWithSameLeftSide.ifPresent(cls->{ + if(!cls.getConstraints().contains(c)) + cls.getConstraints().add(c); + }); + }); + } + + private static Optional getConstraintsWithSameLeftSide(List consWithSameLeftSide, String left) { + return consWithSameLeftSide.stream().filter(csl->isContainedInConsWithLeftSide(csl,left)).findAny(); + } + + private static boolean isContainedInConsWithLeftSide(ConstraintsWithSameLeftSide csl, String left) { + return csl.getConstraints().get(0).getLeft().equals(left); + } + + private static boolean stillWithSameLeftSide(ConstraintsWithSameLeftSide constraints) { + removeUnvalidConstraints(constraints); + return constraints.getConstraints().size()>1; + } + + private static void removeUnvalidConstraints(ConstraintsWithSameLeftSide constraints) { + List toRemove = new ArrayList<>(); + constraints.getConstraints().forEach(c->{ + if(c.getLeft().equals(c.getRight())) + toRemove.add(c); + }); + if(!toRemove.isEmpty()) + constraints.getConstraints().removeAll(toRemove); + } + + private static void removeConstraintsWithSameLeftAndRightSide(List allCons) { + List toRemove = new ArrayList<>(); + allCons.forEach(c->{ + if(c.getLeft().equals(c.getRight())) + toRemove.add(c); + }); + allCons.removeAll(toRemove); + } + + private static void createEqualConstraintsForNames(String name, List equalNames, List eqCons) { + // create an equal constraint for each value in repres + for (String eName : equalNames) { + EqualConstraint ec = new EqualConstraint(eName, name); + eqCons.add(ec); + } + } + + /** + * @param allCons + * @param methodTPHS + * @param list + * @return + */ + public static NameReplacementResult modifyNames(List allCons, List methodTPHS, + ConstraintsWithSameLeftSide list) { + // generate a new name and replace the right hand side for each constraint + // in list with the new name + NameReplacer replacer = new NameReplacer(list.getConstraints(), allCons, methodTPHS); + // new name -> [all old names] + NameReplacementResult replRes = replacer.replaceNames(); + return replRes; + } + + public static NameReplacementResult modifyNames(List allCons, ConstraintsWithSameLeftSide list, List methodAndTPHs, List tphsClass) { + // generate a new name and replace the right hand side for each constraint + // in list with the new name + NameReplacer replacer = new NameReplacer(list.getConstraints(), allCons, methodAndTPHs, tphsClass); + // new name -> [all old names] + NameReplacementResult replRes = replacer.replaceNames(); + return replRes; + } + + public static void updateEqualCons(NameReplacementResult nameReplacementResult, List eqCons) { + List oldNames = nameReplacementResult.getOldNames(); + String newName = nameReplacementResult.getName(); + for (TPHConstraint c : eqCons) { +// if(oldNames.contains(c.getLeft())) +// c.setLeft(newName); + if (oldNames.contains(c.getRight())) + c.setRight(newName); + } + + } + + public static void modifyRelationForConstraintsInCycle(List cycles) { + cycles.stream().map(lc->lc.getConstraints()).flatMap(e->e.stream()).forEach(c->c.setRel(Relation.EQUAL)); + } + + public static List substituteTPHSFormCycle(List allCons, List cycles, TPHExtractor tphExtractor) { + List results = new ArrayList<>(); + cycles.forEach(lc->{ + Set names = getNamesFromCycle(lc); + String newName = names.stream().findFirst().get(); + + List equalNames = new ArrayList<>(names); + + Stream> tphsOfMethods = tphExtractor.ListOfMethodsAndTph.stream().map(m->m.getTphs()); + Stream> localTphsOfMethods = tphExtractor.ListOfMethodsAndTph.stream().map(m->m.getLocalTphs()); + + replaceOldNames(newName, equalNames, tphsOfMethods); + replaceOldNames(newName, equalNames, localTphsOfMethods); + + NameReplacementResult res = new NameReplacementResult(newName, equalNames); + results.add(res); + substituteAll(allCons,names,newName); + }); + return results; + } + + /** + * @param newName + * @param names + * @param tphsOfMethods + */ + public static void replaceOldNames(final String newName, final List names, Stream> tphsOfMethods) { + tphsOfMethods.forEach(tphsMethod->{ + if(tphsMethod.removeAll(names)) + tphsMethod.add(newName); + }); + } + + public static void substituteAll(List allCons, Set names, String newName) { + allCons.stream() + .filter(c-> c.getRel()==Relation.EXTENDS) + .forEach(c->{ + if(names.contains(c.getLeft())) { + c.setLeft(newName); + } else if(names.contains(c.getRight())) { + c.setRight(newName); + } + }); + } + + public static Set getNamesFromCycle(Cycle lc) { + Set names = new HashSet<>(); + lc.getConstraints().forEach(c->names.add(c.getLeft())); + return names; + } + + public static void createResults(List genericsGeneratorResults, + List nameReplacementResults) { + nameReplacementResults.forEach(n->{ + Set equals = new HashSet<>(n.getOldNames()); + TPHConstraint cons = new ExtendsConstraint(n.getName(), Type.getInternalName(Object.class)); + GenericsGeneratorResult ggRes = new GenericsGeneratorResult(cons, equals); + genericsGeneratorResults.add(ggRes); + }); + } + + public static void removeEqualConstraints(List allCons) { + List equalConstraints = getEqualConstraints(allCons); + allCons.removeAll(equalConstraints); + } + + public static List getEqualConstraints(List allCons) { + return allCons.stream().filter(c->c.getRel()==Relation.EQUAL).collect(Collectors.toList()); + } + + public static List createNameReplacementResultsFromEqualConstraints( + List equalCons) { + List nameReplacementResults = new ArrayList<>(); + equalCons.forEach(c->{ + if(isInNameReplacementResults(nameReplacementResults,c.getRight())) { + getNameReplacementByName(nameReplacementResults,c.getRight()).getOldNames().add(c.getLeft()); + } else { + List oldNames = new ArrayList<>(); + oldNames.add(c.getLeft()); + NameReplacementResult nrRes = new NameReplacementResult(c.getRight(), oldNames); + nameReplacementResults.add(nrRes); + } + }); + return nameReplacementResults; + } + + private static NameReplacementResult getNameReplacementByName(List nameReplacementResults, + String name) { + return nameReplacementResults.stream().filter(n->n.getName().equals(name)).findFirst().get(); + } + + public static boolean isInNameReplacementResults(List nameReplacementResults,String name){ + if(nameReplacementResults.isEmpty()) + return false; + return nameReplacementResults.stream().map(r->r.getName()).filter(n->name.equals(n)).findFirst().isPresent(); + } + + public static Optional getConstraintByLeftSide(List allCons, String tph) { + return allCons.stream().filter(c->c.getLeft().equals(tph)).findFirst(); + } + + public static Optional getConstraintByRightSide(List allCons, String tph) { + return allCons.stream().filter(c->c.getRight().equals(tph)).findFirst(); + } + + public static boolean isTPHInGenericGeneratorResult(final List constraints, final String tph) { + return constraints.stream().filter(g->g.getConstraint().getLeft().equals(tph)).findFirst().isPresent(); + } + + /** + * @param allCons + * @param tphsMethod + * @param tphsClass + * @param visitedTPHs + * @param tph + * @return + */ + public static LinkedList createLinkedListForTPHsInRelation(final List allCons, + List tphsMethod, List tphsClass, final Set visitedTPHs, String tph) { + + final LinkedList tphsInRel = new LinkedList<>(); + List tphsList = new ArrayList<>(tphsMethod); + tphsList.addAll(tphsClass); + + boolean isNextSuperTypeFound = findNextSuperTyp(allCons,tphsList ,visitedTPHs, tph, tphsInRel); + if(!isNextSuperTypeFound) + findNextSubType(allCons, tphsList,visitedTPHs, tph, tphsInRel); + return tphsInRel; + } + + public static boolean findNextSubType(List allCons, List tphsList, Set visitedTPHs, String tph, + LinkedList tphsInRel) { + Optional con = getConstraintByRightSide(allCons, tph); + while (con.isPresent()) { + String left = con.get().getLeft(); + String right = con.get().getRight(); + + addTPHsToListFromLeft(tphsInRel, left, right); + markAsVisited(visitedTPHs, left); + + if(tphsList.contains(left)) + return true; + + con = getConstraintByRightSide(allCons, left); + } + return false; + } + + public static void addTPHsToListFromLeft(LinkedList tphsInRel, String left, String right) { + if (tphsInRel.isEmpty()) + tphsInRel.add(right); + + tphsInRel.addFirst(left); + } + + /** + * @param allCons + * @param tphsList + * @param visitedTPHs + * @param tph + * @param tphsInRel + * @return + */ + public static boolean findNextSuperTyp(final List allCons, List tphsList, final Set visitedTPHs, String tph, + final LinkedList tphsInRel) { + Optional con = getConstraintByLeftSide(allCons, tph); + + markAsVisited(visitedTPHs, tph); + + while (con.isPresent()) { + String left = con.get().getLeft(); + String right = con.get().getRight(); + addTPHsToList(tphsInRel, left, right); + + if(tphsList.contains(right)) + return true; + + markAsVisited(visitedTPHs, right); + + con = getConstraintByLeftSide(allCons, right); + } + return false; + } + + public static void markAsVisited(Set visitedTPHs, String left) { + visitedTPHs.add(left); + } + + /** + * @param visitedTPHs + * @param right + * @param left + */ + public static void markAsVisited(final Set visitedTPHs, String left, String right) { + visitedTPHs.add(left); + visitedTPHs.add(right); + } + + /** + * @param tphsInRel + * @param right + * @param left + */ + public static void addTPHsToList(final LinkedList tphsInRel, String left, String right) { + if (tphsInRel.isEmpty()) + tphsInRel.add(left); + tphsInRel.add(right); + } + + public static void removeNotLocalTphs(final LinkedList tphsInRel, final List localTphs, + List tphsClass) { + + while (!localTphs.contains(tphsInRel.peek())) { + tphsInRel.removeFirst(); + } + + String last = tphsInRel.peekLast(); + while (!localTphs.contains(last) && !tphsClass.contains(last)) { + tphsInRel.removeLast(); + last = tphsInRel.peekLast(); + } + } + + /** + * @param nameReplacementResults + * @param subType + * @return + */ + public static Set createEqualSet(final List nameReplacementResults, String subType) { + Optional equals = nameReplacementResults.stream() + .filter(n -> n.getName().equals(subType)).findFirst(); + + Set equalSet = equals.isPresent() ? new HashSet<>(equals.get().getOldNames()) : new HashSet<>(); + return equalSet; + } + + public static String getNextClassTph(List tphsClass, LinkedList tphsInRel) { + + for(int i = 1;i constraints, final List tphsClass) { + + List lefts = constraints.stream().map(r->r.getConstraint()).map(c->c.getLeft()).collect(Collectors.toList()); + List rights = constraints.stream().map(r->r.getConstraint()).map(c->c.getRight()).collect(Collectors.toList()); + List leftsAndRights = new ArrayList<>(lefts); + leftsAndRights.addAll(rights); + List shouldBeClassTphs = leftsAndRights.stream().distinct().collect(Collectors.toList()); + + for(String tph : shouldBeClassTphs) { + if(!tphsClass.contains(tph)) + tphsClass.add(tph); + } + } + + public static void removeClassTPHsFromMethodTPHs(List tphsClass, TPHExtractor tphExtractor) { + + tphExtractor.ListOfMethodsAndTph.stream().map(m->m.getTphs()).forEach(tphs->{ + tphs.removeAll(tphsClass); + }); + + tphExtractor.ListOfMethodsAndTph.stream().map(m->m.getLocalTphs()).forEach(tphs->{ + tphs.removeAll(tphsClass); + }); + + } + + public static LinkedList createLinkedListForTPHsInRelationClass(List allCons, + List tphsClass, List methodTPHs, Set visitedTPHs, String tph) { + final LinkedList tphsInRel = new LinkedList<>(); + + boolean isNextSuperTypeFound = findNextSuperTyp(allCons,tphsClass ,visitedTPHs, tph, tphsInRel); + if(!tphsInRel.isEmpty() && !isNextSuperTypeFound && !methodTPHs.contains(tphsInRel.getLast())) + findNextSubType(allCons, tphsClass,visitedTPHs, tph, tphsInRel); + return tphsInRel; + } + + public static boolean isInResult(String first, List constraints) { + return constraints.stream().map(r->r.getConstraint()).filter(c->c.getLeft().equals(first)).findFirst().isPresent(); + } + + public static Optional getGenericGeneratorResult(List list, + String tph) { + return list.stream().filter(g->g.getConstraint().getLeft().equals(tph)).findFirst(); + } + + public static void removeGenericGeneratorResult(List genericsGenResults, + GenericsGeneratorResult ggResult) { + genericsGenResults.remove(ggResult); + } + + public static Optional getMethodAndTphs(ArrayList listOfMethodsAndTph, String id) { + return listOfMethodsAndTph.stream().filter(m->m.getId().equals(id)).findFirst(); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGeneratorTypes/ConstraintsWithSameLeftSide.java b/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGeneratorTypes/ConstraintsWithSameLeftSide.java new file mode 100644 index 00000000..1b184048 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGeneratorTypes/ConstraintsWithSameLeftSide.java @@ -0,0 +1,35 @@ +package de.dhbwstuttgart.bytecode.genericsGeneratorTypes; + +import java.util.List; + +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; + +public class ConstraintsWithSameLeftSide { + private List constraints; + + /** + * @param constraints + */ + public ConstraintsWithSameLeftSide(List constraints) { + this.constraints = constraints; + } + + /** + * @return the constraints + */ + public List getConstraints() { + return constraints; + } + + /** + * @param constraints the constraints to set + */ + public void setConstraints(List constraints) { + this.constraints = constraints; + } + + @Override + public String toString() { + return "[" + constraints.toString() + "]"; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGeneratorTypes/Cycle.java b/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGeneratorTypes/Cycle.java new file mode 100644 index 00000000..ff6521d8 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGeneratorTypes/Cycle.java @@ -0,0 +1,46 @@ +/** + * + */ +package de.dhbwstuttgart.bytecode.genericsGeneratorTypes; + +import java.util.List; + +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; + +/** + * @author fayez + * + */ +public class Cycle { + private final List constraints; + + /** + * @param constraints + */ + public Cycle(List constraints) { + this.constraints = constraints; + } + + /** + * @return the constraints + */ + public List getConstraints() { + return constraints; + } + + public boolean containConstraint(TPHConstraint constraint) { + for(TPHConstraint c : constraints) { + if(c.equalConstraint(constraint)) + return true; + } + return false; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + constraints.forEach(c->sb.append(c.getLeft()+" -> ")); + sb.append(constraints.get(constraints.size()-1).getRight()); + return sb.toString(); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGeneratorTypes/GenericGeneratorResultsForAllMethods.java b/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGeneratorTypes/GenericGeneratorResultsForAllMethods.java new file mode 100644 index 00000000..091587ff --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGeneratorTypes/GenericGeneratorResultsForAllMethods.java @@ -0,0 +1,41 @@ +/** + * + */ +package de.dhbwstuttgart.bytecode.genericsGeneratorTypes; + +import java.util.Collections; +import java.util.List; + +/** + * @author fayez + * + */ +public class GenericGeneratorResultsForAllMethods { + private final List methodsAndConstraints; + + public GenericGeneratorResultsForAllMethods() { + this(Collections.emptyList()); + } + /** + * @param methodsAndConstraints + */ + public GenericGeneratorResultsForAllMethods(List methodsAndConstraints) { + this.methodsAndConstraints = methodsAndConstraints; + } + + /** + * @return the methodsAndConstraints + */ + public List getMethodsAndConstraints() { + return methodsAndConstraints; + } + + @Override + public String toString() { + String ret = ""; + ret = ret + methodsAndConstraints.stream().reduce("", (x,y) -> x + y.toString(), (x,y) -> x + y); + //ret = ret + "\n"; + return ret; + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGeneratorTypes/GenericGenratorResultForSourceFile.java b/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGeneratorTypes/GenericGenratorResultForSourceFile.java new file mode 100644 index 00000000..3bcf1939 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGeneratorTypes/GenericGenratorResultForSourceFile.java @@ -0,0 +1,52 @@ +/** + * + */ +package de.dhbwstuttgart.bytecode.genericsGeneratorTypes; + +import de.dhbwstuttgart.parser.scope.JavaClassName; + +import java.util.ArrayList; +import java.util.List; +import java.util.NoSuchElementException; + +/** + * The simplify results of a source file (package) + * + * @author fayez + * + */ +public class GenericGenratorResultForSourceFile { + private String pkgName; + private final List genericGeneratorResultForAllClasses = new ArrayList<>(); + + /** + * @param pkgName + */ + public GenericGenratorResultForSourceFile(String pkgName) { + this.pkgName = pkgName; + } + + public List getGenericGeneratorResultForAllClasses() { + return genericGeneratorResultForAllClasses; + } + + /** + * Appends the simplify results of a class to simplifyResForSF + * + * @param sResClass simplify results of a class to added + */ + public void addGenericGeneratorResultClass(GenericsGeneratorResultForClass sResClass) { + genericGeneratorResultForAllClasses.add(sResClass); + } + + public GenericsGeneratorResultForClass getSimplifyResultsByName(JavaClassName name) { + + if (this.pkgName.equals(name.getPackageName())) { + return genericGeneratorResultForAllClasses.stream() + .filter(sr -> sr.getClassName().equals(name)) + .findAny() + .orElse(new GenericsGeneratorResultForClass(name)); + } + return new GenericsGeneratorResultForClass(name); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGeneratorTypes/GenericsGeneratorResult.java b/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGeneratorTypes/GenericsGeneratorResult.java new file mode 100644 index 00000000..fe23f239 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGeneratorTypes/GenericsGeneratorResult.java @@ -0,0 +1,59 @@ +/** + * + */ +package de.dhbwstuttgart.bytecode.genericsGeneratorTypes; + +import java.util.Set; + +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; + +/** + * @author fayez + * + */ +public class GenericsGeneratorResult { + private TPHConstraint constraint; + /** + * contains the names of all type placeholders which are equals to the left side of + * the constraint {@link #constraint}. + */ + private Set equalsTPHs; + /** + * @param constraint + * @param equalsTPHs + */ + public GenericsGeneratorResult(TPHConstraint constraint, Set equalsTPHs) { + this.constraint = constraint; + this.equalsTPHs = equalsTPHs; + } + + /** + * @return the constraint + */ + public TPHConstraint getConstraint() { + return constraint; + } + /** + * @param constraint the constraint to set + */ + public void setConstraint(TPHConstraint constraint) { + this.constraint = constraint; + } + /** + * @return the equalsTPHs + */ + public Set getEqualsTPHs() { + return equalsTPHs; + } + /** + * @param equalsTPHs the equalsTPHs to set + */ + public void setEqualsTPHs(Set equalsTPHs) { + this.equalsTPHs = equalsTPHs; + } + + @Override + public String toString() { + return constraint.toString() + " EqualsTPS: " + equalsTPHs.toString(); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGeneratorTypes/GenericsGeneratorResultForClass.java b/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGeneratorTypes/GenericsGeneratorResultForClass.java new file mode 100644 index 00000000..0a3626d2 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGeneratorTypes/GenericsGeneratorResultForClass.java @@ -0,0 +1,84 @@ +/** + * + */ +package de.dhbwstuttgart.bytecode.genericsGeneratorTypes; + +import de.dhbwstuttgart.parser.scope.JavaClassName; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import com.google.common.collect.Lists; + +/** + * @author fayez + * + */ +public class GenericsGeneratorResultForClass { + private final JavaClassName className; + private final List classConstraints; + private final GenericGeneratorResultsForAllMethods methodsAndTheirConstraints; + + public GenericsGeneratorResultForClass(JavaClassName className) { + this(className, Collections.emptyList(), new GenericGeneratorResultsForAllMethods()); + } + /** + * @param className + * @param classConstraints + * @param methodsAndTheirConstraints + */ + public GenericsGeneratorResultForClass(JavaClassName className, List classConstraints, + GenericGeneratorResultsForAllMethods methodsAndTheirConstraints) { + this.className = className; + this.classConstraints = classConstraints; + this.methodsAndTheirConstraints = methodsAndTheirConstraints; + } + + /** + * @return the className + */ + public JavaClassName getClassName() { + return className; + } + + /** + * @return the classConstraints + */ + public List getClassConstraints() { + return classConstraints; + } + + /** + * @return the methodsAndTheirConstraints + */ + public GenericGeneratorResultsForAllMethods getMethodsAndTheirConstraints() { + return methodsAndTheirConstraints; + } + + public boolean contains(String id) { + return methodsAndTheirConstraints.getMethodsAndConstraints().stream().map(mc -> mc.getMethodID()) + .anyMatch(i -> i.equals(id)); + } + + public List getMethodConstraintsByID(String id) { + Optional methodConstraints = methodsAndTheirConstraints.getMethodsAndConstraints() + .stream() + .filter(mc -> mc.getMethodID().equals(id)) + .findFirst(); + + if (methodConstraints.isPresent()) { + return methodConstraints.get().getConstraints(); + } else { + return Collections.emptyList(); + } + } + + @Override + public String toString() { + String ret = "Classconstraints: "; + ret = ret + classConstraints.stream().reduce("", (x,y) -> x + y.toString(), (x,y) -> x + y); + ret = ret + "\n" + methodsAndTheirConstraints.toString(); + return ret; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGeneratorTypes/MethodAndConstraints.java b/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGeneratorTypes/MethodAndConstraints.java new file mode 100644 index 00000000..bf582707 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGeneratorTypes/MethodAndConstraints.java @@ -0,0 +1,46 @@ +/** + * + */ +package de.dhbwstuttgart.bytecode.genericsGeneratorTypes; + +import java.util.List; + +/** + * @author fayez + * + */ +public class MethodAndConstraints { + private final String methodID; + private final List constraints; + /** + * @param methodID + * @param constraints + */ + public MethodAndConstraints(String methodID, List constraints) { + this.methodID = methodID; + this.constraints = constraints; + } + /** + * @return the methodID + */ + public String getMethodID() { + return methodID; + } + /** + * @return the constraints + */ + public List getConstraints() { + return constraints; + } + + + @Override + public String toString() { + String ret = methodID + ": "; + ret = ret + constraints.stream().reduce("", + (x,y) -> x + y.toString(), + (x,y) -> x + y); + ret = ret + "\n"; + return ret; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGeneratorTypes/NameReplacementResult.java b/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGeneratorTypes/NameReplacementResult.java new file mode 100644 index 00000000..4a91655e --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/genericsGeneratorTypes/NameReplacementResult.java @@ -0,0 +1,49 @@ +/** + * + */ +package de.dhbwstuttgart.bytecode.genericsGeneratorTypes; + +import java.util.List; + +/** + * @author fayez + * + */ +public class NameReplacementResult { + private String name; + private List oldNames; + /** + * @param name + * @param oldNames + */ + public NameReplacementResult(String name, List oldNames) { + this.name = name; + this.oldNames = oldNames; + } + /** + * @return the name + */ + public String getName() { + return name; + } + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + /** + * @return the oldNames + */ + public List getOldNames() { + return oldNames; + } + /** + * @param oldNames the oldNames to set + */ + public void setOldNames(List oldNames) { + this.oldNames = oldNames; + }; + + +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/insertGenerics/ClassConstraint.java b/app/src/main/java/de/dhbwstuttgart/bytecode/insertGenerics/ClassConstraint.java new file mode 100644 index 00000000..130f0ac6 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/insertGenerics/ClassConstraint.java @@ -0,0 +1,16 @@ +package de.dhbwstuttgart.bytecode.insertGenerics; + +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; + +public class ClassConstraint extends TPHConstraint { + //private TPHConstraint constraint; + + public ClassConstraint(String left, String right, Relation rel) { + super(left, right, rel); + } + //besser? + /*public ClassConstraint(TPHConstraint constraint) { + this.constraint = constraint; + }*/ +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/insertGenerics/FamilyOfGeneratedGenerics.java b/app/src/main/java/de/dhbwstuttgart/bytecode/insertGenerics/FamilyOfGeneratedGenerics.java new file mode 100644 index 00000000..ed46e816 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/insertGenerics/FamilyOfGeneratedGenerics.java @@ -0,0 +1,880 @@ +package de.dhbwstuttgart.bytecode.insertGenerics; + +import de.dhbwstuttgart.bytecode.TPHExtractor; +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; +import de.dhbwstuttgart.bytecode.utilities.MethodAndTPH; + +import java.util.*; +import java.util.function.Predicate; + +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.constraints.Constraint; +import de.dhbwstuttgart.typeinference.constraints.Pair; +import de.dhbwstuttgart.typeinference.result.ResultPair; +import de.dhbwstuttgart.typeinference.result.ResultSet; +import de.dhbwstuttgart.typeinference.unify.model.PairOperator; +import org.objectweb.asm.Type; + +public class FamilyOfGeneratedGenerics { + public List allConstraints = new ArrayList<>(); + // HashMap speichert ob TPH in einer Methode oder in der Klasse ist; und wenn es in der Methode ist, in welcher Methode + public HashMap>> posOfTPHs = new HashMap<>(); + public List classConstraints = new ArrayList<>(); + private HashMap mapMethodsAndTph = new HashMap<>(); + public List methodConstraints = new ArrayList<>(); + public HashMap> methodConstraintsWithPosition = new HashMap<>(); + public ResultSet resSet; + public Set oldCons = new HashSet<>(); + + private static final String objectType = Type.getInternalName(Object.class); + + public FamilyOfGeneratedGenerics(TPHExtractor tphExtractor, ResultSet resultSet) { + this.resSet = resultSet; + this.oldCons = tphExtractor.oldConstraints; + this.allConstraints = tphExtractor.allCons; + this.posOfTPHs = positionConverter(tphExtractor.allTPHS, tphExtractor.ListOfMethodsAndTph); + this.classConstraints = getClassConstraints(allConstraints,posOfTPHs); + tphExtractor.ListOfMethodsAndTph.forEach(matph -> this.mapMethodsAndTph.put(matph.getId(), matph)); + this.methodConstraints = getMethodConstraints(allConstraints,classConstraints,posOfTPHs, tphExtractor.ListOfMethodsAndTph); + this.methodConstraintsWithPosition = getMethodConstraintsWithPositionNew(allConstraints,classConstraints,posOfTPHs, tphExtractor.ListOfMethodsAndTph, resSet, oldCons); + } + + public static List getClassConstraints(List cs, HashMap>> posOfTphs) { //Inputparameter List constraintsSet weg + List cs_cl = new ArrayList<>(); + List classConstraints1 = typeOfANodeOfAField(cs, posOfTphs); + for (ClassConstraint cons: classConstraints1) { + if (!checkForDuplicates(cons, cs_cl)) { + cs_cl.add(cons); + } + } + + // if sth new is added to cs_cl, then do same step again + boolean addedToConstraintsListForCC2 = false; + do { + addedToConstraintsListForCC2 = false; + List classConstraints2 = transitiveSubtypeForClassTypes(cs, cs_cl); // in Klammer classConstraints1 oder constraintsSet? beides eher + for (ClassConstraint cons: classConstraints2) { + if (!checkForDuplicates(cons, cs_cl)) { + cs_cl.add(cons); + addedToConstraintsListForCC2 = true; + } + } + } while (addedToConstraintsListForCC2); + + List classConstraints3 = hasNoSupertypeForClassTypes(cs_cl, posOfTphs); + for (ClassConstraint cons: classConstraints3) { + if (!checkForDuplicates(cons, cs_cl)) { + cs_cl.add(cons); + } + } + return cs_cl; + } + + public List getMethodConstraints(List cs, List cs_cl, HashMap>> posOfTphs, List listOfMethodsAndTph) { + List cs_m = new ArrayList<>(); + List methodConstraints1 = typeOfTheMethodInClSigma(cs, posOfTphs); + for (MethodConstraint cons: methodConstraints1) { + if (!checkForDuplicates(cons, cs_m)) { + cs_m.add(cons); + } + } + + // if sth new is added to cs_cl, then do same step again + boolean addedToConstraintsListForMC2 = false; + do { + addedToConstraintsListForMC2 = false; + List methodConstraints2 = firstTransitiveSubtypeForMethodTypes(cs, cs_m); + for (MethodConstraint cons : methodConstraints2) { + if (!checkForDuplicates(cons, cs_m)) { + cs_m.add(cons); + addedToConstraintsListForMC2 = true; + } + } + } while (addedToConstraintsListForMC2); + + // if sth new is added to cs_cl, then do same step again + boolean addedToConstraintsListForMC3 = false; + do { + addedToConstraintsListForMC3 = false; + List methodConstraints3 = secondTransitiveSubtypeForMethodTypes(cs, cs_cl, cs_m); + for (MethodConstraint cons : methodConstraints3) { + if (!checkForDuplicates(cons, cs_m)) { + cs_m.add(cons); + addedToConstraintsListForMC3 = true; + } + } + } while (addedToConstraintsListForMC3); + List methodConstraints4 = hasNoSupertypeForMethodTypes(cs, cs_m, posOfTphs, listOfMethodsAndTph); + for (MethodConstraint cons: methodConstraints4) { + if (!checkForDuplicates(cons, cs_m)) { + cs_m.add(cons); + } + } + List methodConstraints5 = methodTypesWithoutClassTypes(cs_cl, cs_m); + cs_m = methodConstraints5; + return cs_m; + } + + public HashMap> getMethodConstraintsWithPosition(List cs, List cs_cl, HashMap>> posOfTphs, List listOfMethodsAndTph, ResultSet resSet, Set oldCons) { + HashMap> tempMethodConstraintsWithPosition = new HashMap<>(); + for(MethodAndTPH method: listOfMethodsAndTph){ + List methodsAddedToHashMap = new ArrayList<>(); + String currentMethod = method.getId(); + boolean containsCurrentMethod = false; + if(!containsCurrentMethod) { + methodsAddedToHashMap.add(currentMethod); + containsCurrentMethod = true; + List listOfThisMethod = new ArrayList<>(); + HashMap>> posOfTPHsForThisMethod = new HashMap<>(); + for(String s: posOfTphs.keySet()) { + for(PairTphMethod pair: posOfTphs.get(s)) { + if(pair.snd == currentMethod && pair.snd != null) { + posOfTPHsForThisMethod.put(s,posOfTphs.get(s)); + } + } + } + listOfThisMethod = getMethodConstraints(cs,cs_cl,posOfTPHsForThisMethod,listOfMethodsAndTph); + tempMethodConstraintsWithPosition.put(currentMethod, listOfThisMethod); + + List newMCList = firstLineMethodDefinition(cs, posOfTphs, method, resSet); + List newMCList2 = secondLineMethodDefinition(cs, posOfTphs, method, resSet, oldCons); + System.out.println(newMCList); + System.out.println(newMCList2); + } + } + + for(String curMeth: tempMethodConstraintsWithPosition.keySet()){ + for(int i=0; i tempList = new ArrayList<>(list); + for(TPHConstraint tphC: tempList) { + if(tph == tphC.getLeft()) { + return true; + } + } + return false; + } + + /** + * Def. FGG: erste Zeile von cs_cl + * {T < .T' | T is a type variable in a type of a node of a field} + */ + public static List typeOfANodeOfAField(List allConstraints, HashMap>> posOfTphs) { + //RuntimeException re = new RuntimeException("enthält EQUALS-Relation"); + List tempCC = new ArrayList<>(); + for(TPHConstraint allCons: allConstraints){ + if(posOfTphs.containsKey(allCons.getLeft()) && allCons.getRight()!=null && allCons.getRel()==Relation.EXTENDS) { + for(String tph: posOfTphs.keySet()) { + for(PairTphMethod pair: posOfTphs.get(tph)) { + if(tph == allCons.getLeft() && pair.fst == PositionFinder.Position.FIELD) { + ClassConstraint consToAdd = new ClassConstraint(tph, allCons.getRight(), allCons.getRel()); + if (!checkForDuplicates(consToAdd, tempCC)) { + tempCC.add(consToAdd); + } + /*}else if(pair.fst == PositionFinder.Position.FIELD){ + ClassConstraint consToAdd = new ClassConstraint(tph, objectType, Relation.EXTENDS); + if (!checkForDuplicates(consToAdd, tempCC)) { + tempCC.add(consToAdd); + }*/ + } + } + } + } + /*else if (allCons.getRel() != Relation.EXTENDS) { + throw re; + }*/ + } + return tempCC; + } + + /** + * Def. FGG: zweite Zeile von cs_cl + * {T' <. T'' | \exists T: (T <. T') \in cs_cl, (T' <. T'') \in cs } + */ + public static List transitiveSubtypeForClassTypes(List allConstraints, List cs_cl) { + List tempCC = new ArrayList<>(); + ClassConstraint consToAdd; + for(ClassConstraint cCons: cs_cl) { + if(cCons.getLeft() != null && cCons.getRel()==Relation.EXTENDS) { + for(TPHConstraint allCons: allConstraints) { + if(cCons.getRight() == allCons.getLeft() && allCons.getRight() != null && allCons.getRel()==Relation.EXTENDS){ + consToAdd = new ClassConstraint(allCons.getLeft(), allCons.getRight(), allCons.getRel()); + if (!checkForDuplicates(consToAdd, tempCC)) { + tempCC.add(consToAdd); + } + } + } + } + } + return tempCC; + } + + /** + * Def. FGG: dritte Zeile von cs_cl + * {T <. Object | ((T is a type variable in a type of a node of a field + * or (\exists T~: (T~ <. T) \in cs_cl)) and (\existsnot T': T <. T') \in cs)} + */ + public static List hasNoSupertypeForClassTypes(List cs_cl, HashMap>> posOfTphs) { + List tempCC= new ArrayList<>(); + List clCons = new ArrayList<>(cs_cl); + for(String tph: posOfTphs.keySet()) { + for(PairTphMethod pair: posOfTphs.get(tph)) { + boolean tvInField = pair.fst == PositionFinder.Position.FIELD; + boolean hasSmallerTVInClCons = hasSmallerTVInClCons(tph, cs_cl); + if ((tvInField || hasSmallerTVInClCons) && + !checkUpperBound(clCons, tph)) { + ClassConstraint consToAdd = new ClassConstraint(tph, objectType, Relation.EXTENDS); + if (!checkForDuplicates(consToAdd, tempCC)) { + tempCC.add(consToAdd); + } + } + } + } + return tempCC; + } + + public static boolean hasSmallerTVInClCons(String tph, List cs_cl) { + for(ClassConstraint cC: cs_cl) { + if(tph == cC.getRight() && cC.getRel() == Relation.EXTENDS) { + return true; + } + } + return false; + } + + /** + * Def. FGG: erste Zeile von cs_m + * {T < .T' | T is a type variable in a type of the method/constructor m in cl_\sigma, (T <. T') \in cs} + */ + public static List typeOfTheMethodInClSigma(List allConstraints, HashMap>> posOfTphs) { // cl_\sigma?? + //TODO: + List tempMC= new ArrayList<>(); + for(TPHConstraint allCons: allConstraints){ + if(posOfTphs.containsKey(allCons.getLeft()) && allCons.getRight()!=null && allCons.getRel()==Relation.EXTENDS) { + for(String tph: posOfTphs.keySet()) { + for(PairTphMethod pair: posOfTphs.get(tph)) { + if(tph == allCons.getLeft() && (pair.fst == PositionFinder.Position.METHOD || pair.fst == PositionFinder.Position.CONSTRUCTOR)) { + MethodConstraint consToAdd = new MethodConstraint(allCons.getLeft(), allCons.getRight(), allCons.getRel()); + if (!checkForDuplicates(consToAdd, tempMC)) { + tempMC.add(consToAdd); + } + } + } + } + } + } + return tempMC; + } + + + /** + * Def. FGG: zweite Zeile von cs_m + * {R' <. S | (R <. R'), (S <. S') \in cs_m and (R',S) is in the transitive closure of cs} + */ + public List firstTransitiveSubtypeForMethodTypes(List allConstraints, List cs_m) { //transitive closure of cs + //TODO: + List tempMC= new ArrayList<>(); + List tcOfCs = buildTransitiveClosure(allConstraints); + for(MethodConstraint mC1 : cs_m) { //(R <. R') + for(MethodConstraint mC2 : cs_m) { //(S <. S') + String lSide = mC1.getRight(); //R' + String rSide = mC2.getLeft(); //S + for(TPHConstraint tphC : tcOfCs) { + if(tphC.getLeft().equals(lSide)&&tphC.getRight().equals(rSide)) { //is it (R',S) + MethodConstraint consToAdd = new MethodConstraint(lSide, rSide, tphC.getRel()); //create (R'<.S) + if (!checkForDuplicates(consToAdd, tempMC)) { + tempMC.add(consToAdd); + } + } + } + } + } + return tempMC; + } + + /** + * Def. FGG: dritte Zeile von cs_m + * {R' <. S | (R <. R') \in cs_m, (S <. S') \in cs_cl and (R',S) is in the transitive closure of cs} + */ + public List secondTransitiveSubtypeForMethodTypes(List allConstraints, List cs_cl, List cs_m) { + //TODO: + List tempMC= new ArrayList<>(); + List tcOfCs = buildTransitiveClosure(allConstraints); + for(ClassConstraint cC : cs_cl) { + for(MethodConstraint mC : cs_m) { + String leftSide = mC.getRight(); + String rightSide = cC.getLeft(); + for(TPHConstraint tphC : tcOfCs) { + if(tphC.getLeft().equals(leftSide)&&tphC.getRight().equals(rightSide)) { + MethodConstraint consToAdd = new MethodConstraint(tphC.getLeft(), tphC.getRight(), tphC.getRel()); + if (!checkForDuplicates(consToAdd, tempMC)) { + tempMC.add(consToAdd); + } + + } + } + } + } + return tempMC; + } + +/** + * Def. FGG: vierte Zeile von cs_m + * {T <. Object | (T is a type variable in a type of a node of the method/constructor m in cl_\sigma), + * (\existsnot T': T <. T') \in cs)} + */ + public static List hasNoSupertypeForMethodTypes(List allConstraints, List cs_m, HashMap>> posOfTphs, List listOfMethodsAndTph) { + //TODO: + List tempMC= new ArrayList<>(); + for(String tph: posOfTphs.keySet()) { + for(PairTphMethod pair: posOfTphs.get(tph)) { + for(TPHConstraint allCons: allConstraints) { + if((pair.fst.equals(PositionFinder.Position.METHOD) || pair.fst.equals(PositionFinder.Position.CONSTRUCTOR)) && !checkUpperBound(allConstraints,tph)) { + MethodConstraint consToAdd = new MethodConstraint(tph, objectType, Relation.EXTENDS); + if (!checkForDuplicates(consToAdd, tempMC)) { + tempMC.add(consToAdd); + } + } + } + List tempMCObject1 = new ArrayList<>(cs_m); + String currentMethod = ""; + for(MethodAndTPH mat: listOfMethodsAndTph) { + if(mat.getId().equals(pair.snd)) { + currentMethod = mat.getId(); + } + for(TPHConstraint mc1: tempMCObject1) { + if(tph==mc1.getRight() && !checkUpperBound(tempMCObject1,tph)) { + MethodConstraint consToAdd = new MethodConstraint(tph, objectType, Relation.EXTENDS); + if (!checkForDuplicates(consToAdd, tempMC)) { + tempMC.add(consToAdd); + } + } + } + } + } + } + return tempMC; + } + +/** + * nimm die Menge cs_cl aus cs_m raus + */ + public List methodTypesWithoutClassTypes(List cs_cl, List cs_m) { + // erstelle Kopie der Liste cs_cl + List tempCC = new ArrayList<>(); + for(ClassConstraint cc: cs_cl) { + TPHConstraint tphC = new TPHConstraint(cc.getLeft(), cc.getRight(), cc.getRel()); + tempCC.add(tphC); + } + // Transitive Hülle von cs_cl + List tcOfCsCl = buildTransitiveClosure(tempCC); + + List tempMC = new ArrayList<>(); + for(MethodConstraint mc: cs_m) { + TPHConstraint tphC = new TPHConstraint(mc.getLeft(), mc.getRight(), mc.getRel()); + tempMC.add(tphC); + } + List tempMC2 = new ArrayList<>(); + tempMC2.addAll(tempMC); + List tempMCToReturn = new ArrayList<>(); + + for(TPHConstraint cc: tcOfCsCl) { + for(TPHConstraint mc: tempMC) { + if(cc.getLeft().equals(mc.getLeft()) && cc.getRight().equals(mc.getRight())) { + tempMC2.remove(mc); + } + } + } + for(TPHConstraint tphC: tempMC2) { + MethodConstraint mCons = new MethodConstraint(tphC.getLeft(), tphC.getRight(), tphC.getRel()); + tempMCToReturn.add(mCons); + } + return tempMCToReturn; + } + + public static boolean checkForDuplicates(TPHConstraint constraint, List list) { + List tempList = list; + boolean hasSame = false; + for (TPHConstraint tphC: tempList) { + hasSame = constraint.getLeft() == tphC.getLeft() && + constraint.getRight() == tphC.getRight() && + constraint.getRel() == tphC.getRel(); //constraint already in ArrayList if true + if (hasSame) + return true; + } + return false; + } + + public List buildTransitiveClosure(List list) { + List iterList = new ArrayList<>(list); + List runList = new ArrayList<>(list); + List tcList = new ArrayList<>(list); + boolean addedConToList = false; + for (TPHConstraint cons: iterList) { + for (TPHConstraint cons2: runList) { + if(cons.getRight() == cons2.getLeft()) { + TPHConstraint consToAdd = new TPHConstraint(cons.getLeft(), cons2.getRight(), Relation.EXTENDS); + if (!checkForDuplicates(consToAdd,tcList)) { + tcList.add(consToAdd); + addedConToList = true; + if (addedConToList) { + return buildTransitiveClosure(tcList); + } + } + } + } + } + return tcList; + } + + public static boolean checkUpperBound(List cs, String tph) { + for(int i=0; i>> positionConverter(HashMap allTphs, List listOfMethodsAndTphs) { + HashMap>> convertedPositions = new HashMap<>(); + for(String tph: allTphs.keySet()) { + List> currMeth = new ArrayList<>(); + if(allTphs.get(tph)) { //if true, then tph is a method-TPH + for(MethodAndTPH methTph: listOfMethodsAndTphs) { + if (methTph.getTphs().contains(tph)) { + currMeth.add(new PairTphMethod<>(PositionFinder.Position.METHOD, methTph.getId())); + } + } + } else { // else it is in the class-TPH + currMeth.add(new PairTphMethod<>(PositionFinder.Position.FIELD, null)); + } + convertedPositions.put(tph, currMeth); + } + return convertedPositions; + } + +/* public PositionFinder.Position positionConverter(TPHExtractor tphExtractor) { + if(tphExtractor.allTPHS.keySet()) + }*/ + + + + + +/* GeneratedGenericsFinder genGenFinder; + ConstraintsSimplierResult simplifiedConstraints = null; + GenericsGeneratorResultForClass ggResult = null; + Method m; + + public void addMethodConstraints(List cs_m) { + genGenFinder.addMethodConstraints(simplifiedConstraints, ggResult, m); + cs_m.add(); + } +*/ + + public static List firstLineMethodDefinition(List allConstraints, HashMap>> posOfTphs, MethodAndTPH methodAndTPH, ResultSet resSet) { + List tempMC= new ArrayList<>(); + MethodAndTPH methAndTphs = methodAndTPH; + Set undCons = methAndTphs.constraints.getUndConstraints(); + List>> orCons = methAndTphs.constraints.getOderConstraints(); + Iterator it = undCons.iterator(); + while(it.hasNext()) { + Pair p = it.next(); + String ta1 = ((TypePlaceholder) (resSet.resolveType(((TypePlaceholder) p.TA1)).resolvedType)).getName(); + String ta2 = ((TypePlaceholder) (resSet.resolveType(((TypePlaceholder) p.TA2)).resolvedType)).getName(); + Relation r = null; + if(p.GetOperator() == PairOperator.SMALLERDOT) { + r = Relation.EXTENDS; + } else if(p.GetOperator() == PairOperator.EQUALSDOT) { + r = Relation.EQUAL; + } + MethodConstraint mc = new MethodConstraint(ta1, ta2, r); + if(mc.getRel() == Relation.EXTENDS) { + if (!mc.getLeft().equals(mc.getRight())) { //eliminieren der Fälle wie AA<.AA + if(!checkForDuplicates(mc, tempMC)) { + tempMC.add(mc); + } + } + } + } + return tempMC; + } + + public List secondLineMethodDefinition(List allConstraints, HashMap>> posOfTphs, MethodAndTPH methodAndTPH, ResultSet resSet, Set oldCons) { + List tempMC = new ArrayList<>(); //für Ergebnisse basierend auf der neuen Datenstruktur (Ali) + Set tempSet = new HashSet<>(); //für Ergebnisse des ersten Teils der Bedinung basierend auf der alten Datenstruktur + Set tempSet2 = new HashSet<>(); //für Ergebnisse des zweiten Teils der Bedingung basierend auf der alten Datenstruktur + Set tcOfoldConsSet = buildTransitiveClosureForCP(oldCons, resSet); + List tcOfCs = buildTransitiveClosure(allConstraints); + MethodAndTPH methAndTphs = methodAndTPH; + Set undCons = methAndTphs.constraints.getUndConstraints(); + List>> orCons = methAndTphs.constraints.getOderConstraints(); + List>> orConsListConverted = new ArrayList<>(); + //gehe die OrConstraints der aktuellen Methode durch und teile nach Operator auf ( + for(int i=0; i orConsWithEQUAL = new ArrayList(); + List orConsWithEXTENDS = new ArrayList(); + HashMap> orConsInternal = new HashMap<>(); + for(Constraint con: orCons.get(i)) { + Iterator it = con.iterator(); + while(it.hasNext()) { + Pair p = it.next(); + Relation r = null; + if(p.GetOperator() == PairOperator.SMALLERDOT) { + r = Relation.EXTENDS; + orConsWithEXTENDS.add(new TPHConstraint(((TypePlaceholder) p.TA1).getName(), ((TypePlaceholder) p.TA2).getName(), r)); + /*MethodConstraint mc = new MethodConstraint(((TypePlaceholder) (resSet.resolveType(((TypePlaceholder) p.TA1)).resolvedType)).getName(), ((TypePlaceholder) (resSet.resolveType(((TypePlaceholder) p.TA2)).resolvedType)).getName(), r); + if(!checkForDuplicates(mc, tempMC)) { + tempMC.add(mc); + }*/ + } else if(p.GetOperator() == PairOperator.EQUALSDOT) { + r = Relation.EQUAL; + orConsWithEQUAL.add(new TPHConstraint(((TypePlaceholder) p.TA1).getName(), ((TypePlaceholder) p.TA2).getName(), r)); + /*MethodConstraint mc = new MethodConstraint(((TypePlaceholder) (resSet.resolveType(((TypePlaceholder) p.TA1)).resolvedType)).getName(), ((TypePlaceholder) (resSet.resolveType(((TypePlaceholder) p.TA2)).resolvedType)).getName(), r); + if(!checkForDuplicates(mc, tempMC)) { + tempMC.add(mc); + }*/ + } + } + } + orConsInternal.put(Relation.EXTENDS, orConsWithEXTENDS); + orConsInternal.put(Relation.EQUAL, orConsWithEQUAL); + orConsListConverted.add(orConsInternal); + } + + // oldCons sind alle Und- und Oder-Constraints + // zunächst in meine Datenstruktur(Ali) konvertieren + List oldConsList = new ArrayList<>(oldCons); + List oldConsListConverted = new ArrayList<>(); + for(Pair pair: oldConsList) { + Relation r = null; + if(pair.GetOperator() == PairOperator.SMALLERDOT) { + r = Relation.EXTENDS; + } else if(pair.GetOperator() == PairOperator.EQUALSDOT) { + r = Relation.EQUAL; + } + oldConsListConverted.add(new TPHConstraint(((TypePlaceholder) pair.TA1).getName(), ((TypePlaceholder) pair.TA2).getName(), r)); + } + + + // Berechnung des zweiten Teils der Bedingung der Regel + for(int i=0; i extendsSet = new Constraint(); + Constraint equalSet = new Constraint(); + //für jede einzelne OrConstraint-Menge gehe durch + for (Constraint con : orCons.get(i)) { + Iterator it = con.iterator(); + while (it.hasNext()) { + Pair p = it.next(); + if (p.OperatorSmallerDot()) { + extendsSet.add(p); + } else if (p.OperatorEqual()) { + equalSet.add(p); + } + } + Iterator itExtends2 = extendsSet.iterator(); + while(itExtends2.hasNext()) { + Pair pairExtends2 = itExtends2.next(); + Set containedVars = new HashSet<>(methodAndTPH.getTphs()); + String pairExtends2RHSName = ((TypePlaceholder)((resSet.resolveType((TypePlaceholder)pairExtends2.TA2)).resolvedType)).getName(); + Iterator itEqual2 = equalSet.iterator(); + while (itEqual2.hasNext()) { + boolean transClo = false; + Pair pairEqual2 = itEqual2.next(); + //TODO: Auf trans.FamilyOfGeneratedGenerics Huelle pruefen + Pair newPairOld = new Pair(pairExtends2.TA2, pairEqual2.TA1); + Pair newPair2 = new Pair(resSet.resolveType((TypePlaceholder) (pairExtends2.TA2)).resolvedType, resSet.resolveType((TypePlaceholder) (pairEqual2.TA1)).resolvedType, PairOperator.SMALLERDOT); + TPHConstraint newPairTPHConstraint = new TPHConstraint(newPair2); + if (tcOfCs.contains(newPairTPHConstraint)|| (newPairTPHConstraint.getLeft().equals(newPairTPHConstraint.getRight()))) { + transClo = true; + } + TypePlaceholder tphR = (TypePlaceholder) pairEqual2.TA2; + Iterator itUndCons = undCons.iterator(); + boolean rEqExRtilde = false; + while (itUndCons.hasNext()) { + Pair pairUndCons2 = itUndCons.next(); + rEqExRtilde = rEqExRtilde || (tphR == pairUndCons2.TA1); + } + boolean isPairInTExTapostrophe = false; + for(Set> scp: orCons) { + Iterator> itSCP = scp.iterator(); + while(itSCP.hasNext()) { + Constraint cp = itSCP.next(); + Iterator itCP = cp.iterator(); + while(itCP.hasNext()) { + Pair p = itCP.next(); + if(p.OperatorSmallerDot()) { + isPairInTExTapostrophe = isPairInTExTapostrophe || tphR.equals(p.TA1); + } + } + } + + } + + if (transClo && (rEqExRtilde || isPairInTExTapostrophe)) { + if (!newPair2.TA1.equals(newPair2.TA2)) { //eliminieren der Fälle wie AA<.AA + if (!checkForDuplicatesForSets(newPair2, tempSet2)) { + tempSet2.add(newPair2); + } + } + if (!checkForDuplicatesForSets(pairExtends2, tempSet2)) { + tempSet2.add(pairExtends2); + } + } + else { + //containedVars.remove(((TypePlaceholder)newPair2.TA2).getName()); + } + + } + + //String key = ((TypePlaceholder)((resSet.resolveType((TypePlaceholder)pairExtends2.TA2)).resolvedType)).getName(); + //TODO: containedVars stimmt noch nicht. Ueberpruefen, ob ggf. mit den containedVars möglicherweise auch die anderen Faelle + // rEqExRtilde isPairInTExTapostrophe abgedeckt sind => ggf. integrieren + /* + posOfTphs.forEach((x,y) -> { + if (y.contains(new PairTphMethod<>(PositionFinder.Position.METHOD, methodAndTPH.getId()))) { + containedVars.add(x); + }; + } + ); + */ + //Referenzbeispiel Put.jav + if (containedVars.stream().filter(v -> tcOfCs.contains(new TPHConstraint(pairExtends2RHSName, v, Relation.EXTENDS))) + .count() > 0) { + System.out.println(); + //tempSet2.add(pairExtends2); + } + if (posOfTphs.containsKey(pairExtends2RHSName)) {//Refrenzbeispiel TestVector.jav + if (posOfTphs.get(pairExtends2RHSName).contains(new PairTphMethod<>(PositionFinder.Position.METHOD, methodAndTPH.getId()))) { + tempSet2.add(pairExtends2); + } + } + } + } + } + + + // aus der alten Datenstruktur in die neue Datenstruktur (von Ali) für ersten Teil + Iterator itTemp = tempSet.iterator(); + while(itTemp.hasNext()) { + Pair p = itTemp.next(); + String ta1 = ((TypePlaceholder) (resSet.resolveType(((TypePlaceholder) p.TA1)).resolvedType)).getName(); + String ta2 = ((TypePlaceholder) (resSet.resolveType(((TypePlaceholder) p.TA2)).resolvedType)).getName(); + Relation r = null; + if(p.GetOperator() == PairOperator.SMALLERDOT) { + r = Relation.EXTENDS; + } else if(p.GetOperator() == PairOperator.EQUALSDOT) { + r = Relation.EQUAL; + } + MethodConstraint mc = new MethodConstraint(ta1, ta2, r); + if(mc.getRel() == Relation.EXTENDS) { + if(!checkForDuplicates(mc, tempMC)) { + tempMC.add(mc); + } + } + } + + // aus der alten Datenstruktur in die neue Datenstruktur (von Ali) für zweiten Teil + Iterator itTemp2 = tempSet2.iterator(); + while(itTemp2.hasNext()) { + Pair p = itTemp2.next(); + String ta1 = ((TypePlaceholder) (resSet.resolveType(((TypePlaceholder) p.TA1)).resolvedType)).getName(); + String ta2 = ((TypePlaceholder) (resSet.resolveType(((TypePlaceholder) p.TA2)).resolvedType)).getName(); + Relation r = null; + if (p.GetOperator() == PairOperator.SMALLERDOT) { + r = Relation.EXTENDS; + } else if (p.GetOperator() == PairOperator.EQUALSDOT) { + r = Relation.EQUAL; + } + for(TPHConstraint tphCons: tcOfCs) {//TODO: hier werden Elemente der Trans. clo herausgenommen, aber die dazugehoerigen OrCons nicht. + if(ta1 == tphCons.getLeft() && ta2 == tphCons.getRight() && r==Relation.EXTENDS) { + MethodConstraint mc = new MethodConstraint(ta1, ta2, r); + if(!checkForDuplicates(mc, tempMC)) { + tempMC.add(mc); + } + } + } + } + + return tempMC; + } + + + public static Set buildTransitiveClosureForCP(Set constraint, ResultSet resSet) { + Set iterSet = new HashSet<>(constraint); + Set runSet = new HashSet<>(constraint); + Set tcSet = new HashSet<>(constraint); + boolean addedConToList = false; +// for (TPHConstraint cons: iterList) { + Iterator itIterSet = iterSet.iterator(); + while(itIterSet.hasNext()) { + Pair pairIterSet = itIterSet.next(); +// for (TPHConstraint cons2: runList) { + Iterator itRunSet = runSet.iterator(); + while (itRunSet.hasNext()) { + Pair pairRunSet = itRunSet.next(); +// if(cons.getRight() == cons2.getLeft()) { + if(pairIterSet.TA2 == pairRunSet.TA1 && pairIterSet.OperatorSmallerDot() && pairRunSet.OperatorSmallerDot()) { +// TPHConstraint consToAdd = new TPHConstraint(cons.getLeft(), cons2.getRight(), Relation.EXTENDS); + Pair p = new Pair(resSet.resolveType((TypePlaceholder)(pairIterSet.TA1)).resolvedType, resSet.resolveType((TypePlaceholder)(pairRunSet.TA2)).resolvedType, PairOperator.SMALLERDOT); +// if (!checkForDuplicates(consToAdd,tcList)) { + if(!checkForDuplicatesForSets(p, tcSet)) { +// tcList.add(consToAdd); + tcSet.add(p); + addedConToList = true; + if (addedConToList) { + return buildTransitiveClosureForCP(tcSet, resSet); + } + } + } + } + } + System.out.println("tcSet: " + tcSet); + return tcSet; + } + + public static boolean checkForDuplicatesForSets(Pair pair, Set set) { + Set tempSet = set; + boolean hasSame = false; +// for (TPHConstraint tphC: tempList) { + Iterator it = tempSet.iterator(); + while (it.hasNext()) { + Pair p = it.next(); +// hasSame = constraint.getLeft() == tphC.getLeft() && +// constraint.getRight() == tphC.getRight() && +// constraint.getRel() == tphC.getRel(); //constraint already in ArrayList if true + hasSame = pair.TA1 == p.TA1 && + pair.TA2 == p.TA2 && + pair.OperatorSmallerDot() && p.OperatorSmallerDot(); //constraint already in Set if true + if (hasSame) + return true; + } + return false; + } + + public static List hasNoSupertypeForMethodTypesNew(HashMap>> posOfTphs, MethodAndTPH methodAndTPH, List cs_m) { + List tempMC = new ArrayList<>(); + List methCons = new ArrayList<>(cs_m); + MethodAndTPH methAndTphs = methodAndTPH; + for(String tph: posOfTphs.keySet()) { + for(int i=0; i methodTypesWithoutClassTypesNEW(List tphsToCompute, List cs_m) { + List tempMC = new ArrayList<>(cs_m); + List tempMC2 = new ArrayList<>(cs_m); + List toRemove = new ArrayList<>(); + for(String tph: tphsToCompute) { + for(TPHConstraint tphCons: tempMC) { + if(tphCons.getLeft() == tph) { + toRemove.add(tphCons.getRight()); + tempMC2.remove(tphCons); + tempMC2 = methodTypesWithoutClassTypesNEW(toRemove,tempMC2); + } + } + } + return tempMC2; + } + + + + public HashMap> getMethodConstraintsWithPositionNew(List cs, List cs_cl, HashMap>> posOfTphs, List listOfMethodsAndTph, ResultSet resSet, Set oldCons) { + HashMap> tempMethodConstraintsWithPosition = new HashMap<>(); + List newMCList = new ArrayList<>(); + List newMCList2 = new ArrayList<>(); + List hasNoSupType = new ArrayList<>(); + List mcWithoutCc = new ArrayList<>(); + + List methodsAddedToHashMap = new ArrayList<>(); + for(MethodAndTPH method: listOfMethodsAndTph){ + String currentMethod = method.getId(); + boolean containsCurrentMethod = false; + if(!containsCurrentMethod) { + methodsAddedToHashMap.add(currentMethod); + containsCurrentMethod = true; + List listToAdd = new ArrayList<>(); + HashMap>> posOfTPHsForThisMethod = new HashMap<>(); + for(String s: posOfTphs.keySet()) { + for(PairTphMethod pair: posOfTphs.get(s)) { + if(pair.snd == currentMethod && pair.snd != null) { + posOfTPHsForThisMethod.put(s,posOfTphs.get(s)); + } + } + } + + newMCList = firstLineMethodDefinition(cs, posOfTphs, method, resSet); + for(int i=0; i tphs = new ArrayList<>(); + for(String tph: posOfTphs.keySet()) { + for (PairTphMethod p : posOfTphs.get(tph)) { + if(p.fst == PositionFinder.Position.FIELD) { + tphs.add(tph); + mcWithoutCc = methodTypesWithoutClassTypesNEW(tphs, listToAdd); + } + } + } + + tempMethodConstraintsWithPosition.put(currentMethod, mcWithoutCc); + } + for(String curMeth: tempMethodConstraintsWithPosition.keySet()){ + for(int i=0; i input = new ArrayList<>(); + List classpath = new ArrayList<>(); + + JavaTXCompiler compiler = new JavaTXCompiler(input, classpath); + compiler.typeInference(); + + public List getResultOfTypeInference() { + return null; + } + + +} +*/ diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/insertGenerics/MethodConstraint.java b/app/src/main/java/de/dhbwstuttgart/bytecode/insertGenerics/MethodConstraint.java new file mode 100644 index 00000000..89533594 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/insertGenerics/MethodConstraint.java @@ -0,0 +1,10 @@ +package de.dhbwstuttgart.bytecode.insertGenerics; + +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; + +public class MethodConstraint extends TPHConstraint { + public MethodConstraint(String left, String right, Relation rel) { + super(left, right, rel); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/insertGenerics/PairMethodAndConstraint.java b/app/src/main/java/de/dhbwstuttgart/bytecode/insertGenerics/PairMethodAndConstraint.java new file mode 100644 index 00000000..c8f44ea6 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/insertGenerics/PairMethodAndConstraint.java @@ -0,0 +1,47 @@ +package de.dhbwstuttgart.bytecode.insertGenerics; + +import java.util.Objects; + +/** A generic class for pairs. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + */ + + +public class PairMethodAndConstraint { + public final A fst; + public final B snd; + + public PairMethodAndConstraint(A fst, B snd) { + this.fst = fst; + this.snd = snd; + } + + public String toString() { + return "PairTphMethod[" + fst + "," + snd + "]"; + } + + public boolean equals(Object other) { + return + other instanceof PairMethodAndConstraint && + Objects.equals(fst, ((PairMethodAndConstraint)other).fst) && + Objects.equals(snd, ((PairMethodAndConstraint)other).snd); + } + + public int hashCode() { + if (fst == null) return (snd == null) ? 0 : snd.hashCode() + 1; + else if (snd == null) return fst.hashCode() + 2; + else return fst.hashCode() * 17 + snd.hashCode(); + } + + public static PairMethodAndConstraint of(A a, B b) { + return new PairMethodAndConstraint<>(a,b); + } + + public PairMethodAndConstraint add(A fst, B snd){ + return new PairMethodAndConstraint<>(fst,snd); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/insertGenerics/PairTphMethod.java b/app/src/main/java/de/dhbwstuttgart/bytecode/insertGenerics/PairTphMethod.java new file mode 100644 index 00000000..75313ba9 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/insertGenerics/PairTphMethod.java @@ -0,0 +1,43 @@ +package de.dhbwstuttgart.bytecode.insertGenerics; + +import java.util.Objects; + +/** A generic class for pairs. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + */ + + +public class PairTphMethod { + public final A fst; + public final B snd; + + public PairTphMethod(A fst, B snd) { + this.fst = fst; + this.snd = snd; + } + + public String toString() { + return "PairTphMethod[" + fst + "," + snd + "]"; + } + + public boolean equals(Object other) { + return + other instanceof PairTphMethod && + Objects.equals(fst, ((PairTphMethod)other).fst) && + Objects.equals(snd, ((PairTphMethod)other).snd); + } + + public int hashCode() { + if (fst == null) return (snd == null) ? 0 : snd.hashCode() + 1; + else if (snd == null) return fst.hashCode() + 2; + else return fst.hashCode() * 17 + snd.hashCode(); + } + + public static PairTphMethod of(A a, B b) { + return new PairTphMethod<>(a,b); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/insertGenerics/PositionFinder.java b/app/src/main/java/de/dhbwstuttgart/bytecode/insertGenerics/PositionFinder.java new file mode 100644 index 00000000..33ecfbc6 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/insertGenerics/PositionFinder.java @@ -0,0 +1,79 @@ +package de.dhbwstuttgart.bytecode.insertGenerics; + +import de.dhbwstuttgart.syntaxtree.*; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; + +import java.util.HashMap; +import java.util.Set; + +public class PositionFinder{ + static HashMap> posOfTphs = new HashMap>(); + + static PairTphMethod whichMethod; // gibt an, in welcher Methode sich TPH befindet (Position.METHOD, id_of_method) + + public enum Position{ + METHOD, + CONSTRUCTOR, + FIELD + } + + public static HashMap> getPositionOfTPH(SourceFile sf, Set tphs) { + + new Walker().visit(sf); + for (String tph: posOfTphs.keySet()) { + System.out.println(tph + " " + posOfTphs.get(tph)); + } + + return null; + } + public static void putPositionInMethod(String tph, String methodId) { + posOfTphs.put(tph, new PairTphMethod<>(Position.METHOD, methodId)); + } + + public static void putPositionInField(String tph) { + posOfTphs.put(tph, new PairTphMethod<>(Position.FIELD, null)); + } + + public static void putPositionInConstructor(String tph, String id) { + posOfTphs.put(tph, new PairTphMethod<>(Position.CONSTRUCTOR, id)); + } + + + + static class Walker extends AbstractASTWalker{ + Boolean inMethod = false; + Boolean inConstructor = false; + + @Override + public void visit(TypePlaceholder tph) { + if (inMethod) { + if (inConstructor) { +// System.out.println(tph); +// putPositionInConstructor(tph.getName(),); + } +// System.out.println(tph); +// putPositionInMethod(tph.getName(),); + } else { + putPositionInField(tph.getName()); + } + } + + @Override + public void visit(Field field) { + super.visit(field); + } + + @Override + public void visit(Method method) { + inMethod = true; + super.visit(method); + } + + @Override + public void visit(Constructor cons) { + inConstructor = true; + super.visit(cons); + } + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/insertGenerics/preGGenerics.java b/app/src/main/java/de/dhbwstuttgart/bytecode/insertGenerics/preGGenerics.java new file mode 100644 index 00000000..088a435b --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/insertGenerics/preGGenerics.java @@ -0,0 +1,9 @@ +package de.dhbwstuttgart.bytecode.insertGenerics; + +import de.dhbwstuttgart.typeinference.result.ResultSet; + +import java.util.List; + +interface preGGenerics { + public List getResultOfTypeInference(); +} \ No newline at end of file diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/signature/Signature.java b/app/src/main/java/de/dhbwstuttgart/bytecode/signature/Signature.java new file mode 100644 index 00000000..47254170 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/signature/Signature.java @@ -0,0 +1,379 @@ +package de.dhbwstuttgart.bytecode.signature; + +import java.util.*; + +import org.objectweb.asm.Type; +import org.objectweb.asm.signature.SignatureVisitor; +import org.objectweb.asm.signature.SignatureWriter; + +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; +import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor; +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericsGeneratorResult; +import de.dhbwstuttgart.syntaxtree.ClassOrInterface; +import de.dhbwstuttgart.syntaxtree.Constructor; +import de.dhbwstuttgart.syntaxtree.GenericTypeVar; +import de.dhbwstuttgart.syntaxtree.Method; +import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType; +import de.dhbwstuttgart.syntaxtree.type.GenericRefType; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.result.ResultSet; + +public class Signature { + private static final char SUPER_CHAR = '-'; + private static final char EXTENDS_CHAR = '+'; + private static final String SPECIAL_CHAR_FOR_FUN = "$$"; + private static final String SPECIAL_CHAR = "$"; + private ClassOrInterface classOrInterface; + private HashMap genericsAndBounds; + private HashMap genericsAndBoundsMethod; + private final SignatureWriter sw = new SignatureWriter();; + private Constructor constructor; + private Method method; + private HashMap methodParamsAndTypes; + private ResultSet resultSet; + private Map> methodConstraints; + private List consClass; + private List constraints; + +// public Signature(ClassOrInterface classOrInterface, HashMap genericsAndBounds, +// List consClass) { +// this.classOrInterface = classOrInterface; +// this.genericsAndBounds = genericsAndBounds; +// this.consClass = consClass; +// sw = new SignatureWriter(); +// createSignatureForClassOrInterface(); +// } + + public Signature(HashMap genericsAndBounds, + HashMap methodParamsAndTypes, ResultSet resultSet, + List constraints) { + //this.constructor = constructor; + this.genericsAndBounds = genericsAndBounds; + this.methodParamsAndTypes = methodParamsAndTypes; + this.resultSet = resultSet; + this.constraints = constraints; + } + + public Signature(int numberOfParams) { + createSignatureForFunN(numberOfParams); + } + + public Signature(int numberOfParams, String to, String[] paramTypes) { + createSignatureForFunN(numberOfParams, to, paramTypes); + } + + public Signature(ClassOrInterface classOrInterface, HashMap genericsAndBounds, + List consClass) { + this.classOrInterface = classOrInterface; + this.genericsAndBounds = genericsAndBounds; + this.consClass = consClass; + } + + public Signature(HashMap genericsAndBoundsMethod, + HashMap genericsAndBounds, + HashMap methodParamsAndTypes, ResultSet resultSet, + List constraints,List consClass) { + this.genericsAndBoundsMethod = genericsAndBoundsMethod; + this.genericsAndBounds = genericsAndBounds; + this.methodParamsAndTypes = methodParamsAndTypes; + this.resultSet = resultSet; + this.constraints = constraints; + this.consClass = consClass; + } + + public String createSignatureForConstructor(Constructor constructor) { + visitParams(); + sw.visitReturnType().visitBaseType('V'); + return sw.toString(); + } + + public String createSignatureForMethod(Method method) { + defineGenerics(method); + + String ret = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToSignature()); + + visitParams(); + visitReturnType(method, ret); + return sw.toString(); + } + + /** + * @param method + * @param ret + */ + private void visitReturnType(Method method, String ret) { + if (ret.equals("V")) { + sw.visitReturnType().visitBaseType('V'); + } else { + RefTypeOrTPHOrWildcardOrGeneric returnType = method.getReturnType(); + SignatureVisitor sv = sw.visitReturnType(); + doVisitParamsOrReturn(returnType, sv); + } + } + + /** + * + */ + private void visitParams() { + for (String paramName : methodParamsAndTypes.keySet()) { + RefTypeOrTPHOrWildcardOrGeneric t = methodParamsAndTypes.get(paramName); + SignatureVisitor sv = sw.visitParameterType(); + doVisitParamsOrReturn(t, sv); + } + } + + /** + * + * @param method + */ + private void defineGenerics(Method method) { + method.getGenerics().forEach(g -> { + visitTypeVarsAndTheirBounds(g, genericsAndBoundsMethod); + }); + defineGenericsFromConstraints(constraints,genericsAndBoundsMethod); + } + + private void createSignatureForFunN(int numberOfParams, String to, String[] paramTypes) { + defineTypeVariablesForParametersOfFunN(numberOfParams); + + sw.visitFormalTypeParameter("R"); + visitClassBound(to); + // TODO: prüfe ob Return-Type = void, + sw.visitSuperclass().visitClassType(Type.getInternalName(Object.class)); + sw.visitEnd(); + + } + + private void createSignatureForFunN(int numberOfParams) { + + defineTypeVariablesForParametersOfFunN(numberOfParams); + + sw.visitFormalTypeParameter("R"); + // getBounds vom Return-Type + sw.visitClassBound().visitClassType(Type.getInternalName(Object.class)); + sw.visitClassBound().visitEnd(); + // TODO: prüfe ob Return-Type = void, + sw.visitSuperclass().visitClassType(Type.getInternalName(Object.class)); + sw.visitEnd(); + } + + private void defineTypeVariablesForParametersOfFunN(int numberOfParams) { + for (int i = 0; i < numberOfParams; i++) { + int j = i + 1; + sw.visitFormalTypeParameter("T" + j); + // getBounds von Params + sw.visitClassBound().visitClassType(Type.getInternalName(Object.class)); + sw.visitClassBound().visitEnd(); + } + } + + /** + * Visits parameter type or return type with {@link SignatureVisitor} to create + * the method signature + * + * @param t type of parameter or return type + * @param sv true if t is type of parameter + */ + private void doVisitParamsOrReturn(RefTypeOrTPHOrWildcardOrGeneric t, SignatureVisitor sv) { + String type = t.acceptTV(new TypeToString()); + + switch (type) { + case "RT": + String sig = t.acceptTV(new TypeToSignature(constraints)); + sv.visitClassType(sig.substring(1, sig.length())); + break; + case "GRT": + GenericRefType g = (GenericRefType) t; + sv.visitTypeVariable(g.acceptTV(new TypeToSignature(constraints))); + break; + case "TPH": + RefTypeOrTPHOrWildcardOrGeneric r = resultSet.resolveType(t).resolvedType; + // der Fall wenn der Typ eine Interface ist, muss betrachtet werden + // Deswegen muss in ResutSet noch enthalten werden, ob die Type eine + // Interface oder eine Klasse ist. + + // das braucht man nicht es reicht: sv.visitTypeVariable(r.acceptTV(new + // TypeToSignature()) + // + String sig2 = r.acceptTV(new TypeToSignature(constraints)); + if (r instanceof GenericRefType) { + sv.visitTypeVariable(sig2); + } else if (!(r instanceof TypePlaceholder)) { + if (sig2.contains(SPECIAL_CHAR_FOR_FUN)) { + sv.visitInterface().visitClassType(sig2.substring(1)); + } else { + // Kann zwischen GenericRefType und RefType nicht unterscheiden + // Deswegen wird immer geprüft, ob der Name in Generic Maps liegt + String n = sig2.substring(1, sig2.length() - 1); +// if(genericsAndBoundsMethod.containsKey(n) || genericsAndBounds.containsKey(n)) { +// sv.visitTypeVariable(n); +// } else { + sv.visitClassType(n); + sv.visitEnd(); +// } +// sv.visitClassType(n); + } + + } else { + String realName = sig2.substring(1, sig2.length() - 1); + String toVisit = realName+SPECIAL_CHAR; + if(!genericsAndBounds.containsKey(toVisit)) { + Optional equalTPH = getEqualTPHFromClassConstraints(consClass, realName); + if(equalTPH.isPresent()){ + toVisit = equalTPH.get().getConstraint().getLeft() + SPECIAL_CHAR; + } else { + toVisit = getEqualTPH(constraints, realName) + SPECIAL_CHAR; + } + } + sv.visitTypeVariable(toVisit); + } + + break; + + case "SWC": + SuperWildcardType swc = (SuperWildcardType) t; + String sigInner = swc.getInnerType().acceptTV(new TypeToSignature(constraints)); + int length = sigInner.length(); + visitWildCard(sv, sigInner, length, swc.getInnerType(), SUPER_CHAR); + + break; + + case "EWC": + ExtendsWildcardType ewc = (ExtendsWildcardType) t; + String esigInner = ewc.getInnerType().acceptTV(new TypeToSignature(constraints)); + int lengthEWCSig = esigInner.length(); + visitWildCard(sv, esigInner, lengthEWCSig, ewc.getInnerType(), EXTENDS_CHAR); + + break; + default: +// if (!sv) +// sv.visitBaseType('V'); + break; + } + } + + private void visitWildCard(SignatureVisitor sv, String sigInner, int length, RefTypeOrTPHOrWildcardOrGeneric innerType, char superOrExtendsChar) { + if (innerType instanceof TypePlaceholder) { + sv.visitTypeArgument(superOrExtendsChar).visitTypeVariable(sigInner.substring(1, length)); + } else if (innerType instanceof RefType) { + checkInnerSignatureOfWildCard(sv, sigInner, length, superOrExtendsChar); + } else { + sv.visitTypeArgument(superOrExtendsChar).visitTypeVariable(sigInner.substring(1)); + } + } + + private void checkInnerSignatureOfWildCard(SignatureVisitor sv, String sigInner, int length, char superOrExtendsChar) { + if (sigInner.contains(SPECIAL_CHAR_FOR_FUN)) { + sv.visitTypeArgument(superOrExtendsChar).visitInterface().visitClassType(sigInner.substring(1, length)); + } else { + sv.visitTypeArgument(superOrExtendsChar).visitClassType(sigInner.substring(1, length)); + } + } + + private Optional getEqualTPHFromClassConstraints(List consClass, String tph) { + return consClass.stream() + .filter(c -> c.getConstraint().getLeft().equals(tph) || c.getEqualsTPHs().contains(tph)) + .findFirst(); + } + + private String getEqualTPH(List constraints2, String tph) { + return constraints2.stream() + .filter(c -> c.getConstraint().getLeft().equals(tph) || c.getEqualsTPHs().contains(tph)) + .findFirst().get().getConstraint().getLeft(); + } + + /** + * Creates signature for class or interface with {@link SignatureWriter} + * Signature looks like: superclass + */ + public String createSignatureForClassOrInterface() { + defineTypeVariablesForClassOrInterface(); + + defineGenericsFromConstraints(consClass,genericsAndBounds); + + String sClass = classOrInterface.getSuperClass().acceptTV(new TypeToSignature()); + sw.visitSuperclass().visitClassType(sClass.substring(1, sClass.length() - 1)); + sw.visitEnd(); + return sw.toString(); + } + + private void defineTypeVariablesForClassOrInterface() { + Iterator itr = classOrInterface.getGenerics().iterator(); + + while (itr.hasNext()) { + GenericTypeVar g = itr.next(); + visitTypeVarsAndTheirBounds(g, genericsAndBounds); + } + } + + /** + * @param genericsAndBounds2 + * + */ + private void defineGenericsFromConstraints(List constraints, HashMap genericsAndBounds2) { + constraints.forEach(c -> { + String typeVariable = c.getConstraint().getLeft() + SPECIAL_CHAR; + sw.visitFormalTypeParameter(typeVariable); + + String bound = c.getConstraint().getRight(); + bound = checkBound(bound); + genericsAndBounds2.put(typeVariable, bound); + }); + } + + /** + * @param bound + * @return + */ + private String checkBound(String bound) { + if (bound.equals(Type.getInternalName(Object.class))) { + visitClassBound(bound); + } else { + bound += SPECIAL_CHAR; + sw.visitClassBound().visitTypeVariable(bound); + } + return bound; + } + + /** + * @param bound + */ + private void visitClassBound(String bound) { + sw.visitClassBound().visitClassType(bound); + sw.visitClassBound().visitEnd(); + } + + /** + * Get bounds of type variable + * + * @param g type variable + * @param genAndBounds + */ + private void visitTypeVarsAndTheirBounds(GenericTypeVar g, HashMap genAndBounds) { + sw.visitFormalTypeParameter(g.getName()); + + Iterator bItr = g.getBounds().iterator(); + while (bItr.hasNext()) { + RefTypeOrTPHOrWildcardOrGeneric b = bItr.next(); + String boundDesc = b.acceptTV(new TypeToDescriptor()); + // Ensure that <...> extends java.lang.Object OR ... + if (b instanceof GenericRefType) { + sw.visitClassBound().visitTypeVariable(boundDesc); + } else { + visitClassBound(boundDesc); + } + genAndBounds.put(g.getName(), boundDesc); + } + } + + @Override + public String toString() { + if(sw == null) + return super.toString(); + return sw.toString(); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java b/app/src/main/java/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java new file mode 100644 index 00000000..0026b85f --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/signature/TypeToSignature.java @@ -0,0 +1,115 @@ +package de.dhbwstuttgart.bytecode.signature; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Optional; + +import de.dhbwstuttgart.bytecode.funN.FunNGenerator; +import de.dhbwstuttgart.bytecode.funN.FunNUtilities; +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericsGeneratorResult; +import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType; +import de.dhbwstuttgart.syntaxtree.type.GenericRefType; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.syntaxtree.type.TypeVisitor; + +public class TypeToSignature implements TypeVisitor { + private List constraints; + + private final boolean specializedFunN; + + public TypeToSignature() { this(new ArrayList<>(), true); } + + public TypeToSignature(boolean specializedFunN) { this(new ArrayList<>(), specializedFunN); } + + public TypeToSignature(List constraints) { + this(constraints, true); + } + + public TypeToSignature(List constraints, boolean specializedFunN){ + this.constraints = constraints; + this.specializedFunN = specializedFunN; + } + + @Override + public String visit(RefType refType) { + if(refType.getName().toString().equals("void")) + return "V"; + if (refType.getName().toString().matches("Fun\\d+\\$\\$") && specializedFunN){ + FunNUtilities funNUtilities = FunNGenerator.getInstance(); + return funNUtilities.getSpecializedSignature(funNUtilities.getArguments(refType.getParaList()), funNUtilities.getReturnType(refType.getParaList())); + } +// return refType.toString().replace(".", "/"); + String params = ""; + if(refType.getParaList().size()>0){ + params += "<"; + Iterator it = refType.getParaList().iterator(); + while(it.hasNext()){ + RefTypeOrTPHOrWildcardOrGeneric param = it.next(); +// if(param instanceof TypePlaceholder) { +// params += "T" + ((TypePlaceholder) param).getName() + "$"; +// } else if(param instanceof ExtendsWildcardType) { +// params += "+" + ((ExtendsWildcardType) param).getInnerType().acceptTV(new TypeToSignature()); +// } else if(param instanceof SuperWildcardType) { +// params += "-" + ((SuperWildcardType) param).getInnerType().acceptTV(new TypeToSignature()); +// } else { +// params += "L"+param.toString().replace(".", "/"); +// } + params += param.acceptTV(new TypeToSignature(constraints)); + + if(param instanceof TypePlaceholder) + params += ";"; + } + params += ">"; + } +// String t = refType.getName().toString().replace(".", "/"); +// return t.equals("Fun1")?t+"$$"+params+";":t+params+";"; + return "L"+refType.getName().toString().replace(".", "/") + params+";"; + } + + @Override + public String visit(SuperWildcardType superWildcardType) { +// throw new NotImplementedException(); + String sig = "-" + superWildcardType.getInnerType().acceptTV(new TypeToSignature(constraints)); + if(superWildcardType.getInnerType() instanceof TypePlaceholder) + sig += ";"; + return sig; + } + + @Override + public String visit(TypePlaceholder typePlaceholder) { +// return typePlaceholder.toString().replace(".", "/"); + String name = typePlaceholder.getName(); + + if(!constraints.isEmpty()){ + Optional equalName = getEqualTPHFromClassConstraints(constraints, name); + if(equalName.isPresent()) + name = equalName.get().getConstraint().getLeft(); + } + + return "T" + name + "$"; + } + + @Override + public String visit(ExtendsWildcardType extendsWildcardType) { +// throw new NotImplementedException(); + String sig = "+" + extendsWildcardType.getInnerType().acceptTV(new TypeToSignature(constraints)); + if(extendsWildcardType.getInnerType() instanceof TypePlaceholder) + sig += ";"; + return sig; + } + + @Override + public String visit(GenericRefType genericRefType) { + return genericRefType.getParsedName().replace(".", "/"); + } + + private Optional getEqualTPHFromClassConstraints(List listOfConstraints, String tph) { + return listOfConstraints.stream() + .filter(c -> c.getConstraint().getLeft().equals(tph) || c.getEqualsTPHs().contains(tph)) + .findFirst(); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/signature/TypeToString.java b/app/src/main/java/de/dhbwstuttgart/bytecode/signature/TypeToString.java new file mode 100644 index 00000000..a0e280c2 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/signature/TypeToString.java @@ -0,0 +1,38 @@ +package de.dhbwstuttgart.bytecode.signature; + +import de.dhbwstuttgart.exceptions.NotImplementedException; +import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType; +import de.dhbwstuttgart.syntaxtree.type.GenericRefType; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.syntaxtree.type.TypeVisitor; + +public class TypeToString implements TypeVisitor{ + + @Override + public String visit(RefType refType) { + return "RT"; + } + + @Override + public String visit(SuperWildcardType superWildcardType) { + return "SWC"; + } + + @Override + public String visit(TypePlaceholder typePlaceholder) { + return "TPH"; + } + + @Override + public String visit(ExtendsWildcardType extendsWildcardType) { + return "EWC"; + } + + @Override + public String visit(GenericRefType genericRefType) { + return "GRT"; + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/simplifyRes/GenericGenratorResultForSourceFile.java b/app/src/main/java/de/dhbwstuttgart/bytecode/simplifyRes/GenericGenratorResultForSourceFile.java new file mode 100644 index 00000000..a36f6e07 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/simplifyRes/GenericGenratorResultForSourceFile.java @@ -0,0 +1,50 @@ +/** + * + */ +package de.dhbwstuttgart.bytecode.simplifyRes; + +import java.util.ArrayList; +import java.util.List; +import java.util.NoSuchElementException; + +/** + * The simplify results of a source file (package) + * + * @author fayez + * + */ +public class GenericGenratorResultForSourceFile { + private String pkgName; + private final List genericGeneratorResultForAllClasses = new ArrayList<>(); + + /** + * @param pkgName + */ + public GenericGenratorResultForSourceFile(String pkgName) { + this.pkgName = pkgName; + } + + public List getGenericGeneratorResultForAllClasses() { + return genericGeneratorResultForAllClasses; + } + + /** + * Appends the simplify results of a class to simplifyResForSF + * + * @param sResClass simplify results of a class to added + */ + public void addGenericGeneratorResultClass(GenericsGeneratorResultForClass sResClass) { + genericGeneratorResultForAllClasses.add(sResClass); + } + + public GenericsGeneratorResultForClass getSimplifyResultsByName(String pkgName, String name) { + for (int i = 0; i < genericGeneratorResultForAllClasses.size(); i++) { + GenericsGeneratorResultForClass genericsGeneratorResult = genericGeneratorResultForAllClasses.get(i); + if (genericsGeneratorResult.getClassName().equals(name)) { + return genericsGeneratorResult; + } + } + + return new GenericsGeneratorResultForClass(name); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/simplifyRes/GenericsGeneratorResultForClass.java b/app/src/main/java/de/dhbwstuttgart/bytecode/simplifyRes/GenericsGeneratorResultForClass.java new file mode 100644 index 00000000..ff575b67 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/simplifyRes/GenericsGeneratorResultForClass.java @@ -0,0 +1,75 @@ +/** + * + */ +package de.dhbwstuttgart.bytecode.simplifyRes; + +import java.util.Collections; +import java.util.List; + +import com.google.common.base.Optional; + +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericGeneratorResultsForAllMethods; +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericsGeneratorResult; +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.MethodAndConstraints; + +/** + * @author fayez + * + */ +public class GenericsGeneratorResultForClass { + private final String className; + private final List classConstraints; + private final GenericGeneratorResultsForAllMethods methodsAndTheirConstraints; + + public GenericsGeneratorResultForClass(String className) { + this(className, Collections.emptyList(), new GenericGeneratorResultsForAllMethods()); + } + /** + * @param className + * @param classConstraints + * @param methodsAndTheirConstraints + */ + public GenericsGeneratorResultForClass(String className, List classConstraints, + GenericGeneratorResultsForAllMethods methodsAndTheirConstraints) { + this.className = className; + this.classConstraints = classConstraints; + this.methodsAndTheirConstraints = methodsAndTheirConstraints; + } + + /** + * @return the className + */ + public String getClassName() { + return className; + } + + /** + * @return the classConstraints + */ + public List getClassConstraints() { + return classConstraints; + } + + /** + * @return the methodsAndTheirConstraints + */ + public GenericGeneratorResultsForAllMethods getMethodsAndTheirConstraints() { + return methodsAndTheirConstraints; + } + + public boolean contains(String id) { + return methodsAndTheirConstraints.getMethodsAndConstraints().stream().map(mc -> mc.getMethodID()) + .anyMatch(i -> i.equals(id)); + } + + + + + public List getMethodConstraintsByID(String id) { + java.util.Optional methodAndConstraints = methodsAndTheirConstraints.getMethodsAndConstraints().stream().filter(mc -> mc.getMethodID().equals(id)) + .findFirst(); + + return methodAndConstraints.isPresent() ? methodAndConstraints.get().getConstraints() : Collections.emptyList(); + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/ByteCodeForFunNGenerator.java b/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/ByteCodeForFunNGenerator.java new file mode 100644 index 00000000..24b5f627 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/ByteCodeForFunNGenerator.java @@ -0,0 +1,94 @@ +package de.dhbwstuttgart.bytecode.utilities; + +import de.dhbwstuttgart.bytecode.signature.Signature; +import de.dhbwstuttgart.syntaxtree.FormalParameter; +import de.dhbwstuttgart.syntaxtree.statement.ArgumentList; +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; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Iterator; + +public class ByteCodeForFunNGenerator { + + public static void generateBCForFunN(LambdaExpression lambdaExpression, String methDesc, File path) { + ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); + + SignatureWriter methSig = new SignatureWriter(); + + int numberOfParams = 0; + SignatureVisitor paramVisitor = methSig.visitParameterType(); + Iterator itr = lambdaExpression.params.iterator(); + while (itr.hasNext()) { + numberOfParams++; + // getBounds + paramVisitor.visitTypeVariable(CONSTANTS.T + numberOfParams); + itr.next(); + } + methSig.visitReturnType().visitTypeVariable(CONSTANTS.R); + // ")"+lam.getReturn.getBounds + Signature sig = new Signature(numberOfParams); + String name = CONSTANTS.FUN + numberOfParams + CONSTANTS.$$; + classWriter.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC+Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT, name, sig.toString(), + Type.getInternalName(Object.class), null); + MethodVisitor mvApply = classWriter.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_ABSTRACT, "apply", methDesc, + methSig.toString(), null); + mvApply.visitEnd(); + writeClassFile(classWriter.toByteArray(), name, path); + } + + public static void generateBCForFunN(ArgumentList argumentList, String methDesc, File path) { + ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); + + SignatureWriter methSig = new SignatureWriter(); + + int numberOfParams = 0; + SignatureVisitor paramVisitor = methSig.visitParameterType(); + Iterator itr1 = argumentList.getArguments().iterator(); + + while(itr1.hasNext()) { + numberOfParams++; + // getBounds + paramVisitor.visitTypeVariable(CONSTANTS.T + numberOfParams); + itr1.next(); + } + + methSig.visitReturnType().visitTypeVariable(CONSTANTS.R); + // ")"+lam.getReturn.getBounds + Signature sig = new Signature(numberOfParams); + String name = CONSTANTS.FUN + numberOfParams + CONSTANTS.$$; + classWriter.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC+Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT, name, sig.toString(), + Type.getInternalName(Object.class), null); + MethodVisitor mvApply = classWriter.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_ABSTRACT, "apply", methDesc, + methSig.toString(), null); + mvApply.visitEnd(); + writeClassFile(classWriter.toByteArray(), name, path); + } + + + 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)); + output.write(bytecode); + output.close(); + System.out.println(name + ".class file generated"); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/CONSTANTS.java b/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/CONSTANTS.java new file mode 100644 index 00000000..da05e82e --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/CONSTANTS.java @@ -0,0 +1,22 @@ +package de.dhbwstuttgart.bytecode.utilities; + +public interface CONSTANTS { + + String VOID = "void"; + String TPH = "TPH "; + String ANGLEBRACKET = "<"; + String FUN = "Fun"; + String EXTENSIONCLASS = ".class"; + String $$ = "$$"; + String T = "T"; + String R = "R"; + String DESUGAREDMETHODNAME = "lambda$new$"; + String REFTYPE_BYTE = "java/lang/Byte"; + String REFTYPE_SHORT = "java/lang/Short"; + String REFTYPE_INTEGER = "java/lang/Integer"; + String REFTYPE_LONG = "java/lang/Long"; + String REFTYPE_DOUBLE = "java/lang/Double"; + String REFTYPE_FLOAT = "java/lang/Float"; + String REFTYPE_STRING = "java/lang/String"; + String TO_STRING = "toString"; +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/ConstraintsFinder.java b/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/ConstraintsFinder.java new file mode 100644 index 00000000..8597abfb --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/ConstraintsFinder.java @@ -0,0 +1,53 @@ +package de.dhbwstuttgart.bytecode.utilities; + +import java.util.ArrayList; +import java.util.List; + +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.ConstraintsWithSameLeftSide; + +public class ConstraintsFinder { + private List allConstaints; + + public ConstraintsFinder(List allConstaints) { + this.allConstaints = allConstaints; + } + + public List findConstraints() { + List result = new ArrayList<>(); + + List visitedCons = new ArrayList<>(); + for(TPHConstraint c : allConstaints) { + if(c.getRel() == Relation.EXTENDS) { + // get constraints with the same left side + List cons = getConstraints(c,visitedCons); + if(cons.size()>1) { + ConstraintsWithSameLeftSide consWithSameLeftSide = new ConstraintsWithSameLeftSide(cons); + result.add(consWithSameLeftSide); + } + } + } + + return result; + } + + private List getConstraints(TPHConstraint c, List visitedCons) { + List res = new ArrayList<>(); + for(TPHConstraint cons : allConstaints) { + if(!isVisited(cons,visitedCons) && cons.getLeft().equals(c.getLeft())) { + res.add(cons); + visitedCons.add(cons); + } + } + return res; + } + + private boolean isVisited(TPHConstraint cons, List visitedCons) { + for(TPHConstraint c : visitedCons) { + if(c.getLeft().equals(cons.getLeft()) && c.getRight().equals(cons.getRight())) + return true; + } + return false; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/KindOfLambda.java b/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/KindOfLambda.java new file mode 100644 index 00000000..39339cbe --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/KindOfLambda.java @@ -0,0 +1,243 @@ +package de.dhbwstuttgart.bytecode.utilities; + +import de.dhbwstuttgart.syntaxtree.statement.*; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; +import de.dhbwstuttgart.syntaxtree.FormalParameter; +import de.dhbwstuttgart.syntaxtree.ParameterList; +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.statement.Literal; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; + +public class KindOfLambda implements StatementVisitor{ + private ParameterList params; + private boolean isInstanceCapturingLambda = false; + private List argumentList = new ArrayList<>(); + private ArrayList usedVars = new ArrayList<>(); + private ArrayList varsFromInnerLambdas = new ArrayList<>(); + private boolean thisUsed = false; + private ArrayList definedLocals = new ArrayList<>(); + + public KindOfLambda(LambdaExpression lambdaExpression) { + this.params = lambdaExpression.params; + lambdaExpression.methodBody.accept(this); + + } + + public ArrayList getUsedVars() { + return usedVars; + } + + public boolean isInstanceCapturingLambda() { + return this.isInstanceCapturingLambda; + } + + public List getArgumentList() { + return argumentList; + } + + public boolean isThisUsed() { + return thisUsed; + } + + @Override + public void visit(ArgumentList argumentList) { + argumentList.getArguments().forEach(a->a.accept(this)); + + } + + @Override + public void visit(LambdaExpression lambdaExpression) { + lambdaExpression.params.getFormalparalist().forEach(p->varsFromInnerLambdas.add(p.getName())); + lambdaExpression.methodBody.accept(this); + } + + @Override + public void visit(Assign assign) { + assign.rightSide.accept(this); + } + + @Override + public void visit(BinaryExpr binary) { + binary.lexpr.accept(this); + binary.rexpr.accept(this); + } + + @Override + public void visit(Block block) { + for(Statement stmt : block.getStatements()) { + stmt.accept(this); + } + } + + @Override + public void visit(CastExpr castExpr) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(EmptyStmt emptyStmt) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(FieldVar fieldVar) { + fieldVar.receiver.accept(this); + } + + @Override + public void visit(ForStmt forStmt) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(IfStmt ifStmt) { + ifStmt.expr.accept(this); + ifStmt.then_block.accept(this); + ifStmt.else_block.accept(this); + } + + @Override + public void visit(InstanceOf instanceOf) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(LocalVar localVar) { + boolean addVar = !contain(params, localVar.name) && !definedLocals.contains(localVar.name) && + !varsFromInnerLambdas.contains(localVar.name) && !usedVars.contains(localVar.name); + if(addVar) { + argumentList.add(localVar.getType()); + if(thisUsed) { + usedVars.add(1, localVar.name); + } else { + usedVars.add(0, localVar.name); + } + if(!isInstanceCapturingLambda) + isInstanceCapturingLambda=true; + } + } + + private boolean contain(ParameterList params2, String name) { + Iterator itr = params2.iterator(); + while(itr.hasNext()) { + FormalParameter fp = itr.next(); + if(fp.getName().equals(name)) + return true; + } + return false; + } + + @Override + public void visit(LocalVarDecl localVarDecl) { + definedLocals.add(localVarDecl.getName()); + } + + @Override + public void visit(MethodCall methodCall) { + methodCall.receiver.accept(this); + methodCall.arglist.accept(this); + } + + @Override + public void visit(NewClass methodCall) { + methodCall.receiver.accept(this); + methodCall.arglist.accept(this); + } + + @Override + public void visit(NewArray newArray) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(ExpressionReceiver receiver) { + receiver.expr.accept(this); + } + + @Override + public void visit(UnaryExpr unaryExpr) { + + } + + @Override + public void visit(Return aReturn) { + aReturn.retexpr.accept(this); + } + + @Override + public void visit(ReturnVoid aReturn) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(StaticClassName staticClassName) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(Super aSuper) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(This aThis) { + if(!thisUsed) { + thisUsed = true; + this.argumentList.add(0,aThis.getType()); + } + if(!isInstanceCapturingLambda) { + this.isInstanceCapturingLambda = true; + + } + } + + @Override + public void visit(WhileStmt whileStmt) { + whileStmt.expr.accept(this); + whileStmt.loopBlock.accept(this); + + } + + @Override + public void visit(DoStmt whileStmt) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(Literal literal) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(AssignToField assignLeftSide) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(AssignToLocal assignLeftSide) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(SuperCall superCall) { + // TODO Auto-generated method stub + + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/Lambda.java b/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/Lambda.java new file mode 100644 index 00000000..6371c618 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/Lambda.java @@ -0,0 +1,26 @@ +package de.dhbwstuttgart.bytecode.utilities; + +import de.dhbwstuttgart.bytecode.descriptor.DescriptorVisitor; +import de.dhbwstuttgart.syntaxtree.ParameterList; +import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; + +public class Lambda { + private LambdaExpression lambdaExpression; + + public Lambda(LambdaExpression lambdaExpression) { + this.lambdaExpression = lambdaExpression; + } + + public ParameterList getParams() { + return lambdaExpression.params; + } + + public RefTypeOrTPHOrWildcardOrGeneric getReturnType() { + return lambdaExpression.getReturnType(); + } + + public String accept(DescriptorVisitor descVisitor) { + return descVisitor.visit(this); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/MethodAndTPH.java b/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/MethodAndTPH.java new file mode 100644 index 00000000..caaad1be --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/MethodAndTPH.java @@ -0,0 +1,59 @@ +package de.dhbwstuttgart.bytecode.utilities; + +import java.util.ArrayList; + +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; +import de.dhbwstuttgart.typeinference.constraints.Pair; +import de.dhbwstuttgart.typeinference.result.GenericInsertPair; +import de.dhbwstuttgart.typeinference.result.ResultPair; + +public class MethodAndTPH { + + private String id; + private final ArrayList tphs = new ArrayList<>(); + //private final ArrayList pairs = new ArrayList<>(); + private final ArrayList> pairs = new ArrayList<>(); + // tphs of local variables and parameters + private final ArrayList localTphs = new ArrayList<>(); + /* + * its Constraints + * eingefuegt PL 2021-02-15 + */ + public final ConstraintSet constraints; + + public MethodAndTPH(String name, ConstraintSet constraints) { + this.id = name; + this.constraints = constraints; + } + + public void addTph(String tph) { + tphs.add(tph); + } + + public ArrayList getTphs() { + return tphs; + } + +// public ArrayList getPairs(){ +// return pairs; +// } + public ArrayList> getPairs(){ + return pairs; + } + + public String getId() { + return id; + } + + public ArrayList getLocalTphs() { + return localTphs; + } + + @Override + public String toString() { + return id; + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/MethodCallHelper.java b/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/MethodCallHelper.java new file mode 100644 index 00000000..ad3e28fa --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/MethodCallHelper.java @@ -0,0 +1,244 @@ +/** + * + */ +package de.dhbwstuttgart.bytecode.utilities; + +import de.dhbwstuttgart.bytecode.Exception.NotInCurrentPackageException; +import de.dhbwstuttgart.bytecode.descriptor.DescriptorToString; +import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor; +import de.dhbwstuttgart.bytecode.signature.TypeToSignature; +import de.dhbwstuttgart.syntaxtree.*; +import de.dhbwstuttgart.syntaxtree.statement.Expression; +import de.dhbwstuttgart.syntaxtree.statement.MethodCall; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.typeinference.result.ResultSet; +import javassist.NotFoundException; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +import java.io.File; +import java.util.*; + +/** + * @author fayez + * + */ +public class MethodCallHelper { + private MethodCall methCall; + private SourceFile sourceFile; + private ResultSet resultSet; + private File path; + + /** + * @param methCall + * @param sourceFile + * @param resultSet + * @param path TODO + */ + public MethodCallHelper(MethodCall methCall, SourceFile sourceFile, ResultSet resultSet, File path) { + this.methCall = methCall; + this.sourceFile = sourceFile; + this.resultSet = resultSet; + this.path = path; + } + + public String getResolvedType(RefTypeOrTPHOrWildcardOrGeneric type) { + return resultSet.resolveType(type).resolvedType.acceptTV(new TypeToDescriptor()); + } + + public boolean isInCurrPkg(String className) { + for (ClassOrInterface cl : sourceFile.KlassenVektor) { + if (className.equals(cl.getClassName().toString())) + return true; + } + return false; + } + + public String getSuperClass(String className) throws NotInCurrentPackageException { + + for (ClassOrInterface cl : sourceFile.getClasses()) { + if (className.equals(cl.getClassName().toString())) { + return cl.getSuperClass().getName().toString(); + } + } + throw new NotInCurrentPackageException("Class " + className + " is not in the current package."); + } + + public ClassOrInterface getClassFromCurrPkg(String className) throws NotInCurrentPackageException { + for (ClassOrInterface cl : sourceFile.KlassenVektor) { + if (className.equals(cl.getClassName().toString())) + return cl; + } + throw new NotInCurrentPackageException("Class of " + className + " is not in the current package."); + } + + public String getDesc(String className) throws NotInCurrentPackageException, NotFoundException { + String name = methCall.name; + ClassOrInterface clazz = getClassFromCurrPkg(className); + String retType = getResolvedType(methCall.getType()); + ArrayList params = getTypes(methCall.arglist.getArguments()); + + Map genAndBoundsClass = getGenericsAndBounds(clazz.getGenerics()); + modifyGenAndBounds(genAndBoundsClass); + for (Method m : clazz.getMethods()) { + if (name.equals(m.getName()) && retType.equals(getResolvedType(m.getReturnType()))) { + ArrayList paramsOfM = getTypes(m.getParameterList()); + if(areEquals(params,paramsOfM)) { + Map genAndBoundsMethod = getGenericsAndBoundsMethod(m.getGenerics()); + modifyGenAndBounds(genAndBoundsMethod); + boolean hasGen = hasGen(m, genAndBoundsClass); + NormalMethod nm = new NormalMethod(m, (HashMap) genAndBoundsClass, + (HashMap) genAndBoundsMethod, hasGen); + return nm.accept(new DescriptorToString(resultSet)); + } + } + } + + throw new NotFoundException("Method " + name + " is not found"); + } + + private boolean areEquals(ArrayList params, ArrayList paramsOfM) { + if(params.size() != paramsOfM.size()) + return false; + + for(String t : params) { + for(String t2 : paramsOfM) { + if(!t.equals(t2)) + return false; + } + } + return true; + } + + private ArrayList getTypes(ParameterList parameterList) { + Iterator itr = parameterList.iterator(); + ArrayList typeList = new ArrayList<>(); + while (itr.hasNext()) { + FormalParameter fp = itr.next(); + String t = getResolvedType(fp.getType()); + typeList.add(t); + } + + return typeList; + } + + private ArrayList getTypes(List arguments) { + ArrayList types = new ArrayList<>(); + for(int i = 0; i genericsAndBounds) { + String retType = resultSet.resolveType(m.getReturnType()).resolvedType.acceptTV(new TypeToSignature()); + /*Prüfe, ob die Rückgabe-Type der Methode eine Type-Variable ist*/ + boolean hasGenInParameterList = genericsAndBounds.containsKey(retType) || retType.contains("TPH ") || retType.contains("<"); + + Map methodParamsAndTypes = new HashMap<>(); + Iterator itr = m.getParameterList().iterator(); + while(itr.hasNext()) { + FormalParameter fp = itr.next(); + methodParamsAndTypes.put(fp.getName(), resultSet.resolveType(fp.getType()).resolvedType); + } + /*Wenn die Rückgabe-Type eine Typ-variable ist, erzeuge direkt die Signature, wenn nicht, + * prüfe, ob einer der Parameter Typ-Variable als Typ hat*/ + if(!hasGenInParameterList) { + for(String paramName : methodParamsAndTypes.keySet()) { + String typeOfParam = methodParamsAndTypes.get(paramName).acceptTV(new TypeToDescriptor()); + String sigOfParam = methodParamsAndTypes.get(paramName).acceptTV(new TypeToSignature()); + if(genericsAndBounds.containsKey(typeOfParam)||typeOfParam.contains("TPH ")||sigOfParam.contains("<")) { + hasGenInParameterList = true; + break; + } + } + } + return m.getGenerics().iterator().hasNext() || hasGenInParameterList; + } + + private Map getGenericsAndBoundsMethod(Iterable generics) { + Map genAndBounds = new HashMap<>(); + Iterator itr = generics.iterator(); + while (itr.hasNext()) { + GenericTypeVar gtv = itr.next(); + getBoundsOfTypeVar(gtv, genAndBounds); + } + return genAndBounds; + } + + private void modifyGenAndBounds(Map genAndBoundsClass) { + List visited = new ArrayList<>(genAndBoundsClass.size()); + Map toReplace = new HashMap<>(); + for (String tv : genAndBoundsClass.keySet()) { + + if (visited.contains(tv)) + continue; + + List types = new LinkedList<>(); + String bound = genAndBoundsClass.get(tv); + types.add(tv); + visited.add(tv); + boolean doReplace = false; + while (genAndBoundsClass.keySet().contains(bound)) { + doReplace = true; + types.add(bound); + visited.add(bound); + bound = genAndBoundsClass.get(bound); + } + + if (doReplace) { + for (String tt : types) { + toReplace.put(tt, bound); + } + } + } + + for (String key : toReplace.keySet()) { + genAndBoundsClass.replace(key, toReplace.get(key)); + } + + } + + private Map getGenericsAndBounds(GenericDeclarationList generics) { + Map genAndBounds = new HashMap<>(); + Iterator itr = generics.iterator(); + while (itr.hasNext()) { + GenericTypeVar gtv = itr.next(); + getBoundsOfTypeVar(gtv, genAndBounds); + } + return genAndBounds; + } + + private void getBoundsOfTypeVar(GenericTypeVar g, Map genAndBounds) { + + Iterator bItr = g.getBounds().iterator(); + while (bItr.hasNext()) { + RefTypeOrTPHOrWildcardOrGeneric b = bItr.next(); + String boundDesc = b.acceptTV(new TypeToDescriptor()); + genAndBounds.put(g.getName(), boundDesc); + } + } + + public void generateBCForFunN(String methodDescriptor) { + ByteCodeForFunNGenerator.generateBCForFunN(methCall.arglist,methodDescriptor,path); + } + + public String getDescriptorOfApplyMethod(String methodCallType) { + return new DescriptorToString().createDescForFunN(methCall.arglist, methodCallType); + } + + /** + * @param methodCall + */ + public void createCheckCast(MethodCall methodCall, MethodVisitor mv) { + String checkCast = getResolvedType(methodCall.getType()); + if(!checkCast.contains("TPH ")) { + int pos = checkCast.length(); + if(checkCast.contains("<")) + pos = checkCast.indexOf("<"); + mv.visitTypeInsn(Opcodes.CHECKCAST,checkCast.substring(0,pos)); + } + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/MethodFromMethodCall.java b/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/MethodFromMethodCall.java new file mode 100644 index 00000000..28d135e6 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/MethodFromMethodCall.java @@ -0,0 +1,50 @@ +package de.dhbwstuttgart.bytecode.utilities; + +import java.util.HashMap; + +import de.dhbwstuttgart.bytecode.descriptor.DescriptorVisitor; +import de.dhbwstuttgart.syntaxtree.statement.ArgumentList; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; + +public class MethodFromMethodCall { + private ArgumentList argList; + private RefTypeOrTPHOrWildcardOrGeneric returnType; + private String receiverName; + private HashMap genericsAndBoundsMethod; + private HashMap genericsAndBounds; + + public MethodFromMethodCall(ArgumentList argList,RefTypeOrTPHOrWildcardOrGeneric returnType, + String receiverName, HashMap genericsAndBoundsMethod, + HashMap genericsAndBounds) { + this.argList = argList; + this.returnType = returnType; + this.receiverName = receiverName; + this.genericsAndBoundsMethod = genericsAndBoundsMethod; + this.genericsAndBounds = genericsAndBounds; + } + + + public ArgumentList getArgList() { + return argList; + } + + public RefTypeOrTPHOrWildcardOrGeneric getReturnType() { + return returnType; + } + + public String getReceiverName() { + return receiverName; + } + + public HashMap getGenericsAndBoundsMethod(){ + return genericsAndBoundsMethod; + } + + public HashMap getGenericsAndBounds(){ + return genericsAndBounds; + } + + public String accept(DescriptorVisitor descVisitor) { + return descVisitor.visit(this); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/MethodUtility.java b/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/MethodUtility.java new file mode 100644 index 00000000..6a84e97c --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/MethodUtility.java @@ -0,0 +1,34 @@ +/** + * + */ +package de.dhbwstuttgart.bytecode.utilities; + +import java.util.Iterator; + +import de.dhbwstuttgart.syntaxtree.FormalParameter; +import de.dhbwstuttgart.syntaxtree.Method; + +/** + * @author fayez + * + */ +public class MethodUtility { + /** + * Creates an ID for a method + * + * @param resolver type Resolver + * @param method for which the ID will be generated + * @return ID for the given method. + * ID = ReturntypeMethodname(Parametertypes) + */ + public static String createID(Resolver resolver, Method method) { + String id = resolver.getResolvedType(method.getReturnType()) + method.name + "("; + Iterator itr = method.getParameterList().iterator(); + while (itr.hasNext()) { + FormalParameter fp = itr.next(); + id += resolver.getResolvedType(fp.getType()); + } + id += ")"; + return id; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/NameReplacer.java b/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/NameReplacer.java new file mode 100644 index 00000000..89654239 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/NameReplacer.java @@ -0,0 +1,145 @@ +package de.dhbwstuttgart.bytecode.utilities; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; + +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.NameReplacementResult; +import de.dhbwstuttgart.syntaxtree.factory.NameGenerator; + +public class NameReplacer { + //TODO rename + private List constraints; + private List allConstraints; + private List methodAndTPHs; + // TODO rename into tphClass + private List tphs; + private List localTphs; + + public NameReplacer(List constraints, List allConstraints,List tphs, ArrayList localTphs) { + super(); + this.constraints = constraints; + this.allConstraints = allConstraints; + this.tphs = tphs; + this.localTphs = localTphs; + } + + public NameReplacer(List constraints, List allConstraints,List tphs) { + super(); + this.constraints = constraints; + this.allConstraints = allConstraints; + this.tphs = tphs; + } + + public NameReplacer(List constraints, List allConstraints) { + this.constraints = constraints; + this.allConstraints = allConstraints; + } + + public NameReplacer(List constraints, List allConstraints, List methodAndTPHs, + List tphsClass) { + this.constraints = constraints; + this.allConstraints = allConstraints; + this.methodAndTPHs = methodAndTPHs; + this.tphs = tphsClass; + } + + public NameReplacementResult replaceNames() { + String newName = NameGenerator.makeNewName(); + List names = new ArrayList<>(); + substituteRightSidesWithNewName(newName, names); + + substituteNamesInAllConstraints(newName, names); + Stream> tphsOfMethods = methodAndTPHs.stream().map(m->m.getTphs()); + Stream> localTphsOfMethods = methodAndTPHs.stream().map(m->m.getLocalTphs()); + + replaceOldNames(newName, names, tphsOfMethods); + replaceOldNames(newName, names, localTphsOfMethods); + + if(tphs.removeAll(names)) + tphs.add(newName); + + NameReplacementResult res = new NameReplacementResult(newName, names); + + return res; + } + + /** + * @param newName + * @param names + * @param tphsOfMethods + */ + public void replaceOldNames(final String newName, final List names, Stream> tphsOfMethods) { + tphsOfMethods.forEach(tphsMethod->{ + if(tphsMethod.removeAll(names)) + tphsMethod.add(newName); + }); + } + + public NameReplacementResult replaceNamesLocal() { + String newName = NameGenerator.makeNewName(); + List names = new ArrayList<>(); + substituteRightSidesWithNewName(newName, names); + + substituteNamesInAllConstraints(newName, names); + + tphs.removeAll(names); + tphs.add(newName); + + NameReplacementResult res = new NameReplacementResult(newName, names); + + return res; + } + + /** + * @param newName + * @param names + */ + public void substituteNamesInAllConstraints(String newName, List names) { + for(TPHConstraint cons : allConstraints) { + if(names.contains(cons.getLeft())) + cons.setLeft(newName); + if(names.contains(cons.getRight())) + cons.setRight(newName); + } + } + + /** + * @param newName + * @param names + */ + public void substituteRightSidesWithNewName(String newName, List names) { + for(TPHConstraint cons : constraints) { + names.add(cons.getRight()); + cons.setRight(newName); + } + } + + public Map> replaceNamesWithLocals() { + String newName = NameGenerator.makeNewName(); + ArrayList names = new ArrayList<>(); + for(TPHConstraint cons : constraints) { + names.add(cons.getRight()); + cons.setRight(newName); + } + + for(TPHConstraint cons : allConstraints) { + if(names.contains(cons.getLeft())) + cons.setLeft(newName); + if(names.contains(cons.getRight())) + cons.setRight(newName); + } + + tphs.removeAll(names); + tphs.add(newName); + localTphs.removeAll(names); + localTphs.add(newName); + + HashMap> res = new HashMap<>(); + res.put(newName, names); + return res; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/NormalConstructor.java b/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/NormalConstructor.java new file mode 100644 index 00000000..3a16fb00 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/NormalConstructor.java @@ -0,0 +1,40 @@ +package de.dhbwstuttgart.bytecode.utilities; + +import java.util.HashMap; + +import de.dhbwstuttgart.bytecode.descriptor.DescriptorVisitor; +import de.dhbwstuttgart.syntaxtree.Constructor; +import de.dhbwstuttgart.syntaxtree.ParameterList; + +public class NormalConstructor { + private Constructor constructor; + private HashMap genericsAndBounds; + private boolean hasGenerics; + + public NormalConstructor(Constructor constructor, boolean hasGenerics) { + this.constructor = constructor; + this.hasGenerics = hasGenerics; + } + + public NormalConstructor(Constructor constructor, HashMap genericsAndBounds, boolean hasGenerics) { + this.constructor = constructor; + this.genericsAndBounds = genericsAndBounds; + this.hasGenerics = hasGenerics; + } + + public HashMap getGenericsAndBounds() { + return genericsAndBounds; + } + + public boolean hasGen() { + return hasGenerics; + } + + public ParameterList getParameterList() { + return constructor.getParameterList(); + } + + public String accept(DescriptorVisitor descVisitor) { + return descVisitor.visit(this); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/NormalMethod.java b/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/NormalMethod.java new file mode 100644 index 00000000..4e5bc887 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/NormalMethod.java @@ -0,0 +1,56 @@ +package de.dhbwstuttgart.bytecode.utilities; + +import java.util.HashMap; + +import de.dhbwstuttgart.bytecode.descriptor.DescriptorVisitor; +import de.dhbwstuttgart.syntaxtree.Method; +import de.dhbwstuttgart.syntaxtree.ParameterList; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; + +public class NormalMethod { + private Method method; + private HashMap genericsAndBounds; + private HashMap genericsAndBoundsMethod; + private boolean hasGenerics; + + public NormalMethod(Method method, boolean hasGenerics) { + this.method = method; + this.hasGenerics = hasGenerics; + } + + public NormalMethod(Method method, HashMap genericsAndBounds, + HashMap genericsAndBoundsMethod,boolean hasGenerics) { + this.method = method; + this.genericsAndBounds = genericsAndBounds; + this.genericsAndBoundsMethod = genericsAndBoundsMethod; + this.hasGenerics = hasGenerics; + } + + public Method getMethod() { + return method; + } + + public ParameterList getParameterList() { + return method.getParameterList(); + } + + public HashMap getGenericsAndBounds(){ + return genericsAndBounds; + } + + public HashMap getGenericsAndBoundsMethod(){ + return genericsAndBoundsMethod; + } + + public RefTypeOrTPHOrWildcardOrGeneric getReturnType() { + return method.getReturnType(); + } + + public boolean hasGen() { + return this.hasGenerics; + } + + public String accept(DescriptorVisitor descVisitor) { + return descVisitor.visit(this); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/Resolver.java b/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/Resolver.java new file mode 100644 index 00000000..684fdd4b --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/Resolver.java @@ -0,0 +1,33 @@ +/** + * + */ +package de.dhbwstuttgart.bytecode.utilities; + +import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.typeinference.result.ResultSet; + +/** + * @author fayez + * + */ +public class Resolver { + + private ResultSet resultSet; + + /** + * @param resultSet + */ + public Resolver(ResultSet resultSet) { + this.resultSet = resultSet; + } + + public String getResolvedType(RefTypeOrTPHOrWildcardOrGeneric type) { + return resultSet.resolveType(type).resolvedType.acceptTV(new TypeToDescriptor()); + } + + //ToDo Etienne: Check ob benötigt + public RefTypeOrTPHOrWildcardOrGeneric resolve(RefTypeOrTPHOrWildcardOrGeneric type) { + return resultSet.resolveType(type).resolvedType; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/SamMethod.java b/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/SamMethod.java new file mode 100644 index 00000000..1c1b883c --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/bytecode/utilities/SamMethod.java @@ -0,0 +1,32 @@ +package de.dhbwstuttgart.bytecode.utilities; + +import java.util.List; + +import de.dhbwstuttgart.bytecode.descriptor.DescriptorVisitor; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; + +public class SamMethod { + private List argumentList; + private RefTypeOrTPHOrWildcardOrGeneric returnType; + + public SamMethod(List argumentList, RefTypeOrTPHOrWildcardOrGeneric returnType) { + this.argumentList = argumentList; + this.returnType = returnType; + } + + public List getArgumentList() { + return argumentList; + } + + + + public RefTypeOrTPHOrWildcardOrGeneric getReturnType() { + return returnType; + } + + + + public String accept(DescriptorVisitor descVisitor) { + return descVisitor.visit(this); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/core/ConsoleInterface.java b/app/src/main/java/de/dhbwstuttgart/core/ConsoleInterface.java new file mode 100644 index 00000000..14314d83 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/core/ConsoleInterface.java @@ -0,0 +1,38 @@ +package de.dhbwstuttgart.core; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.util.*; +import java.util.stream.Collectors; + +public class ConsoleInterface { + private static final String directory = System.getProperty("user.dir"); + + public static void main(String[] args) throws IOException, ClassNotFoundException { + List input = new ArrayList<>(); + List classpath = new ArrayList<>(); + String outputPath = null; + Iterator it = Arrays.asList(args).iterator(); + while(it.hasNext()){ + String arg = it.next(); + if(arg.equals("-d")){ + outputPath = it.next(); + }else if(arg.startsWith("-d")) { + outputPath = arg.substring(2); + }else if(arg.equals("-cp") || arg.equals("-classpath")){ + String[] cps = it.next().split(":"); + for(String cp : cps){ + classpath.add(new File(cp)); + } + }else{ + input.add(new File(arg)); + } + } + JavaTXCompiler compiler = new JavaTXCompiler(input, classpath); + compiler.typeInference(); + compiler.generateBytecode(outputPath); + } + + +} diff --git a/app/src/main/java/de/dhbwstuttgart/core/IItemWithOffset.java b/app/src/main/java/de/dhbwstuttgart/core/IItemWithOffset.java new file mode 100644 index 00000000..1a6fd194 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/core/IItemWithOffset.java @@ -0,0 +1,9 @@ +package de.dhbwstuttgart.core; + + +import org.antlr.v4.runtime.Token; + +public interface IItemWithOffset +{ + Token getOffset(); +} diff --git a/app/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java b/app/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java new file mode 100644 index 00000000..a62eb263 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/core/JavaTXCompiler.java @@ -0,0 +1,999 @@ +//PL 2018-12-19: typeInferenceOld nach typeInference uebertragen +package de.dhbwstuttgart.core; + +import com.google.common.collect.Lists; +import de.dhbwstuttgart.bytecode.BytecodeGen; +import de.dhbwstuttgart.bytecode.Exception.BytecodeGeneratorError; +import de.dhbwstuttgart.bytecode.genericsGenerator.GeneratedGenericsFinder; +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericGenratorResultForSourceFile; +import de.dhbwstuttgart.bytecode.insertGenerics.FamilyOfGeneratedGenerics; +import de.dhbwstuttgart.environment.CompilationEnvironment; +import de.dhbwstuttgart.environment.DirectoryClassLoader; +import de.dhbwstuttgart.exceptions.DebugException; +import de.dhbwstuttgart.parser.JavaTXParser; +import de.dhbwstuttgart.parser.NullToken; +import de.dhbwstuttgart.parser.scope.GenericsRegistry; +import de.dhbwstuttgart.parser.SyntaxTreeGenerator.SyntaxTreeGenerator; +import de.dhbwstuttgart.parser.antlr.Java8Parser.CompilationUnitContext; +import de.dhbwstuttgart.parser.scope.JavaClassName; +import de.dhbwstuttgart.syntaxtree.ClassOrInterface; +import de.dhbwstuttgart.syntaxtree.GenericTypeVar; +import de.dhbwstuttgart.syntaxtree.Method; +import de.dhbwstuttgart.syntaxtree.ParameterList; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.syntaxtree.TypeScope; +import de.dhbwstuttgart.syntaxtree.FormalParameter; +import de.dhbwstuttgart.syntaxtree.GenericDeclarationList; +import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; +import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory; +import de.dhbwstuttgart.syntaxtree.statement.Block; +import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType; +import de.dhbwstuttgart.syntaxtree.type.GenericRefType; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.syntaxtree.type.TypeVisitor; +import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter; +import de.dhbwstuttgart.typeinference.constraints.Constraint; +import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; +import de.dhbwstuttgart.typeinference.constraints.Pair; +import de.dhbwstuttgart.typeinference.result.ResultSet; +import de.dhbwstuttgart.typeinference.typeAlgo.TYPE; +import de.dhbwstuttgart.typeinference.unify.RuleSet; +import de.dhbwstuttgart.typeinference.unify.TypeUnify; +import de.dhbwstuttgart.typeinference.unify.distributeVariance; +import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; +import de.dhbwstuttgart.typeinference.unify.model.PairOperator; +import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType; +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; +import de.dhbwstuttgart.typeinference.unify.model.UnifyType; +import de.dhbwstuttgart.typeinference.unify.TypeUnifyTask; +import de.dhbwstuttgart.typeinference.unify.UnifyResultListener; +import de.dhbwstuttgart.typeinference.unify.UnifyResultListenerImpl; +import de.dhbwstuttgart.typeinference.unify.UnifyResultModel; +import de.dhbwstuttgart.typeinference.unify.UnifyTaskModel; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; +import java.io.OutputStreamWriter; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.antlr.v4.runtime.Token; +import org.apache.commons.io.output.NullOutputStream; + + +public class JavaTXCompiler { + + //public static JavaTXCompiler INSTANCE; + final CompilationEnvironment environment; + Boolean resultmodel = true; + public final Map sourceFiles = new HashMap<>(); + Boolean log = true; //gibt an ob ein Log-File nach System.getProperty("user.dir")+"src/test/java/logFiles" geschrieben werden soll? + public volatile UnifyTaskModel usedTasks = new UnifyTaskModel(); + private final ClassLoader classLoader; + + //nur fuer Testzwecke of Generated Generics + //wieder loeschen PL 2021-03-22 + public FamilyOfGeneratedGenerics fogg; + + + public JavaTXCompiler(File sourceFile) throws IOException, ClassNotFoundException { + this(Arrays.asList(sourceFile), null); + } + public JavaTXCompiler(File sourceFile, Boolean log) throws IOException, ClassNotFoundException { + this(sourceFile); + this.log = log; + } + public JavaTXCompiler(List sourceFiles) throws IOException, ClassNotFoundException { + this(sourceFiles, null); + } + public JavaTXCompiler(List sources, List contextPath) throws IOException, ClassNotFoundException { + if(contextPath == null || contextPath.isEmpty()){ + //When no contextPaths are given, the working directory is the sources root + contextPath = Lists.newArrayList(new File(System.getProperty("user.dir"))); + } + classLoader = new DirectoryClassLoader(contextPath, ClassLoader.getSystemClassLoader()); + environment = new CompilationEnvironment(sources); + for (File s : sources) { + sourceFiles.put(s, parse(s)); + } + //INSTANCE = this; + } + + public ConstraintSet getConstraints() throws ClassNotFoundException, IOException { + List allClasses = new ArrayList<>();//environment.getAllAvailableClasses(); + List importedClasses = new ArrayList<>(); + ClassOrInterface objectClass = ASTFactory.createClass( + classLoader.loadClass(new JavaClassName("java.lang.Object").toString())); + //Alle Importierten Klassen in allen geparsten Sourcefiles kommen ins FC + for (File forSourceFile : sourceFiles.keySet()){ + for (JavaClassName name : sourceFiles.get(forSourceFile).getImports()) { + //TODO: Hier werden imports von eigenen (.jav) Klassen nicht beachtet + ClassOrInterface importedClass = ASTFactory.createClass( + classLoader.loadClass(name.toString())); + importedClasses.add(importedClass); + } + for(Class c : CompilationEnvironment.loadDefaultPackageClasses(forSourceFile, classLoader)){ + ClassOrInterface importedClass = ASTFactory.createClass(c); + importedClasses.add(importedClass); + } + } + for (File f : this.sourceFiles.keySet()) { + SourceFile sf = sourceFiles.get(f); + sf = new SourceFile(sf.getPkgName(), + sf.KlassenVektor.stream() + .map(cl -> new ClassOrInterface(cl)) + .collect(Collectors.toCollection(ArrayList::new)), + sf.imports); + //sf enthaelt neues Source-File, neue Klassen-Objekte und neue + //ArrayListen-Objekte fuer Fields, Construktoren und Methoden + //Alle anderen Objekte werden nur kopiert. + SourceFile sf_new = sf; + sf.KlassenVektor.forEach(cl -> addMethods(sf_new, cl, importedClasses, objectClass)); + allClasses.addAll(sf.getClasses()); + } + allClasses.addAll(importedClasses); + return new TYPE(sourceFiles.values(), allClasses).getConstraints(); + } + + void addMethods(SourceFile sf, ClassOrInterface cl, List importedClasses, ClassOrInterface objectClass) { + if (!cl.areMethodsAdded()) { + ClassOrInterface superclass = null; + if (cl.getSuperClass().getName().equals(new JavaClassName("java.lang.Object"))) { + superclass = objectClass; + } + else { + Optional optSuperclass = + importedClasses.stream().filter(x -> x.getClassName().equals( + cl.getSuperClass().getName())).findFirst(); + if (optSuperclass.isPresent()) { + superclass = optSuperclass.get(); + } + else { + optSuperclass = + sf.KlassenVektor.stream().filter(x -> x.getClassName().equals( + cl.getSuperClass().getName())).findFirst(); + if (optSuperclass.isPresent()) { + superclass = optSuperclass.get(); + addMethods(sf, superclass, importedClasses, objectClass); + } + else { + //throw new ClassNotFoundException(""); + } + } + } + Iterator paraIt= cl.getSuperClass().getParaList().iterator(); + Iterator tvarVarIt = superclass.getGenerics().iterator(); + + HashMap gtvs = new HashMap<>(); + while (paraIt.hasNext()) { + gtvs.put(tvarVarIt.next().getName(), paraIt.next()); + } + Iterator methodIt = superclass.getMethods().iterator(); + //TODO: PL 2020-05-06: Hier müssen ueberschriebene Methoden noch rausgefiltert werden + while(methodIt.hasNext()) { + Method m = methodIt.next(); + ParameterList newParaList = new ParameterList( + m.getParameterList() + .getFormalparalist() + .stream() + .map(fp -> new FormalParameter(fp.getName(), fp.getType().acceptTV(new TypeExchanger(gtvs)), fp.getOffset())) + .collect(Collectors.toCollection(ArrayList::new)), m.getParameterList().getOffset()); + cl.getMethods().add(new Method(m.modifier, m.name, m.getReturnType().acceptTV(new TypeExchanger(gtvs)), newParaList, m.block, + //new GenericDeclarationList(newGenericsList, ((GenericDeclarationList)m.getGenerics()).getOffset()), + (GenericDeclarationList)m.getGenerics(), + m.getOffset(), true)); + } + + } + cl.setMethodsAdded(); + } + + + + public List getAvailableClasses(SourceFile forSourceFile) throws ClassNotFoundException { + //PL 2018-09-18: List durch Set ersetzt, damit die Klassen nur einmal hinzugefuegt werden + //List allClasses = new ArrayList<>();//environment.getAllAvailableClasses(); + Set allClasses = new HashSet<>(); + + /* PL 2018-09-19 geloescht werden bereits in typeInference hinzugefuegt + } + allClasses.addAll(importedClasses); + + return new TYPE(sourceFiles.values(), allClasses).getConstraints(); + } + + public List getAvailableClasses(SourceFile forSourceFile) throws ClassNotFoundException { + // PL 2018-09-18: List durch Set ersetzt, damit die Klassen nur einmal + // hinzugefuegt werden + // List allClasses = new + // ArrayList<>();//environment.getAllAvailableClasses(); + Set allClasses = new HashSet<>(); + + /* + * PL 2018-09-19 geloescht werden bereits in typeInference hinzugefuegt for + * (SourceFile sf : sourceFiles.values()) { allClasses.addAll(sf.getClasses()); + * } + */ + + List importedClasses = new ArrayList<>(); + for (JavaClassName name : forSourceFile.getImports()) { + // TODO: Hier werden imports von eigenen (.jav) Klassen nicht beachtet + ClassOrInterface importedClass = ASTFactory + .createClass(classLoader.loadClass(name.toString())); + importedClasses.add(importedClass); + allClasses.addAll(importedClasses); + } + return new ArrayList<>(allClasses); + } + + /* + * public List typeInferenceOld() throws ClassNotFoundException { + * List allClasses = new + * ArrayList<>();//environment.getAllAvailableClasses(); //Alle Importierten + * Klassen in allen geparsten Sourcefiles kommen ins FC for(SourceFile sf : + * this.sourceFiles.values()) { allClasses.addAll(getAvailableClasses(sf)); + * allClasses.addAll(sf.getClasses()); } + * + * final ConstraintSet cons = getConstraints(); + * + * FiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses); + * System.out.println(finiteClosure); ConstraintSet unifyCons = + * UnifyTypeFactory.convert(cons); + * + * TypeUnify unify = new TypeUnify(); Set> results = new + * HashSet<>(); try { File logPath = new + * File(System.getProperty("user.dir")+"/target/logFiles/"); logPath.mkdirs(); + * FileWriter logFile = new FileWriter(new File(logPath, "log")); + * logFile.write("FC:\\" + finiteClosure.toString()+"\n"); for(SourceFile sf : + * this.sourceFiles.values()) { logFile.write(ASTTypePrinter.print(sf)); } + * logFile.flush(); Set>> cardProd = + * unifyCons.cartesianProduct(); for (List> xCons : + * cardProd ){ Set xConsSet = new HashSet<>(); for + * (Constraint constraint : xCons) { xConsSet.addAll(constraint); } + * //.collect(Collectors.toCollection(ArrayList::new)))) + * System.out.println(xConsSet); Set methodParaTypeVarNames = + * allClasses.stream().map(x -> x.getMethods().stream().map(y -> + * y.getParameterList().getFormalparalist() .stream().filter(z -> z.getType() + * instanceof TypePlaceholder) .map(z -> + * ((TypePlaceholder)z.getType()).getName()).collect(Collectors.toCollection( + * HashSet::new))) .reduce(new HashSet(), (a,b) -> { a.addAll(b); return + * a;}, (a,b) -> { a.addAll(b); return a;} ) ) .reduce(new HashSet(), + * (a,b) -> { a.addAll(b); return a;} ); + * + * Set constructorParaTypeVarNames = allClasses.stream().map(x -> + * x.getConstructors().stream().map(y -> + * y.getParameterList().getFormalparalist() .stream().filter(z -> z.getType() + * instanceof TypePlaceholder) .map(z -> + * ((TypePlaceholder)z.getType()).getName()).collect(Collectors.toCollection( + * HashSet::new))) .reduce(new HashSet(), (a,b) -> { a.addAll(b); return + * a;}, (a,b) -> { a.addAll(b); return a;} ) ) .reduce(new HashSet(), + * (a,b) -> { a.addAll(b); return a;} ); + * + * Set paraTypeVarNames = methodParaTypeVarNames; + * paraTypeVarNames.addAll(constructorParaTypeVarNames); + * + * Set returnTypeVarNames = allClasses.stream().map(x -> + * x.getMethods().stream().filter(y -> y.getReturnType() instanceof + * TypePlaceholder) .map(z -> + * ((TypePlaceholder)z.getReturnType()).getName()).collect(Collectors. + * toCollection(HashSet::new))).reduce((a,b) -> { a.addAll(b); return a;} + * ).get(); + * + * Set fieldTypeVarNames = allClasses.stream().map(x -> + * x.getFieldDecl().stream().filter(y -> y.getReturnType() instanceof + * TypePlaceholder) .map(z -> + * ((TypePlaceholder)z.getReturnType()).getName()).collect(Collectors. + * toCollection(HashSet::new))).reduce((a,b) -> { a.addAll(b); return a;} + * ).get(); + * + * returnTypeVarNames.addAll(fieldTypeVarNames); + * + * xConsSet = xConsSet.stream().map(x -> { //Hier muss ueberlegt werden, ob //1. + * alle Argument- und Retuntyp-Variablen in allen UnifyPairs // mit + * disableWildcardtable() werden. //2. alle Typvariablen mit Argument- oder + * Retuntyp-Variablen //in Beziehung auch auf disableWildcardtable() gesetzt + * werden muessen //PL 2018-04-23 if ((x.getLhsType() instanceof + * PlaceholderType)) { if (paraTypeVarNames.contains(x.getLhsType().getName())) + * { ((PlaceholderType)x.getLhsType()).setVariance((byte)1); + * ((PlaceholderType)x.getLhsType()).disableWildcardtable(); } if + * (returnTypeVarNames.contains(x.getLhsType().getName())) { + * ((PlaceholderType)x.getLhsType()).setVariance((byte)-1); + * ((PlaceholderType)x.getLhsType()).disableWildcardtable(); } } if + * ((x.getRhsType() instanceof PlaceholderType)) { if + * (paraTypeVarNames.contains(x.getRhsType().getName())) { + * ((PlaceholderType)x.getRhsType()).setVariance((byte)1); + * ((PlaceholderType)x.getRhsType()).disableWildcardtable(); } if + * (returnTypeVarNames.contains(x.getRhsType().getName())) { + * ((PlaceholderType)x.getRhsType()).setVariance((byte)-1); + * ((PlaceholderType)x.getRhsType()).disableWildcardtable(); } } return x;//HIER + * DIE JEWEILS RECHT BZW. LINKE SEITE AUF GLEICHE VARIANZ SETZEN WIE DIE JEWEILS + * ANDERE SEITE }).map( y -> { if ((y.getLhsType() instanceof PlaceholderType) + * && (y.getRhsType() instanceof PlaceholderType)) { if + * (((PlaceholderType)y.getLhsType()).getVariance() != 0 && + * ((PlaceholderType)y.getRhsType()).getVariance() == 0) { + * ((PlaceholderType)y.getRhsType()).setVariance(((PlaceholderType)y.getLhsType( + * )).getVariance()); } if (((PlaceholderType)y.getLhsType()).getVariance() == 0 + * && ((PlaceholderType)y.getRhsType()).getVariance() != 0) { + * ((PlaceholderType)y.getLhsType()).setVariance(((PlaceholderType)y.getRhsType( + * )).getVariance()); } } return y; } ) + * .collect(Collectors.toCollection(HashSet::new)); + * varianceInheritance(xConsSet); Set> result = + * unify.unifySequential(xConsSet, finiteClosure, logFile, log); + * //Set> result = unify.unify(xConsSet, finiteClosure); + * System.out.println("RESULT: " + result); logFile.write("RES: " + + * result.toString()+"\n"); logFile.flush(); results.addAll(result); } + * + * results = results.stream().map(x -> { Optional> res = new + * RuleSet().subst(x.stream().map(y -> { if (y.getPairOp() == + * PairOperator.SMALLERDOTWC) y.setPairOp(PairOperator.EQUALSDOT); return y; + * //alle Paare a <.? b erden durch a =. b ersetzt + * }).collect(Collectors.toCollection(HashSet::new))); if (res.isPresent()) + * {//wenn subst ein Erg liefert wurde was veraendert return new + * TypeUnifyTask().applyTypeUnificationRules(res.get(), finiteClosure); } else + * return x; //wenn nichts veraendert wurde wird x zurueckgegeben + * }).collect(Collectors.toCollection(HashSet::new)); + * System.out.println("RESULT Final: " + results); logFile.write("RES_FINAL: " + + * results.toString()+"\n"); logFile.flush(); logFile.write("PLACEHOLDERS: " + + * PlaceholderType.EXISTING_PLACEHOLDERS); logFile.flush(); } catch (IOException + * e) { e.printStackTrace(); } return results.stream().map((unifyPairs -> new + * ResultSet(UnifyTypeFactory.convert(unifyPairs, + * generateTPHMap(cons))))).collect(Collectors.toList()); } + */ + /** + * Vererbt alle Variancen bei Paaren (a <. theta) oder (Theta <. a) wenn a eine + * Variance !=0 hat auf alle Typvariablen in Theta. + * + * + */ + /* + * private void varianceInheritance(Set eq) { Set + * usedTPH = new HashSet<>(); Set phSet = eq.stream().map(x -> + * { Set pair = new HashSet<>(); if (x.getLhsType() instanceof + * PlaceholderType) pair.add((PlaceholderType)x.getLhsType()); if + * (x.getRhsType() instanceof PlaceholderType) + * pair.add((PlaceholderType)x.getRhsType()); return pair; }).reduce(new + * HashSet<>(), (a,b) -> { a.addAll(b); return a;} , (c,d) -> { c.addAll(d); + * return c;}); + * + * ArrayList phSetVariance = new ArrayList<>(phSet); + * phSetVariance.removeIf(x -> (x.getVariance() == 0)); + * while(!phSetVariance.isEmpty()) { PlaceholderType a = + * phSetVariance.remove(0); usedTPH.add(a); //HashMap + * ht = new HashMap<>(); //ht.put(a, a.getVariance()); Set eq1 = new + * HashSet<>(eq); eq1.removeIf(x -> !(x.getLhsType() instanceof PlaceholderType + * && ((PlaceholderType)x.getLhsType()).equals(a))); eq1.stream().forEach(x -> { + * x.getRhsType().accept(new distributeVariance(), a.getVariance());}); eq1 = + * new HashSet<>(eq); eq1.removeIf(x -> !(x.getRhsType() instanceof + * PlaceholderType && ((PlaceholderType)x.getRhsType()).equals(a))); + * eq1.stream().forEach(x -> { x.getLhsType().accept(new distributeVariance(), + * a.getVariance());}); phSetVariance = new ArrayList<>(phSet); + * phSetVariance.removeIf(x -> (x.getVariance() == 0 || usedTPH.contains(x))); } + * } + */ + + public UnifyResultModel typeInferenceAsync(UnifyResultListener resultListener, Writer logFile) + throws ClassNotFoundException, IOException { + List allClasses = new ArrayList<>();// environment.getAllAvailableClasses(); + // Alle Importierten Klassen in allen geparsten Sourcefiles kommen ins FC + for (File f : this.sourceFiles.keySet()) { + SourceFile sf = sourceFiles.get(f); + allClasses.addAll(getAvailableClasses(sf)); + allClasses.addAll(sf.getClasses()); + allClasses.addAll(CompilationEnvironment.loadDefaultPackageClasses(f,classLoader).stream().map(ASTFactory::createClass).collect(Collectors.toList())); + } + + final ConstraintSet cons = getConstraints(); + Set> results = new HashSet<>(); + UnifyResultModel urm = null; + // urm.addUnifyResultListener(resultListener); + try { + logFile = logFile == null + ? new FileWriter(new File("log_" + sourceFiles.keySet().iterator().next().getName())) + : logFile; + IFiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses, logFile, classLoader); + System.out.println(finiteClosure); + urm = new UnifyResultModel(cons, finiteClosure); + urm.addUnifyResultListener(resultListener); + ConstraintSet unifyCons = UnifyTypeFactory.convert(cons); + + Function distributeInnerVars = x -> { + UnifyType lhs, rhs; + if (((lhs = x.getLhsType()) instanceof PlaceholderType) + && ((rhs = x.getRhsType()) instanceof PlaceholderType) + && (((PlaceholderType) lhs).isInnerType() || ((PlaceholderType) rhs).isInnerType())) { + ((PlaceholderType) lhs).setInnerType(true); + ((PlaceholderType) rhs).setInnerType(true); + } + return x; + + }; + logFile.write(unifyCons.toString()); + unifyCons = unifyCons.map(distributeInnerVars); + logFile.write(unifyCons.toString()); + TypeUnify unify = new TypeUnify(); + // Set> results = new HashSet<>(); Nach vorne gezogen + logFile.write("FC:\\" + finiteClosure.toString() + "\n"); + for (SourceFile sf : this.sourceFiles.values()) { + logFile.write(ASTTypePrinter.print(sf)); + } + logFile.flush(); + + Set methodParaTypeVarNames = allClasses.stream().map(x -> x.getMethods().stream() + .map(y -> y.getParameterList().getFormalparalist().stream() + .filter(z -> z.getType() instanceof TypePlaceholder) + .map(z -> ((TypePlaceholder) z.getType()).getName()) + .collect(Collectors.toCollection(HashSet::new))) + .reduce(new HashSet(), (a, b) -> { + a.addAll(b); + return a; + }, (a, b) -> { + a.addAll(b); + return a; + })).reduce(new HashSet(), (a, b) -> { + a.addAll(b); + return a; + }); + + Set constructorParaTypeVarNames = allClasses.stream().map(x -> x.getConstructors().stream() + .map(y -> y.getParameterList().getFormalparalist().stream() + .filter(z -> z.getType() instanceof TypePlaceholder) + .map(z -> ((TypePlaceholder) z.getType()).getName()) + .collect(Collectors.toCollection(HashSet::new))) + .reduce(new HashSet(), (a, b) -> { + a.addAll(b); + return a; + }, (a, b) -> { + a.addAll(b); + return a; + })).reduce(new HashSet(), (a, b) -> { + a.addAll(b); + return a; + }); + + Set paraTypeVarNames = methodParaTypeVarNames; + paraTypeVarNames.addAll(constructorParaTypeVarNames); + + Set returnTypeVarNames = allClasses.stream() + .map(x -> x.getMethods().stream().filter(y -> y.getReturnType() instanceof TypePlaceholder) + .map(z -> ((TypePlaceholder) z.getReturnType()).getName()) + .collect(Collectors.toCollection(HashSet::new))) + .reduce((a, b) -> { + a.addAll(b); + return a; + }).get(); + + Set fieldTypeVarNames = allClasses.stream() + .map(x -> x.getFieldDecl().stream().filter(y -> y.getReturnType() instanceof TypePlaceholder) + .map(z -> ((TypePlaceholder) z.getReturnType()).getName()) + .collect(Collectors.toCollection(HashSet::new))) + .reduce((a, b) -> { + a.addAll(b); + return a; + }).get(); + + returnTypeVarNames.addAll(fieldTypeVarNames); + + unifyCons = unifyCons.map(x -> { + // Hier muss ueberlegt werden, ob + // 1. alle Argument- und Retuntyp-Variablen in allen UnifyPairs + // mit disableWildcardtable() werden. + // 2. alle Typvariablen mit Argument- oder Retuntyp-Variablen + // in Beziehung auch auf disableWildcardtable() gesetzt werden muessen + // PL 2018-04-23 + if ((x.getLhsType() instanceof PlaceholderType)) { + if (paraTypeVarNames.contains(x.getLhsType().getName())) { + ((PlaceholderType) x.getLhsType()).setVariance((byte) 1); + ((PlaceholderType) x.getLhsType()).disableWildcardtable(); + } + if (returnTypeVarNames.contains(x.getLhsType().getName())) { + ((PlaceholderType) x.getLhsType()).setVariance((byte) -1); + ((PlaceholderType) x.getLhsType()).disableWildcardtable(); + } + } + if ((x.getRhsType() instanceof PlaceholderType)) { + if (paraTypeVarNames.contains(x.getRhsType().getName())) { + ((PlaceholderType) x.getRhsType()).setVariance((byte) 1); + ((PlaceholderType) x.getRhsType()).disableWildcardtable(); + } + if (returnTypeVarNames.contains(x.getRhsType().getName())) { + ((PlaceholderType) x.getRhsType()).setVariance((byte) -1); + ((PlaceholderType) x.getRhsType()).disableWildcardtable(); + } + } + return x;// HIER DIE JEWEILS RECHT BZW. LINKE SEITE AUF GLEICHE VARIANZ SETZEN WIE DIE + // JEWEILS ANDERE SEITE + }); + Set varianceTPHold; + Set varianceTPH = new HashSet<>(); + varianceTPH = varianceInheritanceConstraintSet(unifyCons); + + /* + * PL 2018-11-07 wird in varianceInheritanceConstraintSet erledigt do { //PL + * 2018-11-05 Huellenbildung Variance auf alle TPHs der Terme auf der jeweiligen + * //anderen Seite übertragen varianceTPHold = new HashSet<>(varianceTPH); + * varianceTPH = varianceInheritanceConstraintSet(unifyCons); unifyCons.map( y + * -> { if ((y.getLhsType() instanceof PlaceholderType) && (y.getRhsType() + * instanceof PlaceholderType)) { if + * (((PlaceholderType)y.getLhsType()).getVariance() != 0 && + * ((PlaceholderType)y.getRhsType()).getVariance() == 0) { + * ((PlaceholderType)y.getRhsType()).setVariance(((PlaceholderType)y.getLhsType( + * )).getVariance()); } if (((PlaceholderType)y.getLhsType()).getVariance() == 0 + * && ((PlaceholderType)y.getRhsType()).getVariance() != 0) { + * ((PlaceholderType)y.getLhsType()).setVariance(((PlaceholderType)y.getRhsType( + * )).getVariance()); } } return y; } ); } while + * (!varianceTPHold.equals(varianceTPH)); + */ + + // Set> result = unify.unifySequential(xConsSet, finiteClosure, + // logFile, log); + // Set> result = unify.unify(xConsSet, finiteClosure); + List>> oderConstraints = unifyCons.getOderConstraints()/*.stream().map(x -> { + Set> ret = new HashSet<>(); + for (Constraint y : x) { + ret.add(new HashSet<>(y)); + } + return ret; + }).collect(Collectors.toCollection(ArrayList::new))*/; + unify.unifyAsync(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, logFile, log, urm, + usedTasks); + } catch (IOException e) { + System.err.println("kein LogFile"); + } + return urm; + } + + public List typeInference() throws ClassNotFoundException, IOException { + List allClasses = new ArrayList<>();// environment.getAllAvailableClasses(); + // Alle Importierten Klassen in allen geparsten Sourcefiles kommen ins FC + for (File f : this.sourceFiles.keySet()) { + SourceFile sf = sourceFiles.get(f); + allClasses.addAll(getAvailableClasses(sf)); + allClasses.addAll(sf.getClasses()); + allClasses.addAll(CompilationEnvironment.loadDefaultPackageClasses(f,classLoader).stream().map(ASTFactory::createClass).collect(Collectors.toList())); + } + + final ConstraintSet cons = getConstraints(); + Set> results = new HashSet<>(); + try { + Writer logFile = //new OutputStreamWriter(new NullOutputStream()); + // new FileWriter(new + // File(System.getProperty("user.dir")+"/resources/logFiles/"+"log_"+sourceFiles.keySet().iterator().next().getName())); + new FileWriter(new File(System.getProperty("user.dir") + "/logFiles/" + "log_" + + sourceFiles.keySet().iterator().next().getName())); + IFiniteClosure finiteClosure = UnifyTypeFactory.generateFC(allClasses, logFile, classLoader); + System.out.println(finiteClosure); + ConstraintSet unifyCons = UnifyTypeFactory.convert(cons); + System.out.println("xxx1"); + Function distributeInnerVars = x -> { + UnifyType lhs, rhs; + if (((lhs = x.getLhsType()) instanceof PlaceholderType) + && ((rhs = x.getRhsType()) instanceof PlaceholderType) + && (((PlaceholderType) lhs).isInnerType() || ((PlaceholderType) rhs).isInnerType())) { + ((PlaceholderType) lhs).setInnerType(true); + ((PlaceholderType) rhs).setInnerType(true); + } + return x; + + }; + + logFile.write("Unify:" + unifyCons.toString()); + System.out.println("Unify:" + unifyCons.toString()); + unifyCons = unifyCons.map(distributeInnerVars); + logFile.write("\nUnify_distributeInnerVars: " + unifyCons.toString()); + TypeUnify unify = new TypeUnify(); + // Set> results = new HashSet<>(); Nach vorne gezogen + logFile.write("FC:\\" + finiteClosure.toString() + "\n"); + for (SourceFile sf : this.sourceFiles.values()) { + logFile.write(ASTTypePrinter.print(sf)); + System.out.println(ASTTypePrinter.print(sf)); + } + logFile.flush(); + + Set methodParaTypeVarNames = allClasses.stream().map(x -> x.getMethods().stream() + .map(y -> y.getParameterList().getFormalparalist().stream() + .filter(z -> z.getType() instanceof TypePlaceholder) + .map(z -> ((TypePlaceholder) z.getType()).getName()) + .collect(Collectors.toCollection(HashSet::new))) + .reduce(new HashSet(), (a, b) -> { + a.addAll(b); + return a; + }, (a, b) -> { + a.addAll(b); + return a; + })).reduce(new HashSet(), (a, b) -> { + a.addAll(b); + return a; + }); + + Set constructorParaTypeVarNames = allClasses.stream().map(x -> x.getConstructors().stream() + .map(y -> y.getParameterList().getFormalparalist().stream() + .filter(z -> z.getType() instanceof TypePlaceholder) + .map(z -> ((TypePlaceholder) z.getType()).getName()) + .collect(Collectors.toCollection(HashSet::new))) + .reduce(new HashSet(), (a, b) -> { + a.addAll(b); + return a; + }, (a, b) -> { + a.addAll(b); + return a; + })).reduce(new HashSet(), (a, b) -> { + a.addAll(b); + return a; + }); + + Set paraTypeVarNames = methodParaTypeVarNames; + paraTypeVarNames.addAll(constructorParaTypeVarNames); + + Set returnTypeVarNames = allClasses.stream() + .map(x -> x.getMethods().stream().filter(y -> y.getReturnType() instanceof TypePlaceholder) + .map(z -> ((TypePlaceholder) z.getReturnType()).getName()) + .collect(Collectors.toCollection(HashSet::new))) + .reduce((a, b) -> { + a.addAll(b); + return a; + }).get(); + + Set fieldTypeVarNames = allClasses.stream() + .map(x -> x.getFieldDecl().stream().filter(y -> y.getReturnType() instanceof TypePlaceholder) + .map(z -> ((TypePlaceholder) z.getReturnType()).getName()) + .collect(Collectors.toCollection(HashSet::new))) + .reduce((a, b) -> { + a.addAll(b); + return a; + }).get(); + + returnTypeVarNames.addAll(fieldTypeVarNames); + + unifyCons = unifyCons.map(x -> { + // Hier muss ueberlegt werden, ob + // 1. alle Argument- und Retuntyp-Variablen in allen UnifyPairs + // mit disableWildcardtable() werden. + // 2. alle Typvariablen mit Argument- oder Retuntyp-Variablen + // in Beziehung auch auf disableWildcardtable() gesetzt werden muessen + // PL 2018-04-23 + if ((x.getLhsType() instanceof PlaceholderType)) { + if (paraTypeVarNames.contains(x.getLhsType().getName())) { + ((PlaceholderType) x.getLhsType()).setVariance((byte) 1); + ((PlaceholderType) x.getLhsType()).disableWildcardtable(); + } + if (returnTypeVarNames.contains(x.getLhsType().getName())) { + ((PlaceholderType) x.getLhsType()).setVariance((byte) -1); + ((PlaceholderType) x.getLhsType()).disableWildcardtable(); + } + } + if ((x.getRhsType() instanceof PlaceholderType)) { + if (paraTypeVarNames.contains(x.getRhsType().getName())) { + ((PlaceholderType) x.getRhsType()).setVariance((byte) 1); + ((PlaceholderType) x.getRhsType()).disableWildcardtable(); + } + if (returnTypeVarNames.contains(x.getRhsType().getName())) { + ((PlaceholderType) x.getRhsType()).setVariance((byte) -1); + ((PlaceholderType) x.getRhsType()).disableWildcardtable(); + } + } + return x;// HIER DIE JEWEILS RECHT BZW. LINKE SEITE AUF GLEICHE VARIANZ SETZEN WIE DIE + // JEWEILS ANDERE SEITE + }); + + //PL 2020-02-05 alle Oder-Constraints Receiver und Parameter werden auf variance 1 gesetzt + //Es wird davon ausgegangen, dass in OderConstraints in Bedingungen für Parameter die Typen der Argumente links stehen + //und die Typen der Rückgabewerte immer rechts stehen + + /* + unifyCons.getOderConstraints().forEach(z -> z.forEach(y -> y.forEach(x -> { + if ((x.getLhsType() instanceof PlaceholderType) && x.getPairOp().compareTo(PairOperator.SMALLERDOT) == 0) { + ((PlaceholderType) x.getLhsType()).setVariance((byte)1); + } + else if ((x.getRhsType() instanceof PlaceholderType) && x.getPairOp().compareTo(PairOperator.EQUALSDOT) == 0) { + ((PlaceholderType) x.getRhsType()).setVariance((byte)-1); + } + }))); + */ + + System.out.println("Unify nach Oder-Constraints-Anpassung:" + unifyCons.toString()); + Set varianceTPHold; + Set varianceTPH = new HashSet<>(); + varianceTPH = varianceInheritanceConstraintSet(unifyCons); + + /* + * PL 2018-11-07 wird in varianceInheritanceConstraintSet erledigt do { //PL + * 2018-11-05 Huellenbildung Variance auf alle TPHs der Terme auf der jeweiligen + * //anderen Seite übertragen varianceTPHold = new HashSet<>(varianceTPH); + * varianceTPH = varianceInheritanceConstraintSet(unifyCons); unifyCons.map( y + * -> { if ((y.getLhsType() instanceof PlaceholderType) && (y.getRhsType() + * instanceof PlaceholderType)) { if + * (((PlaceholderType)y.getLhsType()).getVariance() != 0 && + * ((PlaceholderType)y.getRhsType()).getVariance() == 0) { + * ((PlaceholderType)y.getRhsType()).setVariance(((PlaceholderType)y.getLhsType( + * )).getVariance()); } if (((PlaceholderType)y.getLhsType()).getVariance() == 0 + * && ((PlaceholderType)y.getRhsType()).getVariance() != 0) { + * ((PlaceholderType)y.getLhsType()).setVariance(((PlaceholderType)y.getRhsType( + * )).getVariance()); } } return y; } ); } while + * (!varianceTPHold.equals(varianceTPH)); + */ + + // Set> result = unify.unifySequential(xConsSet, finiteClosure, + // logFile, log); + // Set> result = unify.unify(xConsSet, finiteClosure); + List>> oderConstraints = unifyCons.getOderConstraints()//.stream().map(x -> { + /*Set> ret = new HashSet<>(); + for (Constraint y : x) { + ret.add(new HashSet<>(y)); + } + return ret; + }).collect(Collectors.toCollection(ArrayList::new))*/; + if (resultmodel) { + /* UnifyResultModel Anfang */ + UnifyResultModel urm = new UnifyResultModel(cons, finiteClosure); + UnifyResultListenerImpl li = new UnifyResultListenerImpl(); + urm.addUnifyResultListener(li); + unify.unifyParallel(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, logFile, log, urm, + usedTasks); + System.out.println("RESULT Final: " + li.getResults()); + logFile.write("RES_FINAL: " + li.getResults().toString() + "\n"); + logFile.flush(); + return li.getResults(); + } + /* UnifyResultModel End */ + else { + // Set> result = unify.unify(unifyCons.getUndConstraints(), + // oderConstraints, finiteClosure, logFile, log, new UnifyResultModel(cons, + // finiteClosure)); + Set> result = unify.unifyOderConstraints(unifyCons.getUndConstraints(), oderConstraints, + finiteClosure, logFile, log, new UnifyResultModel(cons, finiteClosure), usedTasks); + System.out.println("RESULT: " + result); + logFile.write("RES: " + result.toString() + "\n"); + logFile.flush(); + results.addAll(result); + + results = results.stream().map(x -> { + Optional> res = new RuleSet().subst(x.stream().map(y -> { + if (y.getPairOp() == PairOperator.SMALLERDOTWC) + y.setPairOp(PairOperator.EQUALSDOT); + return y; // alle Paare a <.? b erden durch a =. b ersetzt + }).collect(Collectors.toCollection(HashSet::new))); + if (res.isPresent()) {// wenn subst ein Erg liefert wurde was veraendert + return new TypeUnifyTask().applyTypeUnificationRules(res.get(), finiteClosure); + } else + return x; // wenn nichts veraendert wurde wird x zurueckgegeben + }).collect(Collectors.toCollection(HashSet::new)); + System.out.println("RESULT Final: " + results); + logFile.write("RES_FINAL: " + results.toString() + "\n"); + logFile.flush(); + logFile.write("PLACEHOLDERS: " + PlaceholderType.EXISTING_PLACEHOLDERS); + logFile.flush(); + } + } catch (IOException e) { + System.err.println("kein LogFile"); + } + return results.stream() + .map((unifyPairs -> new ResultSet(UnifyTypeFactory.convert(unifyPairs, Pair.generateTPHMap(cons))))) + .collect(Collectors.toList()); + } + + /** + * Vererbt alle Variancen bei Paaren (a <. theta) oder (Theta <. a) wenn a eine + * Variance !=0 hat auf alle Typvariablen in Theta. + * + * + */ + private Set varianceInheritanceConstraintSet(ConstraintSet cons) { + Set eq = cons.getAll(); + Set usedTPH = new HashSet<>(); + Set phSet = eq.stream().map(x -> { + Set pair = new HashSet<>(); + if (x.getLhsType() instanceof PlaceholderType) + pair.add((PlaceholderType) x.getLhsType()); + if (x.getRhsType() instanceof PlaceholderType) + pair.add((PlaceholderType) x.getRhsType()); + return pair; + }).reduce(new HashSet<>(), (a, b) -> { + a.addAll(b); + return a; + }, (c, d) -> { + c.addAll(d); + return c; + }); + + ArrayList phSetVariance = new ArrayList<>(phSet); + phSetVariance.removeIf(x -> (x.getVariance() == 0)); + while (!phSetVariance.isEmpty()) { + PlaceholderType a = phSetVariance.remove(0); + usedTPH.add(a); + // HashMap ht = new HashMap<>(); + // ht.put(a, a.getVariance()); + // ConstraintSet eq1 = cons; + // eq1.removeIf(x -> !(x.getLhsType() instanceof PlaceholderType && + // ((PlaceholderType)x.getLhsType()).equals(a))); + // durch if-Abfrage im foreach geloest + cons.forEach(x -> { + if (x.getLhsType() instanceof PlaceholderType && ((PlaceholderType) x.getLhsType()).equals(a)) { + x.getRhsType().accept(new distributeVariance(), a.getVariance()); + } + }); + // ` eq1 = new HashSet<>(eq); + // eq1.removeIf(x -> !(x.getRhsType() instanceof PlaceholderType && + // ((PlaceholderType)x.getRhsType()).equals(a))); + // durch if-Abfrage im foreach geloest + cons.forEach(x -> { + if (x.getRhsType() instanceof PlaceholderType && ((PlaceholderType) x.getRhsType()).equals(a)) { + x.getLhsType().accept(new distributeVariance(), a.getVariance()); + } + }); + phSetVariance = new ArrayList<>(phSet); // macht vermutlich keinen Sinn PL 2018-10-18, doch, es koennen neue + // TPHs mit Variancen dazugekommen sein PL 2018-11-07 + phSetVariance.removeIf(x -> (x.getVariance() == 0 || usedTPH.contains(x))); + } + return usedTPH; + } + + private SourceFile parse(File sourceFile) throws IOException, java.lang.ClassNotFoundException { + CompilationUnitContext tree = JavaTXParser.parse(sourceFile); + SyntaxTreeGenerator generator = new SyntaxTreeGenerator(environment.getRegistry(sourceFile, classLoader), + new GenericsRegistry(null)); + SourceFile ret = generator.convert(tree, environment.packageCrawler, classLoader); + return ret; + } + + public void generateBytecodForFile(File path, HashMap classFiles, SourceFile sf, + List typeinferenceResult) throws IOException { + try { + List genericResults = getGeneratedGenericResultsForAllSourceFiles(typeinferenceResult); + BytecodeGen bytecodeGen = new BytecodeGen(classFiles,typeinferenceResult, genericResults, sf,path, classLoader); + bytecodeGen.visit(sf); + this.writeClassFile(bytecodeGen.getClassFiles(), path); + } catch (ClassNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + + public List getGeneratedGenericResultsForAllSourceFiles() + throws ClassNotFoundException, IOException { + List result = new ArrayList<>(); + for (File f : sourceFiles.keySet()) { + SourceFile sf = sourceFiles.get(f); + List typeinferenceResult = this.typeInference(); + GeneratedGenericsFinder sResFinder = new GeneratedGenericsFinder(sf, typeinferenceResult); + GenericGenratorResultForSourceFile simplifyResOfSF = sResFinder.findGeneratedGenerics(); + result.add(simplifyResOfSF); + } + return result; + } + + public List getGeneratedGenericResultsForAllSourceFiles( + List typeinferenceResult) throws ClassNotFoundException { + List result = new ArrayList<>(); + for (File f : sourceFiles.keySet()) { + SourceFile sf = sourceFiles.get(f); + GeneratedGenericsFinder sResFinder = new GeneratedGenericsFinder(sf, typeinferenceResult); + GenericGenratorResultForSourceFile simplifyResOfSF = sResFinder.findGeneratedGenerics(); + this.fogg = sResFinder.getFogg(); + result.add(simplifyResOfSF); + } + return result; + } + + public void generateBytecode() throws ClassNotFoundException, IOException, BytecodeGeneratorError { + generateBytecode((File) null); + } + + /** + * @param path - can be null, then class file output is in the same directory as the parsed source files + */ + public void generateBytecode(String path) throws ClassNotFoundException, IOException, BytecodeGeneratorError { + if(path != null) + generateBytecode(new File(path)); + else + generateBytecode(); + } + + /** + * @param path - can be null, then class file output is in the same directory as the parsed source files + */ + public void generateBytecode(File path) throws ClassNotFoundException, IOException, BytecodeGeneratorError { + List typeinferenceResult = this.typeInference(); + List simplifyResultsForAllSourceFiles = getGeneratedGenericResultsForAllSourceFiles( + typeinferenceResult); + generateBytecode(path, typeinferenceResult, simplifyResultsForAllSourceFiles); + } + + /** + * @param outputPath - can be null, then class file output is in the same directory as the parsed source files + * @param typeinferenceResult + * @param simplifyResultsForAllSourceFiles + * @throws IOException + */ + public void generateBytecode(File outputPath, List typeinferenceResult, + List simplifyResultsForAllSourceFiles) throws IOException { + for (File f : sourceFiles.keySet()) { + HashMap classFiles = new HashMap<>(); + SourceFile sf = sourceFiles.get(f); + File path; + if(outputPath == null){ + path = f.getParentFile(); //Set path to path of the parsed .jav file + }else{ + path = new File(outputPath ,sf.getPkgName().replace(".","/")); //add package path to root path + } + BytecodeGen bytecodeGen = new BytecodeGen(classFiles, typeinferenceResult, simplifyResultsForAllSourceFiles, + sf, path, classLoader); + bytecodeGen.visit(sf); + writeClassFile(bytecodeGen.getClassFiles(), path); + } + } + + private void writeClassFile(HashMap classFiles, File path) throws IOException { + FileOutputStream output; + for (JavaClassName name : classFiles.keySet()) { + byte[] bytecode = classFiles.get(name); + System.out.println("generating " + name + ".class file ..."); + // output = new FileOutputStream(new File(System.getProperty("user.dir") + + // "/testBytecode/generatedBC/" +name+".class")); + File outputFile = new File(path, name.getClassName() + ".class"); + outputFile.getAbsoluteFile().getParentFile().mkdirs(); + output = new FileOutputStream(outputFile); + output.write(bytecode); + output.close(); + System.out.println(name + ".class file generated"); + } + } + + /* PL 2020-03-17 mit TypeExchanger in FCGenerator.java zusammenfuehren */ + /** + * Tauscht die GTVs in einem Typ gegen die entsprechenden Typen in der übergebenen Map aus. + */ + private static class TypeExchanger implements TypeVisitor{ + + private final HashMap gtvs; + + TypeExchanger(HashMap gtvs){ + this.gtvs = gtvs; + } + + @Override + public RefTypeOrTPHOrWildcardOrGeneric visit(RefType refType) { + List params = new ArrayList<>(); + for(RefTypeOrTPHOrWildcardOrGeneric param : refType.getParaList()){ + params.add(param.acceptTV(this)); + } + RefTypeOrTPHOrWildcardOrGeneric ret = new RefType(refType.getName(), params, new NullToken()); + return ret; + } + + @Override + public RefTypeOrTPHOrWildcardOrGeneric visit(SuperWildcardType superWildcardType) { + SuperWildcardType ret = new SuperWildcardType(superWildcardType.getInnerType().acceptTV(this), superWildcardType.getOffset()); + return ret; + } + + @Override + public RefTypeOrTPHOrWildcardOrGeneric visit(TypePlaceholder typePlaceholder) { + return typePlaceholder; //TypePlaceholder der vererbert wird kann bei der Vererbung nicht instanziert werden. + } + + @Override + public RefTypeOrTPHOrWildcardOrGeneric visit(ExtendsWildcardType extendsWildcardType) { + ExtendsWildcardType ret = new ExtendsWildcardType(extendsWildcardType.getInnerType().acceptTV(this), extendsWildcardType.getOffset()); + return ret; + } + + @Override + public RefTypeOrTPHOrWildcardOrGeneric visit(GenericRefType genericRefType) { + if(! gtvs.containsKey(genericRefType.getParsedName())) + throw new DebugException("Dieser Fall darf nicht auftreten"); + return gtvs.get(genericRefType.getParsedName()); + } + + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/environment/CompilationEnvironment.java b/app/src/main/java/de/dhbwstuttgart/environment/CompilationEnvironment.java new file mode 100644 index 00000000..746d1e85 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/environment/CompilationEnvironment.java @@ -0,0 +1,109 @@ +package de.dhbwstuttgart.environment; + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.*; + +import com.google.common.collect.Lists; +import de.dhbwstuttgart.syntaxtree.ClassOrInterface; +import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; +import org.antlr.v4.runtime.tree.TerminalNode; + +import de.dhbwstuttgart.exceptions.DebugException; +import de.dhbwstuttgart.parser.JavaTXParser; +import de.dhbwstuttgart.parser.antlr.Java8Parser.CompilationUnitContext; +import de.dhbwstuttgart.parser.scope.GatherNames; +import de.dhbwstuttgart.parser.scope.JavaClassRegistry; + +/** + * Stellt die Java-Environment dar und speichert alle Binarys, Librarys und Sourcefiles im zu kompilierenden Projekt + * Sie erstellt anhand dieser Informationen die JavaClassNameRegistry + * + * TODO: Zur Initialisierung der CompilationEnvironment sollten alle SourceFiles mit ANTLR geparst werden und alle Klassen Generics und Typen herausgefunden werden + */ +public class CompilationEnvironment { + private final List librarys; + private final List sourceFiles; + public final PackageCrawler packageCrawler; + + /** + * Imitiert die Environment beim Aufruf des JavaCompilers auf einer Menge von java-Dateien + * Die Environment enth�lt automatisch die Java Standard Library + * @param sourceFiles die zu kompilierenden Dateien + */ + public CompilationEnvironment(List sourceFiles) { + /** + * Java 9 bringt einige Änderungen am Classloader + * So funktioniert der BootClassLoader nicht mehr. + * hier gibts ein paar Quellen zum nachlesen: + * http://java9.wtf/class-loading/ + * https://stackoverflow.com/questions/46494112/classloaders-hierarchy-in-java-9 + * + */ + //String bootClassPath = System.getProperty("sun.boot.class.path"); + // DirectoryClassLoader cl = DirectoryClassLoader.getPlatformClassLoader(); + String bootClassPath = System.getProperty("java.class.path"); + librarys = new ArrayList<>(); + for(String path : bootClassPath.split(File.pathSeparator)) { + try { + librarys.add(new URL("file:"+path)); + } catch (MalformedURLException e) { + new DebugException("Fehler im Classpath auf diesem System"); + } + } + //URLClassLoader loader = new URLClassLoader(new URL[0], cl); + //librarys = Arrays.asList(loader.getURLs()); + + this.sourceFiles = sourceFiles; + this.packageCrawler = new PackageCrawler(librarys); + } + + public JavaClassRegistry getRegistry(File forSourceFile, ClassLoader classLoader) throws ClassNotFoundException, IOException { + Map allNames; + CompilationUnitContext tree = JavaTXParser.parse(forSourceFile); + allNames = GatherNames.getNames(tree, packageCrawler, classLoader); + for(Class c : loadDefaultPackageClasses(forSourceFile, classLoader)){ + allNames.put(c.getName(), c.getTypeParameters().length); + } + return new JavaClassRegistry(allNames); + } + + public static List loadDefaultPackageClasses(File forSourceFile, ClassLoader classLoader) throws IOException, ClassNotFoundException { + List ret = new ArrayList<>(); + String packageName = getPackageName(JavaTXParser.parse(forSourceFile)); + //Set classLoader to include default package for this specific source file + File dir = new File(forSourceFile.getAbsoluteFile().getParent()); + String dirPath = dir.toString() + "/"; + if(packageName.length()>0)dirPath = dirPath.substring(0,dirPath.length() - packageName.length()); + String path = dirPath; + ArrayList defaultPath = Lists.newArrayList(new File(path)); + classLoader = new DirectoryClassLoader(defaultPath, classLoader); + //Gather all names in the default package for this source file (classes that are imported by default) + File [] files = dir.listFiles((dir1, name) -> name.endsWith(".class")); + if(files != null)for (File classFile : files) { + String className = classFile.getName().substring(0,classFile.getName().length()-6); + ret.add(classLoader.loadClass(packageName + className)); + } + return ret; + } + + private static String getPackageName(CompilationUnitContext forTree){ + String packageName = ""; + if(forTree.packageDeclaration() != null && forTree.packageDeclaration().Identifier() != null) + for(TerminalNode subPackage : forTree.packageDeclaration().Identifier()){ + packageName += subPackage.toString() + "."; + } + return packageName; + } + + public List getAllAvailableClasses() { + List ret = new ArrayList<>(); + for(Class c : new PackageCrawler(librarys).getAllAvailableClasses()){ + ret.add(ASTFactory.createClass(c)); + } + return ret; + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/environment/DirectoryClassLoader.java b/app/src/main/java/de/dhbwstuttgart/environment/DirectoryClassLoader.java new file mode 100644 index 00000000..a74dbc49 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/environment/DirectoryClassLoader.java @@ -0,0 +1,31 @@ +package de.dhbwstuttgart.environment; + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.List; +import java.util.stream.Collectors; + +public class DirectoryClassLoader extends URLClassLoader { + public DirectoryClassLoader(File directory, java.lang.ClassLoader parent) { + super(generateURLArray(dirToURL(directory)), parent); + } + + public DirectoryClassLoader(List directory, java.lang.ClassLoader parent) { + super(directory.stream().map(DirectoryClassLoader::dirToURL).collect(Collectors.toList()).toArray(new URL[0]), parent); + } + + private static URL[] generateURLArray(URL url) { + return new URL[]{url}; + } + + private static URL dirToURL(File url){ + if(!url.isDirectory())throw new RuntimeException(url.toString() + " is not a directory"); + try { + return url.toURI().toURL(); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/environment/PackageCrawler.java b/app/src/main/java/de/dhbwstuttgart/environment/PackageCrawler.java new file mode 100644 index 00000000..646440b1 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/environment/PackageCrawler.java @@ -0,0 +1,77 @@ +package de.dhbwstuttgart.environment; + +import java.net.URL; +import java.util.*; + +import org.reflections.Reflections; +import org.reflections.scanners.ResourcesScanner; +import org.reflections.scanners.SubTypesScanner; +import org.reflections.util.ConfigurationBuilder; +import org.reflections.util.FilterBuilder; + +import de.dhbwstuttgart.parser.scope.JavaClassName; +import org.reflections.vfs.SystemDir; + +/** + * Hilft beim Durchsuchen von Packages + * Benutzt die Reflections-Library (https://github.com/ronmamo/reflections) + * Hilfe dazu: http://stackoverflow.com/a/9571146 + */ +public class PackageCrawler { + + final URL[] urls; + public PackageCrawler(List urlList) { + urls = urlList.toArray(new URL[0]); + } + + public Set> getClassesInPackage(String packageName){ + /* + List classLoadersList = new LinkedList(); + classLoadersList.add(Thread.currentThread().getContextClassLoader()); + classLoadersList.add(ClasspathHelper.staticClassLoader()); + classLoadersList.add(Thread.currentThread().getContextClassLoader().getParent()); + classLoadersList.add(DirectoryClassLoader.getSystemClassLoader()); + String bootClassPath = System.getProperty("sun.boot.class.path"); + ArrayList urlList = new ArrayList<>(); + for(String path : bootClassPath.split(";")) { + try { + urlList.add(new URL("file:"+path)); + } catch (MalformedURLException e) { + new DebugException("Fehler im Classpath auf diesem System"); + } + } + URL[] urls = urlList.toArray(new URL[0]); + classLoadersList.add(new URLClassLoader(urls, DirectoryClassLoader.getSystemClassLoader())); + */ + Reflections reflections = new Reflections(new ConfigurationBuilder() + .setScanners(new SubTypesScanner(false /* don't exclude Object.class */), new ResourcesScanner()) + .setUrls(urls) + .filterInputsBy(new FilterBuilder().include(FilterBuilder.prefix(packageName)))); + + Set> classes = reflections.getSubTypesOf(Object.class); + + return classes; + } + + public Set> getAllAvailableClasses(){ + Reflections reflections = new Reflections(new ConfigurationBuilder() + .setScanners(new SubTypesScanner(false /* don't exclude Object.class */), new ResourcesScanner()) + .setUrls(urls)); + + Set> classes = reflections.getSubTypesOf(Object.class); + + return classes; + } + + public Map getClassNames(String packageName){ + Map nameList = new HashMap<>(); + Set> classes = getClassesInPackage(packageName); + if(packageName.equals("java.lang") && ! classes.contains(Object.class)) { + classes.add(Object.class); + } + for(Class c : classes){ + nameList.put(c.getName(), c.getTypeParameters().length); + } + return nameList; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/exceptions/DebugException.java b/app/src/main/java/de/dhbwstuttgart/exceptions/DebugException.java new file mode 100644 index 00000000..8f2b70ae --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/exceptions/DebugException.java @@ -0,0 +1,8 @@ +package de.dhbwstuttgart.exceptions; + +public class DebugException extends RuntimeException { + + public DebugException(String message) { + System.err.print(message); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/exceptions/NotImplementedException.java b/app/src/main/java/de/dhbwstuttgart/exceptions/NotImplementedException.java new file mode 100644 index 00000000..846567ce --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/exceptions/NotImplementedException.java @@ -0,0 +1,11 @@ +package de.dhbwstuttgart.exceptions; + +public class NotImplementedException extends RuntimeException { + + public NotImplementedException() { + } + + public NotImplementedException(String string) { + super(string); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/exceptions/ParserError.java b/app/src/main/java/de/dhbwstuttgart/exceptions/ParserError.java new file mode 100644 index 00000000..6541edb3 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/exceptions/ParserError.java @@ -0,0 +1,10 @@ +package de.dhbwstuttgart.exceptions; + +import org.antlr.v4.runtime.Token; + +public class ParserError extends TypeinferenceException{ + + public ParserError(Token offset){ + super("Fehler beim Parsen", offset); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/exceptions/TypeinferenceException.java b/app/src/main/java/de/dhbwstuttgart/exceptions/TypeinferenceException.java new file mode 100644 index 00000000..41e054b3 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/exceptions/TypeinferenceException.java @@ -0,0 +1,46 @@ +package de.dhbwstuttgart.exceptions; + +import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; +import org.antlr.v4.runtime.Token; + +/** + * Eine RuntimeException, welche bei einem Fehler während des Typinferenzalgorithmus ausgelöst wird. + * Dies wird zum Beispiel durch Programmierfehler in der Java-Eingabedatei ausgelöst. + * @author Andreas Stadelmeier, a10023 + * + */ +//TODO: Diese Klasse muss von Exception erben +public class TypeinferenceException extends RuntimeException { + + /** + * Das Offset im Quelltext bei dem das Problem aufgetaucht ist + */ + private Token offset; + private String message; + + public TypeinferenceException(String message, SyntaxTreeNode problemSource) + { + super(message); + this.message=message; + if(problemSource == null)throw new DebugException("TypinferenzException ohne Offset: "+this.message); + this.offset=problemSource.getOffset(); + } + + public TypeinferenceException(String message, Token offset){ + this.message=message; + this.offset = offset; + } + + /** + * + * @return Der Offset an dem im Quellcode der Fehler aufgetreten ist. + */ + public Token getOffset(){ + return offset; + } + + public String getMessage(){ + return this.message; + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/parser/JavaTXParser.java b/app/src/main/java/de/dhbwstuttgart/parser/JavaTXParser.java new file mode 100644 index 00000000..aad0a575 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/parser/JavaTXParser.java @@ -0,0 +1,37 @@ +package de.dhbwstuttgart.parser; + +import de.dhbwstuttgart.environment.CompilationEnvironment; +import de.dhbwstuttgart.parser.SyntaxTreeGenerator.SyntaxTreeGenerator; +import de.dhbwstuttgart.parser.antlr.Java8Lexer; +import de.dhbwstuttgart.parser.antlr.Java8Parser; +import de.dhbwstuttgart.parser.scope.JavaClassRegistry; +import de.dhbwstuttgart.syntaxtree.SourceFile; + +import org.antlr.v4.runtime.ANTLRInputStream; +import org.antlr.v4.runtime.CommonTokenStream; + +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; + +public class JavaTXParser { + public static Java8Parser.CompilationUnitContext parse(File source) throws IOException, java.lang.ClassNotFoundException { + InputStream stream = new FileInputStream(source); + ANTLRInputStream input = new ANTLRInputStream(stream); + Java8Lexer lexer = new Java8Lexer(input); + CommonTokenStream tokens = new CommonTokenStream(lexer); + Java8Parser parser = new Java8Parser(tokens); + return parser.compilationUnit(); + /* + SyntaxTreeGenerator generator = new SyntaxTreeGenerator(environment.getRegistry(source)); + return generator.convert(tree); + */ + } + + /* Für das Typsystem ist es notwendig, dass sich der Source in einer Datei befindet: + public SourceFile parse(String fileContent) throws IOException, java.lang.ClassNotFoundException { + return this.parse(new ByteArrayInputStream(fileContent.getBytes(StandardCharsets.UTF_8))); + } + */ +} diff --git a/app/src/main/java/de/dhbwstuttgart/parser/NullToken.java b/app/src/main/java/de/dhbwstuttgart/parser/NullToken.java new file mode 100644 index 00000000..bbc7c7b5 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/parser/NullToken.java @@ -0,0 +1,57 @@ +package de.dhbwstuttgart.parser; + +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.Token; +import org.antlr.v4.runtime.TokenSource; + +public class NullToken implements Token { + @Override + public String getText() { + return ""; + } + + @Override + public int getType() { + return 0; + } + + @Override + public int getLine() { + return 0; + } + + @Override + public int getCharPositionInLine() { + return 0; + } + + @Override + public int getChannel() { + return 0; + } + + @Override + public int getTokenIndex() { + return 0; + } + + @Override + public int getStartIndex() { + return 0; + } + + @Override + public int getStopIndex() { + return 0; + } + + @Override + public TokenSource getTokenSource() { + return null; + } + + @Override + public CharStream getInputStream() { + return null; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/AssignToLocal.java b/app/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/AssignToLocal.java new file mode 100644 index 00000000..c505bfb6 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/AssignToLocal.java @@ -0,0 +1,20 @@ +package de.dhbwstuttgart.parser.SyntaxTreeGenerator; + +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.statement.AssignLeftSide; +import de.dhbwstuttgart.syntaxtree.statement.Expression; +import de.dhbwstuttgart.syntaxtree.statement.LocalVar; + +public class AssignToLocal extends AssignLeftSide { + public final LocalVar localVar; + + public AssignToLocal(LocalVar leftSide) { + super(leftSide.getType(), leftSide.getOffset()); + localVar = leftSide; + } + + @Override + public void accept(StatementVisitor visitor) { + visitor.visit(this); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/FCGenerator.java b/app/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/FCGenerator.java new file mode 100644 index 00000000..71dcef52 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/FCGenerator.java @@ -0,0 +1,177 @@ +package de.dhbwstuttgart.parser.SyntaxTreeGenerator; + +import de.dhbwstuttgart.exceptions.DebugException; +import de.dhbwstuttgart.parser.NullToken; +import de.dhbwstuttgart.syntaxtree.ClassOrInterface; +import de.dhbwstuttgart.syntaxtree.GenericTypeVar; +import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; +import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory; +import de.dhbwstuttgart.syntaxtree.type.*; +import de.dhbwstuttgart.typeinference.constraints.Pair; +import de.dhbwstuttgart.typeinference.unify.model.*; + +import java.util.*; +import java.util.stream.Collectors; + +import org.antlr.v4.runtime.Token; + +public class FCGenerator { + /** + * Baut die FiniteClosure aus availableClasses. + * Klassen welche nicht in availableClasses vorkommen werden im Java Classpath nachgeschlagen. + * + * @param availableClasses - Alle geparsten Klassen + */ + public static Set toUnifyFC(Collection availableClasses, ClassLoader classLoader) throws ClassNotFoundException { + return toFC(availableClasses, classLoader).stream().map(t -> UnifyTypeFactory.convert(t)).collect(Collectors.toSet()); + } + + public static Set toFC(Collection availableClasses, ClassLoader classLoader) throws ClassNotFoundException { + HashSet pairs = new HashSet<>(); + //PL 2018-09-18: gtvs vor die for-Schleife gezogen, damit immer die gleichen Typeplaceholder eingesetzt werden. + HashMap gtvs = new HashMap<>(); + for(ClassOrInterface cly : availableClasses){ + pairs.addAll(getSuperTypes(cly, availableClasses, gtvs, classLoader)); + } + return pairs; + } + + + + + + + /** + * Bildet eine Kette vom übergebenen Typ bis hin zum höchsten bekannten Typ + * Als Generics werden TPHs benutzt, welche der Unifikationsalgorithmus korrekt interpretieren muss. + * Die verwendeten TPHs werden in der Kette nach oben gereicht, so erhält der selbe GTV immer den selben TPH + * @param forType + * @return + */ + private static List getSuperTypes(ClassOrInterface forType, Collection availableClasses, ClassLoader classLoader) throws ClassNotFoundException { + return getSuperTypes(forType, availableClasses, new HashMap<>(), classLoader); + } + + /** + * + * @param forType + * @param availableClasses + * @param gtvs + * @return + * @throws ClassNotFoundException + */ + private static List getSuperTypes(ClassOrInterface forType, Collection availableClasses, + HashMap gtvs, ClassLoader classLoader) throws ClassNotFoundException { + List params = new ArrayList<>(); + //Die GTVs, die in forType hinzukommen: + HashMap newGTVs = new HashMap<>(); + //Generics mit gleichem Namen müssen den selben TPH bekommen + for(GenericTypeVar gtv : forType.getGenerics()){ + if(!gtvs.containsKey(gtv.getName())){ + TypePlaceholder replacePlaceholder = TypePlaceholder.fresh(new NullToken()); + gtvs.put(gtv.getName(), replacePlaceholder); + newGTVs.put(gtv.getName(), replacePlaceholder); + } + params.add(gtvs.get(gtv.getName())); + } + + + List superClasses = new ArrayList<>(); + superClasses.add(forType.getSuperClass()); + superClasses.addAll(forType.getSuperInterfaces()); + + List retList = new ArrayList<>(); + for(RefType superType : superClasses){ + Optional hasSuperclass = availableClasses.stream().filter(cl -> superType.getName().equals(cl.getClassName())).findAny(); + ClassOrInterface superClass; + if(!hasSuperclass.isPresent()) //Wenn es die Klasse in den available Klasses nicht gibt wird sie im Classpath gesucht. Ansonsten Exception + { + superClass = ASTFactory.createClass(classLoader.loadClass(superType.getName().toString())); + }else{ + superClass = hasSuperclass.get(); + } + /* + Die Parameter der superklasse müssen jetzt nach den Angaben in der Subklasse + modifiziert werden + Beispie: Matrix extends Vector> + Den ersten Parameter mit Vector austauschen und dort alle Generics zu den Typplaceholdern in gtvs austauschen + */ + //Hier vermerken, welche Typen in der Superklasse ausgetauscht werden müssen + Iterator itGenParams = superClass.getGenerics().iterator(); + Iterator itSetParams = superType.getParaList().iterator(); + while(itSetParams.hasNext()){ + RefTypeOrTPHOrWildcardOrGeneric setType = itSetParams.next(); + //In diesem Typ die GTVs durch TPHs und Einsetzungen austauschen: + RefTypeOrTPHOrWildcardOrGeneric setSetType = setType.acceptTV(new TypeExchanger(gtvs)); + newGTVs.put(itGenParams.next().getName(), setSetType); + } + + //Für den superType kann man nun zum Austauschen der Generics wieder die gtvs nehmen: + //Die newGTVs sind nur für den superClass ClassOrInterface welches möglicherweise per reflection geladen wurde abgestimmt + RefTypeOrTPHOrWildcardOrGeneric superRefType = superType.acceptTV(new TypeExchanger(gtvs)); + + RefTypeOrTPHOrWildcardOrGeneric t1 = new RefType(forType.getClassName(), params, new NullToken()); + RefTypeOrTPHOrWildcardOrGeneric t2 = superRefType; + + Pair ret = new Pair(t1, t2, PairOperator.SMALLER); + + List superTypes; + //Rekursiver Aufruf. Abbruchbedingung ist Object als Superklasse: + if(superClass.getClassName().equals(ASTFactory.createObjectClass().getClassName())){ + superTypes = Arrays.asList(new Pair(ASTFactory.createObjectType(), ASTFactory.createObjectType(), PairOperator.SMALLER)); + }else{ + superTypes = getSuperTypes(superClass, availableClasses, newGTVs, classLoader); + } + + retList.add(ret); + retList.addAll(superTypes); + } + + return retList; + } + + /** + * Tauscht die GTVs in einem Typ gegen die entsprechenden Typen in der übergebenen Map aus. + */ + private static class TypeExchanger implements TypeVisitor{ + + private final HashMap gtvs; + + TypeExchanger(HashMap gtvs){ + this.gtvs = gtvs; + } + + @Override + public RefTypeOrTPHOrWildcardOrGeneric visit(RefType refType) { + List params = new ArrayList<>(); + for(RefTypeOrTPHOrWildcardOrGeneric param : refType.getParaList()){ + params.add(param.acceptTV(this)); + } + RefTypeOrTPHOrWildcardOrGeneric ret = new RefType(refType.getName(), params, new NullToken()); + return ret; + } + + @Override + public RefTypeOrTPHOrWildcardOrGeneric visit(SuperWildcardType superWildcardType) { + throw new DebugException("Dieser Fall darf nicht auftreten"); + } + + @Override + public RefTypeOrTPHOrWildcardOrGeneric visit(TypePlaceholder typePlaceholder) { + throw new DebugException("Dieser Fall darf nicht auftreten"); + } + + @Override + public RefTypeOrTPHOrWildcardOrGeneric visit(ExtendsWildcardType extendsWildcardType) { + throw new DebugException("Dieser Fall darf nicht auftreten"); + } + + @Override + public RefTypeOrTPHOrWildcardOrGeneric visit(GenericRefType genericRefType) { + if(! gtvs.containsKey(genericRefType.getParsedName())) + throw new DebugException("Dieser Fall darf nicht auftreten"); + return gtvs.get(genericRefType.getParsedName()); + } + + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/GenericContext.java b/app/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/GenericContext.java new file mode 100644 index 00000000..0cea06ed --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/GenericContext.java @@ -0,0 +1,14 @@ +package de.dhbwstuttgart.parser.SyntaxTreeGenerator; + +import de.dhbwstuttgart.parser.scope.JavaClassName; + +public class GenericContext { + private final String parentMethod; + private final JavaClassName parentClass; + + public GenericContext(JavaClassName parentClass, String parentMethod) { + if(parentMethod == null)parentMethod = ""; + this.parentClass = parentClass; + this.parentMethod = parentMethod; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java b/app/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java new file mode 100644 index 00000000..2b3c99fd --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java @@ -0,0 +1,974 @@ +package de.dhbwstuttgart.parser.SyntaxTreeGenerator; + +import de.dhbwstuttgart.exceptions.NotImplementedException; +import de.dhbwstuttgart.parser.NullToken; +import de.dhbwstuttgart.parser.antlr.Java8Parser; +import de.dhbwstuttgart.parser.scope.GenericsRegistry; +import de.dhbwstuttgart.parser.scope.JavaClassRegistry; +import de.dhbwstuttgart.syntaxtree.*; +import de.dhbwstuttgart.syntaxtree.statement.*; +import de.dhbwstuttgart.syntaxtree.statement.UnaryExpr.Operation; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.syntaxtree.type.Void; + +import org.antlr.v4.runtime.Token; +import org.antlr.v4.runtime.tree.TerminalNode; + +import java.util.*; +import java.util.stream.Collectors; + +public class StatementGenerator { + + private JavaClassRegistry reg; + private Map fields; //PL 2018-11-01 fields eingefuegt, damit die fields immer die gleiche TPH bekommen + private Map localVars; + private GenericsRegistry generics; + + public StatementGenerator(JavaClassRegistry reg, GenericsRegistry generics, Map fields, Map localVars){ + this.reg = reg; + this.generics = generics; + this.fields = fields; + this.localVars = localVars; + } + + public ParameterList convert(Java8Parser.FormalParameterListContext formalParameterListContext) { + List ret = new ArrayList<>(); + List fps = new ArrayList<>(); + if(formalParameterListContext == null || formalParameterListContext.lastFormalParameter() == null) + return new ParameterList(ret, new NullToken()); //Dann ist die Parameterliste leer + + if(formalParameterListContext.lastFormalParameter().formalParameter() == null)throw new NotImplementedException(); + + if(formalParameterListContext != null && formalParameterListContext.formalParameters() != null + && formalParameterListContext.formalParameters().formalParameter() != null){ + fps = new ArrayList<>(formalParameterListContext.formalParameters().formalParameter()); + } + fps.add(formalParameterListContext.lastFormalParameter().formalParameter()); + + for(Java8Parser.FormalParameterContext fp : fps){ + String paramName = SyntaxTreeGenerator.convert(fp.variableDeclaratorId()); + RefTypeOrTPHOrWildcardOrGeneric type; + if(fp.unannType() != null){ + type = TypeGenerator.convert(fp.unannType(), reg, generics); + }else{ + type = TypePlaceholder.fresh(fp.getStart()); + } + ret.add(new FormalParameter(paramName, type, fp.getStart())); + localVars.put(paramName, type); + } + return new ParameterList(ret, ret.get(0).getOffset()); + } + + /* + * StatementGeneration: + */ + + private Statement convert(Java8Parser.StatementContext stmt) { + if (stmt.statementWithoutTrailingSubstatement() != null) { + return convert(stmt.statementWithoutTrailingSubstatement()); + } else if (stmt.whileStatement() != null) { + return convert(stmt.whileStatement()); + } else if (stmt.forStatement() != null) { + return convert(stmt.forStatement()); + } else if (stmt.ifThenElseStatement() != null) { + return convert(stmt.ifThenElseStatement()); + } else if (stmt.ifThenStatement() != null) { + return convert(stmt.ifThenStatement()); + } else if (stmt.labeledStatement() != null) { + return convert(stmt.labeledStatement() ); + }else throw new NotImplementedException(); + } + + private Statement convert(Java8Parser.StatementNoShortIfContext stmt){ + if(stmt.statementWithoutTrailingSubstatement() != null){ + return convert(stmt.statementWithoutTrailingSubstatement()); + }else if(stmt.labeledStatementNoShortIf() != null){ + return convert(stmt.labeledStatementNoShortIf()); + }else if(stmt.ifThenElseStatementNoShortIf() != null){ + return convert(stmt.ifThenElseStatementNoShortIf()); + }else if(stmt.whileStatementNoShortIf() != null){ + return convert(stmt.whileStatementNoShortIf()); + }else if(stmt.forStatementNoShortIf() != null){ + return convert(stmt.forStatementNoShortIf()); + }else throw new NotImplementedException(); + } + + private Statement convert(Java8Parser.StatementWithoutTrailingSubstatementContext stmt) { + if(stmt.block() != null){ + return convert(stmt.block(), false); + }else if(stmt.emptyStatement() != null){ + return new EmptyStmt(stmt.getStart()); + }else if(stmt.expressionStatement() != null){ + return convert(stmt.expressionStatement()); + }else if(stmt.assertStatement() != null){ + return convert(stmt.assertStatement()); + }else if(stmt.switchStatement() != null){ + return convert(stmt.switchStatement()); + }else if(stmt.doStatement() != null){ + return convert(stmt.doStatement()); + }else if(stmt.breakStatement() != null){ + return convert(stmt.breakStatement()); + }else if(stmt.continueStatement() != null){ + return convert(stmt.continueStatement()); + }else if(stmt.returnStatement() != null){ + return convert(stmt.returnStatement()); + }else if(stmt.synchronizedStatement() != null){ + return convert(stmt.synchronizedStatement()); + }else if(stmt.throwStatement() != null){ + return convert(stmt.throwStatement()); + }else if(stmt.tryStatement() != null){ + return convert(stmt.tryStatement()); + }else throw new NotImplementedException(); + } + + public Block convert(Java8Parser.BlockContext block, boolean addTrailingReturn) { + List statements = new ArrayList<>(); + if(block.blockStatements() != null) + for(Java8Parser.BlockStatementContext statementContext : block.blockStatements().blockStatement()){ + List stmt = convert(statementContext); + statements.addAll(stmt); + } + if(addTrailingReturn)statements = SyntacticSugar.addTrailingReturn(statements); + return new Block(statements, block.getStart()); + } + + private List convert(Java8Parser.BlockStatementContext statementContext) { + if(statementContext.localVariableDeclarationStatement() != null){ + return convert(statementContext.localVariableDeclarationStatement()); + }else if(statementContext.classDeclaration() != null){ + throw new NotImplementedException(); + }else{ + return Arrays.asList(convert(statementContext.statement())); + } + } + + private List convert(Java8Parser.LocalVariableDeclarationStatementContext stmt) { + Java8Parser.LocalVariableDeclarationContext declaration = stmt.localVariableDeclaration(); + return convert(declaration); + } + + private Statement convert(Java8Parser.LabeledStatementContext labeledStatementContext) { + throw new NotImplementedException(); + //return convert(labeledStatementContext.statement()); + } + + private Statement convert(Java8Parser.LabeledStatementNoShortIfContext stmt){ + throw new NotImplementedException(); + //return convert(stmt.statementNoShortIf()); + } + + private Statement convert(Java8Parser.ExpressionStatementContext stmt){ + return convert(stmt.statementExpression()); + } + + private Statement convert(Java8Parser.StatementExpressionContext stmt) { + if(stmt.assignment() != null){ + return convert(stmt.assignment()); + }else if(stmt.preIncrementExpression() != null){ + return convert(stmt.preIncrementExpression()); + }else if(stmt.preDecrementExpression() != null){ + return convert(stmt.preDecrementExpression()); + }else if(stmt.postIncrementExpression() != null){ + return convert(stmt.postIncrementExpression()); + }else if(stmt.postDecrementExpression() != null){ + return convert(stmt.postDecrementExpression()); + }else if(stmt.methodInvocation() != null){ + return convert(stmt.methodInvocation()); + }else if(stmt.classInstanceCreationExpression() != null){ + return convert(stmt.classInstanceCreationExpression()); + }else throw new NotImplementedException(); + } + + public Receiver getReceiver(Expression expr){ + if(expr instanceof StaticClassName){ + return (Receiver) expr; + }else { + return new ExpressionReceiver(expr); + } + } + + private Statement convert(Java8Parser.MethodInvocationContext methodInvocationContext) { + String name; + if(methodInvocationContext.methodName()!=null){ + name = methodInvocationContext.methodName().Identifier().getText(); + }else{// if(methodInvocationContext.Identifier() != null){ + name = methodInvocationContext.Identifier().getText(); + } + Expression receiver; + if(methodInvocationContext.typeName() != null){ + receiver = generateLocalOrFieldVarOrClassName(methodInvocationContext.typeName().getText(), methodInvocationContext.typeName().getStart()); + }else if(methodInvocationContext.expressionName()!=null){ + receiver = convert(methodInvocationContext.expressionName()); + }else if(methodInvocationContext.primary() != null){ + receiver = convert(methodInvocationContext.primary()); + }else if(methodInvocationContext.toString().startsWith("super")){ + receiver = new Super(methodInvocationContext.getStart()); + }else if(methodInvocationContext.methodName() != null){ + receiver = new This(methodInvocationContext.getStart()); + }else throw new NotImplementedException(); + + ArgumentList argumentList = convert(methodInvocationContext.argumentList()); + ArrayList argTypes = argumentList.getArguments().stream() + .map(x -> TypePlaceholder.fresh(methodInvocationContext.getStart())) + .collect(Collectors.toCollection(ArrayList::new)); + MethodCall ret = new MethodCall(TypePlaceholder.fresh(methodInvocationContext.getStart()), + getReceiver(receiver), name, argumentList, TypePlaceholder.fresh(methodInvocationContext.getStart()), + argTypes, methodInvocationContext.getStart()); + ret.setStatement(); + return ret; + } + + private ArgumentList convert(Java8Parser.ArgumentListContext argumentListContext) { + if(argumentListContext == null)return new ArgumentList(new ArrayList<>(), new NullToken()); + List args = new ArrayList<>(); + + Token offset = new NullToken(); + for(Java8Parser.ExpressionContext expr : argumentListContext.expression()){ + args.add(convert(expr)); + } + if(args.size()>0)offset = args.get(0).getOffset(); + + return new ArgumentList(args, offset); + } + + /** + * Der Parser kann nicht zwischen einer lokalen Variable, einem Feldzugriff und + * einer Klassenangabe unterscheiden. + * @param expression + * @param offset + * @return + */ + private Expression generateLocalOrFieldVarOrClassName(String expression, Token offset){ + String[] parts = expression.split("\\."); + if(parts.length < 2){ + //Check for localVar: + if(localVars.get(expression) != null){ + return new LocalVar(expression, localVars.get(expression), offset); + }else{ + if(fields.get(expression) != null){//PL 2018-11-01 fields eingefuegt, damit die fields immer die gleiche TPH bekommen + return new FieldVar(new This(offset), expression, fields.get(expression), offset); + + } else { + //kann eigentlich nicht vorkommen + //Dann Muss es ein Feld sein! + return new FieldVar(new This(offset), expression, TypePlaceholder.fresh(offset), offset); + }} + } + return generateFieldVarOrClassname(expression, offset); + } + + private Expression generateFieldVarOrClassname(String expression, Token offset){ + String[] parts = expression.split("\\."); + String whole = ""; + Expression receiver = null; + for(String part : parts){ + whole+=part; + //Check for Classname: + if(reg.contains(whole)){ + receiver = new StaticClassName(reg.getName(whole), offset); + } + whole+="."; + } + + if(parts.length < 2 || parts[0].contentEquals("this") ){ + receiver = new This(offset); + } else if (parts[0].contentEquals("super")) { + receiver = new Super(offset); + }else if(receiver == null){ //Handelt es sich um keinen Statischen Klassennamen: + String part = expression.substring(0,expression.length() - (1 + parts[parts.length-1].length())); + receiver = generateLocalOrFieldVarOrClassName(part, offset); + } + return new FieldVar(receiver, parts[parts.length-1], TypePlaceholder.fresh(offset) ,offset); + } + + private Expression convert(Java8Parser.ExpressionNameContext expressionNameContext) { + return generateLocalOrFieldVarOrClassName(expressionNameContext.getText(), expressionNameContext.getStart()); + } + + + private Statement convert(Java8Parser.ClassInstanceCreationExpressionContext newExpression) { + Java8Parser.TypeArgumentsContext genericArgs = null; + if(newExpression.expressionName()!= null)throw new NotImplementedException(); + if(newExpression.typeArgumentsOrDiamond()!= null){ + if(newExpression.typeArgumentsOrDiamond().typeArguments()!=null){ + genericArgs = newExpression.typeArgumentsOrDiamond().typeArguments(); + } + } + if(newExpression.typeArguments()!= null)throw new NotImplementedException(); + + TerminalNode identifier = newExpression.Identifier(0); + RefType newClass = (RefType) TypeGenerator.convertTypeName(identifier.getText(),genericArgs,identifier.getSymbol(),reg,generics); + + ArgumentList args = convert(newExpression.argumentList()); + ArrayList argTypes = args.getArguments().stream() + .map(x -> TypePlaceholder.fresh(newExpression.getStart())) + .collect(Collectors.toCollection(ArrayList::new)); + Statement ret = new NewClass(newClass, args, null, argTypes, newExpression.getStart()); + ret.setStatement(); + return ret; + } + + private Statement convert(Java8Parser.PreIncrementExpressionContext stmt) { + Expression argument = convert(stmt.unaryExpression()); + Token offset = stmt.getStart(); + Statement ret = new UnaryExpr(UnaryExpr.Operation.PREINCREMENT, argument, TypePlaceholder.fresh(offset), offset); + ret.setStatement(); + return ret; + } + + private Statement convert(Java8Parser.PreDecrementExpressionContext stmt) { + Statement ret = new UnaryExpr(UnaryExpr.Operation.PREDECREMENT, convert(stmt.unaryExpression()), + TypePlaceholder.fresh(stmt.getStart()), stmt.getStart()); + ret.setStatement(); + return ret; + } + + private Statement convert(Java8Parser.PostIncrementExpressionContext stmt) { + Statement ret = new UnaryExpr(UnaryExpr.Operation.POSTINCREMENT, convert(stmt.postfixExpression()), + TypePlaceholder.fresh(stmt.getStart()), stmt.getStart()); + ret.setStatement(); + return ret; + } + + private Statement convert(Java8Parser.PostDecrementExpressionContext stmt) { + Statement ret = new UnaryExpr(UnaryExpr.Operation.POSTDECREMENT, convert(stmt.postfixExpression()), + TypePlaceholder.fresh(stmt.getStart()), stmt.getStart()); + ret.setStatement(); + return ret; + } + + private Statement convert(Java8Parser.AssignmentContext stmt) { + AssignLeftSide leftHandSide = convert(stmt.leftHandSide()); + Statement ret = new Assign(leftHandSide, convert(stmt.expression()), stmt.getStart()); + ret.setStatement(); + return ret; + } + + private AssignLeftSide convert(Java8Parser.LeftHandSideContext leftHandSide) { + Expression leftSide = generateLocalOrFieldVarOrClassName(leftHandSide.getText(), leftHandSide.getStart()); + if(leftSide instanceof FieldVar)return new AssignToField((FieldVar) leftSide); + else if (leftSide instanceof LocalVar)return new AssignToLocal((LocalVar) leftSide); + else throw new NotImplementedException(); + } + + private Statement convert(Java8Parser.IfThenStatementContext stmt){ + //TODO + throw new NotImplementedException(); + } + + private Statement convert(Java8Parser.IfThenElseStatementContext stmt){ + Expression expr = convert(stmt.expression()); + Statement thenBlock = convert(stmt.statementNoShortIf()); + Statement elseBlock = convert(stmt.statement()); + return new IfStmt(TypePlaceholder.fresh(stmt.getStart()), expr, thenBlock, elseBlock, stmt.getStart()); + } + + private Statement convert(Java8Parser.IfThenElseStatementNoShortIfContext stmt){ + //TODO + throw new NotImplementedException(); + } + + private Statement convert(Java8Parser.AssertStatementContext stmt){ + //TODO + throw new NotImplementedException(); + } + + private Statement convert(Java8Parser.SwitchStatementContext stmt){ + //TODO + throw new NotImplementedException(); + } + + private Statement convert(Java8Parser.SwitchBlockContext stmt){ + //TODO + throw new NotImplementedException(); + } + + private Statement convert(Java8Parser.SwitchBlockStatementGroupContext stmt){ + //TODO + throw new NotImplementedException(); + } + + private Statement convert(Java8Parser.WhileStatementContext stmt){ + Expression expr = convert(stmt.expression()); + Statement block = convert(stmt.statement()); + return new WhileStmt(expr, block,stmt.getStart()); + } + + private Statement convert(Java8Parser.WhileStatementNoShortIfContext stmt){ + //TODO + throw new NotImplementedException(); + } + + private Statement convert(Java8Parser.DoStatementContext stmt){ + Statement block = convert(stmt.statement()); + Expression expr = convert(stmt.expression()); + return new DoStmt(expr,block,stmt.getStart()); + } + + private Statement convert(Java8Parser.ForStatementContext stmt){ + if(stmt.basicForStatement() != null){ + return convert(stmt.basicForStatement()); + }else if(stmt.enhancedForStatement() != null){ + return convert(stmt.enhancedForStatement()); + }else throw new NotImplementedException(); + } + + private Statement convert(Java8Parser.ForStatementNoShortIfContext stmt){ + if(stmt.basicForStatementNoShortIf() != null){ + return convert(stmt.basicForStatementNoShortIf()); + }else if(stmt.enhancedForStatementNoShortIf() != null){ + return convert(stmt.enhancedForStatementNoShortIf()); + }else throw new NotImplementedException(); + } + + private Statement convert(Java8Parser.BasicForStatementContext stmt){ + //TODO + throw new NotImplementedException(); + } + + private Statement convert(Java8Parser.BasicForStatementNoShortIfContext stmt){ + //TODO + throw new NotImplementedException(); + } + + private List convert(Java8Parser.ForInitContext stmt){ + if(stmt.statementExpressionList() != null){ + return Arrays.asList(convert(stmt.statementExpressionList())); + }else if(stmt.localVariableDeclaration() != null){ + return convert(stmt.localVariableDeclaration()); + }else throw new NotImplementedException(); + } + + private List convert(Java8Parser.LocalVariableDeclarationContext declaration) { + List ret = new ArrayList<>(); + if(declaration.variableModifier() != null && declaration.variableModifier().size() > 0){ + //TODO + throw new NotImplementedException(); + } + RefTypeOrTPHOrWildcardOrGeneric type; + if(declaration.unannTypeOrAuto().unannType() == null){ + type = TypePlaceholder.fresh(declaration.getStart()); + }else{ + type = TypeGenerator.convert(declaration.unannTypeOrAuto().unannType(), reg, generics); + } + ret.addAll(generateLocalVariableAssignments(declaration.variableDeclaratorList().variableDeclarator(), type)); + return ret; + } + + private List generateLocalVariableAssignments(List varDeclarators, RefTypeOrTPHOrWildcardOrGeneric type){ + List ret = new ArrayList<>(); + for(Java8Parser.VariableDeclaratorContext varDecl : varDeclarators){ + TerminalNode name = varDecl.variableDeclaratorId().Identifier(); + + ret.add(new LocalVarDecl(name.getText(), type, name.getSymbol())); + this.localVars.put(name.getText(), type); + if(varDecl.variableInitializer() != null){ + Expression initValue; + if(varDecl.variableInitializer().arrayInitializer() != null){ + throw new NotImplementedException(); + }else{ + initValue = convert(varDecl.variableInitializer().expression()); + } + ret.add(new Assign(new AssignToLocal(new LocalVar(name.getText(), type, name.getSymbol())) + , initValue, name.getSymbol())); + } + } + return ret; + } + + public Statement generateFieldAssignment(Java8Parser.VariableDeclaratorContext varDecl, RefTypeOrTPHOrWildcardOrGeneric type){ + TerminalNode name = varDecl.variableDeclaratorId().Identifier(); + Expression initValue; + if(varDecl.variableInitializer().arrayInitializer() != null){ + throw new NotImplementedException(); + }else{ + initValue = convert(varDecl.variableInitializer().expression()); + } + return (new Assign(new AssignToField( + new FieldVar(new This(varDecl.getStart()), name.getText(), + type, varDecl.getStart())), + initValue, name.getSymbol())); + } + + private Statement convert(Java8Parser.ForUpdateContext stmt){ + return convert(stmt.statementExpressionList()); + } + + private Statement convert(Java8Parser.StatementExpressionListContext stmt){ + //TODO + throw new NotImplementedException(); + } + + private Statement convert(Java8Parser.EnhancedForStatementContext stmt){ + //TODO + throw new NotImplementedException(); + } + + private Statement convert(Java8Parser.EnhancedForStatementNoShortIfContext stmt){ + //TODO + throw new NotImplementedException(); + } + + private Statement convert(Java8Parser.BreakStatementContext stmt){ + //TODO + throw new NotImplementedException(); + } + + private Statement convert(Java8Parser.ContinueStatementContext stmt){ + //TODO + throw new NotImplementedException(); + } + + private Statement convert(Java8Parser.ReturnStatementContext stmt){ + if(stmt.expression() != null){ + return new Return( convert(stmt.expression()),stmt.getStart() ); + }else{ + return new ReturnVoid(stmt.getStart()); + } + } + + private Statement convert(Java8Parser.ThrowStatementContext stmt){ + //TODO + throw new NotImplementedException(); + } + + private Statement convert(Java8Parser.SynchronizedStatementContext stmt){ + //TODO + throw new NotImplementedException(); + } + + private Statement convert(Java8Parser.TryStatementContext stmt){ + //TODO + throw new NotImplementedException(); + } + + private Statement convert(Java8Parser.CatchesContext stmt){ + //TODO + throw new NotImplementedException(); + } + + private Statement convert(Java8Parser.CatchClauseContext stmt){ + //TODO + throw new NotImplementedException(); + } + +/* +***************+ Expression Conversions: + */ + + private Expression convert(Java8Parser.ExpressionContext expression) { + if(expression.lambdaExpression()!=null){ + return convert(expression.lambdaExpression()); + }else{ + return convert(expression.assignmentExpression()); + } + } + + private Expression convert(Java8Parser.AssignmentExpressionContext expression) { + if(expression.conditionalExpression() != null){ + return convert(expression.conditionalExpression()); + }else{ + return convert(expression.assignment()); + } + } + + private Expression convert(Java8Parser.ConditionalExpressionContext expression) { + if(expression.conditionalOrExpression() != null){ + return convert(expression.conditionalOrExpression()); + }else{ + throw new NotImplementedException(); + } + } + + private Expression convert(Java8Parser.ConditionalOrExpressionContext expression) { + if(expression.conditionalOrExpression() == null){ + return convert(expression.conditionalAndExpression()); + }else{ + throw new NotImplementedException(); + } + } + + private Expression convert(Java8Parser.ConditionalAndExpressionContext expression) { + if(expression.conditionalAndExpression() == null){ + return convert(expression.inclusiveOrExpression()); + }else{ + throw new NotImplementedException(); + } + } + + private Expression convert(Java8Parser.InclusiveOrExpressionContext expression) { + if(expression.inclusiveOrExpression() == null){ + return convert(expression.exclusiveOrExpression()); + }else{ + throw new NotImplementedException(); + } + } + + private Expression convert(Java8Parser.ExclusiveOrExpressionContext expression) { + if(expression.exclusiveOrExpression() == null){ + return convert(expression.andExpression()); + }else{ + throw new NotImplementedException(); + } + } + + private Expression convert(Java8Parser.AndExpressionContext expression) { + if(expression.andExpression() == null){ + return convert(expression.equalityExpression()); + }else{ + throw new NotImplementedException(); + } + } + + private Expression convert(Java8Parser.EqualityExpressionContext expression) { + if(expression.equalityExpression() == null){ + return convert(expression.relationalExpression()); + }else{ + String operator = expression.getChild(1).getText(); + Expression leftSide = convert(expression.equalityExpression()); + Expression rightSide = convert(expression.relationalExpression()); + return new BinaryExpr(convertBinaryOperator(operator), TypePlaceholder.fresh(expression.getStart()), leftSide, rightSide, expression.getStart()); + } + } + + private Expression convert(Java8Parser.RelationalExpressionContext expression) { + if(expression.relationalExpression() == null) { + return convert(expression.shiftExpression()); + }else { + String operator = expression.getChild(1).getText(); + return new BinaryExpr(convertBinaryOperator(operator), TypePlaceholder.fresh(expression.getStart()), + convert(expression.relationalExpression()), + convert(expression.shiftExpression()), expression.getStart()); + } + //}else throw new NotImplementedException(); + } + + private BinaryExpr.Operator convertBinaryOperator(String operator) { + //return BinaryExpr.Operator.ADD; + if(operator.equals("+")) { + return BinaryExpr.Operator.ADD; + }else if(operator.equals("-")) { + return BinaryExpr.Operator.SUB; + }else if(operator.equals("*")) { + return BinaryExpr.Operator.MUL; + }else if(operator.equals("&")) { + return BinaryExpr.Operator.AND; + }else if(operator.equals("|")) { + return BinaryExpr.Operator.OR; + }else if(operator.equals("/")) { + return BinaryExpr.Operator.DIV; + }else if(operator.equals("<")) { + return BinaryExpr.Operator.LESSTHAN; + }else if(operator.equals(">")) { + return BinaryExpr.Operator.BIGGERTHAN; + }else if(operator.equals(">=")) { + return BinaryExpr.Operator.BIGGEREQUAL; + } else if(operator.equals("<=")) { + return BinaryExpr.Operator.LESSEQUAL; + } else if(operator.equals("==")) { + return BinaryExpr.Operator.EQUAL; + } else if(operator.equals("!=")) { + return BinaryExpr.Operator.NOTEQUAL; + } else { + throw new NotImplementedException(); + } +// throw new NotImplementedException(); + } + + private Expression convert(Java8Parser.ShiftExpressionContext expression) { + if(expression.shiftExpression() == null){ + return convert(expression.additiveExpression()); + }else{ + throw new NotImplementedException(); + } + } + + private Expression convert(Java8Parser.AdditiveExpressionContext expression) { + + if(expression.additiveExpression() == null){ + return convert(expression.multiplicativeExpression()); + }else { + Expression leftSide = convert(expression.additiveExpression()); + Expression rightSide = convert(expression.multiplicativeExpression()); + BinaryExpr.Operator op = convertBinaryOperator(expression.getChild(1).getText()); + Token offset = expression.getStart(); + return new BinaryExpr(op, TypePlaceholder.fresh(expression.getStart()), leftSide, rightSide, offset); + } + } + + private Expression convert(Java8Parser.MultiplicativeExpressionContext expression) { + if(expression.multiplicativeExpression() == null){ + return convert(expression.unaryExpression()); + }else{ + Expression leftSide = convert(expression.multiplicativeExpression()); + Expression rightSide = convert(expression.unaryExpression()); + BinaryExpr.Operator op = convertBinaryOperator(expression.getChild(1).getText()); + Token offset = expression.getStart(); + return new BinaryExpr(op, TypePlaceholder.fresh(offset), leftSide, rightSide, offset); + } + } + + private Expression convert(Java8Parser.UnaryExpressionContext expression) { + if(expression.preIncrementExpression() != null){ + return convert(expression.preIncrementExpression()); + }else if(expression.preDecrementExpression() != null){ + return convert(expression.preDecrementExpression()); + }else if(expression.unaryExpressionNotPlusMinus() != null){ + return convert(expression.unaryExpressionNotPlusMinus()); + }else if(expression.getText().startsWith("+")){ + return new UnaryExpr(UnaryExpr.Operation.PLUS, convert(expression.unaryExpression()), + TypePlaceholder.fresh(expression.getStart()), expression.getStart()); + }else if(expression.getText().startsWith("-")){ + return new UnaryExpr(UnaryExpr.Operation.MINUS, convert(expression.unaryExpression()), + TypePlaceholder.fresh(expression.getStart()), expression.getStart()); + }else{ + //Diese Exceptions sollte nie geworfen werden. + //Der Code wurde nur noch nicht getestet. Sollte zur Sicherheit drin bleiben. + throw new NotImplementedException(); + } + } + + private Expression convert(Java8Parser.UnaryExpressionNotPlusMinusContext expression) { + if(expression.postfixExpression() != null){ + return convert(expression.postfixExpression()); + }else if(expression.castExpression() != null){ + return convert(expression.castExpression()); + }else{ + throw new NotImplementedException(); + } + } + + private Expression convert(Java8Parser.CastExpressionContext expressionContext) { + Expression expr = null; + if(expressionContext.unaryExpression() != null){ + throw new NotImplementedException(); + }else if(expressionContext.unaryExpressionNotPlusMinus() != null){ + expr = convert(expressionContext.unaryExpressionNotPlusMinus()); + }else if(expressionContext.lambdaExpression() != null){ + expr = convert(expressionContext.lambdaExpression()); + } + return new CastExpr(TypeGenerator.convert(expressionContext.referenceType(), reg, generics),expr, expressionContext.getStart()); + } + + private Expression convert(Java8Parser.PostfixExpressionContext expression) { + Expression expr; + if(expression.primary() != null){ + expr = convert(expression.primary()); + }else{ + expr = convert(expression.expressionName()); + } + if(expression.postDecrementExpression_lf_postfixExpression() == null && + expression.postIncrementExpression_lf_postfixExpression() == null){ + return expr; + } + + for(Java8Parser.PostIncrementExpression_lf_postfixExpressionContext inc : expression.postIncrementExpression_lf_postfixExpression()){ + expr = new UnaryExpr(UnaryExpr.Operation.POSTINCREMENT, expr, TypePlaceholder.fresh(inc.getStart()), inc.getStart()); + } + for(Java8Parser.PostDecrementExpression_lf_postfixExpressionContext dec : expression.postDecrementExpression_lf_postfixExpression()){ + expr = new UnaryExpr(UnaryExpr.Operation.POSTDECREMENT, expr, TypePlaceholder.fresh(dec.getStart()), dec.getStart()); + } + + return expr; + } + + private Expression convert(Java8Parser.PrimaryContext primary) { + Expression expr; + if(primary.primaryNoNewArray_lfno_primary()!=null){ + expr = convert(primary.primaryNoNewArray_lfno_primary()); + }else{ + expr = convert(primary.arrayCreationExpression()); + } + + if(primary.primaryNoNewArray_lf_primary() != null && primary.primaryNoNewArray_lf_primary().size()>0){ + for(Java8Parser.PrimaryNoNewArray_lf_primaryContext e : primary.primaryNoNewArray_lf_primary()){ + expr = convert(expr, e); + } + } + return expr; + } + + private Expression convert(Expression expr, Java8Parser.PrimaryNoNewArray_lf_primaryContext e) { + if(e.classInstanceCreationExpression_lf_primary() != null){ + throw new NotImplementedException(); + }else if(e.fieldAccess_lf_primary() != null){ + + throw new NotImplementedException(); + }else if(e.arrayAccess_lf_primary() != null){ + throw new NotImplementedException(); + }else if(e.methodReference_lf_primary() != null){ + throw new NotImplementedException(); + }else { + Java8Parser.MethodInvocation_lf_primaryContext ctxt = e.methodInvocation_lf_primary(); + String methodName = ctxt.Identifier().toString(); + ArrayList argTypes = ctxt.argumentList().expression().stream() + .map(x -> TypePlaceholder.fresh(e.getStart())) + .collect(Collectors.toCollection(ArrayList::new)); + return new MethodCall(TypePlaceholder.fresh(e.getStart()), getReceiver(expr), methodName, + convert(ctxt.argumentList()), TypePlaceholder.fresh(e.getStart()), argTypes, e.getStart()); + } + } + + private Expression convert(Java8Parser.ArrayCreationExpressionContext expression) { + throw new NotImplementedException(); + } + + private Expression convert(Java8Parser.PrimaryNoNewArray_lfno_primaryContext expression) { + if(expression.literal() != null){ + return convert(expression.literal()); + }else if(expression.expression()!=null){ + return convert(expression.expression()); + }else if(expression.methodInvocation_lfno_primary() != null){ + return convert(expression.methodInvocation_lfno_primary()); + }else if(expression.classInstanceCreationExpression_lfno_primary() != null) { + return convert(expression.classInstanceCreationExpression_lfno_primary()); + }else if(expression.getText().equals("this")) { + return new This(expression.getStart()); + }else if(expression.fieldAccess_lfno_primary() != null){ + return convert(expression.fieldAccess_lfno_primary()); + }else if(expression.methodReference_lfno_primary() != null){ + throw new NotImplementedException(); + }else if(expression.typeName() != null){ + throw new NotImplementedException(); + }else if(expression.unannPrimitiveType() != null){ + throw new NotImplementedException(); + }else if(expression.arrayAccess_lfno_primary() != null){ + throw new NotImplementedException(); + }else if(expression.fieldAccess_lfno_primary() != null){ + throw new NotImplementedException(); + }else{ + throw new NotImplementedException(); + } + } + + private Expression convert(Java8Parser.FieldAccess_lfno_primaryContext fieldAccess_lfno_primaryContext) { + throw new NotImplementedException(); + } + + private Expression convert(Java8Parser.ClassInstanceCreationExpression_lfno_primaryContext newExpression) { + Java8Parser.TypeArgumentsContext genericArgs = null; + if(newExpression.expressionName()!= null)throw new NotImplementedException(); + if(newExpression.typeArgumentsOrDiamond()!= null){ + if(newExpression.typeArgumentsOrDiamond().typeArguments()!=null){ + genericArgs = newExpression.typeArgumentsOrDiamond().typeArguments(); + } + } + if(newExpression.typeArguments()!= null)throw new NotImplementedException(); + + TerminalNode identifier = newExpression.Identifier(0); + RefType newClass = (RefType) TypeGenerator.convertTypeName(identifier.getText(),genericArgs,identifier.getSymbol(),reg,generics); + + ArgumentList args = convert(newExpression.argumentList()); + ArrayList argTypes = args.getArguments().stream() + .map(x -> TypePlaceholder.fresh(newExpression.getStart())) + .collect(Collectors.toCollection(ArrayList::new)); + return new NewClass(newClass, args, null, argTypes, newExpression.getStart()); + } + + private Expression convert(Java8Parser.LiteralContext literal) { + if(literal.IntegerLiteral() != null){ + Number value = Integer.parseInt(literal.IntegerLiteral().getText()); + return new Literal(TypePlaceholder.fresh(literal.getStart()), + value, literal.getStart()); + } else if(literal.FloatingPointLiteral()!= null){ + Number value = Double.parseDouble(literal.FloatingPointLiteral().getText()); + return new Literal(TypePlaceholder.fresh(literal.getStart()), + value, literal.getStart()); + }else if(literal.BooleanLiteral() != null){ + RefType type = new RefType(reg.getName("java.lang.Boolean"),literal.getStart()); + return new Literal(type, + Boolean.parseBoolean(literal.BooleanLiteral().getText()), + literal.getStart()); + }else if(literal.CharacterLiteral() != null){ + RefType type = new RefType(reg.getName("java.lang.Character"),literal.getStart()); + return new Literal(type, + // das gibt immer ' zurück, der Char befindet sich in Position 1 + //literal.CharacterLiteral().getText().charAt(0), + literal.CharacterLiteral().getText().charAt(1), + literal.getStart()); + }else if(literal.StringLiteral()!=null){ + RefType type = new RefType(reg.getName("java.lang.String"),literal.getStart()); + return new Literal(type, + literal.StringLiteral().getText().substring(1, literal.StringLiteral().getText().length()-1), + literal.getStart()); + }else if(literal.NullLiteral() != null){ + return new Literal(TypePlaceholder.fresh(literal.getStart()), null, + literal.getStart()); + }else { + throw new NotImplementedException(); + } + } + + private Expression convert(Java8Parser.MethodInvocation_lfno_primaryContext methodInvocationContext) { + String name; + if(methodInvocationContext.methodName()!=null){ + name = methodInvocationContext.methodName().Identifier().getText(); + }else{// if(methodInvocationContext.Identifier() != null){ + name = methodInvocationContext.Identifier().getText(); + } + Expression receiver; + if(methodInvocationContext.typeName() != null){ + receiver = generateLocalOrFieldVarOrClassName(methodInvocationContext.typeName().getText(), methodInvocationContext.typeName().getStart()); + }else if(methodInvocationContext.expressionName()!=null){ + receiver = convert(methodInvocationContext.expressionName()); + }else if(methodInvocationContext.toString().startsWith("super")) { + receiver = new Super(methodInvocationContext.getStart()); + }else if(methodInvocationContext.methodName() != null){ + receiver = new This(methodInvocationContext.methodName().getStart()); + }else { + throw new NotImplementedException(); + } + + ArgumentList argumentList = convert(methodInvocationContext.argumentList()); + ArrayList argTypes = argumentList.getArguments().stream() + .map(x -> TypePlaceholder.fresh(methodInvocationContext.getStart())) + .collect(Collectors.toCollection(ArrayList::new)); + MethodCall ret = new MethodCall(TypePlaceholder.fresh(methodInvocationContext.getStart()), + getReceiver(receiver), name, argumentList, TypePlaceholder.fresh(methodInvocationContext.getStart()), + argTypes, methodInvocationContext.getStart()); + return ret; + } + + private Expression convert(Java8Parser.LambdaExpressionContext expression) { + Java8Parser.LambdaParametersContext lambdaParams = expression.lambdaParameters(); + ParameterList params; + if(lambdaParams.Identifier() != null){ + List parameterList = new ArrayList<>(); + parameterList.add(new FormalParameter(lambdaParams.Identifier().getText(), + TypePlaceholder.fresh(lambdaParams.getStart()), lambdaParams.getStart())); + params = new ParameterList(parameterList, lambdaParams.getStart()); + }else if(lambdaParams.formalParameterList() != null){ + params = convert(lambdaParams.formalParameterList()); + //}else if( lambdaParams.inferredFormalParameterList != null){ + }else { + params = new ParameterList(new ArrayList<>(), expression.getStart()); + } + + HashMap lambdaLocals = new HashMap<>(); + lambdaLocals.putAll(localVars); + for(FormalParameter param : params.getFormalparalist()){ + lambdaLocals.put(param.getName(), param.getType()); + } + StatementGenerator lambdaGenerator = new StatementGenerator(reg, generics, fields, lambdaLocals); + + Block block; + if(expression.lambdaBody().expression() != null){ + List statements = new ArrayList<>(); + statements.add(new Return(lambdaGenerator.convert(expression.lambdaBody().expression()), + expression.lambdaBody().expression().getStart())); + block = new Block(statements, expression.lambdaBody().getStart()); + }else{ + block = lambdaGenerator.convert(expression.lambdaBody().block(), true); + } + List funNParams = new ArrayList<>(); + funNParams.add(TypePlaceholder.fresh(expression.getStart()));//ret-Type + params.getFormalparalist().forEach(formalParameter -> //Für jeden Parameter einen TPH anfügen: + funNParams.add(TypePlaceholder.fresh(expression.getStart()))); + RefTypeOrTPHOrWildcardOrGeneric lambdaType = TypePlaceholder.fresh(expression.getStart()); + //RefType lambdaType = new RefType(reg.getName("Fun"+params.getFormalparalist().size()), + //funNParams, name.getStart()); + return new LambdaExpression(lambdaType, params, block, expression.getStart()); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntacticSugar.java b/app/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntacticSugar.java new file mode 100644 index 00000000..d7926004 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntacticSugar.java @@ -0,0 +1,43 @@ +package de.dhbwstuttgart.parser.SyntaxTreeGenerator; + +import de.dhbwstuttgart.exceptions.NotImplementedException; +import de.dhbwstuttgart.parser.NullToken; +import de.dhbwstuttgart.syntaxtree.AbstractASTWalker; +import de.dhbwstuttgart.syntaxtree.Constructor; +import de.dhbwstuttgart.syntaxtree.statement.*; + +import java.util.List; + +public class SyntacticSugar { + + public static List addTrailingReturn(List statements){ + if(statements.size()!=0) { + Statement lastStmt = statements.get(statements.size() - 1); + ReturnFinder hasReturn = new ReturnFinder(); + lastStmt.accept(hasReturn); + if(hasReturn.hasReturn)return statements; + } + statements.add(new ReturnVoid(new NullToken())); + return statements; + } + + private static class ReturnFinder extends AbstractASTWalker{ + public boolean hasReturn = false; + @Override + public void visit(Return aReturn) { + hasReturn = true; + } + + @Override + public void visit(ReturnVoid aReturn) { + hasReturn = true; + } + } + + private static boolean hasReturn(Block block){ + for(Statement s : block.getStatements()) + if(s instanceof Return)return true; + return false; + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java b/app/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java new file mode 100644 index 00000000..33559a8e --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java @@ -0,0 +1,516 @@ +package de.dhbwstuttgart.parser.SyntaxTreeGenerator; + +import de.dhbwstuttgart.environment.PackageCrawler; +import de.dhbwstuttgart.exceptions.NotImplementedException; +import java.lang.ClassNotFoundException; + +import de.dhbwstuttgart.exceptions.TypeinferenceException; +import de.dhbwstuttgart.parser.NullToken; +import de.dhbwstuttgart.parser.antlr.Java8Parser; +import de.dhbwstuttgart.parser.scope.GatherNames; +import de.dhbwstuttgart.parser.scope.GenericsRegistry; +import de.dhbwstuttgart.parser.scope.JavaClassName; +import de.dhbwstuttgart.parser.scope.JavaClassRegistry; +import de.dhbwstuttgart.syntaxtree.*; +import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; +import de.dhbwstuttgart.syntaxtree.statement.*; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; + +import java.lang.reflect.Modifier; +import java.net.URL; +import java.sql.Ref; +import java.util.*; +import java.util.stream.Collectors; + +//import jdk.internal.dynalink.support.TypeConverterFactory; +import org.antlr.v4.runtime.CommonToken; +import org.antlr.v4.runtime.Token; +import org.antlr.v4.runtime.tree.TerminalNode; + +public class SyntaxTreeGenerator{ + private JavaClassRegistry reg; + private final GenericsRegistry globalGenerics; + private String pkgName = ""; + Set imports = new HashSet(); + private Map fields = new HashMap<>(); //PL 2018-11-01 fields eingefuegt, damit die fields immer die gleiche TPH bekommen + + List fieldInitializations = new ArrayList<>(); //PL 2019-10-23: Muss für jede Klasse neu initilisiert werden + + public SyntaxTreeGenerator(JavaClassRegistry reg, GenericsRegistry globalGenerics){ + //Die Generics müssen während des Bauens des AST erstellt werden, + // da diese mit der Methode oder Klasse, in welcher sie deklariert werden + // verknüpft sein müssen. Dennoch werden die Namen aller Generics in einer globalen Datenbank benötigt. + this.globalGenerics = globalGenerics; + this.reg = reg; + } + + + public JavaClassRegistry getReg(){ + return this.reg; + } + + // Converts type name to String. + public String convertTypeName(Java8Parser.TypeNameContext ctx){ + String ret; + if(ctx.packageOrTypeName() == null){ + ret = ctx.Identifier().toString(); + } + else{ + ret = convertPackageOrTypeName(ctx.packageOrTypeName()) + "." + ctx.Identifier().toString(); + } + return ret; + } + + // Converts PackageOrTypeName to String. + public String convertPackageOrTypeName(Java8Parser.PackageOrTypeNameContext ctx){ + String ret; + if(ctx.packageOrTypeName() == null){ + ret = ctx.Identifier().toString(); + } + else{ + ret = convertPackageOrTypeName(ctx.packageOrTypeName()) + "." + ctx.Identifier().toString(); + } + return ret; + } + + public SourceFile convert(Java8Parser.CompilationUnitContext ctx, PackageCrawler packageCrawler, ClassLoader classLoader) throws ClassNotFoundException{ + if(ctx.packageDeclaration()!=null)this.pkgName = convert(ctx.packageDeclaration()); + List classes = new ArrayList<>(); + Map imports = GatherNames.getImports(ctx, packageCrawler, classLoader); + this.imports = imports.keySet().stream().map(name -> reg.getName(name)).collect(Collectors.toSet()); + for(Java8Parser.TypeDeclarationContext typeDecl : ctx.typeDeclaration()){ + ClassOrInterface newClass; + if(typeDecl.classDeclaration() != null){ + newClass = convertClass(typeDecl.classDeclaration()); + } + else{ + newClass = convertInterface(typeDecl.interfaceDeclaration()); + } + classes.add(newClass); + } + return new SourceFile(this.pkgName, classes, this.imports); + } + + private String convert(Java8Parser.PackageDeclarationContext packageDeclarationContext) { + String ret = ""; + for(TerminalNode identifier : packageDeclarationContext.Identifier()){ + ret += identifier.getText()+"."; + } + ret = ret.substring(0, ret.length()-1); + return ret; + } + + public Method convert(Java8Parser.MethodDeclarationContext methodDeclarationContext, JavaClassName parentClass, RefType superClass, GenericsRegistry generics) { + Java8Parser.MethodHeaderContext header = methodDeclarationContext.methodHeader(); + int modifiers = SyntaxTreeGenerator.convert(methodDeclarationContext.methodModifier()); + GenericsRegistry localGenerics = createGenerics(methodDeclarationContext.methodHeader().typeParameters(), + parentClass, header.methodDeclarator().Identifier().getText(), reg, generics); + localGenerics.putAll(generics); + return convert(modifiers, header, methodDeclarationContext.methodBody(),parentClass, superClass, localGenerics); + } + + public Method convert(Java8Parser.InterfaceMethodDeclarationContext ctx, JavaClassName parentClass, RefType superClass, GenericsRegistry generics) { + Java8Parser.MethodHeaderContext header = ctx.methodHeader(); + int modifiers = SyntaxTreeGenerator.convertInterfaceModifier(ctx.interfaceMethodModifier()); + + GenericsRegistry localGenerics = createGenerics(header.typeParameters(), parentClass, header.methodDeclarator().Identifier().getText(), reg, generics); + localGenerics.putAll(generics); + + return convert(modifiers, header, ctx.methodBody(),parentClass, superClass, localGenerics); + } + + private Method convert(int modifiers, Java8Parser.MethodHeaderContext header, Java8Parser.MethodBodyContext body, + JavaClassName parentClass, RefType superClass, GenericsRegistry localGenerics) { + + StatementGenerator stmtGen = new StatementGenerator(reg, localGenerics, fields, new HashMap<>()); + + String name = header.methodDeclarator().Identifier().getText(); + GenericDeclarationList gtvDeclarations = new GenericDeclarationList(new ArrayList<>(), header.getStart()); + if(header.typeParameters() != null){ + gtvDeclarations = TypeGenerator.convert(header.typeParameters(), parentClass, name, reg, localGenerics); + }else{ + gtvDeclarations = new GenericDeclarationList(new ArrayList<>(), header.getStart()); + } + RefTypeOrTPHOrWildcardOrGeneric retType; + if(header.result() != null){ + if(header.result().unannType() != null){ + retType = TypeGenerator.convert(header.result().unannType(), reg, localGenerics); + } + else retType = new de.dhbwstuttgart.syntaxtree.type.Void(header.result().getStart()); + }else{ + retType = TypePlaceholder.fresh(header.getStart()); + } + ParameterList parameterList = stmtGen.convert(header.methodDeclarator().formalParameterList()); + Block block = null; + if(body.block() == null){ + if(! Modifier.isAbstract(modifiers)){ + //TODO: Error! Abstrakte Methode ohne abstrakt Keyword + } + }else{ + block = stmtGen.convert(body.block(),true); + } + if(parentClass.equals(new JavaClassName(name))){ + return new Constructor(modifiers, name, retType, parameterList, block, gtvDeclarations, header.getStart() /*, fieldInitializations geloescht PL 2018-11-24 */); + }else{ + return new Method(modifiers, name, retType, parameterList,block, gtvDeclarations, header.getStart()); + } + } + + private ClassOrInterface convertClass(Java8Parser.ClassDeclarationContext ctx) { + ClassOrInterface newClass; + fieldInitializations = new ArrayList<>(); //PL 2019-10-22: muss für jede Klasse neu initilisiert werden + if(ctx.normalClassDeclaration() != null){ + newClass = convertNormal(ctx.normalClassDeclaration()); + } + else{ + newClass = convertEnum(ctx.enumDeclaration()); + } + return newClass; + } + + private ClassOrInterface convertNormal(Java8Parser.NormalClassDeclarationContext ctx) { + int modifiers = 0; + if(ctx.classModifier() != null){ + for(Java8Parser.ClassModifierContext mod : ctx.classModifier()){ + int newModifier = convert(mod); + modifiers += newModifier; + } + } + String className = this.pkgName + (this.pkgName.length()>0?".":"") + ctx.Identifier().getText(); + JavaClassName name = reg.getName(className); //Holt den Package Namen mit dazu + if(! name.toString().equals(className)){ //Kommt die Klasse schon in einem anderen Package vor? + throw new TypeinferenceException("Name " + className + " bereits vorhanden in " + reg.getName(className).toString() + ,ctx.getStart()); + } + GenericsRegistry generics = createGenerics(ctx.typeParameters(), name, "", reg, new GenericsRegistry(globalGenerics)); + Token offset = ctx.getStart(); + GenericDeclarationList genericClassParameters; + if(ctx.typeParameters() == null){ + genericClassParameters = createEmptyGenericDeclarationList(ctx.Identifier()); + }else{ + genericClassParameters = TypeGenerator.convert(ctx.typeParameters(), name, "",reg, generics); + } + RefType superClass ; + if(ctx.superclass() != null){ + superClass = convert(ctx.superclass()); + }else{ + superClass = new RefType(ASTFactory.createObjectClass().getClassName(), ctx.getStart()); + } + List fielddecl = convertFields(ctx.classBody(), generics); + //fieldInitializations = generateFieldInitializations(ctx.classBody(), generics); + List methodsAndConstructors = convertMethods(ctx.classBody(), name, superClass, generics); + List methods = new ArrayList<>(); + List konstruktoren = new ArrayList<>(); + //int noOfMethods = methods.size(); + for(int i = 0; i < methodsAndConstructors.size(); i++){ + Method m = methodsAndConstructors.get(i); + if(m instanceof Constructor){ + konstruktoren.add((Constructor) m); + } + else { + methods.add(m); + } + } + if(konstruktoren.size()<1){//Standardkonstruktor anfügen: + konstruktoren.add( + generateStandardConstructor( + ctx.Identifier().getText(), name, superClass, + genericClassParameters, offset) + ); + } + + Boolean isInterface = false; + List implementedInterfaces = convert(ctx.superinterfaces(), generics); + + return new ClassOrInterface(modifiers, name, fielddecl, + Optional.of(this.generatePseudoConstructor(ctx.Identifier().getText(), name, superClass, genericClassParameters, offset)), + methods, konstruktoren, genericClassParameters, superClass, + isInterface, implementedInterfaces, offset); + } + + /* + private List generateFieldInitializations(Java8Parser.ClassBodyContext classBodyContext, GenericsRegistry generics) { + List ret = new ArrayList<>(); + for(Java8Parser.ClassBodyDeclarationContext classMember : classBodyContext.classBodyDeclaration()){ + if(classMember.classMemberDeclaration() != null){ + Java8Parser.ClassMemberDeclarationContext classMemberDeclarationContext = classMember.classMemberDeclaration(); + if(classMemberDeclarationContext.fieldDeclaration() != null + && classMemberDeclarationContext.fieldDeclaration().variableDeclaratorList() != null){ + for(Java8Parser.VariableDeclaratorContext ctx : classMemberDeclarationContext.fieldDeclaration().variableDeclaratorList().variableDeclarator()) { + String fieldName = ctx.variableDeclaratorId().Identifier().getText(); + if(ctx.variableDeclaratorId().dims() != null)throw new NotImplementedException(); + Token offset = ctx.getStart(); + RefTypeOrTPHOrWildcardOrGeneric fieldType; + for(Field f : fields) + AssignToField leftSide = new AssignToField(new FieldVar(new This(offset), fieldName, )); + ret.addAll(); + } + }else if(classMemberDeclarationContext.methodDeclaration()!= null){ + //Do nothing! + } + } + } + return ret; + } +*/ + + private List convert(Java8Parser.SuperinterfacesContext ctx, GenericsRegistry generics) { + if(ctx == null)return new ArrayList<>(); + return convert(ctx.interfaceTypeList(), generics); + } + + private List convert(Java8Parser.InterfaceTypeListContext ctx, GenericsRegistry generics) { + List ret = new ArrayList<>(); + for(Java8Parser.InterfaceTypeContext interfaceType : ctx.interfaceType()){ + ret.add((RefType) TypeGenerator.convert(interfaceType.classType(), reg, generics)); + } + return ret; + } + + /** + * http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.8.9 + */ + private Constructor generateStandardConstructor(String className, JavaClassName parentClass, RefType superClass, GenericDeclarationList classGenerics, Token offset){ + RefType classType = ClassOrInterface.generateTypeOfClass(reg.getName(className), classGenerics, offset); + ParameterList params = new ParameterList(new ArrayList<>(), offset); + Block block = new Block(new ArrayList<>(), offset); + return new Constructor(Modifier.PUBLIC, className, classType, params, block, classGenerics, offset /*, fieldInitializations geloescht PL 2018-11-24 */); + } + + /* fieldInitializations werden in einem Psedokonstruktor in der abstrakten Syntax gespeichert */ + private Constructor generatePseudoConstructor(String className, JavaClassName parentClass, RefType superClass, GenericDeclarationList classGenerics, Token offset){ + RefType classType = ClassOrInterface.generateTypeOfClass(reg.getName(className), classGenerics, offset); + ParameterList params = new ParameterList(new ArrayList<>(), offset); + Block block = new Block(new ArrayList<>(fieldInitializations), offset); + return new Constructor(Modifier.PUBLIC, className, classType, params, block, classGenerics, offset /*, fieldInitializations geloescht PL 2018-11-24 */); + } + + private RefType convert(Java8Parser.SuperclassContext superclass) { + if(superclass.classType().classOrInterfaceType() != null){ + throw new NotImplementedException(); + }else{ + RefTypeOrTPHOrWildcardOrGeneric ret = TypeGenerator.convertTypeName(superclass.classType().Identifier().getText(), superclass.classType().typeArguments(), + superclass.getStart(), reg, globalGenerics); + if(ret instanceof RefType){ + return (RefType) ret; + }else{ + throw new TypeinferenceException(superclass.getText() + " ist kein gültiger Supertyp", superclass.getStart()); + } + } + } + + private List convertMethods(Java8Parser.ClassBodyContext classBodyContext, + JavaClassName parentClass, RefType superClass, GenericsRegistry generics) { + List ret = new ArrayList<>(); + for(Java8Parser.ClassBodyDeclarationContext classMember : classBodyContext.classBodyDeclaration()){ + if(classMember.classMemberDeclaration() != null){ + Java8Parser.ClassMemberDeclarationContext classMemberDeclarationContext = classMember.classMemberDeclaration(); + if(classMemberDeclarationContext.fieldDeclaration() != null){ + //Do nothing! + }else if(classMemberDeclarationContext.methodDeclaration()!= null){ + + ret.add(this.convert(classMemberDeclarationContext.methodDeclaration(), parentClass, superClass, generics)); + } + } + } + return ret; + } + + private List convertFields(Java8Parser.ClassBodyContext classBodyContext, GenericsRegistry generics) { + List ret = new ArrayList<>(); + for(Java8Parser.ClassBodyDeclarationContext classMember : classBodyContext.classBodyDeclaration()){ + if(classMember.classMemberDeclaration() != null){ + Java8Parser.ClassMemberDeclarationContext classMemberDeclarationContext = classMember.classMemberDeclaration(); + if(classMemberDeclarationContext.fieldDeclaration() != null){ + ret.addAll(convert(classMember.classMemberDeclaration().fieldDeclaration(), generics)); + }else if(classMemberDeclarationContext.methodDeclaration()!= null){ + //Do nothing! + } + } + } + return ret; + } + + public static int convert(List methodModifierContexts) { + int ret = 0; + for(Java8Parser.MethodModifierContext mod : methodModifierContexts){ + if(mod.annotation() == null)convertModifier(mod.getText()); + } + return ret; + } + + public static int convertInterfaceModifier(List methodModifierContexts) { + int ret = 0; + for(Java8Parser.InterfaceMethodModifierContext mod : methodModifierContexts){ + if(mod.annotation() == null)convertModifier(mod.getText()); + } + return ret; + } + + private List convert(Java8Parser.FieldDeclarationContext fieldDeclarationContext, GenericsRegistry generics) { + List ret = new ArrayList<>(); + int modifiers = 0; + for(Java8Parser.FieldModifierContext fieldModifierContext : fieldDeclarationContext.fieldModifier()){ + modifiers+=(convert(fieldModifierContext)); + } + RefTypeOrTPHOrWildcardOrGeneric fieldType; + if(fieldDeclarationContext.unannTypeOrAuto() != null + && fieldDeclarationContext.unannTypeOrAuto().unannType() != null){ + fieldType = TypeGenerator.convert(fieldDeclarationContext.unannTypeOrAuto().unannType(), reg, generics); + }else{ + fieldType = TypePlaceholder.fresh(fieldDeclarationContext.variableDeclaratorList().getStart()); //PL 2019-12-06: variableDeclaratorList() eingefuegt, um als Token nicht die Modifier zu bekommen + } + for(Java8Parser.VariableDeclaratorContext varCtx : fieldDeclarationContext.variableDeclaratorList().variableDeclarator()){ + String fieldName = convert(varCtx.variableDeclaratorId()); + fields.put(fieldName, fieldType); + if(varCtx.variableInitializer() != null){ + initializeField(varCtx, fieldType, generics); + } + ret.add(new Field(fieldName,fieldType,modifiers,varCtx.getStart())); + } + return ret; + } + + public static String convert(Java8Parser.VariableDeclaratorIdContext variableDeclaratorIdContext) { + return variableDeclaratorIdContext.getText(); + } + + // Initialize a field by creating implicit constructor. + private void initializeField(Java8Parser.VariableDeclaratorContext ctx, RefTypeOrTPHOrWildcardOrGeneric typeOfField, GenericsRegistry generics){ + StatementGenerator statementGenerator = new StatementGenerator(reg, generics, fields, new HashMap<>()); + fieldInitializations.add(statementGenerator.generateFieldAssignment(ctx, typeOfField)); + } + + public static int convertModifier(String modifier){ + HashMap modifiers = new HashMap<>(); + modifiers.put(Modifier.toString(Modifier.PUBLIC), Modifier.PUBLIC); + modifiers.put(Modifier.toString(Modifier.PRIVATE), Modifier.PRIVATE); + modifiers.put(Modifier.toString(Modifier.PROTECTED), Modifier.PROTECTED); + modifiers.put(Modifier.toString(Modifier.ABSTRACT), Modifier.ABSTRACT); + modifiers.put(Modifier.toString(Modifier.STATIC), Modifier.STATIC); + modifiers.put(Modifier.toString(Modifier.STRICT), Modifier.STRICT); + modifiers.put(Modifier.toString(Modifier.FINAL), Modifier.FINAL); + modifiers.put(Modifier.toString(Modifier.TRANSIENT), Modifier.TRANSIENT); + modifiers.put(Modifier.toString(Modifier.VOLATILE), Modifier.VOLATILE); + modifiers.put(Modifier.toString(Modifier.SYNCHRONIZED), Modifier.SYNCHRONIZED); + modifiers.put(Modifier.toString(Modifier.NATIVE), Modifier.NATIVE); + modifiers.put(Modifier.toString(Modifier.INTERFACE), Modifier.INTERFACE); + int ret = 0; + for(String m : modifiers.keySet()){ + if(modifier.contains(m))ret+=modifiers.get(m); + } + return ret; + } + + private int convert(Java8Parser.ClassModifierContext ctx){ + if(ctx.annotation() != null)return 0; + return convertModifier(ctx.getText()); + } + + private int convert(Java8Parser.FieldModifierContext ctx){ + if(ctx.annotation() != null)return 0; + return convertModifier(ctx.getText()); + } + + private int convert(Java8Parser.InterfaceModifierContext ctx) { + if(ctx.annotation() != null)return 0; + return convertModifier(ctx.getText()); + } + + private ClassOrInterface convertEnum(Java8Parser.EnumDeclarationContext ctx){ + return null; + } + + private ClassOrInterface convertInterface(Java8Parser.InterfaceDeclarationContext ctx){ + if(ctx.normalInterfaceDeclaration() != null){ + return convertNormal(ctx.normalInterfaceDeclaration()); + }else{ + throw new NotImplementedException(); + } + } + + private ClassOrInterface convertNormal(Java8Parser.NormalInterfaceDeclarationContext ctx) { + int modifiers = 0; + if(ctx.interfaceModifier() != null){ + for( Java8Parser.InterfaceModifierContext mod : ctx.interfaceModifier()){ + int newModifier = convert(mod); + modifiers += newModifier; + } + } + if(!Modifier.isInterface(modifiers))modifiers += Modifier.INTERFACE; + + JavaClassName name = reg.getName(ctx.Identifier().getText()); + + GenericsRegistry generics = createGenerics(ctx.typeParameters(), name, "", reg, new GenericsRegistry(globalGenerics)); + + GenericDeclarationList genericParams; + if(ctx.typeParameters() != null){ + genericParams = TypeGenerator.convert(ctx.typeParameters(), name, "",reg, generics); + }else{ + genericParams = createEmptyGenericDeclarationList(ctx.Identifier()); + } + RefType superClass = ASTFactory.createObjectType(); + + List fields = convertFields(ctx.interfaceBody()); + List methods = convertMethods(ctx.interfaceBody(), name, superClass, generics); + + List extendedInterfaces = convert(ctx.extendsInterfaces(), generics); + + return new ClassOrInterface(modifiers, name, fields, Optional.empty(), methods, new ArrayList<>(), + genericParams, superClass, true, extendedInterfaces, ctx.getStart()); + } + + private GenericDeclarationList createEmptyGenericDeclarationList(TerminalNode classNameIdentifier) { + CommonToken gtvOffset = new CommonToken(classNameIdentifier.getSymbol()); + gtvOffset.setCharPositionInLine(gtvOffset.getCharPositionInLine()+classNameIdentifier.getText().length()); + gtvOffset.setStartIndex(gtvOffset.getStopIndex()+1); + return new GenericDeclarationList(new ArrayList<>(), gtvOffset); + } + + private GenericsRegistry createGenerics(Java8Parser.TypeParametersContext ctx, JavaClassName parentClass, String parentMethod, JavaClassRegistry reg, GenericsRegistry generics) { + GenericsRegistry ret = new GenericsRegistry(this.globalGenerics); + ret.putAll(generics); + if(ctx == null || ctx.typeParameterList() == null)return ret; + for(Java8Parser.TypeParameterContext tp : ctx.typeParameterList().typeParameter()){ + ret.put(tp.Identifier().getText(), new GenericContext(parentClass, parentMethod)); + } + for(Java8Parser.TypeParameterContext tp : ctx.typeParameterList().typeParameter()){ + TypeGenerator.convert(tp, parentClass, parentMethod, reg, ret); + } + return ret; + } + + private List convert(Java8Parser.ExtendsInterfacesContext extendsInterfacesContext, GenericsRegistry generics) { + if(extendsInterfacesContext == null)return new ArrayList<>(); + return convert(extendsInterfacesContext.interfaceTypeList(), generics); + } + + private List convertMethods(Java8Parser.InterfaceBodyContext interfaceBodyContext, + JavaClassName parentClass, RefType superClass, GenericsRegistry generics) { + List ret = new ArrayList<>(); + for(Java8Parser.InterfaceMemberDeclarationContext member : interfaceBodyContext.interfaceMemberDeclaration()){ + if(member.interfaceMethodDeclaration() != null){ + ret.add(this.convert(member.interfaceMethodDeclaration(), parentClass, superClass, generics)); + //new Method(name, type, modifier, params, null, genericDecls, member.interfaceMethodDeclaration().getStart()); + }else{ + throw new NotImplementedException(); + } + } + return ret; + } + + private List convertFields(Java8Parser.InterfaceBodyContext interfaceBodyContext) { + List ret = new ArrayList<>(); + for(Java8Parser.InterfaceMemberDeclarationContext member : interfaceBodyContext.interfaceMemberDeclaration()){ + if(member.constantDeclaration() != null){ + //TODO: Erstelle hier ein Feld! + throw new NotImplementedException(); + } + } + return ret; + } + + +} diff --git a/app/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/TypeGenerator.java b/app/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/TypeGenerator.java new file mode 100644 index 00000000..d55e9349 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/TypeGenerator.java @@ -0,0 +1,222 @@ +package de.dhbwstuttgart.parser.SyntaxTreeGenerator; + +import de.dhbwstuttgart.exceptions.NotImplementedException; +import de.dhbwstuttgart.exceptions.TypeinferenceException; +import de.dhbwstuttgart.parser.antlr.Java8Parser; +import de.dhbwstuttgart.parser.antlr.Java8Parser.UnannClassType_lfno_unannClassOrInterfaceTypeContext; +import de.dhbwstuttgart.parser.scope.GenericsRegistry; +import de.dhbwstuttgart.parser.scope.JavaClassName; +import de.dhbwstuttgart.parser.scope.JavaClassRegistry; +import de.dhbwstuttgart.syntaxtree.GenericDeclarationList; +import de.dhbwstuttgart.syntaxtree.GenericTypeVar; +import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; +import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType; +import de.dhbwstuttgart.syntaxtree.type.GenericRefType; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import org.antlr.v4.runtime.Token; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class TypeGenerator { + + public static RefTypeOrTPHOrWildcardOrGeneric convert(Java8Parser.UnannClassOrInterfaceTypeContext unannClassOrInterfaceTypeContext, JavaClassRegistry reg, GenericsRegistry generics) { + Java8Parser.TypeArgumentsContext arguments=null; + /* PL 2019-03-19 auskommentiert ANFANG + if(unannClassOrInterfaceTypeContext.unannClassType_lfno_unannClassOrInterfaceType() != null){ + arguments = unannClassOrInterfaceTypeContext.unannClassType_lfno_unannClassOrInterfaceType().typeArguments(); + }else{// if(unannClassOrInterfaceTypeContext.unannInterfaceType_lfno_unannClassOrInterfaceType() != null){ + arguments = unannClassOrInterfaceTypeContext.unannInterfaceType_lfno_unannClassOrInterfaceType().unannClassType_lfno_unannClassOrInterfaceType().typeArguments(); + } + PL 2019-03-19 auskommentiert ENDE */ + /** + * Problem sind hier die verschachtelten Typen mit verschachtelten Typargumenten + * Beispiel: Typ.InnererTyp + */ + String name = unannClassOrInterfaceTypeContext.getText(); + if(name.contains("<")){ + name = name.split("<")[0]; //Der Typ ist alles vor den ersten Argumenten + /* Fuer Debug-Zwecke + unannClassOrInterfaceTypeContext.unannInterfaceType_lfno_unannClassOrInterfaceType(); + unannClassOrInterfaceTypeContext.unannClassType_lfno_unannClassOrInterfaceType().getText(); + //unannClassOrInterfaceTypeContext.unannInterfaceType_lfno_unannClassOrInterfaceType().unannClassType_lfno_unannClassOrInterfaceType().typeArguments(); + //UnannClassType_lfno_unannClassOrInterfaceTypeContext + unannClassOrInterfaceTypeContext.unannClassType_lf_unannClassOrInterfaceType(0); + unannClassOrInterfaceTypeContext.unannClassType_lf_unannClassOrInterfaceType(0).getText(); + unannClassOrInterfaceTypeContext.unannClassType_lf_unannClassOrInterfaceType(1); + unannClassOrInterfaceTypeContext.unannClassType_lf_unannClassOrInterfaceType(1).getText(); + unannClassOrInterfaceTypeContext.unannClassType_lfno_unannClassOrInterfaceType().getText(); + //unannClassOrInterfaceTypeContext.unannInterfaceType_lf_unannClassOrInterfaceType(); + //unannClassOrInterfaceTypeContext.unannInterfaceType_lf_unannClassOrInterfaceType(0).getText(); + //unannClassOrInterfaceTypeContext.unannInterfaceType_lf_unannClassOrInterfaceType(1).getText(); + //unannClassOrInterfaceTypeContext.unannInterfaceType_lfno_unannClassOrInterfaceType().getText(); + */ + int lastElement = new ArrayList<>(unannClassOrInterfaceTypeContext.unannClassType_lf_unannClassOrInterfaceType()).size()-1; + if (lastElement >=0) {//qualifizierter Name z.B.: java.util.Vector + arguments = unannClassOrInterfaceTypeContext.unannClassType_lf_unannClassOrInterfaceType(lastElement).typeArguments(); + } + else { //unqualifizierter Name z.B.: Vector + arguments = unannClassOrInterfaceTypeContext.unannClassType_lfno_unannClassOrInterfaceType().typeArguments(); + } + } + return convertTypeName(name, arguments, unannClassOrInterfaceTypeContext.getStart(), reg, generics); + } + + public static RefTypeOrTPHOrWildcardOrGeneric convert(Java8Parser.UnannTypeContext unannTypeContext, JavaClassRegistry reg, GenericsRegistry genericsRegistry) { + if(unannTypeContext.unannPrimitiveType()!=null){ + if(unannTypeContext.unannPrimitiveType().getText().equals("boolean")){ + return new RefType(ASTFactory.createClass(Boolean.class).getClassName(), unannTypeContext.getStart()); + }else{ + Java8Parser.NumericTypeContext numericType = unannTypeContext.unannPrimitiveType().numericType(); + throw new NotImplementedException(); + } + }else + if(unannTypeContext.unannReferenceType().unannArrayType()!=null){ + //System.out.println(unannTypeContext.getText()); + throw new NotImplementedException(); + }else + if(unannTypeContext.unannReferenceType().unannTypeVariable()!=null){ + JavaClassName name = reg.getName(unannTypeContext.unannReferenceType().unannTypeVariable().Identifier().toString()); + return new RefType(name, unannTypeContext.getStart()); + } + return TypeGenerator.convert(unannTypeContext.unannReferenceType().unannClassOrInterfaceType(), reg, genericsRegistry); + } + + public static GenericDeclarationList convert(Java8Parser.TypeParametersContext typeParametersContext, + JavaClassName parentClass, String parentMethod, JavaClassRegistry reg, GenericsRegistry generics) { + Token endOffset = typeParametersContext.getStop(); + List typeVars = new ArrayList<>(); + for(Java8Parser.TypeParameterContext typeParameter : typeParametersContext.typeParameterList().typeParameter()){ + typeVars.add(convert(typeParameter, parentClass, parentMethod, reg, generics)); + endOffset = typeParameter.getStop(); + } + return new GenericDeclarationList(typeVars, endOffset); + } + + public static GenericTypeVar convert(Java8Parser.TypeParameterContext typeParameter, JavaClassName parentClass, String parentMethod, JavaClassRegistry reg, GenericsRegistry generics) { + String name = typeParameter.Identifier().getText(); + //TODO: Es müssen erst alle GenericTypeVars generiert werden, dann können die bounds dieser Generics ermittelt werden + //Problem ist erlaubt, würde aber bei den Bounds von A den Generic B nicht als solchen erkennen + List bounds = TypeGenerator.convert(typeParameter.typeBound(),reg, generics); + + GenericTypeVar ret = new GenericTypeVar(name, bounds, typeParameter.getStart(), typeParameter.getStop()); + return ret; + } + + public static List convert(Java8Parser.TypeBoundContext typeBoundContext, JavaClassRegistry reg, GenericsRegistry generics) { + List ret = new ArrayList<>(); + if(typeBoundContext == null){ + ret.add(ASTFactory.createObjectType()); + return ret; + } + if(typeBoundContext.typeVariable() != null){ + ret.add(convertTypeName(typeBoundContext.typeVariable().Identifier().getText(), null, typeBoundContext.typeVariable().getStart(), reg, generics)); + return ret; + } + if(typeBoundContext.classOrInterfaceType() != null){ + ret.add(convert(typeBoundContext.classOrInterfaceType(), reg, generics)); + if(typeBoundContext.additionalBound() != null) + for(Java8Parser.AdditionalBoundContext addCtx : typeBoundContext.additionalBound()){ + ret.add(convert(addCtx.interfaceType())); + } + return ret; + }else{ + throw new NotImplementedException(); + } + } + + private static RefTypeOrTPHOrWildcardOrGeneric convert(Java8Parser.ClassOrInterfaceTypeContext classOrInterfaceTypeContext, JavaClassRegistry reg, GenericsRegistry generics) { + Java8Parser.ClassType_lfno_classOrInterfaceTypeContext ctx = classOrInterfaceTypeContext.classType_lfno_classOrInterfaceType(); + if(ctx.typeArguments() != null && + classOrInterfaceTypeContext.classType_lf_classOrInterfaceType().size() > 0) + throw new NotImplementedException(); + String typeName = ctx.Identifier().toString(); + Java8Parser.ClassType_lf_classOrInterfaceTypeContext nextCtx = null; + for(Java8Parser.ClassType_lf_classOrInterfaceTypeContext forEachCtx : classOrInterfaceTypeContext.classType_lf_classOrInterfaceType()){ + nextCtx = forEachCtx; + typeName += "." + forEachCtx.Identifier().toString(); + } + Java8Parser.TypeArgumentsContext arguments = nextCtx!=null?nextCtx.typeArguments():ctx.typeArguments(); + return convertTypeName(typeName, arguments, classOrInterfaceTypeContext.getStart(), reg, generics); + } + + private static RefTypeOrTPHOrWildcardOrGeneric convert(Java8Parser.InterfaceTypeContext interfaceTypeContext) { + throw new NotImplementedException(); + } + + public static RefTypeOrTPHOrWildcardOrGeneric convert(Java8Parser.ReferenceTypeContext referenceTypeContext, JavaClassRegistry reg, GenericsRegistry generics) { + if(referenceTypeContext.classOrInterfaceType() != null){ + if(referenceTypeContext.classOrInterfaceType().classType_lfno_classOrInterfaceType()!= null){ + return convert(referenceTypeContext.classOrInterfaceType(), reg, generics);//return convertTypeName(referenceTypeContext.getText(), ctx.typeArguments(),referenceTypeContext.getStart(), reg, generics); + }else{ + throw new NotImplementedException(); + } + }else{ + throw new NotImplementedException(); + } + } + + public static RefTypeOrTPHOrWildcardOrGeneric convert(Java8Parser.WildcardContext wildcardContext, JavaClassRegistry reg, GenericsRegistry generics) { + if(wildcardContext.wildcardBounds() != null){ + if(wildcardContext.wildcardBounds().getText().substring(0, 7).equals("extends")){ + return new ExtendsWildcardType(convert(wildcardContext.wildcardBounds().referenceType(), reg, generics), wildcardContext.getStart()); + }else{ + return new SuperWildcardType(convert(wildcardContext.wildcardBounds().referenceType(), reg, generics), wildcardContext.getStart()); + } + }else{ + throw new NotImplementedException(); //Wildcard ohne Bound + } + } + + public static RefTypeOrTPHOrWildcardOrGeneric convertTypeName(String name, Token offset, JavaClassRegistry reg, GenericsRegistry generics){ + return convertTypeName(name, null, offset, reg, generics); + } + + public static RefTypeOrTPHOrWildcardOrGeneric convertTypeName( + String name, Java8Parser.TypeArgumentsContext typeArguments, Token offset, JavaClassRegistry reg, GenericsRegistry generics){ + if(!reg.contains(name)){ //Dann könnte es ein generischer Type oder ein FunN$$-Type sein + if(generics.contains(name)){ + return new GenericRefType(name, offset); + }else{ + Pattern p = Pattern.compile("Fun(\\d+)[$][$]"); + Matcher m = p.matcher(name); + if (m.matches()) {//es ist FunN$$-Type + return new RefType(new JavaClassName(name), convert(typeArguments, reg, generics), offset); + } else { + throw new TypeinferenceException("Der Typ "+ name + " ist nicht vorhanden",offset); + }} + } + if(typeArguments == null){ + List params = new ArrayList<>(); + for(int i = 0; i convert(Java8Parser.TypeArgumentsContext typeArguments, + JavaClassRegistry reg, GenericsRegistry generics){ + List ret = new ArrayList<>(); + for(Java8Parser.TypeArgumentContext arg : typeArguments.typeArgumentList().typeArgument()){ + if(arg.wildcard() != null){ + ret.add(convert(arg.wildcard(), reg, generics)); + }else{ + ret.add(convert(arg.referenceType(), reg, generics)); + } + } + return ret; + } + + public static RefTypeOrTPHOrWildcardOrGeneric convert(Java8Parser.ClassTypeContext ctx, JavaClassRegistry reg, GenericsRegistry generics) { + if(ctx.classOrInterfaceType() != null)throw new NotImplementedException(); + return convertTypeName(ctx.Identifier().getText(), ctx.typeArguments(), ctx.getStart(), reg, generics); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/parser/TODO b/app/src/main/java/de/dhbwstuttgart/parser/TODO new file mode 100644 index 00000000..165cb562 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/parser/TODO @@ -0,0 +1,5 @@ += Grammatik = + +* Core-Problem: Typinferenz vs. Konstruktoren +* möglicherweise Problem: falsche Return-Expressions + diff --git a/app/src/main/java/de/dhbwstuttgart/parser/notes/GetNames b/app/src/main/java/de/dhbwstuttgart/parser/notes/GetNames new file mode 100644 index 00000000..2c59e3bc --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/parser/notes/GetNames @@ -0,0 +1,15 @@ +* Methode als statische Klasse +* Methode gibt eine JavaClassRegistry zurück (für mehr als 1 S0ourcefile). +* Suchmuster: \n rule +* Generell: lieber leere Listen und wenig null verwenden (Spezialfälle ausgenommen). + +== Fehler/Exceptions == + +* Eigene wie z.B. TypeCheckExceptions +* Fehler sollen an Semantikchecker usw. weiter gegeben werden. + +== Offset == + +* Evtl. Zeichen im File/in der Klasse durch Antlr ermitteln. +* z.B. ParserRuleContext.getStart() +* Anstatt offset: Instanz des entsprechenden ParserRuleContext (liefert evtl. noch mehr Infos) diff --git a/app/src/main/java/de/dhbwstuttgart/parser/notes/TODO b/app/src/main/java/de/dhbwstuttgart/parser/notes/TODO new file mode 100644 index 00000000..8d04f716 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/parser/notes/TODO @@ -0,0 +1,3 @@ +* fieldDeclarations +* Imports +* (Q)Generics diff --git a/app/src/main/java/de/dhbwstuttgart/parser/notes/questions b/app/src/main/java/de/dhbwstuttgart/parser/notes/questions new file mode 100644 index 00000000..61a725af --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/parser/notes/questions @@ -0,0 +1,2 @@ +* Ablegen der Type Parameter: kompletter Name? +* Typen (unannType etc.) diff --git a/app/src/main/java/de/dhbwstuttgart/parser/parse_tree b/app/src/main/java/de/dhbwstuttgart/parser/parse_tree new file mode 100644 index 00000000..13078b55 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/parser/parse_tree @@ -0,0 +1,18 @@ +* Listener-Pattern für das Projekt eher ungeeignet. + += Herangehensweise/Format = + +* CompilatunUnit (Rot) wird zu Source-File (Root) +* Im Paket Syntaxtree finden sich die Klassen, die ich letztendlich erzeugen muss. +* Kann hier auch Veränderungen vornehmen (Pull Request) +* Wichtig! Typnamen müssen aufgelöst werden können (also z.B. java.lang.util.ArrayList (JavaClassRegistry). + += Idee bei mehreren Files = +* Zunächst alle Files anschauen und Pakate/Klassen für die spätere Verwendung "registrieren". +* Danach erst das komplette Package/alle Klassen imselben Verzeichnis parsen. + +== Fragen/PProbleme SyntaxTreeGenerator == + +* ClassRegistry: Unklar, woher diese kommen soll. +* Konstruktor für Class fehlt. +* Namenskonflikt Class vs. Class in Java? diff --git a/app/src/main/java/de/dhbwstuttgart/parser/scope/GatherNames.java b/app/src/main/java/de/dhbwstuttgart/parser/scope/GatherNames.java new file mode 100644 index 00000000..aec9f8b4 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/parser/scope/GatherNames.java @@ -0,0 +1,103 @@ +package de.dhbwstuttgart.parser.scope; + +import java.net.URL; +import java.net.URLClassLoader; +import java.util.*; + +import de.dhbwstuttgart.parser.antlr.Java8BaseListener; +import de.dhbwstuttgart.syntaxtree.AbstractASTWalker; +import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor; +import org.antlr.v4.runtime.tree.ParseTreeWalker; +import org.antlr.v4.runtime.tree.TerminalNode; + +import de.dhbwstuttgart.environment.PackageCrawler; +import de.dhbwstuttgart.parser.antlr.Java8Parser; + +public class GatherNames { + + public static Map getNames(Java8Parser.CompilationUnitContext ctx, PackageCrawler packages, ClassLoader classLoader) throws ClassNotFoundException{ + Map ret = new HashMap<>(); + String pkgName = getPackageName(ctx); + String nameString = ""; + for (Java8Parser.TypeDeclarationContext typeDecl : ctx.typeDeclaration()){ + if(typeDecl.interfaceDeclaration() != null){ + if(typeDecl.interfaceDeclaration().normalInterfaceDeclaration() != null){ + if(pkgName != ""){ + nameString = pkgName + "." + typeDecl.interfaceDeclaration().normalInterfaceDeclaration().Identifier().toString(); + } + else{ + nameString = typeDecl.interfaceDeclaration().normalInterfaceDeclaration().Identifier().toString(); + } + int numGenerics = typeDecl.interfaceDeclaration().normalInterfaceDeclaration().typeParameters()!=null? + typeDecl.interfaceDeclaration().normalInterfaceDeclaration().typeParameters().typeParameterList().typeParameter().size():0; + //Die Generic TypeParameter Definitionen Nicht! an die JavaClassName-Registry anfügen: + /* //Diese gelängen dadurch in den globalen Scope, was sie schließlich nicht sind + if(typeDecl.classDeclaration().normalClassDeclaration().typeParameters() != null){ + for(Java8Parser.TypeParameterContext tp : typeDecl.classDeclaration().normalClassDeclaration().typeParameters().typeParameterList().typeParameter()){ + //this.reg.add(tp.Identifier().toString()); + } + } + */ + ret.put(nameString, numGenerics); + } + } + else{ + if(typeDecl.classDeclaration().normalClassDeclaration() != null){ + if(!pkgName.isEmpty()){ + nameString = pkgName + "." + typeDecl.classDeclaration().normalClassDeclaration().Identifier().toString(); + } + else{ + nameString = typeDecl.classDeclaration().normalClassDeclaration().Identifier().toString(); + } + //Die Generic TypeParameter Definitionen Nicht! an die JavaClassName-Registry anfügen: + /* //Diese gelängen dadurch in den globalen Scope, was sie schließlich nicht sind + if(typeDecl.classDeclaration().normalClassDeclaration().typeParameters() != null){ + for(Java8Parser.TypeParameterContext tp : typeDecl.classDeclaration().normalClassDeclaration().typeParameters().typeParameterList().typeParameter()){ + this.reg.add(tp.Identifier().toString()); + } + } + */ + int numGenerics = typeDecl.classDeclaration().normalClassDeclaration().typeParameters()!=null? + typeDecl.classDeclaration().normalClassDeclaration().typeParameters().typeParameterList().typeParameter().size():0; + + ret.put(nameString, numGenerics); + } + } + } + ret.putAll(getImports(ctx, packages, classLoader)); + return ret; + } + + public static Map getImports(Java8Parser.CompilationUnitContext ctx, PackageCrawler packages, ClassLoader classLoader) throws ClassNotFoundException { + Map ret = new HashMap<>(); + //ret.putAll(packages.getClassNames("java.lang")); + for(Java8Parser.ImportDeclarationContext importDeclCtx : ctx.importDeclaration()){ + if(importDeclCtx.singleTypeImportDeclaration() != null){ + Class cl = classLoader.loadClass(importDeclCtx.singleTypeImportDeclaration().typeName().getText()); + ret.put(cl.getName(), cl.getTypeParameters().length); + } + else if(importDeclCtx.typeImportOnDemandDeclaration() != null){ + ret.putAll(packages.getClassNames(importDeclCtx.typeImportOnDemandDeclaration().packageOrTypeName().getText())); + } + else if(importDeclCtx.singleStaticImportDeclaration() != null){ + Class cl = classLoader.loadClass(importDeclCtx.singleStaticImportDeclaration().typeName().getText()+"."+importDeclCtx.singleStaticImportDeclaration().Identifier().getText()); + ret.put(cl.getName(), cl.getTypeParameters().length); + } + else{ + ret.putAll(packages.getClassNames(importDeclCtx.staticImportOnDemandDeclaration().typeName().getText())); + } + } + return ret; + } + + private static String getPackageName(Java8Parser.CompilationUnitContext ctx){ + String pkgName = ""; + if(ctx.packageDeclaration() != null){ + for(TerminalNode t : ctx.packageDeclaration().Identifier()){ + pkgName = pkgName + "." + t.toString(); + } + pkgName = pkgName.substring(1); + } + return pkgName; + } +} \ No newline at end of file diff --git a/app/src/main/java/de/dhbwstuttgart/parser/scope/GenericsRegistry.java b/app/src/main/java/de/dhbwstuttgart/parser/scope/GenericsRegistry.java new file mode 100644 index 00000000..e0b32e64 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/parser/scope/GenericsRegistry.java @@ -0,0 +1,50 @@ +package de.dhbwstuttgart.parser.scope; + +import de.dhbwstuttgart.parser.SyntaxTreeGenerator.GenericContext; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +public class GenericsRegistry { + private final List registry = new ArrayList<>(); + public final GenericsRegistry globalRegistry; + + public GenericsRegistry(GenericsRegistry globalRegistry){ + this.globalRegistry = globalRegistry; + } + + public void put(String name, GenericContext genericContext){ + registry.add(new GenericVariable(genericContext,name)); + if(globalRegistry != null)globalRegistry.put(name, genericContext); + } + + public boolean contains(String name) { + Optional ret = registry.stream().map(((GenericVariable genericVariable) -> genericVariable.name.equals(name))) + .reduce(((a, b) -> a || b)); + if(ret.isPresent()) + return ret.get(); + return false; + } + + public GenericContext get(String name) { + return registry.stream() + .filter((genericVariable -> genericVariable.name.equals(name))).findAny().get().context; + } + + public void putAll(GenericsRegistry generics) { + for(GenericVariable generic : generics.registry){ + this.put(generic.name, generic.context); + } + } +} + +class GenericVariable{ + final GenericContext context; + final String name; + + GenericVariable(GenericContext context, String name){ + this.context = context; + this.name = name; + } +} \ No newline at end of file diff --git a/app/src/main/java/de/dhbwstuttgart/parser/scope/JavaClassName.java b/app/src/main/java/de/dhbwstuttgart/parser/scope/JavaClassName.java new file mode 100644 index 00000000..534d0916 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/parser/scope/JavaClassName.java @@ -0,0 +1,146 @@ +package de.dhbwstuttgart.parser.scope; + + +import java.util.ArrayList; +import java.util.List; + +/** + * Stellt den Namen einer Java Klasse dar. + * Dieser kann auch den Packagenamen mit beinhalten: de.dhbwstuttgart.typeinference.Menge + * + * @author Andreas Stadelmeier + */ +public class JavaClassName { + + public static final JavaClassName Void = new JavaClassName("void"); + private String name; + private PackageName packageName; + + public JavaClassName(String name){ + if(name == null)throw new NullPointerException(); + + String[] names = name.split("[.]"); + boolean match = true; + if(names.length == 1){ + //packageName = new PackageName(); + this.name = name; + }else { + name = names[names.length-1]; + List packageNames = new ArrayList(); + for(int i = 0; i names = new ArrayList<>(); + + public PackageName(List packageNames) { + names = packageNames; + } + + public PackageName() { + //Do nothing + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((names == null) ? 0 : names.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + PackageName other = (PackageName) obj; + if (names == null) { + if (other.names != null) + return false; + } else if (!names.equals(other.names)) + return false; + return true; + } + + @Override + public String toString() { + String ret = ""; + if(names == null)return ""; + for(String n : names)ret+=n+"."; + if (ret != null && ret.length() > 0 && ret.charAt(ret.length() - 1) == '.') { + ret = ret.substring(0, ret.length() - 1); + } + return ret; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/parser/scope/JavaClassRegistry.java b/app/src/main/java/de/dhbwstuttgart/parser/scope/JavaClassRegistry.java new file mode 100644 index 00000000..d9ab804c --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/parser/scope/JavaClassRegistry.java @@ -0,0 +1,49 @@ +package de.dhbwstuttgart.parser.scope; + +import de.dhbwstuttgart.exceptions.NotImplementedException; + +import java.util.*; + +/** + * Speichert die Klassen f�r einen bestimmten Projektscope + */ +public class JavaClassRegistry { + final Map existingClasses = new HashMap<>(); + + public JavaClassRegistry(Map initialNames){ + for(String name : initialNames.keySet()){ + existingClasses.put(new JavaClassName(name), initialNames.get(name)); + } + } + + public JavaClassName getName(String className) { + for(JavaClassName name : existingClasses.keySet()){ + if(name.equals(new JavaClassName(className)))return name; + } + throw new NotImplementedException(); + } + + @Override + public String toString(){ + return existingClasses.toString(); + } + + public List getAllFromPackage(String packageName) { + List ret = new ArrayList<>(); + for(JavaClassName className : this.existingClasses.keySet()){ + JavaClassName toCompare = new JavaClassName(packageName + "." + JavaClassName.stripClassName(className.toString())); + if(toCompare.toString().equals(className.toString())){ + ret.add(className); + } + } + return ret; + } + + public boolean contains(String whole) { + return existingClasses.containsKey(new JavaClassName(whole)); + } + + public int getNumberOfGenerics(String name) { + return existingClasses.get(new JavaClassName(name)); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/ASTVisitor.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/ASTVisitor.java new file mode 100644 index 00000000..5f77601d --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/ASTVisitor.java @@ -0,0 +1,34 @@ +package de.dhbwstuttgart.syntaxtree; + +import de.dhbwstuttgart.syntaxtree.type.*; + +public interface ASTVisitor extends StatementVisitor{ + + void visit(SourceFile sourceFile); + + void visit(GenericTypeVar genericTypeVar); + + void visit(FormalParameter formalParameter); + + void visit(GenericDeclarationList genericTypeVars); + + void visit(Field field); + + void visit(Method field); + + void visit(Constructor field); + + void visit(ParameterList formalParameters); + + void visit(ClassOrInterface classOrInterface); + + void visit(RefType refType); + + void visit(SuperWildcardType superWildcardType); + + void visit(TypePlaceholder typePlaceholder); + + void visit(ExtendsWildcardType extendsWildcardType); + + void visit(GenericRefType genericRefType); +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/AbstractASTWalker.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/AbstractASTWalker.java new file mode 100644 index 00000000..0cbad897 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/AbstractASTWalker.java @@ -0,0 +1,269 @@ +package de.dhbwstuttgart.syntaxtree; + +import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; +import de.dhbwstuttgart.syntaxtree.statement.*; +import de.dhbwstuttgart.syntaxtree.statement.Literal; +import de.dhbwstuttgart.syntaxtree.type.*; + +import java.util.Iterator; + +public abstract class AbstractASTWalker implements ASTVisitor{ + @Override + public void visit(Constructor cons) { + visitMethod(cons); + } + + @Override + public void visit(SourceFile sourceFile) { + for(ClassOrInterface cl : sourceFile.getClasses()){ + cl.accept(this); + } + } + + @Override + public void visit(ArgumentList argumentList) { + for(Expression expr : argumentList.getArguments()){ + expr.accept(this); + } + } + + @Override + public void visit(GenericTypeVar genericTypeVar) { + + } + + @Override + public void visit(FormalParameter formalParameter) { + formalParameter.getType().accept((ASTVisitor) this); + } + + @Override + public void visit(GenericDeclarationList genericTypeVars) { + Iterator genericIterator = genericTypeVars.iterator(); + if(genericIterator.hasNext()){ + while(genericIterator.hasNext()){ + genericIterator.next().accept(this); + } + } + } + + @Override + public void visit(Field field) { + field.getType().accept(this); + } + + @Override + public void visit(Method method) { + visitMethod(method); + } + + private void visitMethod(Method method){ + method.getReturnType().accept(this); + method.getParameterList().accept(this); + if(method.block != null) + method.block.accept(this); + } + + @Override + public void visit(ParameterList formalParameters) { + Iterator it = formalParameters.getFormalparalist().iterator(); + if(it.hasNext()){ + while(it.hasNext()){ + it.next().accept(this); + } + } + } + + @Override + public void visit(ClassOrInterface classOrInterface) { + classOrInterface.getGenerics().accept(this); + for(Field f : classOrInterface.getFieldDecl()){ + f.accept(this); + } + for(Constructor c : classOrInterface.getConstructors()){ + c.accept(this); + } + for(Method m : classOrInterface.getMethods()){ + m.accept(this); + } + } + + @Override + public void visit(RefType refType) { + Iterator genericIterator = refType.getParaList().iterator(); + if(genericIterator.hasNext()){ + while(genericIterator.hasNext()){ + genericIterator.next().accept(this); + } + } + } + + @Override + public void visit(SuperWildcardType superWildcardType) { + superWildcardType.getInnerType().accept(this); + } + + @Override + public void visit(TypePlaceholder typePlaceholder) { + } + + @Override + public void visit(ExtendsWildcardType extendsWildcardType) { + extendsWildcardType.getInnerType().accept(this); + } + + @Override + public void visit(GenericRefType genericRefType) { + } + + @Override + public void visit(LambdaExpression lambdaExpression) { + lambdaExpression.params.accept(this); + lambdaExpression.methodBody.accept(this); + } + + @Override + public void visit(Assign assign) { + assign.lefSide.accept(this); + assign.rightSide.accept(this); + assign.rightSide.getType().accept((ASTVisitor) this); + } + + @Override + public void visit(BinaryExpr binary) { + + } + + @Override + public void visit(Block block) { + for(Statement stmt : block.getStatements()){ + stmt.accept(this); + } + } + + @Override + public void visit(CastExpr castExpr) { + + } + + @Override + public void visit(EmptyStmt emptyStmt) { + + } + + @Override + public void visit(FieldVar fieldVar) { + fieldVar.receiver.accept(this); + } + + @Override + public void visit(ForStmt forStmt) { + forStmt.body_Loop_block.accept(this); + } + + @Override + public void visit(IfStmt ifStmt) { + ifStmt.then_block.accept(this); + ifStmt.else_block.accept(this); + } + + @Override + public void visit(InstanceOf instanceOf) { + + } + + @Override + public void visit(LocalVar localVar) { + + } + + + @Override + public void visit(LocalVarDecl localVarDecl) { + localVarDecl.getType().accept(this); + } + + @Override + public void visit(MethodCall methodCall) { + methodCall.receiver.accept(this); + methodCall.getArgumentList().accept(this); + methodCall.getArgumentList().getArguments().forEach(a -> a.getType().accept((ASTVisitor) this)); + } + + + @Override + public void visit(NewClass methodCall) { + visit((MethodCall) methodCall); + } + + @Override + public void visit(NewArray newArray) { + + } + + @Override + public void visit(ExpressionReceiver receiver) { + receiver.expr.accept(this); + } + + @Override + public void visit(UnaryExpr unaryExpr) { + unaryExpr.expr.accept(this); + } + + @Override + public void visit(Return aReturn) { + aReturn.retexpr.accept(this); + aReturn.getType().accept((ASTVisitor) this); + } + + @Override + public void visit(ReturnVoid aReturn) { + + } + + @Override + public void visit(StaticClassName staticClassName) { + + } + + @Override + public void visit(Super aSuper) { + + } + + @Override + public void visit(This aThis) { + + } + + @Override + public void visit(WhileStmt whileStmt) { + whileStmt.loopBlock.accept(this); + } + + @Override + public void visit(DoStmt whileStmt) { + whileStmt.loopBlock.accept(this); + } + + @Override + public void visit(Literal literal) { + + } + + @Override + public void visit(AssignToField assignLeftSide) { + assignLeftSide.field.accept(this); + } + + @Override + public void visit(AssignToLocal assignLeftSide) { + assignLeftSide.localVar.accept(this); + } + + @Override + public void visit(SuperCall superCall) { + this.visit((MethodCall)superCall); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/ClassOrInterface.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/ClassOrInterface.java new file mode 100644 index 00000000..459ae46d --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/ClassOrInterface.java @@ -0,0 +1,167 @@ +package de.dhbwstuttgart.syntaxtree; + +import de.dhbwstuttgart.core.IItemWithOffset; +import de.dhbwstuttgart.exceptions.DebugException; +import de.dhbwstuttgart.parser.NullToken; +import de.dhbwstuttgart.parser.scope.JavaClassName; +import de.dhbwstuttgart.syntaxtree.statement.Statement; +import de.dhbwstuttgart.syntaxtree.type.GenericRefType; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.typeinference.constraints.Constraint; +import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; +import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation; +import org.antlr.v4.runtime.Token; + +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Optional; + +/** + * Stellt jede Art von Klasse dar. Auch abstrakte Klassen und Interfaces + */ +public class ClassOrInterface extends SyntaxTreeNode implements TypeScope{ + private Boolean methodAdded = false; //wird benoetigt bei in JavaTXCompiler.getConstraints() + protected int modifiers; + protected JavaClassName name; + private List fields = new ArrayList<>(); + private Optional fieldInitializations; //PL 2018-11-24: Noetig, um Bytecode fuer initializators nur einmal zu erzeugen + private List methods = new ArrayList<>(); + private GenericDeclarationList genericClassParameters; + private RefType superClass; + protected boolean isInterface; + private List implementedInterfaces; + private List constructors; + + + public ClassOrInterface(int modifiers, JavaClassName name, List fielddecl, Optional fieldInitializations, List methods, List constructors, GenericDeclarationList genericClassParameters, + RefType superClass, Boolean isInterface, List implementedInterfaces, Token offset){ + super(offset); + if(isInterface && !Modifier.isInterface(modifiers))modifiers += Modifier.INTERFACE; + this.modifiers = modifiers; + this.name = name; + this.fields = fielddecl; + this.fieldInitializations= fieldInitializations; + this.genericClassParameters = genericClassParameters; + this.superClass = superClass; + this.isInterface = isInterface; + this.implementedInterfaces = implementedInterfaces; + this.methods = methods; + this.constructors = constructors; + } + + /* erzeugt fuer Fields, Konstruktoren und Methoden neue ArrayList-Objekte + * alle anderen Datenobjekte werden nur kopiert. + */ + public ClassOrInterface(ClassOrInterface cl){ + super(cl.getOffset()); + this.modifiers = cl.modifiers; + this.name = cl.name; + this.fields = new ArrayList<>(cl.fields); + this.fieldInitializations= cl.fieldInitializations; + this.genericClassParameters = cl.genericClassParameters; + this.superClass = cl.superClass; + this.isInterface = cl.isInterface; + this.implementedInterfaces = cl.implementedInterfaces; + this.methods = new ArrayList<>(cl.methods); + this.constructors = new ArrayList<>(cl.constructors); + } + + //Gets if it is added + public Boolean areMethodsAdded() { + return methodAdded; + } + + //Sets that it is added + public void setMethodsAdded() { + methodAdded = true; + } + + // Gets class name + public JavaClassName getClassName(){ + return this.name; + } + + // Get modifiers + public int getModifiers(){ + return this.modifiers; + } + + public List getFieldDecl(){ + return this.fields; + } + + public Optional getfieldInitializations(){ + return this.fieldInitializations; + } + + public List getMethods(){ + return this.methods; + } + + /* + public RefType getType() { + return generateTypeOfClass(this.getClassName(), this.getGenerics(), this.getOffset()); + } + */ + //TODO: Das hier ist ein Problem. Je nach Kontext wird hier ein anderer Typ benötigt + public static RefType generateTypeOfClass(JavaClassName name, GenericDeclarationList genericsOfClass ,Token offset){ + //Hier wird immer ein generischer Typ generiert, also mit Type placeholdern + List params = new ArrayList<>(); + for(GenericTypeVar genericTypeVar : genericsOfClass){ + //params.add(genericTypeVar.getTypePlaceholder()); + params.add(TypePlaceholder.fresh(offset)); + } + return new RefType(name, params, offset); + } + + /** + * + * @return die aktuelle Klasse als RefType + */ + public RefType generateTypeOfThisClass(){ + List params = new ArrayList<>(); + for(GenericTypeVar genericTypeVar : this.getGenerics()){ + //params.add(genericTypeVar.getTypePlaceholder()); + params.add(new GenericRefType(genericTypeVar.getName(), new NullToken())); + } + return new RefType(name, params, new NullToken()); + } + /** + * Die Superklasse im Kontext dieser ClassOrInterface + * Das bedeutet, dass generische Variablen als GenericRefTypes dargestellt sind + */ + public RefType getSuperClass() { + return superClass; + } + + public GenericDeclarationList getGenerics() { + return this.genericClassParameters; + } + + @Override + public RefTypeOrTPHOrWildcardOrGeneric getReturnType() { + return null; + } + + public List getConstructors() { + return constructors; + } + + @Override + public void accept(ASTVisitor visitor) { + visitor.visit(this); + } + + public Collection getSuperInterfaces() { + return implementedInterfaces; + } + + public String toString() { + return this.name.toString() + this.genericClassParameters.toString(); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/Constructor.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/Constructor.java new file mode 100644 index 00000000..24b3bb81 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/Constructor.java @@ -0,0 +1,39 @@ +package de.dhbwstuttgart.syntaxtree; + +import de.dhbwstuttgart.syntaxtree.statement.Statement; +import de.dhbwstuttgart.syntaxtree.statement.SuperCall; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import org.antlr.v4.runtime.Token; + +import de.dhbwstuttgart.syntaxtree.statement.Block; + +import java.util.List; + +public class Constructor extends Method { + + + //TODO: Constructor braucht ein super-Statement + public Constructor(int modifier, String name, RefTypeOrTPHOrWildcardOrGeneric returnType, ParameterList parameterList, Block codeInsideConstructor, + GenericDeclarationList gtvDeclarations, Token offset /*, List fieldInitializations geloescht PL 2018-11-24 */) { + super(modifier, name, returnType, parameterList, /*codeInsideConstructor,*/ prepareBlock(codeInsideConstructor ) /*,fieldInitializations )geloescht PL 2018-11-24 )*/, gtvDeclarations, offset); + + } + + /** + * @param fieldInitializations - Das sind die Statements, + * welche die Felder der zugehörigen Klasse dieses + * Konstruktor initialisieren + */ + protected static Block prepareBlock(Block constructorBlock /*, List fieldInitializations new ArrayList<>() geloescht PL 2018-11-24 */){ + List statements = constructorBlock.getStatements(); + statements.add(0, new SuperCall(null, null, constructorBlock.getOffset())); + /* statements.addAll(fieldInitializations); geloescht PL 2018-11-24 */ + return new Block(statements, constructorBlock.getOffset()); + } + + @Override + public void accept(ASTVisitor visitor) { + visitor.visit(this); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/ExceptionList.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/ExceptionList.java new file mode 100644 index 00000000..78f0020d --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/ExceptionList.java @@ -0,0 +1,14 @@ +package de.dhbwstuttgart.syntaxtree; + +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; + +import java.util.List; + +public class ExceptionList +{ + private List exceptions; + + public ExceptionList(List exceptions){ + this.exceptions = exceptions; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/Field.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/Field.java new file mode 100644 index 00000000..8a4230e3 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/Field.java @@ -0,0 +1,44 @@ +package de.dhbwstuttgart.syntaxtree; + +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import org.antlr.v4.runtime.Token; + +import java.util.ArrayList; + +public class Field extends SyntaxTreeNode implements TypeScope{ + + public final int modifier; + private String name; + private RefTypeOrTPHOrWildcardOrGeneric type; + + public Field(String name, RefTypeOrTPHOrWildcardOrGeneric type, int modifier, Token offset){ + super(offset); + this.name = name; + this.type = type; + this.modifier = modifier; + } + + public String getName(){ + return this.name; + } + + public RefTypeOrTPHOrWildcardOrGeneric getType() { + return type; + } + + @Override + public void accept(ASTVisitor visitor) { + visitor.visit(this); + } + + @Override + public Iterable getGenerics() { + return new ArrayList<>(); + } + + @Override + public RefTypeOrTPHOrWildcardOrGeneric getReturnType() { + return type; + } +} + diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/FieldDeclaration.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/FieldDeclaration.java new file mode 100644 index 00000000..a0c420e8 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/FieldDeclaration.java @@ -0,0 +1,28 @@ +package de.dhbwstuttgart.syntaxtree; + +import de.dhbwstuttgart.syntaxtree.statement.Expression; +import org.antlr.v4.runtime.Token; + +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; + +/** + * Eine Feldinitialisation steht für eine Felddeklaration mit gleichzeitiger Wertzuweisung + * Beispiel: 'public Feld FeldVar = FeldWert;' + * @author janulrich + * + */ +public class FieldDeclaration extends Field{ + + private Expression wert; + + /** + * Dieser Konstruktor der FieldDeclaration erstellt den Syntaxknoten vollständig. + * Kein nachträgliches hinzfügen von Informationen oder aufrufen von parserPostProcessing ist notwendig. + */ + public FieldDeclaration(String name, RefTypeOrTPHOrWildcardOrGeneric typ, int modifier, Expression value, Token offset){ + super(name, typ, modifier, offset);//Dieser Deklarator wird nicht vom Parser aufgerufen. Dadurch gibt es auch keinen Offset + this.wert = value; + } + + +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/FormalParameter.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/FormalParameter.java new file mode 100644 index 00000000..8e7e7983 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/FormalParameter.java @@ -0,0 +1,29 @@ +package de.dhbwstuttgart.syntaxtree; + +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import org.antlr.v4.runtime.Token; + +public class FormalParameter extends SyntaxTreeNode +{ + private RefTypeOrTPHOrWildcardOrGeneric type; + private String name; + + public FormalParameter(String name, RefTypeOrTPHOrWildcardOrGeneric type, Token offset){ + super(offset); + this.name = name; + this.type = type; + } + + public RefTypeOrTPHOrWildcardOrGeneric getType() { + return type; + } + + public String getName() { + return name; + } + + @Override + public void accept(ASTVisitor visitor) { + visitor.visit(this); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/GenericDeclarationList.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/GenericDeclarationList.java new file mode 100644 index 00000000..426b57f3 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/GenericDeclarationList.java @@ -0,0 +1,52 @@ +package de.dhbwstuttgart.syntaxtree; + +import org.antlr.v4.runtime.Token; + +import com.google.common.collect.Lists; + +import de.dhbwstuttgart.parser.NullToken; + +import java.util.*; + + +/** + * Stellt eine Deklarations-Liste von Generischen Variablen dar. + * Kann vor Methoden und Klassen auftauchen. (<....>) + * @author janulrich + * + */ +public class GenericDeclarationList extends SyntaxTreeNode implements Iterable{ + + private Token offsetOfLastElement; + private List gtvs = new ArrayList<>(); + + @SuppressWarnings("unchecked") + public GenericDeclarationList(Iterable values, Token endOffset) { + super(endOffset); + gtvs = isListOfGenericTypeVar(values) ? (List)values : Lists.newArrayList(values); + this.offsetOfLastElement = endOffset; + } + + public GenericDeclarationList(ArrayList values, Token endOffset) { + super(endOffset); + gtvs = values; + this.offsetOfLastElement = endOffset; } + + private boolean isListOfGenericTypeVar(Iterable values) { + return values instanceof List && ((List)values).size() > 0 && ((List)values).get(0) instanceof GenericTypeVar; + } + + @Override + public Iterator iterator() { + return gtvs.iterator(); + } + + @Override + public void accept(ASTVisitor visitor) { + visitor.visit(this); + } + + public String toString() { + return this.gtvs.toString(); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/GenericTypeVar.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/GenericTypeVar.java new file mode 100644 index 00000000..6ee03b60 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/GenericTypeVar.java @@ -0,0 +1,64 @@ +package de.dhbwstuttgart.syntaxtree; + +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; + +import org.antlr.v4.runtime.Token; + +import java.util.ArrayList; +import java.util.List; + +/** + * Entspricht einem GenericTypeVar, jedoch mit Bounds + * (d.h. vorgaben, von welchem Typ die Typevar sein darf + * => extends Class x + * => implements Interface y + * ... + * @author hoti 4.5.06 + * + */ +public class GenericTypeVar extends SyntaxTreeNode +{ + + /** + * Hier sind die Bounds in Form von Type-Objekten abgespeichert + */ + List bounds=new ArrayList(); + private Token endOffset; + private String name; + + public GenericTypeVar(String s, List bounds, Token offset, Token endOffset) + { + super(offset); + name = s; + if(bounds != null)for(RefTypeOrTPHOrWildcardOrGeneric t : bounds){ + //if(t!=null)this.extendVars.add(t); + } + //this.genericTypeVar = new RefType(s,offset); + this.bounds = bounds; + this.endOffset = endOffset; + } + + public List getBounds() + { + return bounds; + } + + public String toString() + { + return "BoGTV " + this.name; + } + + public String getName(){ + return name.toString(); + } + + /* + public JavaClassName definingClass(){ + return name.getParentClass(); + } +*/ + @Override + public void accept(ASTVisitor visitor) { + visitor.visit(this); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/Method.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/Method.java new file mode 100644 index 00000000..9eda85e4 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/Method.java @@ -0,0 +1,96 @@ +package de.dhbwstuttgart.syntaxtree; + +import java.util.ArrayList; + +import de.dhbwstuttgart.parser.NullToken; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; +import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; +import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation; +import de.dhbwstuttgart.typeinference.typeAlgo.TYPE; +import de.dhbwstuttgart.typeinference.typeAlgo.TYPEStmt; +import org.antlr.v4.runtime.Token; + +import de.dhbwstuttgart.core.IItemWithOffset; +import de.dhbwstuttgart.syntaxtree.statement.Block; + +/** + * Stellt eine Methode dar. Problem: Parser kann nicht zwischen Methode und + * Konstruktor unterscheiden. Daher kann diese Klasse beides sein. Dies wird mit + * dem ParserPostProcessing behoben. + * + * @author janulrich + * + */ +public class Method extends SyntaxTreeNode implements IItemWithOffset, TypeScope +{ + public final Block block; + public final int modifier; + public final String name; + private ParameterList parameterlist = new ParameterList(new ArrayList<>(), new NullToken()); + private ExceptionList exceptionlist; + private GenericDeclarationList generics; + private final RefTypeOrTPHOrWildcardOrGeneric returnType; + public final Boolean isInherited; + + /* + * its Constraints + * eingefuegt PL 2021-02-15 + */ + public final ConstraintSet constraints = new ConstraintSet(); + + public Method(int modifier, String name, RefTypeOrTPHOrWildcardOrGeneric returnType, ParameterList parameterList, Block block, + GenericDeclarationList gtvDeclarations, Token offset) { + super(offset); + this.name = name; + this.modifier = modifier; + this.returnType = returnType; + this.parameterlist = parameterList; + this.block = block; + this.generics = gtvDeclarations; + this.isInherited = false; + } + + public Method(int modifier, String name, RefTypeOrTPHOrWildcardOrGeneric returnType, ParameterList parameterList, Block block, + GenericDeclarationList gtvDeclarations, Token offset, Boolean isInherited) { + super(offset); + this.name = name; + this.modifier = modifier; + this.returnType = returnType; + this.parameterlist = parameterList; + this.block = block; + this.generics = gtvDeclarations; + this.isInherited = isInherited; + } + + public ParameterList getParameterList() { + return parameterlist; + } + + public Iterable getGenerics() { + return generics; + } + + @Override + public RefTypeOrTPHOrWildcardOrGeneric getReturnType() { + return this.returnType; + } + + public ConstraintSet getConstraints() { + return this.constraints; + } + + @Override + public void accept(ASTVisitor visitor) { + visitor.visit(this); + } + + @Override + public Token getOffset() { + return super.getOffset(); + } + + public String getName() { + return name; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/ParameterList.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/ParameterList.java new file mode 100644 index 00000000..2540f907 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/ParameterList.java @@ -0,0 +1,42 @@ +package de.dhbwstuttgart.syntaxtree; + + + +import org.antlr.v4.runtime.Token; + +import java.util.Iterator; +import java.util.List; + + +public class ParameterList extends SyntaxTreeNode implements Iterable +{ + private List formalparameter; + + public ParameterList(List params, Token offset){ + super(offset); + this.formalparameter = params; + } + + public FormalParameter getParameterAt(int i) + { + if (i >= formalparameter.size() ) return null; + + return formalparameter.get(i); + } + + + public List getFormalparalist() + { + return formalparameter; + } + + @Override + public Iterator iterator() { + return formalparameter.iterator(); + } + + @Override + public void accept(ASTVisitor visitor) { + visitor.visit(this); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/SourceFile.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/SourceFile.java new file mode 100644 index 00000000..f9ec340b --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/SourceFile.java @@ -0,0 +1,59 @@ +package de.dhbwstuttgart.syntaxtree; +import java.io.File; +import java.util.*; + +import de.dhbwstuttgart.parser.NullToken; +import de.dhbwstuttgart.parser.scope.JavaClassName; +import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; +import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation; +//import sun.security.x509.X509CertInfo; + + +public class SourceFile extends SyntaxTreeNode{ + private String pkgName; + + public final List KlassenVektor; + public final Set imports; + + /** + * Die SourceFile repräsntiert eine zu einem Syntaxbaum eingelesene Java-Datei. + * SourceFile stellt dabei den Wurzelknoten des Syntaxbaumes dar. + */ + public SourceFile(String pkgName, List classDefinitions, Set imports){ + super(new NullToken()); + this.KlassenVektor = classDefinitions; + this.pkgName = pkgName; + this.imports = imports; + } + + public SourceFile(SourceFile sf) { + super(new NullToken()); + this.KlassenVektor = new ArrayList<>(sf.KlassenVektor); + this.imports = new HashSet<>(sf.imports); + } + + + public String getPkgName(){ + return this.pkgName; + } + + // Get imports (to test implementation) + public Set getImports(){ + return this.imports; + } + + public List getClasses() { + return KlassenVektor; + } + + public List getAllMethods() { + List ret = new ArrayList<>(); + getClasses().forEach(cl -> ret.addAll(cl.getMethods())); + return ret; + } + + @Override + public void accept(ASTVisitor visitor) { + visitor.visit(this); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/StatementVisitor.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/StatementVisitor.java new file mode 100644 index 00000000..d6e0d1d5 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/StatementVisitor.java @@ -0,0 +1,65 @@ +package de.dhbwstuttgart.syntaxtree; + +import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; +import de.dhbwstuttgart.syntaxtree.statement.*; + +public interface StatementVisitor { + + void visit(ArgumentList argumentList); + + void visit(LambdaExpression lambdaExpression); + + void visit(Assign assign); + + void visit(BinaryExpr binary); + + void visit(Block block); + + void visit(CastExpr castExpr); + + void visit(EmptyStmt emptyStmt); + + void visit(FieldVar fieldVar); + + void visit(ForStmt forStmt); + + void visit(IfStmt ifStmt); + + void visit(InstanceOf instanceOf); + + void visit(LocalVar localVar); + + void visit(LocalVarDecl localVarDecl); + + void visit(MethodCall methodCall); + + void visit(NewClass methodCall); + + void visit(NewArray newArray); + + void visit(Return aReturn); + + void visit(ReturnVoid aReturn); + + void visit(StaticClassName staticClassName); + + void visit(Super aSuper); + + void visit(This aThis); + + void visit(WhileStmt whileStmt); + + void visit(DoStmt whileStmt); + + void visit(AssignToField assignLeftSide); + + void visit(AssignToLocal assignLeftSide); + + void visit(SuperCall superCall); + + void visit(ExpressionReceiver expressionReceiver); + + void visit(UnaryExpr unaryExpr); + + void visit(Literal literal); +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/SyntaxTreeNode.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/SyntaxTreeNode.java new file mode 100644 index 00000000..a9886e27 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/SyntaxTreeNode.java @@ -0,0 +1,23 @@ +package de.dhbwstuttgart.syntaxtree; + +import java.util.ArrayList; +import java.util.List; + +import de.dhbwstuttgart.core.IItemWithOffset; +import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation; +import org.antlr.v4.runtime.Token; +//import org.antlr.v4.runtime.misc.Pair; + +public abstract class SyntaxTreeNode implements IItemWithOffset{ + private final Token offset; + + public SyntaxTreeNode(Token offset){ + this.offset = offset; + } + + public Token getOffset(){ + return offset; + } + + public abstract void accept(ASTVisitor visitor); +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/TypeScope.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/TypeScope.java new file mode 100644 index 00000000..f651648b --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/TypeScope.java @@ -0,0 +1,12 @@ +package de.dhbwstuttgart.syntaxtree; + +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; + +import java.util.Collection; + + +public interface TypeScope { + Iterable getGenerics(); + + RefTypeOrTPHOrWildcardOrGeneric getReturnType(); +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java new file mode 100644 index 00000000..79b6d281 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java @@ -0,0 +1,264 @@ +package de.dhbwstuttgart.syntaxtree.factory; + +import java.lang.reflect.*; +import java.lang.reflect.Constructor; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.Set; + +import de.dhbwstuttgart.exceptions.NotImplementedException; +import de.dhbwstuttgart.parser.NullToken; +import de.dhbwstuttgart.parser.SyntaxTreeGenerator.GenericContext; +import de.dhbwstuttgart.parser.scope.JavaClassName; +import de.dhbwstuttgart.parser.scope.JavaClassRegistry; +import de.dhbwstuttgart.syntaxtree.Field; +import de.dhbwstuttgart.syntaxtree.Method; +import de.dhbwstuttgart.syntaxtree.type.*; +import de.dhbwstuttgart.syntaxtree.type.Void; +import de.dhbwstuttgart.syntaxtree.*; +import de.dhbwstuttgart.syntaxtree.statement.Block; +import de.dhbwstuttgart.syntaxtree.statement.Statement; +import de.dhbwstuttgart.syntaxtree.type.WildcardType; +import org.antlr.v4.runtime.Token; + +/** + * Anmerkung: + * Die ASTFactory Methoden, welche ASTBäume aus java.lang.Class Objekten generieren, können davon ausgehen, + * dass alle Imports und Typnamen korrekt sind und müssen diese nicht überprüfen. + */ +public class ASTFactory { + + public static ClassOrInterface createClass(java.lang.Class jreClass){ + JavaClassName name = new JavaClassName(jreClass.getName()); + List methoden = new ArrayList<>(); + List konstruktoren = new ArrayList<>(); + for(java.lang.reflect.Constructor constructor : jreClass.getConstructors()){ + createConstructor(constructor, jreClass).map(c -> konstruktoren.add(c)); + } + Set allMethods = new HashSet<>(Arrays.asList(jreClass.getMethods())); + Set allDeclaredMethods = new HashSet<>(Arrays.asList(jreClass.getDeclaredMethods())); + Set allInheritedMethods = new HashSet<>(allMethods); + allInheritedMethods.removeAll(allDeclaredMethods); + for(java.lang.reflect.Method method : allDeclaredMethods){ + methoden.add(createMethod(method, jreClass, false)); + } + for(java.lang.reflect.Method method : allInheritedMethods){ + methoden.add(createMethod(method, jreClass, true)); + } + List felder = new ArrayList<>(); + for(java.lang.reflect.Field field : jreClass.getDeclaredFields()){ + felder.add(createField(field, name)); + } + int modifier = jreClass.getModifiers(); + boolean isInterface = jreClass.isInterface(); + //see: https://stackoverflow.com/questions/9934774/getting-generic-parameter-from-supertype-class + ParameterizedType parameterSuperClass = null; + Type tempSuperClass = jreClass.getGenericSuperclass(); + if(tempSuperClass != null && tempSuperClass instanceof ParameterizedType) + parameterSuperClass = (ParameterizedType) tempSuperClass; + java.lang.Class superjreClass = jreClass.getSuperclass(); + RefType superClass; + if(parameterSuperClass != null){ + superClass = (RefType) createType(parameterSuperClass); + }else if(superjreClass != null){ + superClass = (RefType) createType(superjreClass); + }else{//Jede Klasse und jedes Interface erbt von Object: (auch Object selbst!) + superClass = (RefType) createType(java.lang.Object.class); + } + List implementedInterfaces = new ArrayList<>(); + for(Type jreInterface : jreClass.getGenericInterfaces()){ + implementedInterfaces.add((RefType) createType(jreInterface)); + } + GenericDeclarationList genericDeclarationList = createGenerics(jreClass.getTypeParameters(), jreClass, null); + + Token offset = new NullToken(); //Braucht keinen Offset, da diese Klasse nicht aus einem Quellcode geparst wurde + + return new ClassOrInterface(modifier, name, felder, Optional.empty() /* eingefuegt PL 2018-11-24 */,methoden, konstruktoren, genericDeclarationList, superClass,isInterface, implementedInterfaces, offset); + } + + private static Field createField(java.lang.reflect.Field field, JavaClassName jreClass) { + return new Field(field.getName(), createType(field.getGenericType()), field.getModifiers(), new NullToken()); + } + + //private static RefType createType(Class classType) { + // return createClass(classType).getType(); + //} + + private static Optional createConstructor(Constructor constructor, Class inClass) { + String name = constructor.getName(); + RefTypeOrTPHOrWildcardOrGeneric returnType = createType(inClass); + Parameter[] jreParams = constructor.getParameters(); + Type[] jreGenericParams = constructor.getGenericParameterTypes(); + List params = new ArrayList<>(); + int i = 0; + for(Type jreParam : jreGenericParams){ + RefTypeOrTPHOrWildcardOrGeneric paramType = createType(jreParam); + params.add(new FormalParameter(jreParams[i].getName(),paramType, new NullToken())); + i++; + } + ParameterList parameterList = new ParameterList(params, new NullToken()); + Block block = new Block(new ArrayList(), new NullToken()); + GenericDeclarationList gtvDeclarations = createGenerics(constructor.getTypeParameters(), inClass, constructor.getName()); + Token offset = new NullToken(); + int modifier = constructor.getModifiers(); + + if(inClass.equals(java.lang.Object.class)){ + return Optional.empty(); + } + + return Optional.of(new de.dhbwstuttgart.syntaxtree.Constructor(modifier, name,returnType, parameterList, block, gtvDeclarations, offset /*, new ArrayList<>() geloescht PL 2018-11-24 */)); + } + + public static Method createMethod(java.lang.reflect.Method jreMethod, java.lang.Class inClass, Boolean isInherited){ + String name = jreMethod.getName(); + RefTypeOrTPHOrWildcardOrGeneric returnType; + Type jreRetType; + if(jreMethod.getGenericReturnType()!=null){ + jreRetType = jreMethod.getGenericReturnType(); + }else{ + jreRetType = jreMethod.getReturnType(); + } + returnType = createType(jreRetType); + Parameter[] jreParams = jreMethod.getParameters(); + Type[] jreGenericParams = jreMethod.getGenericParameterTypes(); + List params = new ArrayList<>(); + int i = 0; + for(Type jreParam : jreGenericParams){ + RefTypeOrTPHOrWildcardOrGeneric paramType = createType(jreParam); + params.add(new FormalParameter(jreParams[i].getName(),paramType, new NullToken())); + i++; + } + ParameterList parameterList = new ParameterList(params, new NullToken()); + Block block = new Block(new ArrayList(), new NullToken()); + GenericDeclarationList gtvDeclarations = createGenerics(jreMethod.getTypeParameters(), inClass, jreMethod.getName()); + Token offset = new NullToken(); + + return new Method(jreMethod.getModifiers(), name,returnType, parameterList, block, gtvDeclarations, offset, isInherited); + } + + public static GenericDeclarationList createGenerics(TypeVariable[] typeParameters, Class context, String methodName){ + List gtvs = new ArrayList<>(); + for(TypeVariable jreTV : typeParameters){ + de.dhbwstuttgart.syntaxtree.GenericTypeVar gtv = createGeneric(jreTV, jreTV.getName(), context, methodName); + gtvs.add(gtv); + } + return new GenericDeclarationList(gtvs,new NullToken()); + } + + private static RefTypeOrTPHOrWildcardOrGeneric createType(java.lang.reflect.Type type){ + if(type.getTypeName().equals("void")){ + return new Void(new NullToken()); + }else if(type.getTypeName().equals("int")){ + return new RefType(new JavaClassName("java.lang.Integer"), new ArrayList<>(), new NullToken()); + }else if(type.getTypeName().equals("byte")){ + return new RefType(new JavaClassName("java.lang.Byte"), new ArrayList<>(), new NullToken()); + }else if(type.getTypeName().equals("boolean")){ + return new RefType(new JavaClassName("java.lang.Boolean"), new ArrayList<>(), new NullToken()); + }else if(type.getTypeName().equals("char")){ + return new RefType(new JavaClassName("java.lang.Char"), new ArrayList<>(), new NullToken()); + }else if(type.getTypeName().equals("short")){ + return new RefType(new JavaClassName("java.lang.Short"), new ArrayList<>(), new NullToken()); + }else if(type.getTypeName().equals("double")){ + return new RefType(new JavaClassName("java.lang.Double"), new ArrayList<>(), new NullToken()); + }else if(type.getTypeName().equals("long")){ + return new RefType(new JavaClassName("java.lang.Long"), new ArrayList<>(), new NullToken()); + }else{ + if(type instanceof TypeVariable){ + //GTVDeclarationContext via "(TypeVariable) type).getGenericDeclaration()" + return new GenericRefType(type.getTypeName(), new NullToken()); + } + List params = new ArrayList<>(); + if(type instanceof ParameterizedType){ + for(Type t : ((ParameterizedType)type).getActualTypeArguments()){ + params.add(createType(t)); + } + } + String name = type.getTypeName(); + if(name.contains("<")){ //Komischer fix. Type von Generischen Typen kann die Generics im Namen enthalten Type + //Diese entfernen: + name = name.split("<")[0]; + } + if(type instanceof java.lang.reflect.WildcardType){ + java.lang.reflect.WildcardType wildcardType = (java.lang.reflect.WildcardType) type; + if(wildcardType.getLowerBounds().length > 0){ + return new SuperWildcardType(createType(wildcardType.getLowerBounds()[0]), new NullToken()); + }else if(wildcardType.getUpperBounds().length > 0){ + return new ExtendsWildcardType(createType(wildcardType.getUpperBounds()[0]), new NullToken()); + }else{//Es handelt sich um den '?'-Typ: + return new ExtendsWildcardType(createObjectType(), new NullToken()); + } + }else{ + RefType ret = new RefType(new JavaClassName(name), params, new NullToken()); + return ret; + } + } + } + + public static de.dhbwstuttgart.syntaxtree.GenericTypeVar createGeneric(TypeVariable jreTypeVar, String jreTVName, Class context, String parentMethod){ + JavaClassName parentClass = new JavaClassName(context.getName()); + List genericBounds = new ArrayList<>(); + java.lang.reflect.Type[] bounds = jreTypeVar.getBounds(); + if(bounds.length > 0){ + for(java.lang.reflect.Type bound : bounds){ + genericBounds.add(createType(bound)); + } + } + return new de.dhbwstuttgart.syntaxtree.GenericTypeVar(jreTVName, genericBounds, new NullToken(), new NullToken()); + } + + public static ClassOrInterface createObjectClass() { + return createClass(Object.class); + } + public static RefType createObjectType() { + return new RefType(createClass(Object.class).getClassName(), new NullToken()); + } + + /* + public Constructor createEmptyConstructor(Class parent){ + Block block = new Block(); + block.setType(new de.dhbwstuttgart.syntaxtree.type.Void(block, 0)); + block.statements.add(new SuperCall(block)); + + return ASTFactory.createConstructor(parent, new ParameterList(), block); + } + + public static Constructor createConstructor(Class superClass, ParameterList paralist, Block block){ + block.parserPostProcessing(superClass); + + Method method = ASTFactory.createMethod("", paralist, block, superClass); + method.setType(new de.dhbwstuttgart.syntaxtree.type.Void(block, 0)); + + return new Constructor(method, superClass); + } + + public static Class createClass(String className, RefType type, Modifiers modifiers, Menge supertypeGenPara, SourceFile parent) { + // TODO bytecode createClass + //String name, RefType superClass, Modifiers modifiers, Menge supertypeGenPara + Class generatedClass = new Class(className, type, modifiers, supertypeGenPara); + generatedClass.addField(ASTFactory.createEmptyConstructor(generatedClass)); + + generatedClass.parserPostProcessing(parent); + + return generatedClass; + } + + public static Class createObject(){ + return createClass(java.lang.Object.class); + } + + public static Class createInterface(String className, RefType superClass, Modifiers modifiers, + Menge supertypeGenPara, SourceFile parent){ + Class generatedClass = new Class(new JavaClassName(className), new ArrayList(), new ArrayList(), modifiers, + true, superClass, new ArrayList(), new GenericDeclarationList(), -1); + generatedClass.parserPostProcessing(parent); + return generatedClass; + } + + public static RefType createObjectType(){ + return createObjectClass().getType(); + } + */ +} \ No newline at end of file diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/factory/NameGenerator.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/factory/NameGenerator.java new file mode 100644 index 00000000..06414b98 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/factory/NameGenerator.java @@ -0,0 +1,91 @@ +package de.dhbwstuttgart.syntaxtree.factory; + +public class NameGenerator { + + private static String strNextName = "A"; + + /** + * Setzt den zu Beginn der Typinferenz auf "A" zurueck. + * Dies ist bei JUnit-Test noetig + * TypePlaceholder.
Author: Martin Pluemicke + * @return void + */ + public static void reset() { + strNextName = "A"; + } + + /** + * Berechnet einen neuen, eindeutigen Namen f�r eine neue + * TypePlaceholder.
Author: J�rg B�uerle + * @return Der Name + */ + public static String makeNewName() + { + // otth: Funktion berechnet einen neuen Namen anhand eines alten gespeicherten + String strReturn = strNextName; + + // n�chster Name berechnen und in strNextName speichern + inc( strNextName.length() - 1 ); + + return strReturn; + } + + /** + * Hilfsfunktion zur Berechnung eines neuen Namens + *
Author: J�rg B�uerle + * @param i + */ + private static void inc(int i) + { + // otth: Hilfsfunktion zur Berechnung eines neuen Namens + // otth: Erh�hung des Buchstabens an der Stelle i im String strNextName + // otth: Nach �berlauf: rekursiver Aufruf + + // falls i = -1 --> neuer Buchstabe vorne anf�gen + if ( i == -1 ) + { + strNextName = "A" + strNextName; + return; + } + + char cBuchstabe = (char)(strNextName.charAt( i )); + cBuchstabe++; + if ( cBuchstabe - 65 > 25 ) + { + // aktuelle Stelle: auf A zuruecksetzen + manipulate( i, 'A' ); + + // vorherige Stelle erh�hen + inc( i - 1 ); + } + else + { + // aktueller Buchstabe �ndern + manipulate( i, cBuchstabe ); + } + + } + + /** + * Hilfsfunktion zur Berechnung eines neuen Namens. + *
Author: J�rg B�uerle + * @param nStelle + * @param nWert + */ + private static void manipulate( int nStelle, char nWert ) + { + // otth: Hilfsfunktion zur Berechnung eines neuen Namens + // otth: Ersetzt im String 'strNextName' an der Position 'nStelle' den Buchstaben durch 'nWert' + + String strTemp = ""; + for( int i = 0; i < strNextName.length(); i++) + { + if ( i == nStelle ) + strTemp = strTemp + nWert; + else + strTemp = strTemp + strNextName.charAt( i ); + } + strNextName = strTemp; + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/factory/PrimitiveMethodsGenerator.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/factory/PrimitiveMethodsGenerator.java new file mode 100644 index 00000000..e8be6859 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/factory/PrimitiveMethodsGenerator.java @@ -0,0 +1,9 @@ +package de.dhbwstuttgart.syntaxtree.factory; + +/** + * Generiert Hilfsmethoden für die Unary und Binary Operatoren + * Diese Methoden stellen die möglichen Operationen +,-,++, etc dar + */ +public class PrimitiveMethodsGenerator { + +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/factory/UnifyTypeFactory.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/factory/UnifyTypeFactory.java new file mode 100644 index 00000000..468f9647 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/factory/UnifyTypeFactory.java @@ -0,0 +1,285 @@ +package de.dhbwstuttgart.syntaxtree.factory; + +import java.io.FileWriter; +import java.io.Writer; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import de.dhbwstuttgart.exceptions.NotImplementedException; +import de.dhbwstuttgart.parser.NullToken; +import de.dhbwstuttgart.parser.SyntaxTreeGenerator.FCGenerator; +import de.dhbwstuttgart.parser.scope.JavaClassName; +import de.dhbwstuttgart.syntaxtree.ClassOrInterface; +import de.dhbwstuttgart.syntaxtree.type.*; +import de.dhbwstuttgart.syntaxtree.type.Void; +import de.dhbwstuttgart.syntaxtree.type.WildcardType; +import de.dhbwstuttgart.typeinference.constraints.Constraint; +import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; +import de.dhbwstuttgart.typeinference.constraints.Pair; +import de.dhbwstuttgart.typeinference.result.PairNoResult; +import de.dhbwstuttgart.typeinference.result.PairTPHEqualTPH; +import de.dhbwstuttgart.typeinference.result.PairTPHequalRefTypeOrWildcardType; +import de.dhbwstuttgart.typeinference.result.PairTPHsmallerTPH; +import de.dhbwstuttgart.typeinference.result.ResultPair; +import de.dhbwstuttgart.typeinference.unify.model.*; + +public class UnifyTypeFactory { + + private static ArrayList PLACEHOLDERS = new ArrayList<>(); + + public static FiniteClosure generateFC(List fromClasses, Writer logFile, ClassLoader classLoader) throws ClassNotFoundException { + /* + Die transitive Hülle muss funktionieren. + Man darf schreiben List
extends AL + und Vector extends List + hier muss dann aber dennoch die Vererbung V < L < AL + hergestellt werden. + In einem solchen Vererbungsbaum dürfen die TPH auch die gleichen Namen haben. + Generell dürfen sie immer die gleichen Namen haben. + TODO: die transitive Hülle bilden + */ + return new FiniteClosure(FCGenerator.toUnifyFC(fromClasses, classLoader), logFile); + } + + public static UnifyPair generateSmallerPair(UnifyType tl, UnifyType tr){ + return new UnifyPair(tl, tr, PairOperator.SMALLER); + } + + public static UnifyPair generateSmallerDotPair(UnifyType tl, UnifyType tr){ + return new UnifyPair(tl, tr, PairOperator.SMALLERDOT); + } + + public static UnifyPair generateSmallNotEqualDotPair(UnifyType tl, UnifyType tr){ + return new UnifyPair(tl, tr, PairOperator.SMALLERNEQDOT); + } + + public static UnifyPair generateEqualDotPair(UnifyType tl, UnifyType tr){ + return new UnifyPair(tl, tr, PairOperator.EQUALSDOT); + } + + /** + * Convert from + * ASTType -> UnifyType + */ + public static UnifyType convert(RefTypeOrTPHOrWildcardOrGeneric t, Boolean innerType){ + if(t instanceof GenericRefType){ + return UnifyTypeFactory.convert((GenericRefType)t, innerType); + }else if(t instanceof TypePlaceholder){ + return UnifyTypeFactory.convert((TypePlaceholder)t, innerType); + }else if(t instanceof ExtendsWildcardType){ + return UnifyTypeFactory.convert((ExtendsWildcardType)t, innerType); + }else if(t instanceof SuperWildcardType){ + return UnifyTypeFactory.convert((SuperWildcardType)t, innerType); + }else if(t instanceof RefType){ + return UnifyTypeFactory.convert((RefType)t, innerType); + } + //Es wurde versucht ein Typ umzuwandeln, welcher noch nicht von der Factory abgedeckt ist + throw new NotImplementedException("Der Typ "+t+" kann nicht umgewandelt werden"); + } + + public static UnifyType convert(RefType t, Boolean innerType){ + //Check if it is a FunN Type: + Pattern p = Pattern.compile("Fun(\\d+)[$][$]"); + Matcher m = p.matcher(t.getName().toString()); + boolean b = m.matches(); + if(b){ + Integer N = Integer.valueOf(m.group(1)); + if((N + 1) == t.getParaList().size()){ + return convertFunN(t.getParaList(), false); + } + } + UnifyType ret; + if(t.getParaList() != null && t.getParaList().size() > 0){ + List params = new ArrayList<>(); + for(RefTypeOrTPHOrWildcardOrGeneric pT : t.getParaList()){ + params.add(UnifyTypeFactory.convert(pT, true)); + } + ret = new ReferenceType(t.getName().toString(),new TypeParams(params)); + }else{ + ret = new ReferenceType(t.getName().toString(), false); + } + return ret; + } + + public static UnifyType convertFunN(List paraList, Boolean innerType){ + UnifyType ret; + List params = new ArrayList<>(); + if(paraList != null && paraList.size() > 0){ + for(RefTypeOrTPHOrWildcardOrGeneric pT : paraList){ + params.add(UnifyTypeFactory.convert(pT, false)); + } + } + ret = FunNType.getFunNType(new TypeParams(params)); + return ret; + } + + public static UnifyType convert(TypePlaceholder tph, Boolean innerType){ + if (tph.getName().equals("AFR")) { + System.out.println("XXX"+innerType); + } + PlaceholderType ntph = new PlaceholderType(tph.getName()); + ntph.setVariance(tph.getVariance()); + int in = PLACEHOLDERS.indexOf(ntph); + if (in == -1) { + PLACEHOLDERS.add(ntph); + ntph.setInnerType(innerType); + return ntph; + } + else { + PlaceholderType oldpht = PLACEHOLDERS.get(in); + oldpht.setInnerType(oldpht.isInnerType() || innerType); + return oldpht; + } + } + + public static UnifyType convert(GenericRefType t, Boolean innerType){ + return new ReferenceType(t.getParsedName(), true); + } + + public static UnifyType convert(WildcardType t, Boolean innerType){ + if(t.isExtends()) + return new ExtendsType(UnifyTypeFactory.convert(t.getInnerType(), false)); + else if(t.isSuper()) + return new SuperType(UnifyTypeFactory.convert(t.getInnerType(), false)); + else throw new NotImplementedException(); + } + + + public static ConstraintSet convert(ConstraintSet constraints) { + return constraints.map(UnifyTypeFactory::convert); + } + + //NEVER USED + public static Constraint convert(Constraint constraint){ + Constraint unifyPairConstraint = constraint.stream() + .map(UnifyTypeFactory::convert) + .collect(Collectors.toCollection( () -> new Constraint (constraint.isInherited(), convert(constraint.getExtendConstraint())))); + return unifyPairConstraint; + } + + public static UnifyPair convert(Pair p) { + UnifyPair ret = null; + if(p.GetOperator().equals(PairOperator.SMALLERDOT)) { + ret = generateSmallerDotPair(UnifyTypeFactory.convert(p.TA1, false) + , UnifyTypeFactory.convert(p.TA2, false)); + //return ret; + }else if(p.GetOperator().equals(PairOperator.SMALLERNEQDOT)) { + ret = generateSmallNotEqualDotPair(UnifyTypeFactory.convert(p.TA1, false) + , UnifyTypeFactory.convert(p.TA2, false)); + //return ret; + }else if(p.GetOperator().equals(PairOperator.EQUALSDOT)) { + ret = generateEqualDotPair(UnifyTypeFactory.convert(p.TA1, false) + , UnifyTypeFactory.convert(p.TA2, false)); + //return ret; + }else if(p.GetOperator().equals(PairOperator.SMALLER)){ + ret = generateSmallerPair(UnifyTypeFactory.convert(p.TA1, false), + UnifyTypeFactory.convert(p.TA2, false)); + }else throw new NotImplementedException(); + UnifyType lhs, rhs; + if (((lhs = ret.getLhsType()) instanceof PlaceholderType) + && ((PlaceholderType)lhs).isWildcardable() + && (rhs = ret.getLhsType()) instanceof PlaceholderType) { + if (lhs.getName().equals("AQ")) { + System.out.println(""); + } + ((PlaceholderType)rhs).enableWildcardtable(); + } + + if (((rhs = ret.getLhsType()) instanceof PlaceholderType) + && ((PlaceholderType)rhs).isWildcardable() + && (lhs = ret.getLhsType()) instanceof PlaceholderType) { + if (rhs.getName().equals("AQ")) { + System.out.println(""); + } + ((PlaceholderType)lhs).enableWildcardtable(); + } + return ret; + } + + /** + * Convert from + * UnifyType -> ASTType + */ + public static Set convert(Set unifyPairSet, Map tphs) { + return unifyPairSet.stream().map( + unifyPair -> convert(unifyPair, tphs)) + .collect(Collectors.toSet()); + } + + public static ResultPair convert(UnifyPair mp, Map tphs) { + if (mp == null) { return null;} //kann bei basePairs passieren + RefTypeOrTPHOrWildcardOrGeneric tl = UnifyTypeFactory.convert(mp.getLhsType(), tphs); + RefTypeOrTPHOrWildcardOrGeneric tr = UnifyTypeFactory.convert(mp.getRhsType(), tphs); + if(tl instanceof TypePlaceholder){ + if(tr instanceof TypePlaceholder) { + + if(mp.getPairOp().equals(PairOperator.EQUALSDOT)) { + return new PairTPHEqualTPH((TypePlaceholder)tl, (TypePlaceholder)tr); + //Einfach ignorieren TODO: Das hier muss ausgebessert werden: + //return new PairTPHequalRefTypeOrWildcardType((TypePlaceholder)tl, ASTFactory.createObjectType()); + }else{ + return new PairTPHsmallerTPH((TypePlaceholder)tl, (TypePlaceholder)tr, convert(mp.getBasePair(), tphs)); + } + }else if(tr instanceof RefType){ + return new PairTPHequalRefTypeOrWildcardType((TypePlaceholder)tl, (RefType) tr); + }else if(tr instanceof WildcardType){ + return new PairTPHequalRefTypeOrWildcardType((TypePlaceholder)tl, (WildcardType) tr); + }else if(tr instanceof GenericRefType){ + return new PairTPHequalRefTypeOrWildcardType((TypePlaceholder)tl, (GenericRefType) tr); + }else throw new NotImplementedException(); + }else return new PairNoResult(tl, tr);//throw new NotImplementedException(); + } + + public static RefTypeOrTPHOrWildcardOrGeneric convert(ReferenceType t, Map tphs) { + if(JavaClassName.Void.equals(t.getName()))return new Void(new NullToken()); + if (t.isGenTypeVar()) return new GenericRefType(t.getName(),new NullToken()); + RefType ret = new RefType(new JavaClassName(t.getName()),convert(t.getTypeParams(), tphs),new NullToken()); + return ret; + } + + public static RefTypeOrTPHOrWildcardOrGeneric convert(FunNType t, Map tphs) { + RefType ret = new RefType(new JavaClassName(t.getName()), convert(t.getTypeParams(), tphs), new NullToken()); + return ret; + } + + public static RefTypeOrTPHOrWildcardOrGeneric convert(SuperType t, Map tphs) { + RefTypeOrTPHOrWildcardOrGeneric innerType = convert(t.getSuperedType(), tphs); + return new SuperWildcardType(innerType, new NullToken()); + } + + public static RefTypeOrTPHOrWildcardOrGeneric convert(ExtendsType t, Map tphs) { + RefTypeOrTPHOrWildcardOrGeneric innerType = convert(t.getExtendedType(), tphs); + return new ExtendsWildcardType(innerType, new NullToken()); + } + + public static RefTypeOrTPHOrWildcardOrGeneric convert(PlaceholderType t, Map tphs) { + TypePlaceholder ret = tphs.get(t.getName()); + if(ret == null){ //Dieser TPH wurde vom Unifikationsalgorithmus erstellt + ret = TypePlaceholder.fresh(new NullToken()); + tphs.put(t.getName(), ret); + } + ret.setVariance(t.getVariance()); + return ret; + } + + public static RefTypeOrTPHOrWildcardOrGeneric convert(UnifyType t, Map tphs) { + if(t instanceof FunNType)return convert((FunNType) t, tphs); + if(t instanceof ReferenceType)return convert((ReferenceType) t, tphs); + if(t instanceof SuperType)return convert((SuperType) t, tphs); + if(t instanceof ExtendsType)return convert((ExtendsType) t, tphs); + if(t instanceof PlaceholderType)return convert((PlaceholderType) t, tphs); + throw new NotImplementedException("Der Typ "+t+" kann nicht umgewandelt werden"); + } + + private static List convert(TypeParams typeParams, Map tphs) { + List ret = new ArrayList<>(); + for(UnifyType uT : typeParams){ + RefTypeOrTPHOrWildcardOrGeneric toAdd = convert(uT, tphs); + ret.add(toAdd); + } + return ret; + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/ArgumentList.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/ArgumentList.java new file mode 100644 index 00000000..ed5a082b --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/ArgumentList.java @@ -0,0 +1,33 @@ +package de.dhbwstuttgart.syntaxtree.statement; + + +import de.dhbwstuttgart.syntaxtree.ASTVisitor; +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; +import org.antlr.v4.runtime.Token; + +import java.util.List; + +public class ArgumentList extends SyntaxTreeNode +{ + public ArgumentList(List expr, Token offset) { + super(offset); + this.expr = expr; + } + + private List expr; + + public List getArguments(){ + return expr; + } + + + @Override + public void accept(ASTVisitor visitor) { + visitor.visit(this); + } + + public void accept(StatementVisitor visitor) { + visitor.visit(this); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Assign.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Assign.java new file mode 100644 index 00000000..3af2de6f --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Assign.java @@ -0,0 +1,29 @@ + +package de.dhbwstuttgart.syntaxtree.statement; + +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; +import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; +import de.dhbwstuttgart.typeinference.unify.model.PairOperator; +import org.antlr.v4.runtime.Token; + +/* +Aufbau: +rightSide = leftSide + */ +public class Assign extends Statement +{ + public final Expression rightSide; + public final AssignLeftSide lefSide; + + public Assign(AssignLeftSide leftHandSide, Expression value, Token offset) { + super(leftHandSide.getType(), offset); + this.rightSide = value; + this.lefSide = leftHandSide; + } + + @Override + public void accept(StatementVisitor visitor) { + visitor.visit(this); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/AssignLeftSide.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/AssignLeftSide.java new file mode 100644 index 00000000..13fec3f8 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/AssignLeftSide.java @@ -0,0 +1,12 @@ +package de.dhbwstuttgart.syntaxtree.statement; + +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import org.antlr.v4.runtime.Token; + +public abstract class AssignLeftSide extends TypableStatement{ + + public AssignLeftSide(RefTypeOrTPHOrWildcardOrGeneric type, Token offset) { + super(type, offset); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/AssignToField.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/AssignToField.java new file mode 100644 index 00000000..931443d1 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/AssignToField.java @@ -0,0 +1,16 @@ +package de.dhbwstuttgart.syntaxtree.statement; + +import de.dhbwstuttgart.syntaxtree.StatementVisitor; + +public class AssignToField extends AssignLeftSide{ + public final FieldVar field; + public AssignToField(FieldVar fieldVar) { + super(fieldVar.getType(), fieldVar.getOffset()); + field = fieldVar; + } + + @Override + public void accept(StatementVisitor visitor) { + visitor.visit(this); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/BinaryExpr.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/BinaryExpr.java new file mode 100644 index 00000000..4fab15cc --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/BinaryExpr.java @@ -0,0 +1,44 @@ +package de.dhbwstuttgart.syntaxtree.statement; + + +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import org.antlr.v4.runtime.Token; + +public class BinaryExpr extends Expression +{ + @Override + public void accept(StatementVisitor visitor) { + visitor.visit(this); + } + + public enum Operator{ + ADD, // + + SUB, // - + MUL, // * + MOD, // Modulo Operator % + AND, // && + OR, // || + DIV, // / + LESSTHAN, // < + BIGGERTHAN, // > + LESSEQUAL, // <= + BIGGEREQUAL, // >= + EQUAL, // == + NOTEQUAL // != + } + + public final Operator operation; + public final Expression lexpr; + public final Expression rexpr; + + public BinaryExpr(Operator operation, RefTypeOrTPHOrWildcardOrGeneric type, Expression lexpr, Expression rexpr, Token offset) + { + super(type,offset); + + this.operation = operation; + this.lexpr = lexpr; + this.rexpr = rexpr; + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Block.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Block.java new file mode 100644 index 00000000..73a92c7e --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Block.java @@ -0,0 +1,33 @@ +package de.dhbwstuttgart.syntaxtree.statement; +import java.util.*; + +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; +import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; +import org.antlr.v4.runtime.Token; + + +public class Block extends Statement +{ + public Block(List statements, Token offset) { + super(TypePlaceholder.fresh(offset), offset); + this.statements = statements; + } + + + + public List statements = new ArrayList<>(); + + public List getStatements() + { + return statements; + } + + @Override + public void accept(StatementVisitor visitor) { + visitor.visit(this); + } +} + + diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/CastExpr.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/CastExpr.java new file mode 100644 index 00000000..15fedbbc --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/CastExpr.java @@ -0,0 +1,25 @@ +package de.dhbwstuttgart.syntaxtree.statement; + +import de.dhbwstuttgart.exceptions.NotImplementedException; +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; +import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; +import org.antlr.v4.runtime.Token; + + +public class CastExpr extends Expression +{ + public CastExpr(RefTypeOrTPHOrWildcardOrGeneric castType, Expression expr, Token offset) + { + super(castType, offset); + this.expr = expr; + } + + public Expression expr; + + @Override + public void accept(StatementVisitor visitor) { + visitor.visit(this); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/DoStmt.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/DoStmt.java new file mode 100644 index 00000000..b24396bb --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/DoStmt.java @@ -0,0 +1,18 @@ +package de.dhbwstuttgart.syntaxtree.statement; + +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import org.antlr.v4.runtime.Token; + +public class DoStmt extends WhileStmt +{ + public DoStmt(Expression expr, Statement loopBlock, Token offset) + { + super(expr, loopBlock, offset); + } + + @Override + public void accept(StatementVisitor visitor) { + visitor.visit(this); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/EmptyStmt.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/EmptyStmt.java new file mode 100644 index 00000000..ff80e47f --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/EmptyStmt.java @@ -0,0 +1,22 @@ +package de.dhbwstuttgart.syntaxtree.statement; + +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.type.Void; +import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; +import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; +import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation; +import org.antlr.v4.runtime.Token; + + +public class EmptyStmt extends Statement +{ + public EmptyStmt(Token offset) + { + super(new Void(offset),offset); + } + + @Override + public void accept(StatementVisitor visitor) { + visitor.visit(this); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Expression.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Expression.java new file mode 100644 index 00000000..0413e124 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Expression.java @@ -0,0 +1,17 @@ + +package de.dhbwstuttgart.syntaxtree.statement; + +import de.dhbwstuttgart.syntaxtree.ASTVisitor; +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; +import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; +import org.antlr.v4.runtime.Token; + +public abstract class Expression extends TypableStatement +{ + public Expression(RefTypeOrTPHOrWildcardOrGeneric type, Token offset){ + super(type, offset); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/ExpressionReceiver.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/ExpressionReceiver.java new file mode 100644 index 00000000..409cfe68 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/ExpressionReceiver.java @@ -0,0 +1,21 @@ +package de.dhbwstuttgart.syntaxtree.statement; + +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import org.antlr.v4.runtime.Token; + +public class ExpressionReceiver extends Receiver +{ + public final Expression expr; + + public ExpressionReceiver(Expression expr) + { + super(expr.getType(), expr.getOffset()); + this.expr = expr; + } + + @Override + public void accept(StatementVisitor visitor) { + visitor.visit(this); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/FieldVar.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/FieldVar.java new file mode 100644 index 00000000..9380e951 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/FieldVar.java @@ -0,0 +1,31 @@ +package de.dhbwstuttgart.syntaxtree.statement; + +import de.dhbwstuttgart.exceptions.TypeinferenceException; +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.typeinference.assumptions.FieldAssumption; +import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; +import de.dhbwstuttgart.typeinference.constraints.Constraint; +import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; +import de.dhbwstuttgart.typeinference.unify.model.PairOperator; +import org.antlr.v4.runtime.Token; + +import java.util.HashSet; +import java.util.Set; + +public class FieldVar extends Expression { + + public final String fieldVarName; + public final Expression receiver; + + public FieldVar(Expression receiver, String fieldVarName, RefTypeOrTPHOrWildcardOrGeneric type, Token offset) { + super(type, offset); + this.fieldVarName = fieldVarName; + this.receiver = receiver; + } + + @Override + public void accept(StatementVisitor visitor) { + visitor.visit(this); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/ForStmt.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/ForStmt.java new file mode 100644 index 00000000..1f933366 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/ForStmt.java @@ -0,0 +1,29 @@ + +package de.dhbwstuttgart.syntaxtree.statement; + +import de.dhbwstuttgart.exceptions.NotImplementedException; +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; +import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; + +public class ForStmt extends Statement +{ + + private Expression head_Initializer_1; + private Expression head_Condition_1; + private Expression head_Loop_expr_1; + private Expression head_Initializer; + private Expression head_Condition; + private Expression head_Loop_expr; + public Block body_Loop_block; + + public ForStmt(int offset, int variableLength) + { + super(null,null); + } + + @Override + public void accept(StatementVisitor visitor) { + visitor.visit(this); + } +} \ No newline at end of file diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/IfStmt.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/IfStmt.java new file mode 100644 index 00000000..4af1e770 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/IfStmt.java @@ -0,0 +1,30 @@ +package de.dhbwstuttgart.syntaxtree.statement; + +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; +import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; +import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation; +import org.antlr.v4.runtime.Token; + + +public class IfStmt extends Statement +{ + public final Expression expr; + public final Statement then_block; + public final Statement else_block; + + public IfStmt(RefTypeOrTPHOrWildcardOrGeneric type, + Expression expr, Statement thenBlock, Statement elseBlock, Token offset) + { + super(type,offset); + this.expr = expr; + this.then_block = thenBlock; + this.else_block = elseBlock; + } + + @Override + public void accept(StatementVisitor visitor) { + visitor.visit(this); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/InstanceOf.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/InstanceOf.java new file mode 100644 index 00000000..02fd667b --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/InstanceOf.java @@ -0,0 +1,24 @@ +package de.dhbwstuttgart.syntaxtree.statement; + +import de.dhbwstuttgart.exceptions.NotImplementedException; +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; + + +public class InstanceOf extends BinaryExpr +{ + public Expression expr; + private RefTypeOrTPHOrWildcardOrGeneric reftype; + + public InstanceOf(int offset,int variableLength) + { + super(null, null, null, null, null); + throw new NotImplementedException(); + // #JB# 20.04.2005 + } + + @Override + public void accept(StatementVisitor visitor) { + visitor.visit(this); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/JavaInternalExpression.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/JavaInternalExpression.java new file mode 100644 index 00000000..366c0602 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/JavaInternalExpression.java @@ -0,0 +1,12 @@ +package de.dhbwstuttgart.syntaxtree.statement; + +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import org.antlr.v4.runtime.Token; + +import java.nio.charset.StandardCharsets; + +public abstract class JavaInternalExpression extends Statement{ + public JavaInternalExpression(RefTypeOrTPHOrWildcardOrGeneric retType, Token offset){ + super(retType, offset); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/LambdaExpression.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/LambdaExpression.java new file mode 100644 index 00000000..40e65958 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/LambdaExpression.java @@ -0,0 +1,42 @@ +package de.dhbwstuttgart.syntaxtree.statement; + +import de.dhbwstuttgart.syntaxtree.*; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; +import de.dhbwstuttgart.typeinference.constraints.Constraint; +import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; +import de.dhbwstuttgart.typeinference.constraints.Pair; +import org.antlr.v4.runtime.Token; +//import sun.reflect.generics.reflectiveObjects.NotImplementedException; + +import java.util.ArrayList; + +public class LambdaExpression extends Expression implements TypeScope { + public final Block methodBody; + public final ParameterList params; + + public LambdaExpression(RefTypeOrTPHOrWildcardOrGeneric type, ParameterList params, Block methodBody, Token offset) { + super(type,offset); + this.methodBody = methodBody; + this.params = params; + } + + @Override + public void accept(StatementVisitor visitor) { + visitor.visit(this); + } + + @Override + public Iterable getGenerics() { + //Lambda-Ausdrücke haben keine Generics + return new ArrayList<>(); + } + + @Override + public RefTypeOrTPHOrWildcardOrGeneric getReturnType() { + //RefType type = (RefType) this.getType(); + //return type.getParaList().get(0); + return methodBody.getType(); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Literal.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Literal.java new file mode 100644 index 00000000..8bbaae0a --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Literal.java @@ -0,0 +1,24 @@ +package de.dhbwstuttgart.syntaxtree.statement; + + +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.statement.Expression; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; +import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; +import org.antlr.v4.runtime.Token; + +public class Literal extends Expression +{ + public final Object value; + + public Literal(RefTypeOrTPHOrWildcardOrGeneric type, Object value, Token offset) { + super(type, offset); + this.value = value; + } + + @Override + public void accept(StatementVisitor visitor) { + visitor.visit(this); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/LocalVar.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/LocalVar.java new file mode 100644 index 00000000..91094a7a --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/LocalVar.java @@ -0,0 +1,27 @@ +package de.dhbwstuttgart.syntaxtree.statement; + +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import org.antlr.v4.runtime.Token; + +public class LocalVar extends Statement{ + + public final String name; + + public LocalVar(String n, RefTypeOrTPHOrWildcardOrGeneric type, Token offset) + { + super(type,offset); + this.name = n; + } + + public LocalVar(Expression e1, RefTypeOrTPHOrWildcardOrGeneric type, String access) + { + super(type,e1.getOffset()); + this.name = access; + } + + @Override + public void accept(StatementVisitor visitor) { + visitor.visit(this); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/LocalVarDecl.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/LocalVarDecl.java new file mode 100644 index 00000000..fde48e51 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/LocalVarDecl.java @@ -0,0 +1,31 @@ +package de.dhbwstuttgart.syntaxtree.statement; + + +import de.dhbwstuttgart.exceptions.NotImplementedException; +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; +import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; +import org.antlr.v4.runtime.Token; + + +public class LocalVarDecl extends Statement +{ + + private String name; + + public LocalVarDecl(String name, RefTypeOrTPHOrWildcardOrGeneric type, Token offset) + { + super(type, offset); + this.name = name; + } + + @Override + public void accept(StatementVisitor visitor) { + visitor.visit(this); + } + + public String getName() { + return name; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/MethodCall.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/MethodCall.java new file mode 100644 index 00000000..4ef09d86 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/MethodCall.java @@ -0,0 +1,49 @@ +package de.dhbwstuttgart.syntaxtree.statement; + +import de.dhbwstuttgart.exceptions.TypeinferenceException; +import de.dhbwstuttgart.syntaxtree.*; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; +import de.dhbwstuttgart.typeinference.constraints.Constraint; +import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; +import de.dhbwstuttgart.typeinference.assumptions.MethodAssumption; +import de.dhbwstuttgart.typeinference.constraints.Pair; +import de.dhbwstuttgart.typeinference.unify.model.PairOperator; +import org.antlr.v4.runtime.Token; + +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; + +import java.util.*; + + +public class MethodCall extends Statement +{ + public final String name; + public final Receiver receiver; + + public final ArgumentList arglist; + + public RefTypeOrTPHOrWildcardOrGeneric receiverType; + public final ArrayList argTypes; + + public MethodCall(RefTypeOrTPHOrWildcardOrGeneric retType, Receiver receiver, String methodName, ArgumentList argumentList, + RefTypeOrTPHOrWildcardOrGeneric receiverType, ArrayList argTypes, Token offset){ + super(retType,offset); + this.arglist = argumentList; + this.name = methodName; + this.receiver = receiver; + this.receiverType = receiverType; + this.argTypes = argTypes; + } + + + @Override + public void accept(StatementVisitor visitor) { + visitor.visit(this); + } + + public ArgumentList getArgumentList() { + return arglist; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/NewArray.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/NewArray.java new file mode 100644 index 00000000..14c54d8c --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/NewArray.java @@ -0,0 +1,24 @@ +package de.dhbwstuttgart.syntaxtree.statement; +import java.util.List; + +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; +import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; +import de.dhbwstuttgart.exceptions.NotImplementedException; + + +public class NewArray extends Expression +{ + public NewArray(int offset,int variableLength) + { + super(null,null); + } + private RefTypeOrTPHOrWildcardOrGeneric type; + public List expr; + + @Override + public void accept(StatementVisitor visitor) { + visitor.visit(this); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/NewClass.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/NewClass.java new file mode 100644 index 00000000..f27bc3e8 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/NewClass.java @@ -0,0 +1,42 @@ +package de.dhbwstuttgart.syntaxtree.statement; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import de.dhbwstuttgart.exceptions.TypeinferenceException; +import de.dhbwstuttgart.parser.NullToken; +import de.dhbwstuttgart.syntaxtree.ClassOrInterface; +import de.dhbwstuttgart.syntaxtree.Method; +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.typeinference.assumptions.MethodAssumption; +import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; +import de.dhbwstuttgart.typeinference.constraints.Constraint; +import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; +import de.dhbwstuttgart.typeinference.constraints.Pair; +import de.dhbwstuttgart.typeinference.unify.model.PairOperator; +import org.antlr.v4.runtime.Token; +import de.dhbwstuttgart.exceptions.NotImplementedException; + + +public class NewClass extends MethodCall +{ + /** + * + * @param newClass Typ der Instanzierten Klasse + * @param args Argumente mit denen der New-Call aufgerufen wurde + * @param start + */ + public NewClass(RefType newClass, ArgumentList args, RefTypeOrTPHOrWildcardOrGeneric receiverType, + ArrayList argTypes, Token start) { + super(newClass, new ExpressionReceiver(new EmptyStmt(start)), newClass.getName().toString(), + args, receiverType, argTypes, start); + } + + @Override + public void accept(StatementVisitor visitor) { + visitor.visit(this); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Receiver.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Receiver.java new file mode 100644 index 00000000..93ee36a0 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Receiver.java @@ -0,0 +1,12 @@ +package de.dhbwstuttgart.syntaxtree.statement; + +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import org.antlr.v4.runtime.Token; + +public abstract class Receiver extends Expression +{ + public Receiver(RefTypeOrTPHOrWildcardOrGeneric type, Token offset) + { + super(type, offset); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Return.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Return.java new file mode 100644 index 00000000..5a6a5312 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Return.java @@ -0,0 +1,21 @@ +package de.dhbwstuttgart.syntaxtree.statement; + +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import org.antlr.v4.runtime.Token; + + +public class Return extends Statement +{ + public final Expression retexpr; + + public Return(Expression retExpr, Token offset) + { + super(retExpr.getType(),offset); + this.retexpr = retExpr; + } + + @Override + public void accept(StatementVisitor visitor) { + visitor.visit(this); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/ReturnVoid.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/ReturnVoid.java new file mode 100644 index 00000000..ca64b2c5 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/ReturnVoid.java @@ -0,0 +1,15 @@ +package de.dhbwstuttgart.syntaxtree.statement; + +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import org.antlr.v4.runtime.Token; + +public class ReturnVoid extends Return{ + public ReturnVoid(Token offset) { + super(new EmptyStmt(offset), offset); + } + + @Override + public void accept(StatementVisitor visitor) { + visitor.visit(this); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Statement.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Statement.java new file mode 100644 index 00000000..aad50736 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Statement.java @@ -0,0 +1,25 @@ +package de.dhbwstuttgart.syntaxtree.statement; + +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import org.antlr.v4.runtime.Token; + + +public abstract class Statement extends Expression +{ + /* zeigt an, dass eine StatementExpression als Statement benutzt wird + */ + private boolean isStatement = false; + + public Statement(RefTypeOrTPHOrWildcardOrGeneric type, Token offset) + { + super(type, offset); + } + + public void setStatement() { + isStatement=true; + } + + public boolean getStatement() { + return isStatement; + } +} \ No newline at end of file diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/StaticClassName.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/StaticClassName.java new file mode 100644 index 00000000..a7089d8c --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/StaticClassName.java @@ -0,0 +1,20 @@ +package de.dhbwstuttgart.syntaxtree.statement; + +import de.dhbwstuttgart.parser.scope.JavaClassName; +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; +import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; +import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation; +import org.antlr.v4.runtime.Token; + +public class StaticClassName extends Receiver { + public StaticClassName(JavaClassName className, Token offset) { + super(new RefType(className, offset), offset); + } + + @Override + public void accept(StatementVisitor visitor) { + visitor.visit(this); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Super.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Super.java new file mode 100644 index 00000000..fbeba99b --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Super.java @@ -0,0 +1,21 @@ +package de.dhbwstuttgart.syntaxtree.statement; + +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; +import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; +import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation; +import org.antlr.v4.runtime.Token; +import de.dhbwstuttgart.exceptions.NotImplementedException; + +public class Super extends Expression +{ + public Super(Token offset) + { + super(null,null); + } + + @Override + public void accept(StatementVisitor visitor) { + visitor.visit(this); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/SuperCall.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/SuperCall.java new file mode 100644 index 00000000..3b7eebbf --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/SuperCall.java @@ -0,0 +1,31 @@ +package de.dhbwstuttgart.syntaxtree.statement; + +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.Void; +import org.antlr.v4.runtime.Token; + +import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; + +import java.util.ArrayList; + + +public class SuperCall extends MethodCall +{ + public SuperCall(RefTypeOrTPHOrWildcardOrGeneric receiverType, + ArrayList argTypes, Token offset){ + this(new ArgumentList(new ArrayList(), offset), receiverType, argTypes, offset); + } + + public SuperCall(ArgumentList argumentList, RefTypeOrTPHOrWildcardOrGeneric receiverType, + ArrayList argTypes, Token offset){ + super(new Void(offset), new ExpressionReceiver(new This(offset)), "", argumentList, receiverType, argTypes, offset); + } + + + @Override + public void accept(StatementVisitor visitor) { + visitor.visit(this); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/This.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/This.java new file mode 100644 index 00000000..cd7ef5ec --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/This.java @@ -0,0 +1,26 @@ +package de.dhbwstuttgart.syntaxtree.statement; + +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import org.antlr.v4.runtime.Token; +import de.dhbwstuttgart.exceptions.NotImplementedException; + +public class This extends Expression +{ + public This(Token offset) + { + super(TypePlaceholder.fresh(offset),offset); + } + + public ArgumentList arglist; + + @Override + public void accept(StatementVisitor visitor) { + visitor.visit(this); + } + + public String toString() { + return "this: "+ this.getType(); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/ThisCall.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/ThisCall.java new file mode 100644 index 00000000..26579d2f --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/ThisCall.java @@ -0,0 +1,19 @@ +package de.dhbwstuttgart.syntaxtree.statement; + +import de.dhbwstuttgart.syntaxtree.Constructor; + + + +public class ThisCall extends MethodCall +{ + public ThisCall(Receiver receiver, ArgumentList arglist, int offset) + { + super(null, null, null, null, null, null, null); + + } + + public ArgumentList arglist; + +} + + diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/TypableStatement.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/TypableStatement.java new file mode 100644 index 00000000..a2166d2d --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/TypableStatement.java @@ -0,0 +1,28 @@ +package de.dhbwstuttgart.syntaxtree.statement; + +import de.dhbwstuttgart.syntaxtree.ASTVisitor; +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import org.antlr.v4.runtime.Token; + +public abstract class TypableStatement extends SyntaxTreeNode{ + private RefTypeOrTPHOrWildcardOrGeneric type; + + public TypableStatement(RefTypeOrTPHOrWildcardOrGeneric type, Token offset){ + super(offset); + if(type == null)throw new NullPointerException(); + this.type = type; + } + + public RefTypeOrTPHOrWildcardOrGeneric getType(){ + return type; + } + + public abstract void accept(StatementVisitor visitor); + + @Override + public void accept(ASTVisitor visitor) { + this.accept((StatementVisitor)visitor); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/UnaryExpr.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/UnaryExpr.java new file mode 100644 index 00000000..ca06146a --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/UnaryExpr.java @@ -0,0 +1,37 @@ +package de.dhbwstuttgart.syntaxtree.statement; + + +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.statement.Expression; +import de.dhbwstuttgart.syntaxtree.statement.JavaInternalExpression; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import org.antlr.v4.runtime.Token; + +public class UnaryExpr extends JavaInternalExpression +{ + public enum Operation{ + NOT, + MINUS, + PREINCREMENT, + PREDECREMENT, + POSTINCREMENT, + PLUS, POSTDECREMENT + } + + + public final Operation operation; + public Expression expr; + + public UnaryExpr(Operation operation, Expression argument, RefTypeOrTPHOrWildcardOrGeneric retType, Token offset) + { + super(retType, offset); + this.expr = argument; + this.operation = operation; + } + @Override + public void accept(StatementVisitor visitor) { + visitor.visit(this); + } + + +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/WhileStmt.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/WhileStmt.java new file mode 100644 index 00000000..0127a505 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/statement/WhileStmt.java @@ -0,0 +1,28 @@ +package de.dhbwstuttgart.syntaxtree.statement; + + +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; +import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; +import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation; +import de.dhbwstuttgart.exceptions.NotImplementedException; +import org.antlr.v4.runtime.Token; + +public class WhileStmt extends Statement +{ + public final Expression expr; + public final Statement loopBlock; + + public WhileStmt(Expression expr, Statement loopBlock, Token offset) + { + super(TypePlaceholder.fresh(offset), offset); + this.expr = expr; + this.loopBlock = loopBlock; + } + + @Override + public void accept(StatementVisitor visitor) { + visitor.visit(this); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/type/ExtendsWildcardType.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/type/ExtendsWildcardType.java new file mode 100644 index 00000000..663bc9dc --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/type/ExtendsWildcardType.java @@ -0,0 +1,62 @@ +package de.dhbwstuttgart.syntaxtree.type; + + +import de.dhbwstuttgart.syntaxtree.ASTVisitor; +import de.dhbwstuttgart.typeinference.result.ResultSetVisitor; +import org.antlr.v4.runtime.Token; + +/** + * Stellt eine Wildcard mit oberer Grenze dar. + * z.B. void test(? extends Number var){..} + * ... + * @author luar 2.12.06 + * + */ + +public class ExtendsWildcardType extends WildcardType{ + + /** + * Author: Arne Lüdtke
+ * Standard Konstruktor für eine ExtendsWildcard + */ + public ExtendsWildcardType (RefTypeOrTPHOrWildcardOrGeneric extendsType, Token offset) + { + super(extendsType, offset); + } + + @Override + public boolean isExtends() { + return true; + } + + @Override + public boolean isSuper() { + return false; + } + + @Override + public String toString() { + return "? extends "+innerType.toString(); + } + + @Override + public void accept(ASTVisitor visitor) { + visitor.visit(this); + } + + @Override + public
A acceptTV(TypeVisitor visitor) { + return visitor.visit(this); + } + + @Override + public void accept(ResultSetVisitor visitor) { + visitor.visit(this); + } + + @Override + public boolean equals(Object o) { + // TODO Auto-generated method stub + return false; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/type/GenericRefType.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/type/GenericRefType.java new file mode 100644 index 00000000..644dbaee --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/type/GenericRefType.java @@ -0,0 +1,49 @@ +package de.dhbwstuttgart.syntaxtree.type; + +import de.dhbwstuttgart.syntaxtree.ASTVisitor; +import de.dhbwstuttgart.typeinference.result.ResultSetVisitor; +import org.antlr.v4.runtime.Token; + +public class GenericRefType extends RefTypeOrTPHOrWildcardOrGeneric +{ + private String name; + + public GenericRefType(String name, Token offset) + { + super(offset); + this.name = name; + } + + public String getParsedName(){ + return name.toString(); + } + + @Override + public void accept(ASTVisitor visitor) { + visitor.visit(this); + } + + @Override + public A acceptTV(TypeVisitor visitor) { + return visitor.visit(this); + } + + @Override + public void accept(ResultSetVisitor visitor) { + visitor.visit(this); + } + + @Override + public boolean equals(Object o) { + // TODO Auto-generated method stub + return false; + } + + + @Override + public String toString() + { + return "GTV " + this.name; + } +} + diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/type/RefType.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/type/RefType.java new file mode 100644 index 00000000..26f25fcf --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/type/RefType.java @@ -0,0 +1,125 @@ +package de.dhbwstuttgart.syntaxtree.type; + +import de.dhbwstuttgart.parser.scope.JavaClassName; +import de.dhbwstuttgart.syntaxtree.ASTVisitor; +import de.dhbwstuttgart.typeinference.result.ResultSetVisitor; +import org.antlr.v4.runtime.Token; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + + +public class RefType extends RefTypeOrTPHOrWildcardOrGeneric +{ + protected final JavaClassName name; + protected final List parameter; + /** + * Ist primitiveFlag auf true, muss beim Codegen dieser Reftype durch + * den primitiven Datentyp ersetzt werden + * + * Bsp: java.lang.Integer mit Flag wird dann zu [int] + */ + private boolean primitiveFlag=false; + + public RefType(JavaClassName fullyQualifiedName, Token offset) + { + this(fullyQualifiedName, new ArrayList<>(), offset); + } + + @Override + public String toString(){ + String params = ""; + if(parameter.size()>0){ + params += "<"; + Iterator it = parameter.iterator(); + while(it.hasNext()){ + RefTypeOrTPHOrWildcardOrGeneric param = it.next(); + params += param.toString(); + if(it.hasNext())params += ", "; + } + params += ">"; + } + return this.name.toString() + params; + } + + @Override + public int hashCode() { + int hash = 0; + hash += super.hashCode(); + hash += this.name.hashCode();//Nur den Name hashen. Sorgt für langsame, aber funktionierende HashMaps + return hash; + } + + public RefType(JavaClassName fullyQualifiedName, List parameter, Token offset) + { + super(offset); + this.name = (fullyQualifiedName); + this.parameter = parameter; + } + + public JavaClassName getName() + { + return name; + } + + public List getParaList(){ + if(this.parameter==null)return new ArrayList<>(); + return this.parameter; + } + + /** + * Author: Jrg Buerle
+ * @return + */ + public boolean equals(Object obj) + { + if(obj instanceof RefType){ + boolean ret = true; + + //if(!(super.equals(obj))) PL 2020-03-12 muss vll. einkommentiert werden + // return false; + + if(parameter==null || parameter.size()==0){ + ret &= (((RefType)obj).getParaList()==null || ((RefType)obj).getParaList().size()==0); + } + else{ + if(((RefType)obj).getParaList()==null){ + ret = false; + } + else if(parameter.size() != ((RefType)obj).getParaList().size()) + { + ret = false; + } + else + { + for(int i = 0; i A acceptTV(TypeVisitor
visitor) { + return visitor.visit(this); + } + + @Override + public void accept(ResultSetVisitor visitor) { + visitor.visit(this); + } +} + diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/type/RefTypeOrTPHOrWildcardOrGeneric.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/type/RefTypeOrTPHOrWildcardOrGeneric.java new file mode 100644 index 00000000..22c8ab4b --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/type/RefTypeOrTPHOrWildcardOrGeneric.java @@ -0,0 +1,22 @@ +package de.dhbwstuttgart.syntaxtree.type; + +import de.dhbwstuttgart.syntaxtree.ASTVisitor; +import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; +import de.dhbwstuttgart.typeinference.result.ResultSetVisitor; +import org.antlr.v4.runtime.Token; + +public abstract class RefTypeOrTPHOrWildcardOrGeneric extends SyntaxTreeNode{ + public RefTypeOrTPHOrWildcardOrGeneric(Token offset) { + super(offset); + } + + @Override + public abstract void accept(ASTVisitor visitor); + + public abstract A acceptTV(TypeVisitor visitor); + public abstract void accept(ResultSetVisitor visitor); + + @Override + public abstract boolean equals(Object o); + +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/type/SuperWildcardType.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/type/SuperWildcardType.java new file mode 100644 index 00000000..6a61b9cb --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/type/SuperWildcardType.java @@ -0,0 +1,73 @@ +package de.dhbwstuttgart.syntaxtree.type; + + +import de.dhbwstuttgart.syntaxtree.ASTVisitor; +import de.dhbwstuttgart.typeinference.result.ResultSetVisitor; +import org.antlr.v4.runtime.Token; + +/** + * Stellt eine Wildcard mit unterer Grenze dar. + * z.B. void test(? super Integer var){..} + * ... + * @author luar 2.12.06 + * + */ + +public class SuperWildcardType extends WildcardType{ + + /** + * Author: Arne Lüdtke
+ * Standard Konstruktor für eine SuperWildcard + */ + public SuperWildcardType( RefTypeOrTPHOrWildcardOrGeneric innerType, Token offset) + { + super(innerType, offset); + } + + /** + * Author: Arne Lüdtke
+ * Gibt den Typen in der Wildcard zurück. + * Beispiel: ? super Integer. + * Integer wird zurückgegeben. + */ + public RefTypeOrTPHOrWildcardOrGeneric getInnerType() + { + return this.innerType; + } + + @Override + public String toString() { + return "? super "+innerType.toString(); + } + + @Override + public boolean isExtends() { + return false; + } + + @Override + public boolean isSuper() { + return true; + } + + @Override + public void accept(ASTVisitor visitor) { + visitor.visit(this); + } + + @Override + public
A acceptTV(TypeVisitor visitor) { + return visitor.visit(this); + } + + @Override + public void accept(ResultSetVisitor visitor) { + visitor.visit(this); + } + + @Override + public boolean equals(Object o) { + // TODO Auto-generated method stub + return false; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/type/TypePlaceholder.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/type/TypePlaceholder.java new file mode 100644 index 00000000..38932247 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/type/TypePlaceholder.java @@ -0,0 +1,102 @@ +package de.dhbwstuttgart.syntaxtree.type; +import java.util.Hashtable; + +import de.dhbwstuttgart.syntaxtree.ASTVisitor; +import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; +import de.dhbwstuttgart.syntaxtree.factory.NameGenerator; +import de.dhbwstuttgart.typeinference.result.ResultSetVisitor; +import org.antlr.v4.runtime.Token; + +/** + * Repr�sentiert einen Typparameter f�r einen vom Programmierer nicht angegeben + * Typ. Jede TypePlaceholder besitzt einen eindeutigen Namen aus einem Namenspool + * und + * ist in einer zentralen Registry, d.h. einer Hashtable abgelegt. + * @author J�rg B�uerle + * @version $Date: 2013/06/19 12:45:37 $ + */ +public class TypePlaceholder extends RefTypeOrTPHOrWildcardOrGeneric +{ + private final String name; + + /** + * wird im Generate Generics Teil nach der Rueckumwandlung nach dem Unify genutzt + */ + private int variance = 0; + + + /** + * Privater Konstruktor - Eine TypePlaceholder-Variable wird �ber die + * Factory-Methode fresh() erzeugt. + *
Author: J�rg B�uerle + */ + private TypePlaceholder(String name, Token offset) + { + super(offset); + this.name = name; + } + + + /** + * @author Andreas Stadelmeier, a10023 + * Ruft die TypePlaceholder.fresh()-Methode auf. + * Fügt zusätzlich einen Replacementlistener hinzu. + * @return + */ + public static TypePlaceholder fresh(Token position){ + return new TypePlaceholder(NameGenerator.makeNewName(), position); + } + + + /** + * Author: J�rg B�uerle
+ * @return + */ + public boolean equals(Object obj) + { + if(obj instanceof TypePlaceholder){ + return this.toString().equals(((TypePlaceholder)obj).toString()); + //return super.equals(obj); + } + else{ + return false; + } + } + + @Override + public int hashCode() { + return this.getName().hashCode(); + } + + public String toString() + { + return "TPH " + this.name; + } + + public String getName() { + return name; + } + + public void setVariance(int variance) { + this.variance= variance; + } + + public int getVariance() { + return this.variance; + } + + @Override + public void accept(ASTVisitor visitor) { + visitor.visit(this); + } + + @Override + public
A acceptTV(TypeVisitor visitor) { + return visitor.visit(this); + } + + @Override + public void accept(ResultSetVisitor visitor) { + visitor.visit(this); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/type/TypeVisitor.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/type/TypeVisitor.java new file mode 100644 index 00000000..a3b7796f --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/type/TypeVisitor.java @@ -0,0 +1,13 @@ +package de.dhbwstuttgart.syntaxtree.type; + +public interface TypeVisitor { + A visit(RefType refType); + + A visit(SuperWildcardType superWildcardType); + + A visit(TypePlaceholder typePlaceholder); + + A visit(ExtendsWildcardType extendsWildcardType); + + A visit(GenericRefType genericRefType); +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/type/Void.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/type/Void.java new file mode 100644 index 00000000..6a322dcb --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/type/Void.java @@ -0,0 +1,14 @@ +package de.dhbwstuttgart.syntaxtree.type; + +import org.antlr.v4.runtime.Token; + +import de.dhbwstuttgart.parser.scope.JavaClassName; + + +public class Void extends RefType +{ + public Void(Token offset) { + super(JavaClassName.Void, offset); + } +} + diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/type/WildcardType.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/type/WildcardType.java new file mode 100644 index 00000000..208138b6 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/type/WildcardType.java @@ -0,0 +1,42 @@ +package de.dhbwstuttgart.syntaxtree.type; + +import org.antlr.v4.runtime.Token; + +/** + * Stellt eine Wildcard in Java dar. + * z.B. void Test(? var){..} + * @author luar 2.12.06 + * + */ + +public abstract class WildcardType extends RefTypeOrTPHOrWildcardOrGeneric { + + protected RefTypeOrTPHOrWildcardOrGeneric innerType = null; + + /** + * Author: Arne Lüdtke
+ * Standard Konstruktor für eine Wildcard + */ + public WildcardType(RefTypeOrTPHOrWildcardOrGeneric innerType, Token offset) + { + super(offset); + this.innerType = innerType; + } + + public RefTypeOrTPHOrWildcardOrGeneric getInnerType(){ + return innerType; + } + + /** + * Author: Arne Lüdtke
+ * Gibt String Entsprechung zurück. + */ + public String toString() + { + return "?"; + } + + + public abstract boolean isExtends(); + public abstract boolean isSuper(); +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/visual/ASTPrinter.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/visual/ASTPrinter.java new file mode 100644 index 00000000..9d04b298 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/visual/ASTPrinter.java @@ -0,0 +1,13 @@ +package de.dhbwstuttgart.syntaxtree.visual; + +import de.dhbwstuttgart.syntaxtree.*; + +public class ASTPrinter { + + public static String print(SourceFile toPrint){ + StringBuilder output = new StringBuilder(); + new OutputGenerator(output).visit(toPrint); + return output.toString(); + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/visual/ASTTypePrinter.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/visual/ASTTypePrinter.java new file mode 100644 index 00000000..cbfc1a19 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/visual/ASTTypePrinter.java @@ -0,0 +1,13 @@ +package de.dhbwstuttgart.syntaxtree.visual; + +import de.dhbwstuttgart.syntaxtree.*; + +public class ASTTypePrinter extends ASTPrinter{ + + public static String print(SourceFile toPrint){ + StringBuilder output = new StringBuilder(); + new TypeOutputGenerator(output).visit(toPrint); + return output.toString(); + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/visual/OutputGenerator.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/visual/OutputGenerator.java new file mode 100644 index 00000000..9a3228fe --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/visual/OutputGenerator.java @@ -0,0 +1,381 @@ +package de.dhbwstuttgart.syntaxtree.visual; + +import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; +import de.dhbwstuttgart.syntaxtree.*; +import de.dhbwstuttgart.syntaxtree.statement.*; +import de.dhbwstuttgart.syntaxtree.type.*; + +import java.lang.reflect.Modifier; +import java.util.Iterator; +import java.util.Optional; + +public class OutputGenerator implements ASTVisitor{ + private static final String TAB = " "; + String tabs = ""; + protected final StringBuilder out; + + public OutputGenerator(StringBuilder out){ + this.out = out; + } + + public void tab() { + tabs += TAB; + } + + public void untab() { + tabs = tabs.substring(0,tabs.length()-TAB.length()); + } + + @Override + public void visit(SourceFile sourceFile) { + for(ClassOrInterface cl : sourceFile.getClasses()){ + cl.accept(this); + } + } + + @Override + public void visit(ArgumentList argumentList) { + out.append("("); + Iterator expressionIterator = argumentList.getArguments().iterator(); + while(expressionIterator.hasNext()){ + expressionIterator.next().accept(this); + if(expressionIterator.hasNext())out.append(", "); + } + out.append(")"); + } + + @Override + public void visit(GenericTypeVar genericTypeVar) { + out.append(genericTypeVar.getName().toString()); + } + + @Override + public void visit(FormalParameter formalParameter) { + formalParameter.getType().accept(this); + out.append(" "); + out.append(formalParameter.getName()); + } + + @Override + public void visit(GenericDeclarationList genericTypeVars) { + Iterator genericIterator = genericTypeVars.iterator(); + if(genericIterator.hasNext()){ + out.append("<"); + while(genericIterator.hasNext()){ + genericIterator.next().accept(this); + if(genericIterator.hasNext())out.append(", "); + } + out.append(">"); + } + } + + @Override + public void visit(Field field) { + field.getType().accept(this); + out.append(" "); + out.append(field.getName()); + out.append(";"); + } + + @Override + public void visit(Method method) { + method.getReturnType().accept(this); + out.append(" " + method.getName()); + method.getParameterList().accept(this); + if(method.block != null) + method.block.accept(this); + out.append("\n"); + } + + @Override + public void visit(Constructor method) { + out.append(method.getName()); + method.getParameterList().accept(this); + method.block.accept(this); + out.append("\n"); + } + + @Override + public void visit(ParameterList formalParameters) { + out.append("("); + Iterator genericIterator = formalParameters.getFormalparalist().iterator(); + if(genericIterator.hasNext()){ + while(genericIterator.hasNext()){ + genericIterator.next().accept(this); + if(genericIterator.hasNext())out.append(", "); + } + } + out.append(")"); + } + + @Override + public void visit(ClassOrInterface classOrInterface) { + if((Modifier.INTERFACE & classOrInterface.getModifiers()) == 1){ + out.append("interface "); + }else{ + out.append("class "); + } + out.append(classOrInterface.getClassName().toString()); + classOrInterface.getGenerics().accept(this); + out.append(" {\n\n"); + tab(); + for(Field f : classOrInterface.getFieldDecl()){ + out.append(tabs); + f.accept(this); + out.append("\n"); + } + if (classOrInterface.getfieldInitializations().isPresent()) {//PL 2019-11-28: Zum Ausdrucken der Fieldinitializer + classOrInterface.getfieldInitializations().get().accept(this); + } + for(Method m : classOrInterface.getMethods()){ + out.append(tabs); + m.accept(this); + out.append("\n"); + } + for(Constructor m : classOrInterface.getConstructors()){ + out.append(tabs); + m.accept(this); + out.append("\n"); + } + untab(); + out.append("}"); + } + + @Override + public void visit(RefType refType) { + out.append(refType.getName().toString()); + Iterator genericIterator = refType.getParaList().iterator(); + if(genericIterator.hasNext()){ + out.append("<"); + while(genericIterator.hasNext()){ + genericIterator.next().accept(this); + if(genericIterator.hasNext())out.append(", "); + } + out.append(">"); + } + } + + @Override + public void visit(SuperWildcardType superWildcardType) { + out.append("? super "); + superWildcardType.getInnerType().accept(this); + } + + @Override + public void visit(TypePlaceholder typePlaceholder) { + out.append("TPH "+ typePlaceholder.getName()); + } + + @Override + public void visit(ExtendsWildcardType extendsWildcardType) { + out.append("? extends "); + extendsWildcardType.getInnerType().accept(this); + } + + @Override + public void visit(GenericRefType genericRefType) { + out.append(genericRefType.getParsedName().toString()); + } + + @Override + public void visit(LambdaExpression lambdaExpression) { + lambdaExpression.params.accept(this); + out.append(" -> "); + lambdaExpression.methodBody.accept(this); + } + + @Override + public void visit(Assign assign) { + assign.lefSide.accept(this); + out.append(" = "); + assign.rightSide.accept(this); + } + + @Override + public void visit(BinaryExpr binary) { + binary.lexpr.accept(this); + out.append(" op "); + binary.rexpr.accept(this); + } + + @Override + public void visit(Block block) { + tab(); + out.append("{\n"); + for(Statement stmt : block.getStatements()){ + out.append(tabs); + stmt.accept(this); + out.append(";\n"); + } + untab(); + out.append(tabs); + out.append("}"); + } + + @Override + public void visit(CastExpr castExpr) { + + } + + @Override + public void visit(EmptyStmt emptyStmt) { + + } + + @Override + public void visit(FieldVar fieldVar) { + fieldVar.receiver.accept(this); + out.append("." + fieldVar.fieldVarName); + } + + @Override + public void visit(ForStmt forStmt) { + + } + + @Override + public void visit(IfStmt ifStmt) { + out.append("if("); + ifStmt.expr.accept(this); + out.append(")\n"); + tab(); + out.append(tabs); + ifStmt.then_block.accept(this); + untab(); + if(ifStmt.else_block != null){ + out.append("\n" + tabs + "else\n"); + tab(); + out.append(tabs); + ifStmt.else_block.accept(this); + untab(); + } + } + + @Override + public void visit(InstanceOf instanceOf) { + + } + + @Override + public void visit(LocalVar localVar) { + out.append(localVar.name); + } + + @Override + public void visit(LocalVarDecl localVarDecl) { + localVarDecl.getType().accept(this); + out.append(" " + localVarDecl.getName()); + } + + @Override + public void visit(MethodCall methodCall) { + methodCall.receiver.accept(this); + out.append("."+methodCall.name); + methodCall.getArgumentList().accept(this); + } + + @Override + public void visit(NewClass methodCall) { + out.append("new "); + out.append(methodCall.name); + methodCall.getArgumentList().accept(this); + } + + @Override + public void visit(NewArray newArray) { + + } + + @Override + public void visit(Return aReturn) { + out.append("return "); + aReturn.retexpr.accept(this); + } + + @Override + public void visit(ReturnVoid aReturn) { + out.append("return"); + } + + @Override + public void visit(StaticClassName staticClassName) { + + } + + @Override + public void visit(Super aSuper) { + + } + + @Override + public void visit(This aThis) { + out.append("this"); + } + + @Override + public void visit(WhileStmt whileStmt) { + out.append("while("); + whileStmt.expr.accept(this); + out.append(")"); + whileStmt.loopBlock.accept(this); + } + + @Override + public void visit(DoStmt whileStmt) { + out.append("do "); + whileStmt.loopBlock.accept(this); + out.append("while("); + whileStmt.expr.accept(this); + out.append(");"); + } + + @Override + public void visit(AssignToField assignLeftSide) { + assignLeftSide.field.accept(this); + } + + @Override + public void visit(AssignToLocal assignLeftSide) { + assignLeftSide.localVar.accept(this); + } + + @Override + public void visit(SuperCall superCall) { + out.append("super("); + superCall.arglist.accept(this); + out.append(")"); + } + + @Override + public void visit(ExpressionReceiver receiver) { + receiver.expr.accept(this); + } + + @Override + public void visit(UnaryExpr unaryExpr) { + if(unaryExpr.operation == UnaryExpr.Operation.MINUS){ + out.append("-"); + } + if(unaryExpr.operation == UnaryExpr.Operation.PLUS){ + out.append("+"); + } + if(unaryExpr.operation == UnaryExpr.Operation.PREDECREMENT){ + out.append("--"); + } + if(unaryExpr.operation == UnaryExpr.Operation.PREINCREMENT){ + out.append("++"); + } + unaryExpr.expr.accept(this); + if(unaryExpr.operation == UnaryExpr.Operation.POSTDECREMENT){ + out.append("--"); + } + if(unaryExpr.operation == UnaryExpr.Operation.POSTINCREMENT){ + out.append("++"); + } + } + + @Override + public void visit(de.dhbwstuttgart.syntaxtree.statement.Literal literal) { + out.append(literal.value); + } +} \ No newline at end of file diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/visual/ResultSetOutputGenerator.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/visual/ResultSetOutputGenerator.java new file mode 100644 index 00000000..f50b05a6 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/visual/ResultSetOutputGenerator.java @@ -0,0 +1,34 @@ +package de.dhbwstuttgart.syntaxtree.visual; + +import de.dhbwstuttgart.syntaxtree.type.*; +import de.dhbwstuttgart.typeinference.result.*; + +public class ResultSetOutputGenerator extends OutputGenerator implements ResultSetVisitor{ + + public ResultSetOutputGenerator(StringBuilder out) { + super(out); + } + + @Override + public void visit(PairTPHsmallerTPH p) { + print(p, "<"); + } + + @Override + public void visit(PairTPHequalRefTypeOrWildcardType p) { + print(p, "=."); + } + + @Override + public void visit(PairTPHEqualTPH p) { + print(p, "=."); + } + + private void print(ResultPair p , String operator){ + out.append("("); + p.getLeft().accept((ResultSetVisitor) this); + out.append(" "+operator+" "); + p.getRight().accept((ResultSetVisitor) this); + out.append(")"); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/visual/ResultSetPrinter.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/visual/ResultSetPrinter.java new file mode 100644 index 00000000..fc67a723 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/visual/ResultSetPrinter.java @@ -0,0 +1,20 @@ +package de.dhbwstuttgart.syntaxtree.visual; + +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.typeinference.result.ResultPair; +import de.dhbwstuttgart.typeinference.result.ResultSet; + +import java.util.Set; + +public class ResultSetPrinter { + + public static String print(ResultSet toPrint){ + StringBuilder output = new StringBuilder(); + for(ResultPair p : toPrint.results){ + p.accept(new ResultSetOutputGenerator(output)); + output.append("\n"); + } + return output.toString(); + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/syntaxtree/visual/TypeOutputGenerator.java b/app/src/main/java/de/dhbwstuttgart/syntaxtree/visual/TypeOutputGenerator.java new file mode 100644 index 00000000..8a210db1 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/syntaxtree/visual/TypeOutputGenerator.java @@ -0,0 +1,224 @@ +package de.dhbwstuttgart.syntaxtree.visual; + +import de.dhbwstuttgart.syntaxtree.*; +import de.dhbwstuttgart.syntaxtree.statement.*; +import de.dhbwstuttgart.syntaxtree.statement.Literal; +import de.dhbwstuttgart.syntaxtree.type.*; + +public class TypeOutputGenerator extends OutputGenerator { + + TypeOutputGenerator(StringBuilder out){ + super(out); + } + + @Override + public void visit(SourceFile sourceFile) { + super.visit(sourceFile); + } + + @Override + public void visit(ArgumentList argumentList) { + super.visit(argumentList); + } + + @Override + public void visit(GenericTypeVar genericTypeVar) { + super.visit(genericTypeVar); + } + + @Override + public void visit(FormalParameter formalParameter) { + super.visit(formalParameter); + } + + @Override + public void visit(GenericDeclarationList genericTypeVars) { + super.visit(genericTypeVars); + } + + @Override + public void visit(Field field) { + super.visit(field); + } + + @Override + public void visit(Method method) { + super.visit(method); + } + + @Override + public void visit(ParameterList formalParameters) { + super.visit(formalParameters); + } + + @Override + public void visit(ClassOrInterface classOrInterface) { + super.visit(classOrInterface); + } + + @Override + public void visit(RefType refType) { + super.visit(refType); + } + + @Override + public void visit(SuperWildcardType superWildcardType) { + super.visit(superWildcardType); + } + + @Override + public void visit(TypePlaceholder typePlaceholder) { + super.visit(typePlaceholder); + } + + @Override + public void visit(ExtendsWildcardType extendsWildcardType) { + super.visit(extendsWildcardType); + } + + @Override + public void visit(GenericRefType genericRefType) { + super.visit(genericRefType); + } + + @Override + public void visit(LambdaExpression lambdaExpression) { + out.append("("); + super.visit(lambdaExpression); + out.append(")"); + this.out.append("::"); + lambdaExpression.getType().accept(this); + } + + @Override + public void visit(Assign assign) { + super.visit(assign); + } + + @Override + public void visit(BinaryExpr binary) { + binary.lexpr.accept(this); + out.append(" | "); + binary.rexpr.accept(this); + } + + @Override + public void visit(Block block) { + out.append("("); + super.visit(block); + out.append(")"); + this.out.append("::"); + block.getType().accept(this); + } + + @Override + public void visit(CastExpr castExpr) { + super.visit(castExpr); + } + + @Override + public void visit(EmptyStmt emptyStmt) { + super.visit(emptyStmt); + } + + @Override + public void visit(FieldVar fieldVar) { + out.append("("); + super.visit(fieldVar); + out.append(")"); + this.out.append("::"); + fieldVar.getType().accept(this); + } + + @Override + public void visit(ForStmt forStmt) { + super.visit(forStmt); + } + + @Override + public void visit(IfStmt ifStmt) { + super.visit(ifStmt); + } + + @Override + public void visit(InstanceOf instanceOf) { + super.visit(instanceOf); + } + + @Override + public void visit(LocalVar localVar) { + out.append("("); + super.visit(localVar); + out.append(")"); + this.out.append("::"); + localVar.getType().accept(this); + } + + @Override + public void visit(LocalVarDecl localVarDecl) { + super.visit(localVarDecl); + } + + @Override + public void visit(MethodCall methodCall) { + out.append("("); + super.visit(methodCall); + out.append(")"); + this.out.append("::"); + methodCall.getType().accept(this); + } + + @Override + public void visit(NewClass methodCall) { + super.visit(methodCall); + } + + @Override + public void visit(NewArray newArray) { + super.visit(newArray); + } + + @Override + public void visit(ExpressionReceiver receiver) { + super.visit(receiver); + } + + @Override + public void visit(Return aReturn) { + super.visit(aReturn); + } + + @Override + public void visit(ReturnVoid aReturn) { + super.visit(aReturn); + } + + @Override + public void visit(StaticClassName staticClassName) { + super.visit(staticClassName); + } + + @Override + public void visit(Super aSuper) { + super.visit(aSuper); + } + + @Override + public void visit(This aThis) { + out.append("("); + super.visit(aThis); + out.append(")"); + this.out.append("::"); + aThis.getType().accept(this); + } + + @Override + public void visit(WhileStmt whileStmt) { + super.visit(whileStmt); + } + + @Override + public void visit(Literal literal) { + super.visit(literal); + } +} \ No newline at end of file diff --git a/app/src/main/java/de/dhbwstuttgart/target/ByteArrayClassLoader.java b/app/src/main/java/de/dhbwstuttgart/target/ByteArrayClassLoader.java new file mode 100644 index 00000000..428e214d --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/ByteArrayClassLoader.java @@ -0,0 +1,16 @@ +package de.dhbwstuttgart.target; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +public class ByteArrayClassLoader extends ClassLoader { + public Class loadClass(byte[] code) { + return this.defineClass(null, code, 0, code.length); + } + + public Class loadClass(Path path) throws IOException { + var code = Files.readAllBytes(path); + return this.defineClass(null, code, 0, code.length); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/bytecode/CodeGenException.java b/app/src/main/java/de/dhbwstuttgart/target/bytecode/CodeGenException.java new file mode 100644 index 00000000..f517e767 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/bytecode/CodeGenException.java @@ -0,0 +1,7 @@ +package de.dhbwstuttgart.target.bytecode; + +public class CodeGenException extends RuntimeException { + public CodeGenException(String cause) { + super(cause); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java b/app/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java new file mode 100755 index 00000000..04bee492 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/bytecode/Codegen.java @@ -0,0 +1,1033 @@ +package de.dhbwstuttgart.target.bytecode; + +import de.dhbwstuttgart.syntaxtree.statement.Block; +import de.dhbwstuttgart.target.tree.*; +import de.dhbwstuttgart.target.tree.expression.*; +import de.dhbwstuttgart.target.tree.type.*; +import org.objectweb.asm.*; + +import java.lang.invoke.CallSite; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.*; + +import static org.objectweb.asm.Opcodes.*; +import static de.dhbwstuttgart.target.tree.expression.TargetBinaryOp.*; +import static de.dhbwstuttgart.target.tree.expression.TargetLiteral.*; + +public class Codegen { + private final TargetClass clazz; + private final ClassWriter cw; + public final String className; + private int lambdaCounter = 0; + private final HashMap lambdas = new HashMap<>(); + + public Codegen(TargetClass clazz) { + this.clazz = clazz; + this.className = clazz.qualifiedName(); + this.cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); + } + + private record LocalVar(int index, String name, TargetType type) {} + + private static class Scope { + Scope parent; + Map locals = new HashMap<>(); + + Scope(Scope parent) { + this.parent = parent; + } + + void add(LocalVar var) { + locals.put(var.name, var); + } + + LocalVar get(String name) { + var local = locals.get(name); + if (local != null) { + return local; + } + if (parent != null) { + return parent.get(name); + } + throw new CodeGenException("Unknown symbol '" + name + "'"); + } + } + + private static class State { + Scope scope = new Scope(null); + int localCounter; + MethodVisitor mv; + + State(MethodVisitor mv, int localCounter) { + this.mv = mv; + this.localCounter = localCounter; + } + + void enterScope() { + this.scope = new Scope(this.scope); + } + + void exitScope() { + this.scope = this.scope.parent; + } + + LocalVar createVariable(String name, TargetType type) { + var local = new LocalVar(localCounter, name, type); + scope.add(local); + localCounter += 1; + return local; + } + } + + private void boxPrimitive(State state, TargetType type) { + var mv = state.mv; + if (type.equals(TargetType.Boolean) || type.equals(TargetType.boolean_)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false); + } else if (type.equals(TargetType.Byte) || type.equals(TargetType.byte_)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false); + } else if (type.equals(TargetType.Double) || type.equals(TargetType.double_)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false); + } else if (type.equals(TargetType.Long) || type.equals(TargetType.long_)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false); + } else if (type.equals(TargetType.Integer) || type.equals(TargetType.int_)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false); + } else if (type.equals(TargetType.Float) || type.equals(TargetType.float_)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false); + } else if (type.equals(TargetType.Short) || type.equals(TargetType.short_)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false); + } else if (type.equals(TargetType.Char) || type.equals(TargetType.char_)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Char", "valueOf", "(C)Ljava/lang/Char;", false); + } + } + + private void unboxPrimitive(State state, TargetType type) { + var mv = state.mv; + if (type.equals(TargetType.Boolean)) { + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false); + } else if (type.equals(TargetType.Byte)) { + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B", false); + } else if (type.equals(TargetType.Double)) { + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false); + } else if (type.equals(TargetType.Long)) { + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false); + } else if (type.equals(TargetType.Integer)) { + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false); + } else if (type.equals(TargetType.Float)) { + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false); + } else if (type.equals(TargetType.Short)) { + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S", false); + } else if (type.equals(TargetType.Char)) { + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Char", "charValue", "()C", false); + } + } + + private void generateRelationalOperator(State state, TargetRelationalOp op, TargetType type, int code) { + var mv = state.mv; + Label if_true = new Label(); + Label end = new Label(); + generate(state, op.left()); + convertTo(state, op.left().type(), type); + generate(state, op.right()); + convertTo(state, op.right().type(), type); + mv.visitJumpInsn(code, if_true); + mv.visitInsn(ICONST_0); + mv.visitJumpInsn(GOTO, end); + mv.visitLabel(if_true); + mv.visitInsn(ICONST_1); + mv.visitLabel(end); + } + + private void generateRelationalOperator(State state, TargetRelationalOp op, TargetType type, int cmp, int code) { + var mv = state.mv; + Label if_true = new Label(); + Label end = new Label(); + generate(state, op.left()); + convertTo(state, op.left().type(), type); + generate(state, op.right()); + convertTo(state, op.right().type(), type); + mv.visitInsn(cmp); + mv.visitJumpInsn(code, if_true); + mv.visitInsn(ICONST_0); + mv.visitJumpInsn(GOTO, end); + mv.visitLabel(if_true); + mv.visitInsn(ICONST_1); + mv.visitLabel(end); + } + + private void convertToString(State state, TargetType type) { + var mv = state.mv; + if (type.equals(TargetType.Boolean)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(Z)Ljava/lang/Boolean;", false); + } else if (type.equals(TargetType.Byte)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(B)Ljava/lang/Byte;", false); + } else if (type.equals(TargetType.Double)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(D)Ljava/lang/Double;", false); + } else if (type.equals(TargetType.Long)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(J)Ljava/lang/Long;", false); + } else if (type.equals(TargetType.Integer)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(I)Ljava/lang/Integer;", false); + } else if (type.equals(TargetType.Float)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(F)Ljava/lang/Float;", false); + } else if (type.equals(TargetType.Short)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(S)Ljava/lang/Short;", false); + } else if (type.equals(TargetType.Char)) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(C)Ljava/lang/Char;", false); + } + } + + private void convertTo(State state, TargetType source, TargetType dest) { + var mv = state.mv; + if (source.equals(dest)) + return; + if (source.equals(TargetType.Long)) { + if (dest.equals(TargetType.Integer)) { + mv.visitInsn(L2I); + } else if (dest.equals(TargetType.Float)) + mv.visitInsn(L2F); + else if (dest.equals(TargetType.Double)) + mv.visitInsn(L2D); + else if (dest.equals(TargetType.Byte) + || dest.equals(TargetType.Char) + || dest.equals(TargetType.Short)) { + mv.visitInsn(L2I); + convertTo(state, TargetType.Integer, dest); + } + } else if (source.equals(TargetType.Float)) { + if (dest.equals(TargetType.Integer)) + mv.visitInsn(F2I); + else if (dest.equals(TargetType.Double)) + mv.visitInsn(F2D); + else if (dest.equals(TargetType.Long)) + mv.visitInsn(F2L); + else if (dest.equals(TargetType.Byte) + || dest.equals(TargetType.Char) + || dest.equals(TargetType.Short)) { + mv.visitInsn(F2I); + convertTo(state, TargetType.Integer, dest); + } + } else if (source.equals(TargetType.Double)) { + if (dest.equals(TargetType.Integer)) + mv.visitInsn(D2I); + else if (dest.equals(TargetType.Float)) + mv.visitInsn(D2F); + else if (dest.equals(TargetType.Long)) + mv.visitInsn(D2L); + else if (dest.equals(TargetType.Byte) + || dest.equals(TargetType.Char) + || dest.equals(TargetType.Short)) { + mv.visitInsn(D2I); + convertTo(state, TargetType.Integer, dest); + } + } else if (source.equals(TargetType.Byte) + || source.equals(TargetType.Char) + || source.equals(TargetType.Short) + || source.equals(TargetType.Integer)) { + if (dest.equals(TargetType.Byte)) + mv.visitInsn(I2B); + else if (dest.equals(TargetType.Char)) + mv.visitInsn(I2C); + else if (dest.equals(TargetType.Short)) + mv.visitInsn(I2S); + else if (dest.equals(TargetType.Long)) + mv.visitInsn(I2L); + else if (dest.equals(TargetType.Float)) + mv.visitInsn(I2F); + else if (dest.equals(TargetType.Double)) + mv.visitInsn(I2D); + } else { + boxPrimitive(state, source); + mv.visitTypeInsn(CHECKCAST, dest.getInternalName()); + unboxPrimitive(state, dest); + } + } + + private TargetType largerType(TargetType left, TargetType right) { + if (left.equals(TargetType.String) || right.equals(TargetType.String)) { + return TargetType.String; + } else if (left.equals(TargetType.Double) || right.equals(TargetType.Double)) { + return TargetType.Double; + } else if (left.equals(TargetType.Float) || right.equals(TargetType.Float)) { + return TargetType.Float; + } else if (left.equals(TargetType.Long) || right.equals(TargetType.Long)) { + return TargetType.Long; + } else { + return TargetType.Integer; + } + } + + private void generateBinaryOp(State state, TargetBinaryOp op) { + var mv = state.mv; + switch (op) { + case Add add: { + if (add.type().equals(TargetType.String)) { + mv.visitTypeInsn(NEW, "java/lang/StringBuilder"); + mv.visitInsn(DUP); + generate(state, add.left()); + convertToString(state, add.left().type()); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "", "(Ljava/lang/String;)V", false); + } else { + generate(state, add.left()); + convertTo(state, add.left().type(), add.type()); + generate(state, add.right()); + convertTo(state, add.right().type(), add.type()); + var type = add.type(); + if (type.equals(TargetType.Byte) + || type.equals(TargetType.Char) + || type.equals(TargetType.Integer) + || type.equals(TargetType.Short)) { + mv.visitInsn(IADD); + } else if (type.equals(TargetType.Long)) { + mv.visitInsn(LADD); + } else if (type.equals(TargetType.Float)) { + mv.visitInsn(FADD); + } else if (type.equals(TargetType.Double)) { + mv.visitInsn(DADD); + } else { + throw new CodeGenException("Invalid argument to Add expression"); + } + } + if (add.type().equals(TargetType.String)) { + generate(state, add.right()); + convertToString(state, add.right().type()); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false); + } + break; + } + case Sub sub: { + generate(state, sub.left()); + convertTo(state, sub.left().type(), op.type()); + generate(state, sub.right()); + convertTo(state, sub.right().type(), op.type()); + var type = sub.type(); + if (type.equals(TargetType.Byte) + || type.equals(TargetType.Char) + || type.equals(TargetType.Integer) + || type.equals(TargetType.Short)) { + mv.visitInsn(ISUB); + } else if (type.equals(TargetType.Long)) { + mv.visitInsn(LSUB); + } else if (type.equals(TargetType.Float)) { + mv.visitInsn(FSUB); + } else if (type.equals(TargetType.Double)) { + mv.visitInsn(DSUB); + } else { + throw new CodeGenException("Invalid argument to Sub expression"); + } + break; + } + case Div div: { + generate(state, div.left()); + convertTo(state, div.left().type(), op.type()); + generate(state, div.right()); + convertTo(state, div.right().type(), op.type()); + var type = div.type(); + if (type.equals(TargetType.Byte) + || type.equals(TargetType.Char) + || type.equals(TargetType.Integer) + || type.equals(TargetType.Short)) { + mv.visitInsn(IDIV); + } else if (type.equals(TargetType.Long)) { + mv.visitInsn(LDIV); + } else if (type.equals(TargetType.Float)) { + mv.visitInsn(FDIV); + } else if (type.equals(TargetType.Double)) { + mv.visitInsn(DDIV); + } else { + throw new CodeGenException("Invalid argument to Div expression"); + } + break; + } + case Mul mul: { + generate(state, mul.left()); + convertTo(state, mul.left().type(), op.type()); + generate(state, mul.right()); + convertTo(state, mul.right().type(), op.type()); + var type = mul.type(); + if (type.equals(TargetType.Byte) + || type.equals(TargetType.Char) + || type.equals(TargetType.Integer) + || type.equals(TargetType.Short)) { + mv.visitInsn(IMUL); + } else if (type.equals(TargetType.Long)) { + mv.visitInsn(LMUL); + } else if (type.equals(TargetType.Float)) { + mv.visitInsn(FMUL); + } else if (type.equals(TargetType.Double)) { + mv.visitInsn(DMUL); + } else { + throw new CodeGenException("Invalid argument to Mul expression"); + } + break; + } + case Rem rem: { + generate(state, rem.left()); + convertTo(state, rem.left().type(), op.type()); + generate(state, rem.right()); + convertTo(state, rem.right().type(), op.type()); + var type = rem.type(); + if (type.equals(TargetType.Byte) + || type.equals(TargetType.Char) + || type.equals(TargetType.Integer) + || type.equals(TargetType.Short)) { + mv.visitInsn(IREM); + } else if (type.equals(TargetType.Long)) { + mv.visitInsn(LREM); + } else if (type.equals(TargetType.Float)) { + mv.visitInsn(FREM); + } else if (type.equals(TargetType.Double)) { + mv.visitInsn(DREM); + } else { + throw new CodeGenException("Invalid argument to Rem expression"); + } + break; + } + case Or or: { + Label or_false = new Label(); + Label or_true = new Label(); + Label end = new Label(); + generate(state, or.left()); + mv.visitJumpInsn(IFNE, or_true); + generate(state, or.right()); + mv.visitJumpInsn(IFEQ, or_false); + mv.visitLabel(or_true); + mv.visitInsn(ICONST_1); + mv.visitJumpInsn(GOTO, end); + mv.visitLabel(or_false); + mv.visitInsn(ICONST_0); + mv.visitLabel(end); + break; + } + case And and: { + Label and_false = new Label(); + Label end = new Label(); + generate(state, and.left()); + mv.visitJumpInsn(IFEQ, and_false); + generate(state, and.right()); + mv.visitJumpInsn(IFEQ, and_false); + mv.visitInsn(ICONST_1); + mv.visitJumpInsn(GOTO, end); + mv.visitLabel(and_false); + mv.visitInsn(ICONST_0); + mv.visitLabel(end); + break; + } + case BAnd band: { + generate(state, band.left()); + convertTo(state, band.left().type(), op.type()); + generate(state, band.right()); + convertTo(state, band.right().type(), op.type()); + if (band.type().equals(TargetType.Long)) + mv.visitInsn(LAND); + else mv.visitInsn(IAND); + break; + } + case BOr bor: { + generate(state, bor.left()); + convertTo(state, bor.left().type(), op.type()); + generate(state, bor.right()); + convertTo(state, bor.right().type(), op.type()); + if (bor.type().equals(TargetType.Long)) + mv.visitInsn(LOR); + else mv.visitInsn(IOR); + break; + } + case XOr xor: { + generate(state, xor.left()); + convertTo(state, xor.left().type(), op.type()); + generate(state, xor.right()); + convertTo(state, xor.right().type(), op.type()); + if (xor.type().equals(TargetType.Long)) + mv.visitInsn(LXOR); + else mv.visitInsn(IXOR); + break; + } + case Shl shl: { + generate(state, shl.left()); + convertTo(state, shl.left().type(), op.type()); + generate(state, shl.right()); + convertTo(state, shl.right().type(), op.type()); + if (shl.type().equals(TargetType.Long)) + mv.visitInsn(LSHL); + else mv.visitInsn(ISHL); + break; + } + case Shr shr: { + generate(state, shr.left()); + convertTo(state, shr.left().type(), op.type()); + generate(state, shr.right()); + convertTo(state, shr.right().type(), op.type()); + if (shr.type().equals(TargetType.Long)) + mv.visitInsn(LSHR); + else mv.visitInsn(ISHR); + break; + } + case UShr ushr: { + generate(state, ushr.left()); + convertTo(state, ushr.left().type(), op.type()); + generate(state, ushr.right()); + convertTo(state, ushr.right().type(), op.type()); + if (ushr.type().equals(TargetType.Long)) + mv.visitInsn(LUSHR); + else mv.visitInsn(IUSHR); + break; + } + case Greater greater: { + var type = largerType(greater.left().type(), greater.right().type()); + if (type.equals(TargetType.Long)) { + generateRelationalOperator(state, greater, type, LCMP, IFGT); + } else if (type.equals(TargetType.Float)) { + generateRelationalOperator(state, greater, type, FCMPL, IFGT); + } else if (type.equals(TargetType.Double)) { + generateRelationalOperator(state, greater, type, DCMPL, IFGT); + } else { + generateRelationalOperator(state, greater, type, IF_ICMPGT); + } + break; + } + case Less less: { + var type = largerType(less.left().type(), less.right().type()); + if (type.equals(TargetType.Long)) { + generateRelationalOperator(state, less, type, LCMP, IFLT); + } else if (type.equals(TargetType.Float)) { + generateRelationalOperator(state, less, type, FCMPL, IFLT); + } else if (type.equals(TargetType.Double)) { + generateRelationalOperator(state, less, type, DCMPL, IFLT); + } else { + generateRelationalOperator(state, less, type, IF_ICMPLT); + } + break; + } + case GreaterOrEqual greaterOrEqual: { + var type = largerType(greaterOrEqual.left().type(), greaterOrEqual.right().type()); + if (type.equals(TargetType.Long)) { + generateRelationalOperator(state, greaterOrEqual, type, LCMP, IFGE); + } else if (type.equals(TargetType.Float)) { + generateRelationalOperator(state, greaterOrEqual, type, FCMPL, IFGE); + } else if (type.equals(TargetType.Double)) { + generateRelationalOperator(state, greaterOrEqual, type, DCMPL, IFGE); + } else { + generateRelationalOperator(state, greaterOrEqual, type, IF_ICMPGE); + } + break; + } + case LessOrEqual lessOrEqual: { + var type = largerType(lessOrEqual.left().type(), lessOrEqual.right().type()); + if (type.equals(TargetType.Long)) { + generateRelationalOperator(state, lessOrEqual, type, LCMP, IFLE); + } else if (type.equals(TargetType.Float)) { + generateRelationalOperator(state, lessOrEqual, type, FCMPL, IFLE); + } else if (type.equals(TargetType.Double)) { + generateRelationalOperator(state, lessOrEqual, type, DCMPL, IFLE); + } else { + generateRelationalOperator(state, lessOrEqual, type, IF_ICMPLE); + } + break; + } + case Equal equal: { + var type = largerType(equal.left().type(), equal.right().type()); + if (type.equals(TargetType.Long)) { + generateRelationalOperator(state, equal, type, LCMP, IFEQ); + } else if (type.equals(TargetType.Float)) { + generateRelationalOperator(state, equal, type, FCMPL, IFEQ); + } else if (type.equals(TargetType.Double)) { + generateRelationalOperator(state, equal, type, DCMPL, IFEQ); + } else if (type.equals(TargetType.Char) + || type.equals(TargetType.Short) + || type.equals(TargetType.Byte) + || type.equals(TargetType.Integer) + || type.equals(TargetType.Boolean)) { + generateRelationalOperator(state, equal, type, IF_ICMPEQ); + } else { + generateRelationalOperator(state, equal, type, IF_ACMPEQ); + } + break; + } + case NotEqual notEqual: { + var type = largerType(notEqual.left().type(), notEqual.right().type()); + if (type.equals(TargetType.Long)) { + generateRelationalOperator(state, notEqual, type, LCMP, IFNE); + } else if (type.equals(TargetType.Float)) { + generateRelationalOperator(state, notEqual, type, FCMPL, IFNE); + } else if (type.equals(TargetType.Double)) { + generateRelationalOperator(state, notEqual, type, DCMPL, IFNE); + } else if (type.equals(TargetType.Char) + || type.equals(TargetType.Short) + || type.equals(TargetType.Byte) + || type.equals(TargetType.Integer)) { + generateRelationalOperator(state, notEqual, type, IF_ICMPNE); + } else { + generateRelationalOperator(state, notEqual, type, IF_ACMPNE); + } + break; + } + } + } + + private void afterIncDec(State state, TargetUnaryOp op) { + var mv = state.mv; + if (op.expr() instanceof TargetLocalVar localVar) { + mv.visitVarInsn(ASTORE, state.scope.get(localVar.name()).index); + } else if (op.expr() instanceof TargetFieldVar fieldVar) { + generate(state, fieldVar.left()); + mv.visitInsn(SWAP); + mv.visitFieldInsn(PUTFIELD, fieldVar.owner().getInternalName(), fieldVar.right(), fieldVar.type().toSignature()); + } + } + + private void generateUnaryOp(State state, TargetUnaryOp op) { + var mv = state.mv; + switch (op) { + case TargetUnaryOp.Add add: + // This literally does nothing + generate(state, add.expr()); + break; + case TargetUnaryOp.Negate negate: + generate(state, negate.expr()); + if (negate.type().equals(TargetType.Double)) + mv.visitInsn(DNEG); + else if (negate.type().equals(TargetType.Float)) + mv.visitInsn(FNEG); + else if (negate.type().equals(TargetType.Long)) + mv.visitInsn(LNEG); + else mv.visitInsn(INEG); + break; + case TargetUnaryOp.Not not: + generate(state, not.expr()); + if (not.type().equals(TargetType.Long)) { + mv.visitLdcInsn(-1L); + mv.visitInsn(LXOR); + } else { + mv.visitInsn(ICONST_M1); + mv.visitInsn(IXOR); + } + break; + case TargetUnaryOp.PreIncrement preIncrement: + generate(state, preIncrement.expr()); + if (preIncrement.type().equals(TargetType.Float)) { + mv.visitLdcInsn(1F); + mv.visitInsn(FADD); + mv.visitInsn(DUP); + } else if (preIncrement.type().equals(TargetType.Double)) { + mv.visitLdcInsn(1D); + mv.visitInsn(DADD); + mv.visitInsn(DUP2); + } else if (preIncrement.type().equals(TargetType.Long)) { + mv.visitLdcInsn(1L); + mv.visitInsn(LADD); + mv.visitInsn(DUP2); + } else { + mv.visitLdcInsn(1); + mv.visitInsn(IADD); + mv.visitInsn(DUP); + } + boxPrimitive(state, preIncrement.type()); + afterIncDec(state, preIncrement); + break; + case TargetUnaryOp.PreDecrement preDecrement: + generate(state, preDecrement.expr()); + if (preDecrement.type().equals(TargetType.Float)) { + mv.visitLdcInsn(1F); + mv.visitInsn(FSUB); + mv.visitInsn(DUP); + } else if (preDecrement.type().equals(TargetType.Double)) { + mv.visitLdcInsn(1D); + mv.visitInsn(DSUB); + mv.visitInsn(DUP2); + } else if (preDecrement.type().equals(TargetType.Long)) { + mv.visitLdcInsn(1L); + mv.visitInsn(LSUB); + mv.visitInsn(DUP2); + } else { + mv.visitLdcInsn(1); + mv.visitInsn(ISUB); + mv.visitInsn(DUP); + } + boxPrimitive(state, preDecrement.type()); + afterIncDec(state, preDecrement); + break; + case TargetUnaryOp.PostIncrement postIncrement: + generate(state, postIncrement.expr()); + if (postIncrement.type().equals(TargetType.Float)) { + mv.visitInsn(DUP); + mv.visitLdcInsn(1F); + mv.visitInsn(FADD); + } else if (postIncrement.type().equals(TargetType.Double)) { + mv.visitInsn(DUP2); + mv.visitLdcInsn(1D); + mv.visitInsn(DADD); + } else if (postIncrement.type().equals(TargetType.Long)) { + mv.visitInsn(DUP2); + mv.visitLdcInsn(1L); + mv.visitInsn(LADD); + } else { + mv.visitInsn(DUP); + mv.visitLdcInsn(1); + mv.visitInsn(IADD); + } + boxPrimitive(state, postIncrement.type()); + afterIncDec(state, postIncrement); + break; + case TargetUnaryOp.PostDecrement postDecrement: + generate(state, postDecrement.expr()); + if (postDecrement.type().equals(TargetType.Float)) { + mv.visitInsn(DUP); + mv.visitLdcInsn(1F); + mv.visitInsn(FSUB); + } else if (postDecrement.type().equals(TargetType.Double)) { + mv.visitInsn(DUP2); + mv.visitLdcInsn(1D); + mv.visitInsn(DSUB); + } else if (postDecrement.type().equals(TargetType.Long)) { + mv.visitInsn(DUP2); + mv.visitLdcInsn(1L); + mv.visitInsn(LSUB); + } else { + mv.visitInsn(DUP); + mv.visitLdcInsn(1); + mv.visitInsn(ISUB); + } + boxPrimitive(state, postDecrement.type()); + afterIncDec(state, postDecrement); + break; + } + } + + private void generateLambdaExpression(State state, TargetLambdaExpression lambda) { + var mv = state.mv; + + TargetMethod impl; + if (lambdas.containsKey(lambda)) { + impl = lambdas.get(lambda); + } else { + var name = "lambda$" + lambdaCounter++; + var parameters = new ArrayList<>(lambda.captures()); + parameters.addAll(lambda.params()); + + impl = new TargetMethod( + 0, name, Set.of(), + parameters, lambda.returnType(), lambda.block() + ); + generateMethod(impl); + lambdas.put(lambda, impl); + } + + var mt = MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class, + MethodType.class, MethodType.class, MethodHandle.class, MethodType.class); + + var bootstrap = new Handle(H_INVOKESTATIC, "java/lang/invoke/LambdaMetafactory", "metafactory", + mt.toMethodDescriptorString(), false); + var handle = new Handle( + H_INVOKEVIRTUAL, clazz.getName(), impl.name(), + impl.getDescriptor(), false + ); + + // TODO maybe make this a function? + var desugared = "("; + for (var param : lambda.params()) + desugared += "Ljava/lang/Object;"; + desugared += ")"; + if (lambda.returnType() != null) + desugared += "Ljava/lang/Object;"; + else desugared += "V"; + + var params = new ArrayList(); + params.add(new TargetRefType(clazz.qualifiedName())); + params.addAll(lambda.captures().stream().map(MethodParameter::type).toList()); + + var descriptor = TargetMethod.getDescriptor(lambda.type(), params.toArray(TargetType[]::new)); + mv.visitVarInsn(ALOAD, 0); + for (var capture : lambda.captures()) + mv.visitVarInsn(ALOAD, state.scope.get(capture.name()).index); + + mv.visitInvokeDynamicInsn("apply", descriptor, + bootstrap, Type.getType(desugared), handle, + Type.getType(TargetMethod.getDescriptor(impl.returnType(), lambda.params().stream().map(MethodParameter::type).toArray(TargetType[]::new))) + ); + } + + private void generate(State state, TargetExpression expr) { + var mv = state.mv; + switch (expr) { + case TargetClassName className: + break; // NOP + case TargetBlock block: { + var localCounter = state.localCounter; + state.enterScope(); + for (var e : block.statements()) { + generate(state, e); + if (e instanceof TargetMethodCall) { + if (e.type() != null) mv.visitInsn(POP); + } else if (e instanceof TargetStatementExpression) { + mv.visitInsn(POP); + } + } + state.exitScope(); + state.localCounter = localCounter; + break; + } + case TargetCast cast: + generate(state, cast.expr()); + convertTo(state, cast.expr().type(), cast.type()); + break; + case TargetInstanceOf instanceOf: + mv.visitTypeInsn(INSTANCEOF, instanceOf.right().getInternalName()); + break; + case TargetLiteral literal: + switch (literal) { + case IntLiteral intLiteral: + mv.visitLdcInsn(intLiteral.value()); + break; + case FloatLiteral floatLiteral: + mv.visitLdcInsn(floatLiteral.value()); + break; + case LongLiteral longLiteral: + mv.visitLdcInsn(longLiteral.value()); + break; + case StringLiteral stringLiteral: + mv.visitLdcInsn(stringLiteral.value()); + break; + case CharLiteral charLiteral: + mv.visitIntInsn(BIPUSH, charLiteral.value()); + break; + case DoubleLiteral doubleLiteral: + mv.visitLdcInsn(doubleLiteral.value()); + break; + case BooleanLiteral booleanLiteral: + if (booleanLiteral.value()) { + mv.visitInsn(ICONST_1); + } else { + mv.visitInsn(ICONST_0); + } + break; + } + break; + case TargetVarDecl varDecl: { + var local = state.createVariable(varDecl.name(), varDecl.varType()); + if (varDecl.value() != null) { + generate(state, varDecl.value()); + boxPrimitive(state, varDecl.varType()); + mv.visitVarInsn(ASTORE, local.index()); + } + break; + } + case TargetBinaryOp op: + generateBinaryOp(state, op); + break; + case TargetUnaryOp op: + generateUnaryOp(state, op); + break; + case TargetAssign assign: { + switch (assign.left()) { + case TargetLocalVar localVar: { + generate(state, assign.right()); + boxPrimitive(state, assign.right().type()); + var local = state.scope.get(localVar.name()); + mv.visitInsn(DUP); + mv.visitVarInsn(ASTORE, local.index()); + break; + } + case TargetFieldVar dot: { + generate(state, dot.left()); + generate(state, assign.right()); + boxPrimitive(state, assign.right().type()); + if (dot.isStatic()) + mv.visitInsn(DUP); + else mv.visitInsn(DUP_X1); + mv.visitFieldInsn(dot.isStatic() ? PUTSTATIC : PUTFIELD, dot.owner().getInternalName(), dot.right(), dot.type().toSignature()); + break; + } + default: + throw new CodeGenException("Invalid assignment"); + } + break; + } + case TargetLocalVar localVar: { + LocalVar local = state.scope.get(localVar.name()); + mv.visitVarInsn(ALOAD, local.index()); + unboxPrimitive(state, local.type()); + break; + } + case TargetFieldVar dot: { + if (!dot.isStatic()) + generate(state, dot.left()); + mv.visitFieldInsn(dot.isStatic() ? GETSTATIC : GETFIELD, dot.left().type().getInternalName(), dot.right(), dot.type().toSignature()); + unboxPrimitive(state, dot.type()); + break; + } + case TargetFor _for: { + state.enterScope(); + var localCounter = state.localCounter; + if (_for.init() != null) + generate(state, _for.init()); + Label start = new Label(); + Label end = new Label(); + mv.visitLabel(start); + if (_for.termination() != null) + generate(state, _for.termination()); + mv.visitJumpInsn(IFEQ, end); + generate(state, _for.body()); + if (_for.increment() != null) { + generate(state, _for.increment()); + if (_for.increment().type() != null) { + mv.visitInsn(POP); + } + } + mv.visitJumpInsn(GOTO, start); + mv.visitLabel(end); + state.exitScope(); + state.localCounter = localCounter; + break; + } + case TargetWhile _while: { + Label start = new Label(); + Label end = new Label(); + mv.visitLabel(start); + generate(state, _while.cond()); + mv.visitJumpInsn(IFEQ, end); + generate(state, _while.body()); + mv.visitJumpInsn(GOTO, start); + mv.visitLabel(end); + break; + } + case TargetIf _if: { + generate(state, _if.cond()); + Label _else = new Label(); + Label end = new Label(); + mv.visitJumpInsn(IFEQ, _else); + generate(state, _if.if_body()); + mv.visitJumpInsn(GOTO, end); + mv.visitLabel(_else); + if (_if.else_body() != null) { + generate(state, _if.else_body()); + } + mv.visitLabel(end); + break; + } + case TargetReturn ret: { + if (ret.expression() != null) { + generate(state, ret.expression()); + boxPrimitive(state, ret.expression().type()); + mv.visitInsn(ARETURN); + } else mv.visitInsn(RETURN); + break; + } + case TargetThis _this: { + mv.visitVarInsn(ALOAD, 0); + break; + } + case TargetSuper _super: { + mv.visitVarInsn(ALOAD, 0); + break; + } + case TargetMethodCall call: { + generate(state, call.expr()); + for (var i = 0; i < call.args().size(); i++) { + var e = call.args().get(i); + var arg = call.parameterTypes().get(i); + generate(state, e); + if (!(arg instanceof TargetPrimitiveType)) + boxPrimitive(state, e.type()); + } + var descriptor = call.getDescriptor(); + if (call.owner() instanceof TargetFunNType) // Decay FunN + descriptor = TargetMethod.getDescriptor( + call.returnType() == null ? null : TargetType.Object, + call.parameterTypes().stream().map(x -> TargetType.Object).toArray(TargetType[]::new) + ); + + mv.visitMethodInsn(call.isInterface() ? INVOKEINTERFACE : call.isStatic() ? INVOKESTATIC: call.name().equals("") ? INVOKESPECIAL : INVOKEVIRTUAL, + call.owner().getInternalName(), call.name(), descriptor, call.isInterface()); + + if (call.returnType() != null && !(call.returnType() instanceof TargetPrimitiveType)) { + if (!call.returnType().equals(call.type()) && !(call.type() instanceof TargetGenericType)) + mv.visitTypeInsn(CHECKCAST, call.type().getInternalName()); + unboxPrimitive(state, call.type()); + } + break; + } + case TargetLambdaExpression lambda: + generateLambdaExpression(state, lambda); + break; + case TargetNew _new: { + mv.visitTypeInsn(NEW, _new.type().getInternalName()); + mv.visitInsn(DUP); + for (TargetExpression e : _new.params()) { + generate(state, e); + boxPrimitive(state, e.type()); + } + mv.visitMethodInsn(INVOKESPECIAL, _new.type().getInternalName(), "", _new.getDescriptor(), false); + break; + } + default: + throw new CodeGenException("Unexpected value: " + expr); + } + } + + private void generateField(TargetField field) { + cw.visitField(field.access() | ACC_PUBLIC, field.name(), field.type().toSignature(), field.type().toGenericSignature(), null); + } + + private void generateConstructor(TargetConstructor constructor) { + MethodVisitor mv = cw.visitMethod(constructor.access() | ACC_PUBLIC, "", constructor.getDescriptor(), constructor.getSignature(), null); + mv.visitCode(); + var state = new State(mv, 1); + for (var param: constructor.parameters()) + state.createVariable(param.name(), param.type()); + + var stmts = constructor.block().statements(); + generate(state, stmts.get(0)); + if (constructor.fieldInitializer() != null) { + var stmts2 = constructor.fieldInitializer().statements(); + for (var i = 1; i < stmts2.size(); i++) { + generate(state, stmts2.get(i)); + } + } + for (var i = 1; i < stmts.size(); i++) + generate(state, stmts.get(i)); + + mv.visitInsn(RETURN); + mv.visitMaxs(0, 0); + mv.visitEnd(); + } + + private void generateMethod(TargetMethod method) { + // TODO The older codegen has set ACC_PUBLIC for all methods, good for testing but bad for everything else + MethodVisitor mv = cw.visitMethod(method.access() | ACC_PUBLIC, method.name(), method.getDescriptor(), method.getSignature(), null); + mv.visitCode(); + var state = new State(mv, method.isStatic() ? 0 : 1); + for (var param: method.parameters()) + state.createVariable(param.name(), param.type()); + generate(state, method.block()); + if (method.returnType() == null) + mv.visitInsn(RETURN); + mv.visitMaxs(0, 0); + mv.visitEnd(); + } + + private static String generateSignature(TargetClass clazz) { + String ret = "<"; + for (var generic : clazz.generics()) { + ret += generic.name() + ":" + generic.bound().toGenericSignature(); + } + ret += ">"; + ret += clazz.superType().toGenericSignature(); + + return ret; + } + + public byte[] generate() { + cw.visit(V1_8, clazz.modifiers() | ACC_PUBLIC, clazz.qualifiedName(), + generateSignature(clazz), clazz.superType() != null ? clazz.superType().getInternalName(): "java/lang/Object", + clazz.implementingInterfaces().stream().map(TargetType::toSignature).toArray(String[]::new) + ); + clazz.fields().forEach(this::generateField); + clazz.constructors().forEach(this::generateConstructor); + clazz.methods().forEach(this::generateMethod); + + cw.visitEnd(); + return cw.toByteArray(); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java b/app/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java new file mode 100644 index 00000000..61be1e8c --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/generate/ASTToTargetAST.java @@ -0,0 +1,727 @@ +package de.dhbwstuttgart.target.generate; + +import com.google.j2objc.annotations.LoopTranslation; +import de.dhbwstuttgart.bytecode.funN.FunNGenerator; +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.parser.NullToken; +import de.dhbwstuttgart.syntaxtree.*; +import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; +import de.dhbwstuttgart.syntaxtree.statement.*; +import de.dhbwstuttgart.syntaxtree.type.*; +import de.dhbwstuttgart.target.tree.*; +import de.dhbwstuttgart.target.tree.expression.TargetBlock; +import de.dhbwstuttgart.target.tree.expression.TargetExpression; +import de.dhbwstuttgart.target.tree.type.*; +import de.dhbwstuttgart.typeinference.result.*; +import de.dhbwstuttgart.target.ByteArrayClassLoader; + +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class ASTToTargetAST { + + static RefType OBJECT = ASTFactory.createObjectType(); // TODO It would be better if I could call this directly but the hashcode seems to change + + protected List all; + protected Sigma sigma; + protected ClassOrInterface currentClass; // TODO This is only needed because of SuperCall, maybe there's a better way? + + private class Sigma { + Map>> computedGenericsOfMethods = new HashMap<>(); + Map> usedTPHsOfMethods = new HashMap<>(); + Map>> computedGenericsOfClasses = new HashMap<>(); + + Set simplifiedConstraints = new HashSet<>(); + Map concreteTypes = new HashMap<>(); + Map equality = new HashMap<>(); + + Sigma(ResultSet constraints) { + ASTToTargetAST.this.sigma = this; + + Set> equalitySet = new HashSet<>(); + Map> unified = new HashMap<>(); + + for (var constraint : constraints.results) { + if (constraint instanceof PairTPHEqualTPH p) { + if (unified.containsKey(p.getLeft())) { + var equals = unified.get(p.getLeft()); + equals.add(p.getRight()); + unified.put(p.getLeft(), equals); + } else if (unified.containsKey(p.getRight())) { + var equals = unified.get(p.getRight()); + equals.add(p.getLeft()); + unified.put(p.getRight(), equals); + } else { + List equals = new ArrayList<>(); + equals.add(p.getLeft()); + equals.add(p.getRight()); + unified.put(p.getLeft(), equals); + unified.put(p.getRight(), equals); + equalitySet.add(equals); + } + } + } + + for (var constraint : constraints.results) { + if (constraint instanceof PairTPHsmallerTPH p) { + var left = p.left; + var right = p.right; + if (unified.containsKey(left)) + left = unified.get(left).get(0); + if (unified.containsKey(right)) + right = unified.get(right).get(0); + + simplifiedConstraints.add(new PairTPHsmallerTPH(left, right)); + } + } + System.out.println("Simplified constraints: " + simplifiedConstraints); + + for (var equality : equalitySet) { + var first = equality.get(0); + for (var i = 1; i < equality.size(); i++) + this.equality.put(equality.get(i), first); + } + + for (var constraint : constraints.results) { + if (constraint instanceof PairTPHequalRefTypeOrWildcardType p) { + concreteTypes.put(this.equality.getOrDefault(p.left, p.left), p.right); + } + } + } + + void findTypeVariables(RefTypeOrTPHOrWildcardOrGeneric type, Set typeVariables) { + if (type instanceof TypePlaceholder tph) { + tph = equality.getOrDefault(tph, tph); + if (concreteTypes.containsKey(tph)) { + findTypeVariables(concreteTypes.get(tph), typeVariables); + return; + } + typeVariables.add(tph); + } else if (type instanceof RefType refType) { + for (var t : refType.getParaList()) + findTypeVariables(t, typeVariables); + } + } + + boolean hasBound(TypePlaceholder name, Set> generics) { + return generics.stream().anyMatch(generic -> generic.getLeft().equals(name)); + } + + boolean containsRelation(Set> result, PairTPHsmallerTPH pair) { + // Check if both the right and the left are already part of a relation + var containsLeft = false; + for (var pair2 : result) { + if (pair2.getLeft().equals(pair.left)) { + containsLeft = true; + break; + } + } + var containsRight = false; + for (var pair2 : result) { + if (pair2.getRight().equals(pair.right)) { + containsRight = true; + break; + } + } + return containsLeft && containsRight; + } + + // Family of generated Generics + Set> generics(ClassOrInterface owner, Method method) { + if (computedGenericsOfMethods.containsKey(method)) + return computedGenericsOfMethods.get(method); + + Set> result = new HashSet<>(); + computedGenericsOfMethods.put(method, result); + + var genericsOfClass = generics(owner); + var simplifiedConstraints = new HashSet<>(this.simplifiedConstraints); + + HashSet typeVariables = new HashSet<>(); + HashSet typeVariablesOfFields = new HashSet<>(); + HashSet allTypeVariables = new HashSet<>(); + + for (var field : owner.getFieldDecl()) { + findTypeVariables(field.getType(), typeVariablesOfFields); + } + + //findTypeVariables(method.getReturnType(), typeVariables); + for (var arg : method.getParameterList().getFormalparalist()) { + findTypeVariables(arg.getType(), typeVariables); + } + + method.block.accept(new TracingStatementVisitor() { + @Override + public void visit(LocalVarDecl localVarDecl) { + findTypeVariables(localVarDecl.getType(), typeVariables); + } + + @Override + public void visit(MethodCall methodCall) { + super.visit(methodCall); + findTypeVariables(methodCall.getType(), typeVariables); + } + + @Override + public void visit(Assign assign) {} + }); + + // Type variables with bounds that are also type variables of the method + for (var typeVariable : new HashSet<>(typeVariables)) { + for (var pair : simplifiedConstraints) { + if (pair.left.equals(typeVariable) && typeVariables.contains(pair.right)) { + result.add(new PairTPHsmallerTPH(pair.left, equality.getOrDefault(pair.right, pair.right))); + typeVariables.add(pair.right); + } + } + } + + var visitedMethods = new HashSet(); + method.block.accept(new TracingStatementVisitor() { + @Override + public void visit(MethodCall methodCall) { + super.visit(methodCall); + + if (methodCall.receiver instanceof ExpressionReceiver expressionReceiver) { + if (expressionReceiver.expr instanceof This) { + var optMethod = findMethod(owner, methodCall.name, methodCall.getArgumentList()); + if (optMethod.isEmpty()) return; + var method = optMethod.get(); + if (visitedMethods.contains(method)) return; + visitedMethods.add(method); + + var generics = generics(owner, method); + Set> all = new HashSet<>(generics); + + // Reflexive and Transitive closure + HashSet> toAdd = new HashSet<>(); + int sizeBefore; + do { + sizeBefore = all.size(); + toAdd.clear(); + for (var g1 : all) { + for (var g2 : all) { + if (g1 instanceof PairTPHsmallerTPH pair) { + if (g2.getLeft().equals(pair.getLeft()) && generics.stream().anyMatch(generic -> generic.getLeft().equals(pair.getRight()))) + toAdd.add(new PairTPHsmallerTPH((TypePlaceholder) g1.getLeft(), (TypePlaceholder) g2.getRight())); + } + } + } + all.addAll(toAdd); + } while (sizeBefore < all.size()); + for (var generic : all) { + toAdd.add(new PairTPHsmallerTPH((TypePlaceholder) generic.getLeft(), (TypePlaceholder) generic.getLeft())); + } + all.addAll(toAdd); + + HashSet newPairs = new HashSet<>(); + // Loop from hell + outer: + for (var tph : typeVariables) { + for (var generic : all) { + if (!(generic.getRight() instanceof TypePlaceholder type)) + continue; + + for (var pair : simplifiedConstraints) { + if (!(pair.left.equals(tph) && pair.right.equals(generic.getLeft()))) + continue; + + for (var tph2 : typeVariables) { + for (var pair2 : simplifiedConstraints) { + if (!(pair2.right.equals(tph2) && pair2.left.equals(type))) + continue; + if (tph.equals(tph2)) continue; + + var newPair = new PairTPHsmallerTPH(tph, tph2); + newPairs.add(newPair); + + if (!containsRelation(result, newPair)) + result.add(newPair); + continue outer; + } + } + } + } + } + simplifiedConstraints.addAll(newPairs); + } + } + } + }); + + // Type variables with bounds that are also type variables of fields + for (var typeVariable : new HashSet<>(typeVariables)) { + for (var pair : simplifiedConstraints) { + if (pair.left.equals(typeVariable) && typeVariablesOfFields.contains(pair.right)) { + result.add(new PairTPHsmallerTPH(pair.left, equality.getOrDefault(pair.right, pair.right))); + typeVariables.add(pair.right); + } + } + } + + // All unbounded type variables + outer: + for (var typeVariable : typeVariables) { + for (var pair : simplifiedConstraints) { + if (pair.left.equals(typeVariable) && typeVariables.contains(pair.right)) + continue outer; + } + if (!hasBound(typeVariable, genericsOfClass)) + result.add(new PairTPHequalRefTypeOrWildcardType(typeVariable, OBJECT)); + } + + // All unbounded bounds + outer: + for (var pair : simplifiedConstraints) { + for (var pair2 : simplifiedConstraints) { + if (pair.right.equals(pair2.left)) + continue outer; + } + if (!hasBound(pair.right, genericsOfClass) && typeVariables.contains(pair.right)) + result.add(new PairTPHequalRefTypeOrWildcardType(pair.right, OBJECT)); + } + + eliminateCyclesAndInfima(result); + System.out.println(method.name + ": " + result); + + Set allUsedTPHs = new HashSet<>(); + allUsedTPHs.addAll(typeVariables); + allUsedTPHs.addAll(typeVariablesOfFields); + usedTPHsOfMethods.put(method, allUsedTPHs); + + return result; + } + + void findAllBounds(RefTypeOrTPHOrWildcardOrGeneric type, Set> generics) { + if (type instanceof TypePlaceholder tph) { + tph = equality.getOrDefault(tph, tph); + + var concreteType = concreteTypes.get(tph); + if (concreteType != null) { + findAllBounds(concreteType, generics); + return; + } + + for (var rsp : simplifiedConstraints) { + var left = equality.getOrDefault(rsp.left, rsp.left); + var right = equality.getOrDefault(rsp.right, rsp.right); + if (left.equals(tph)) { + var pair = new PairTPHsmallerTPH(tph, right); + if (!generics.contains(pair)) { + generics.add(pair); + findAllBounds(right, generics); + } + return; + } + } + generics.add(new PairTPHequalRefTypeOrWildcardType(tph, OBJECT)); + } else if (type instanceof RefType refType) { + refType.getParaList().forEach(t -> findAllBounds(t, generics)); + } + } + + Set> generics(ClassOrInterface classOrInterface) { + if (computedGenericsOfClasses.containsKey(classOrInterface)) + return computedGenericsOfClasses.get(classOrInterface); + + Set> result = new HashSet<>(); + for (var field : classOrInterface.getFieldDecl()) { + findAllBounds(field.getType(), result); + } + computedGenericsOfClasses.put(classOrInterface, result); + eliminateCyclesAndInfima(result); + eliminateInnerTypeVariables(classOrInterface, result); + equalizeTypeVariables(result); + + System.out.println("Class " + classOrInterface.getClassName().getClassName() + ": " + result); + return result; + } + + void equalizeTypeVariables(Set> input) { + for (var pair : new HashSet<>(input)) { + if (pair instanceof PairTPHsmallerTPH ptph) { + if (ptph.left.getVariance() == 1 && ptph.right.getVariance() == -1) { + equality.put(ptph.left, ptph.right); + input.remove(ptph); + for (var pair2 : new HashSet<>(input)) { + if (pair2 instanceof PairTPHsmallerTPH ptph2 && ptph2.right.equals(ptph.left)) { + input.remove(pair2); + input.add(new PairTPHsmallerTPH(ptph2.left, ptph.right)); + } + } + } + } + } + } + + void findTphs(RefTypeOrTPHOrWildcardOrGeneric type, Set tphs) { + if (type instanceof RefType refType) { + refType.getParaList().forEach(t -> findTphs(t, tphs)); + } else if (type instanceof TypePlaceholder tph) { + tph = equality.getOrDefault(tph, tph); + var concreteType = concreteTypes.get(tph); + if (concreteType != null) { + findTphs(concreteType, tphs); + return; + } + tphs.add(tph); + } + } + + void eliminateInnerTypeVariables(ClassOrInterface classOrInterface, Set> input) { + Set referenced = new HashSet<>(); + for (var field : classOrInterface.getFieldDecl()) { + findTphs(field.getType(), referenced); + } + for (var method : classOrInterface.getMethods()) { + generics(classOrInterface, method); + referenced.addAll(usedTPHsOfMethods.get(method)); + } + + var oldInput = new HashSet<>(input); + for (var pair : oldInput) { + if (!referenced.contains(pair.getLeft())) { + input.remove(pair); + for (var pair2 : oldInput) { + if (pair2.getRight().equals(pair.getLeft())) { + input.remove(pair2); + if (pair instanceof PairTPHsmallerTPH) + input.add(new PairTPHsmallerTPH((TypePlaceholder) pair2.getLeft(), (TypePlaceholder) pair.getRight())); + else + input.add(new PairTPHequalRefTypeOrWildcardType((TypePlaceholder) pair2.getLeft(), pair.getRight())); + } + } + } + } + } + + void eliminateCyclesAndInfima(Set> input) { + // Eliminate cycles + var cycles = findCycles(input); + for (var cycle : cycles) { + var newTph = TypePlaceholder.fresh(new NullToken()); + input.add(new PairTPHequalRefTypeOrWildcardType(newTph, OBJECT)); + cycle.add(cycle.get(0)); // Make it a complete cycle + for (var i = 0; i < cycle.size() - 1; i++) { + var left = cycle.get(i); + var right = cycle.get(i + 1); + var pair = new PairTPHsmallerTPH(left, right); + input.remove(pair); + equality.put(left, newTph); + } + } + // Eliminate infima + var foundInfima = false; + do { + foundInfima = false; + for (var constraint : new HashSet<>(input)) { + var left = (TypePlaceholder) constraint.getLeft(); + Set infima = new HashSet<>(); + for (var pair : input) { + if (pair instanceof PairTPHsmallerTPH stph) + if (pair.getLeft().equals(constraint.getLeft())) + infima.add(stph); + } + if (infima.size() > 1) { + foundInfima = true; + var newTph = TypePlaceholder.fresh(new NullToken()); + input.add(new PairTPHsmallerTPH(left, newTph)); + input.removeAll(infima); + for (var infimum : infima) { + equality.put(infimum.right, newTph); + new HashSet<>(input).forEach(pair -> { + if (pair.getLeft().equals(infimum.right)) { + input.remove(pair); + if (pair instanceof PairTPHsmallerTPH stph) { + input.add(new PairTPHsmallerTPH(newTph, stph.right)); + } else if (pair instanceof PairTPHequalRefTypeOrWildcardType rtph) { + input.add(new PairTPHequalRefTypeOrWildcardType(newTph, rtph.getRight())); + } + } else if (pair.getRight().equals(infimum.right)) { + input.remove(pair); + if (pair instanceof PairTPHsmallerTPH stph) { + input.add(new PairTPHsmallerTPH(stph.left, newTph)); + } + } + }); + } + } + } + } while (foundInfima); + } + + TargetType get(TypePlaceholder tph) { + if (equality.containsKey(tph)) { + return get(equality.get(tph)); + } + var type = concreteTypes.get(tph); + if (type == null) return new TargetGenericType(tph.getName()); + return convert(type); + } + } + + protected ByteArrayClassLoader classLoader; + protected SourceFile sourceFile; + + public ASTToTargetAST(List resultSets) { + this(resultSets, null, new ByteArrayClassLoader()); + } + + public ASTToTargetAST(List resultSets, SourceFile sourceFile, ByteArrayClassLoader classLoader) { + this.classLoader = classLoader; + this.sourceFile = sourceFile; + + all = new ArrayList<>(); + for (var set : resultSets) { + all.add(new Sigma(set)); + } + this.sigma = all.get(0); + } + + static Set allNodes(Set> input) { + return input.stream() + .filter(pair -> pair instanceof PairTPHsmallerTPH) + .flatMap(pair -> Stream.of((TypePlaceholder) pair.getLeft(), (TypePlaceholder) pair.getRight())).collect(Collectors.toSet()); + } + + static Set outgoingEdgesOf(TypePlaceholder tph, Set> input) { + return input.stream() + .filter(pair -> pair instanceof PairTPHsmallerTPH && pair.getLeft().equals(tph)) + .map(pair -> (TypePlaceholder) pair.getRight()).collect(Collectors.toSet()); + } + + static boolean containsEdge(TypePlaceholder a, TypePlaceholder b, Set> input) { + return input.stream().anyMatch(pair -> pair.getLeft().equals(a) && pair.getRight().equals(b)); + } + + // Tiernan simple cycles algorithm + // Adapted from https://github.com/jgrapht/jgrapht/blob/master/jgrapht-core/src/main/java/org/jgrapht/alg/cycle/TiernanSimpleCycles.java + static Set> findCycles(Set> input) { + Map indices = new HashMap<>(); + List path = new ArrayList<>(); + Set pathSet = new HashSet<>(); + Map> blocked = new HashMap<>(); + Set> cycles = new HashSet<>(); + + int index = 0; + for (var tph : allNodes(input)) { + blocked.put(tph, new HashSet<>()); + indices.put(tph, index++); + } + + var vertexIterator = allNodes(input).iterator(); + if (!vertexIterator.hasNext()) return cycles; + + TypePlaceholder startOfPath = null; + TypePlaceholder endOfPath = vertexIterator.next(); + TypePlaceholder temp = null; + int endIndex = 0; + boolean extensionFound = false; + path.add(endOfPath); + pathSet.add(endOfPath); + + while (true) { + do { + extensionFound = false; + for (TypePlaceholder n : outgoingEdgesOf(endOfPath, input)) { + int cmp = indices.get(n).compareTo(indices.get(path.get(0))); + if ((cmp > 0) && !pathSet.contains(n) && !blocked.get(endOfPath).contains(n)) { + path.add(n); + pathSet.add(n); + endOfPath = n; + extensionFound = true; + break; + } + } + } while (extensionFound); + + startOfPath = path.get(0); + if (containsEdge(endOfPath, startOfPath, input)) { + List cycle = new ArrayList<>(path); + cycles.add(cycle); + } + if (path.size() > 1) { + blocked.get(endOfPath).clear(); + endIndex = path.size() - 1; + path.remove(endIndex); + pathSet.remove(endOfPath); + --endIndex; + temp = endOfPath; + endOfPath = path.get(endIndex); + blocked.get(endOfPath).add(temp); + continue; + } + if (vertexIterator.hasNext()) { + path.clear(); + pathSet.clear(); + endOfPath = vertexIterator.next(); + path.add(endOfPath); + pathSet.add(endOfPath); + for (TypePlaceholder tph : blocked.keySet()) { + blocked.get(tph).clear(); + } + continue; + } + break; + } + return cycles; + } + + Optional findMethod(ClassOrInterface owner, String name, ArgumentList argumentList) { + return owner.getMethods().stream().filter( + m -> m.name.equals(name) && parameterEquals(m.getParameterList(), argumentList) + ).findFirst(); + } + + boolean parameterEquals(ParameterList parameterList, ArgumentList argumentList) { + var pars = parameterList.getFormalparalist(); + var arguments = argumentList.getArguments(); + if (pars.size() != arguments.size()) + return false; + + for (var i = 0; i < pars.size(); i++) { + var type1 = convert(pars.get(i).getType()); + var type2 = convert(arguments.get(i).getType()); + if (type2 instanceof TargetGenericType && type1 instanceof TargetGenericType) + return true; + if (!type1.equals(type2)) return false; + } + + return true; + } + + Set convert(Set> result) { + return result.stream().map(p -> { + if (p instanceof PairTPHsmallerTPH pair) { + return new TargetGeneric(pair.left.getName(), new TargetGenericType(pair.right.getName())); + } else if (p instanceof PairTPHequalRefTypeOrWildcardType pair) { + return new TargetGeneric(pair.left.getName(), convert(pair.right)); + } else { + throw new IllegalArgumentException(); + } + }).collect(Collectors.toSet()); + } + + public TargetClass convert(ClassOrInterface input) { + currentClass = input; + TargetBlock fieldInitializer = null; + if (input.getfieldInitializations().isPresent()) + fieldInitializer = convert(input.getfieldInitializations().get().block); + TargetBlock finalFieldInitializer = fieldInitializer; + + return new TargetClass(input.getModifiers(), input.getClassName().toString(), convert(input.getSuperClass()), + convert(sigma.generics(input)), + input.getSuperInterfaces().stream().map(this::convert).toList(), + input.getConstructors().stream().map(constructor -> this.convert(constructor, finalFieldInitializer)).flatMap(List::stream).toList(), + input.getFieldDecl().stream().map(this::convert).toList(), + input.getMethods().stream().map(this::convert).flatMap(List::stream).toList() + ); + } + + private List convert(ParameterList input) { + return input.getFormalparalist().stream() + .map(param -> new MethodParameter(convert(param.getType()), param.getName())).toList(); + } + + private List convert(Constructor input, TargetBlock fieldInitializer) { + sigma = all.get(0); + List result = new ArrayList<>(); + Set> parameterSet = new HashSet<>(); + + for (var s : all) { + sigma = s; + var generics = sigma.generics(currentClass, input); + List params = convert(input.getParameterList()); + if (parameterSet.stream().noneMatch(p -> p.equals(params))) { + result.add(new TargetConstructor(input.modifier, convert(generics), params, convert(input.block), fieldInitializer)); + parameterSet.add(params); + } + } + + return result; + } + + private List convert(Method input) { + sigma = all.get(0); + List result = new ArrayList<>(); + Set> parameterSet = new HashSet<>(); + + for (var s : all) { + sigma = s; + var generics = sigma.generics(currentClass, input); + List params = convert(input.getParameterList()); + if (parameterSet.stream().noneMatch(p -> p.equals(params))) { + result.add(new TargetMethod( + input.modifier, + input.name, convert(generics), params, + convert(input.getReturnType()), + convert(input.block) + )); + parameterSet.add(params); + } + } + + return result; + } + + protected TargetBlock convert(Block block) { + return new TargetBlock(block.statements.stream().map(this::convert).toList()); + } + + protected TargetExpression convert(Expression expr) { + var converter = new StatementToTargetExpression(this); + expr.accept(converter); + return converter.result; + } + + private TargetField convert(Field input) { + return new TargetField( + input.modifier, + convert(input.getType()), + input.getName() + ); + } + + private final Set usedFunN = new HashSet<>(); + + protected TargetType convert(RefTypeOrTPHOrWildcardOrGeneric input) { + return input.acceptTV(new TypeVisitor<>() { + @Override + public TargetType visit(RefType refType) { + var name = refType.getName().toString(); + if (name.equals("void")) return null; + + var params = refType.getParaList().stream().map(ASTToTargetAST.this::convert).toList(); + if (name.matches("Fun\\d\\$\\$")) { // TODO This seems like a bad idea + if (!usedFunN.contains(params.size() - 1)) { + usedFunN.add(params.size() - 1); + classLoader.loadClass(FunNGenerator.getInstance().generateSuperBytecode(params.size() - 1)); + } + return new TargetFunNType(params.size() - 1, params); + } + return new TargetRefType(name, params); + } + + @Override + public TargetType visit(SuperWildcardType superWildcardType) { + return new TargetSuperWildcard(convert(superWildcardType.getInnerType())); + } + + @Override + public TargetType visit(TypePlaceholder typePlaceholder) { + return sigma.get(typePlaceholder); + } + + @Override + public TargetType visit(ExtendsWildcardType extendsWildcardType) { + return new TargetExtendsWildcard(convert(extendsWildcardType.getInnerType())); + } + + @Override + public TargetType visit(GenericRefType genericRefType) { + return new TargetGenericType(genericRefType.getParsedName()); + } + }); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java b/app/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java new file mode 100644 index 00000000..8ca6e052 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java @@ -0,0 +1,358 @@ +package de.dhbwstuttgart.target.generate; + +import de.dhbwstuttgart.exceptions.NotImplementedException; +import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; +import de.dhbwstuttgart.parser.scope.JavaClassName; +import de.dhbwstuttgart.syntaxtree.ClassOrInterface; +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.statement.*; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.target.tree.MethodParameter; +import de.dhbwstuttgart.target.tree.expression.*; +import de.dhbwstuttgart.target.tree.type.TargetFunNType; +import de.dhbwstuttgart.target.tree.type.TargetRefType; +import de.dhbwstuttgart.target.tree.type.TargetSpecializedType; +import de.dhbwstuttgart.target.tree.type.TargetType; + +import java.lang.reflect.Method; +import java.util.*; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +public class StatementToTargetExpression implements StatementVisitor { + + public StatementToTargetExpression(ASTToTargetAST converter) { + this.converter = converter; + } + + public TargetExpression result; + private final ASTToTargetAST converter; + + @Override + public void visit(ArgumentList argumentList) { + throw new NotImplementedException(); + } + + @Override + public void visit(LambdaExpression lambdaExpression) { + var parameters = StreamSupport + .stream(lambdaExpression.params.spliterator(), false) + .map(p -> new MethodParameter(converter.convert(p.getType()), p.getName())) + .toList(); + + List captures = new ArrayList<>(); + lambdaExpression.methodBody.accept(new TracingStatementVisitor() { + // TODO The same mechanism is implemented in Codegen, maybe use it from there? + final Stack> localVariables = new Stack<>(); + { localVariables.push(new HashSet<>()); } + + boolean hasLocalVar(String name) { + for (var localVariables : this.localVariables) { + if (localVariables.contains(name)) return true; + } + return false; + } + + @Override + public void visit(Block block) { + localVariables.push(new HashSet<>()); + super.visit(block); + localVariables.pop(); + } + + @Override + public void visit(LocalVar localVar) { + super.visit(localVar); + var capture = new MethodParameter(converter.convert(localVar.getType()), localVar.name); + if (!hasLocalVar(localVar.name) && !parameters.contains(capture) && !captures.contains(capture)) + captures.add(capture); + } + + @Override + public void visit(LocalVarDecl varDecl) { + var localVariables = this.localVariables.peek(); + localVariables.add(varDecl.getName()); + } + + @Override + public void visit(LambdaExpression lambda) {} // Don't look at lambda expressions + }); + + result = new TargetLambdaExpression( + new TargetFunNType(parameters.size(), parameters.stream().map(MethodParameter::type).toList()), + captures, parameters, converter.convert(lambdaExpression.getReturnType()), converter.convert(lambdaExpression.methodBody) + ); + } + + @Override + public void visit(Assign assign) { + TargetExpression left; + if (assign.lefSide instanceof AssignToLocal) { + left = converter.convert(((AssignToLocal) assign.lefSide).localVar); + } else { + left = converter.convert(((AssignToField) assign.lefSide).field); + } + + result = new TargetAssign(converter.convert(assign.getType()), left, converter.convert(assign.rightSide)); + } + + @Override + public void visit(BinaryExpr binary) { + result = switch (binary.operation) { + case ADD -> new TargetBinaryOp.Add(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); + case SUB -> new TargetBinaryOp.Sub(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); + case MUL -> new TargetBinaryOp.Mul(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); + case MOD -> new TargetBinaryOp.Rem(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); + case AND -> new TargetBinaryOp.And(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); + case OR -> new TargetBinaryOp.Or(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); + case DIV -> new TargetBinaryOp.Div(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); + case LESSTHAN -> new TargetBinaryOp.Less(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); + case BIGGERTHAN -> new TargetBinaryOp.Greater(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); + case LESSEQUAL -> new TargetBinaryOp.LessOrEqual(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); + case BIGGEREQUAL -> new TargetBinaryOp.GreaterOrEqual(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); + case EQUAL -> new TargetBinaryOp.Equal(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); + case NOTEQUAL -> new TargetBinaryOp.NotEqual(converter.convert(binary.getType()), converter.convert(binary.lexpr), converter.convert(binary.rexpr)); + }; + } + + @Override + public void visit(Block block) { + result = converter.convert(block); + } + + @Override + public void visit(CastExpr castExpr) { + result = new TargetCast(converter.convert(castExpr.getType()), converter.convert(castExpr.expr)); + } + + @Override + public void visit(EmptyStmt emptyStmt) { + result = null; + } + + @Override + public void visit(FieldVar fieldVar) { + result = new TargetFieldVar( + converter.convert(fieldVar.getType()), + converter.convert(fieldVar.receiver.getType()), + false, + converter.convert(fieldVar.receiver), + fieldVar.fieldVarName); + } + + @Override + public void visit(ForStmt forStmt) { + // TODO Doesn't seem to be fully implemented yet + throw new NotImplementedException(); + } + + @Override + public void visit(IfStmt ifStmt) { + result = new TargetIf( + converter.convert(ifStmt.expr), + converter.convert(ifStmt.then_block), + converter.convert(ifStmt.else_block) + ); + } + + @Override + public void visit(InstanceOf instanceOf) { + result = new TargetInstanceOf(converter.convert(instanceOf.lexpr), converter.convert(instanceOf.rexpr.getType())); + } + + @Override + public void visit(LocalVar localVar) { + result = new TargetLocalVar(converter.convert(localVar.getType()), localVar.name); + } + + @Override + public void visit(LocalVarDecl localVarDecl) { + // TODO No value, is this correct? + result = new TargetVarDecl(converter.convert(localVarDecl.getType()), localVarDecl.getName(), null); + } + + static boolean convertsTo(TargetType from, TargetType to) { + if (to.equals(TargetType.Object)) return true; // TODO Consider type coercion and suptyping + return to.equals(from); + } + + Method findMethod(JavaClassName className, String name, List args) { + if (converter.sourceFile != null && converter.sourceFile.imports.contains(className)) { + try { + var clazz = converter.classLoader.loadClass(className.toString()); + + outer: for (var method : clazz.getMethods()) { + if (method.getParameterTypes().length != args.size()) continue; + if (!method.getName().equals(name)) continue; + + for (var i = 0; i < method.getParameterTypes().length; i++) { + var param = method.getParameterTypes()[i]; + var arg = args.get(i); + if (param.isPrimitive()) { + arg = TargetType.toPrimitive(arg); + } + if (!convertsTo(arg, Objects.requireNonNull(TargetType.toTargetType(param)))) continue outer; + } + return method; + } + } catch (ClassNotFoundException ignored) {} + } + if (converter.sourceFile != null) { // TODO Multiple source files + var thisClass = converter.sourceFile.KlassenVektor.stream() + .filter(classOrInterface -> classOrInterface.getClassName().equals(className)).findFirst(); + + if (thisClass.isPresent()) { + var superClass = thisClass.get().getSuperClass().getName(); + return findMethod(superClass, name, args); + } + } + return null; + } + + @Override + public void visit(MethodCall methodCall) { + var receiverType = converter.convert(methodCall.receiver.getType()); + var isFunNType = receiverType instanceof TargetFunNType; + var returnType = isFunNType ? TargetType.Object : converter.convert(methodCall.getType()); + var receiverName = new JavaClassName(converter.convert(methodCall.receiver.getType()).name()); + var argList = methodCall.arglist.getArguments().stream().map(expr -> converter.convert(expr.getType())).toList(); + + Method foundMethod = null; + if (methodCall.receiver instanceof ExpressionReceiver expressionReceiver && expressionReceiver.expr instanceof This) { + var thisMethod = converter.findMethod(converter.currentClass, methodCall.name, methodCall.arglist); + if (thisMethod.isEmpty()) { + foundMethod = findMethod(converter.currentClass.getSuperClass().getName(), methodCall.name, argList); + } + } else { + foundMethod = findMethod(receiverName, methodCall.name, argList); + } + + if (foundMethod != null) { + returnType = TargetType.toTargetType(foundMethod.getReturnType()); + argList = Stream.of(foundMethod.getParameterTypes()).map(TargetType::toTargetType).toList(); + } + + result = new TargetMethodCall( + converter.convert(methodCall.getType()), + returnType, argList, + converter.convert(methodCall.receiver), + methodCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), + receiverType, + methodCall.name, false, isFunNType + ); + } + + @Override + public void visit(NewClass newClass) { + result = new TargetNew( + new TargetRefType(newClass.name), + newClass.getArgumentList().getArguments().stream().map(converter::convert).toList() + ); + } + + @Override + public void visit(NewArray newArray) { + // TODO + throw new NotImplementedException(); + } + + @Override + public void visit(Return aReturn) { + result = new TargetReturn(converter.convert(aReturn.retexpr)); + } + + @Override + public void visit(ReturnVoid aReturn) { + result = new TargetReturn(null); + } + + @Override + public void visit(StaticClassName staticClassName) { + result = new TargetClassName(converter.convert(staticClassName.getType())); + } + + @Override + public void visit(Super aSuper) { + result = new TargetSuper(converter.convert(aSuper.getType())); + } + + @Override + public void visit(This aThis) { + result = new TargetThis(converter.convert(aThis.getType())); + } + + @Override + public void visit(WhileStmt whileStmt) { + result = new TargetWhile(converter.convert(whileStmt.expr), converter.convert(whileStmt.loopBlock)); + } + + @Override + public void visit(DoStmt whileStmt) { + throw new NotImplementedException(); + } + + // TODO These two might not be necessary + @Override + public void visit(AssignToField assignLeftSide) { + result = converter.convert(assignLeftSide.field); + } + + @Override + public void visit(AssignToLocal assignLeftSide) { + result = converter.convert(assignLeftSide.localVar); + } + + @Override + public void visit(SuperCall superCall) { + var aSuper = converter.convert(converter.currentClass.getSuperClass()); + var type = converter.convert(superCall.getType()); + result = new TargetMethodCall( + type, type, + superCall.argTypes == null ? List.of() : superCall.argTypes.stream().map(converter::convert).toList(), + new TargetSuper(aSuper), + superCall.getArgumentList().getArguments().stream().map(converter::convert).toList(), + aSuper, + superCall.name, false, false + ); + } + + @Override + public void visit(ExpressionReceiver expressionReceiver) { + result = converter.convert(expressionReceiver.expr); + } + + @Override + public void visit(UnaryExpr unaryExpr) { + result = switch (unaryExpr.operation) { + case NOT -> new TargetUnaryOp.Not(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr)); + case MINUS -> new TargetUnaryOp.Negate(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr)); + case PREINCREMENT -> new TargetUnaryOp.PreIncrement(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr)); + case PREDECREMENT -> new TargetUnaryOp.PreDecrement(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr)); + case POSTINCREMENT -> new TargetUnaryOp.PostIncrement(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr)); + case PLUS -> new TargetUnaryOp.Add(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr)); + case POSTDECREMENT -> new TargetUnaryOp.PostDecrement(converter.convert(unaryExpr.getType()), converter.convert(unaryExpr.expr)); + }; + } + + @Override + public void visit(Literal literal) { + if (literal.value instanceof Integer + || literal.value instanceof Short + || literal.value instanceof Byte) { + + result = new TargetLiteral.IntLiteral((int) literal.value); + } else if (literal.value instanceof Float) { + result = new TargetLiteral.FloatLiteral((float) literal.value); + } else if (literal.value instanceof Double) { + result = new TargetLiteral.DoubleLiteral((double) literal.value); + } else if (literal.value instanceof Long) { + result = new TargetLiteral.LongLiteral((long) literal.value); + } else if (literal.value instanceof Character) { + result = new TargetLiteral.CharLiteral((char) literal.value); + } else if (literal.value instanceof String) { + result = new TargetLiteral.StringLiteral((String) literal.value); + } else if (literal.value instanceof Boolean) { + result = new TargetLiteral.BooleanLiteral((boolean) literal.value); + } + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/generate/TracingStatementVisitor.java b/app/src/main/java/de/dhbwstuttgart/target/generate/TracingStatementVisitor.java new file mode 100644 index 00000000..6fc9c248 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/generate/TracingStatementVisitor.java @@ -0,0 +1,159 @@ +package de.dhbwstuttgart.target.generate; + +import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.statement.*; + + +// This visitor walks the entire tree, individual methods may be overridden +public abstract class TracingStatementVisitor implements StatementVisitor { + + @Override + public void visit(MethodCall methodCall) { + methodCall.receiver.accept(this); + methodCall.getArgumentList().accept(this); + } + + @Override + public void visit(ArgumentList argumentList) { + argumentList.getArguments().forEach(expr -> expr.accept(this)); + } + + @Override + public void visit(LambdaExpression lambdaExpression) { + lambdaExpression.methodBody.accept(this); + } + + @Override + public void visit(Assign assign) { + assign.rightSide.accept(this); + } + + @Override + public void visit(BinaryExpr binary) { + binary.lexpr.accept(this); + binary.rexpr.accept(this); + } + + @Override + public void visit(Block block) { + for (var expr : block.statements) + expr.accept(this); + } + + @Override + public void visit(CastExpr castExpr) { + + } + + @Override + public void visit(EmptyStmt emptyStmt) { + + } + + @Override + public void visit(FieldVar fieldVar) { + + } + + @Override + public void visit(ForStmt forStmt) { + forStmt.body_Loop_block.accept(this); + } + + @Override + public void visit(IfStmt ifStmt) { + ifStmt.then_block.accept(this); + ifStmt.else_block.accept(this); + } + + @Override + public void visit(InstanceOf instanceOf) { + + } + + @Override + public void visit(LocalVar localVar) { + + } + + @Override + public void visit(LocalVarDecl localVarDecl) { + + } + + @Override + public void visit(NewClass newClass) { + this.visit((MethodCall) newClass); + } + + @Override + public void visit(NewArray newArray) { + newArray.expr.forEach(expr -> expr.accept(this)); + } + + @Override + public void visit(Return aReturn) { + aReturn.retexpr.accept(this); + } + + @Override + public void visit(ReturnVoid aReturn) { + + } + + @Override + public void visit(StaticClassName staticClassName) { + + } + + @Override + public void visit(Super aSuper) { + + } + + @Override + public void visit(This aThis) { + + } + + @Override + public void visit(WhileStmt whileStmt) { + whileStmt.loopBlock.accept(this); + } + + @Override + public void visit(DoStmt whileStmt) { + whileStmt.loopBlock.accept(this); + } + + @Override + public void visit(AssignToField assignLeftSide) { + + } + + @Override + public void visit(AssignToLocal assignLeftSide) { + + } + + @Override + public void visit(SuperCall superCall) { + + } + + @Override + public void visit(ExpressionReceiver expressionReceiver) { + expressionReceiver.expr.accept(this); + } + + @Override + public void visit(UnaryExpr unaryExpr) { + unaryExpr.expr.accept(this); + } + + @Override + public void visit(Literal literal) { + + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/MethodParameter.java b/app/src/main/java/de/dhbwstuttgart/target/tree/MethodParameter.java new file mode 100644 index 00000000..4ae31828 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/MethodParameter.java @@ -0,0 +1,6 @@ +package de.dhbwstuttgart.target.tree; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record MethodParameter(TargetType type, String name) { +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/TargetClass.java b/app/src/main/java/de/dhbwstuttgart/target/tree/TargetClass.java new file mode 100644 index 00000000..50cb9f71 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/TargetClass.java @@ -0,0 +1,47 @@ +package de.dhbwstuttgart.target.tree; + +import de.dhbwstuttgart.target.tree.expression.TargetBlock; +import de.dhbwstuttgart.target.tree.type.TargetRefType; +import de.dhbwstuttgart.target.tree.type.TargetType; + +import java.lang.annotation.Target; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public record TargetClass(int modifiers, String qualifiedName, TargetType superType, Set generics, List implementingInterfaces, + List constructors, List fields, List methods) { + + public TargetClass(int modifiers, String qualifiedName) { + this(modifiers, qualifiedName, TargetType.Object, new HashSet<>(), new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), new ArrayList<>()); + } + public TargetClass(int modifiers, String qualifiedName, List implementingInterfaces) { + this(modifiers, qualifiedName, TargetType.Object, new HashSet<>(), implementingInterfaces, new ArrayList<>(), new ArrayList<>(), new ArrayList<>()); + } + + public String getName() { + return qualifiedName.replaceAll("\\.", "/"); + } + + public void addMethod(int access, String name, Set generics, List parameterTypes, TargetType returnType, TargetBlock block) { + this.methods.add(new TargetMethod(access, name, generics, parameterTypes, returnType, block)); + } + + public void addMethod(int access, String name, List parameterTypes, TargetType returnType, TargetBlock block) { + addMethod(access, name, Set.of(), parameterTypes, returnType, block); + } + + public void addConstructor(int access, Set generics, List paramterTypes, TargetBlock block) { + this.constructors.add(new TargetConstructor(access, generics, paramterTypes, block, null)); + } + + public void addConstructor(int access, List paramterTypes, TargetBlock block) { + addConstructor(access, Set.of(), paramterTypes, block); + } + + public void addField(int access, TargetRefType type, String name) { + this.fields.add(new TargetField(access, type, name)); + } +} + diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/TargetConstructor.java b/app/src/main/java/de/dhbwstuttgart/target/tree/TargetConstructor.java new file mode 100644 index 00000000..4d2cca14 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/TargetConstructor.java @@ -0,0 +1,19 @@ +package de.dhbwstuttgart.target.tree; + +import de.dhbwstuttgart.target.tree.expression.TargetBlock; +import de.dhbwstuttgart.target.tree.type.TargetType; + +import java.util.List; +import java.util.Set; + +public record TargetConstructor(int access, Set generics, List parameters, TargetBlock block, TargetBlock fieldInitializer) { + + public String getDescriptor() { + return TargetMethod.getDescriptor(null, parameters.stream().map(MethodParameter::type).toArray(TargetType[]::new)); + } + + public String getSignature() { + return TargetMethod.getSignature(generics, parameters, null); + } +} + diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/TargetField.java b/app/src/main/java/de/dhbwstuttgart/target/tree/TargetField.java new file mode 100644 index 00000000..3a22bade --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/TargetField.java @@ -0,0 +1,11 @@ +package de.dhbwstuttgart.target.tree; + +import de.dhbwstuttgart.target.tree.type.TargetType; +import org.objectweb.asm.Opcodes; + +public record TargetField(int access, TargetType type, String name) { + public boolean isStatic() { + return (access & Opcodes.ACC_STATIC) != 0; + } +} + diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/TargetGeneric.java b/app/src/main/java/de/dhbwstuttgart/target/tree/TargetGeneric.java new file mode 100644 index 00000000..ad70ae71 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/TargetGeneric.java @@ -0,0 +1,6 @@ +package de.dhbwstuttgart.target.tree; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record TargetGeneric(String name, TargetType bound) { +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/TargetInterface.java b/app/src/main/java/de/dhbwstuttgart/target/tree/TargetInterface.java new file mode 100644 index 00000000..f15acad4 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/TargetInterface.java @@ -0,0 +1,6 @@ +package de.dhbwstuttgart.target.tree; + +import java.util.List; + +public record TargetInterface(String name, List methods, List extendedInterfaces) { +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java b/app/src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java new file mode 100644 index 00000000..2865603f --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/TargetMethod.java @@ -0,0 +1,49 @@ +package de.dhbwstuttgart.target.tree; + +import de.dhbwstuttgart.target.tree.expression.TargetBlock; +import de.dhbwstuttgart.target.tree.type.TargetType; +import org.objectweb.asm.Opcodes; + +import java.util.List; +import java.util.Set; + +public record TargetMethod(int access, String name, Set generics, List parameters, TargetType returnType, TargetBlock block) { + public static String getDescriptor(TargetType returnType, TargetType... parameters) { + String ret = "("; + for (var parameterType : parameters) { + ret += parameterType.toSignature(); + } + ret += ")"; + if (returnType == null) ret += "V"; + else ret += returnType.toSignature(); + return ret; + } + + public static String getSignature(Set generics, List parameters, TargetType returnType) { + String ret = "<"; + for (var generic : generics) { + ret += generic.name() + ":" + generic.bound().toGenericSignature(); + } + ret += ">("; + for (var param : parameters) { + ret += param.type().toGenericSignature(); + } + ret += ")"; + if (returnType == null) ret += "V"; + else ret += returnType.toGenericSignature(); + return ret; + } + + public String getDescriptor() { + return getDescriptor(returnType, parameters.stream().map(MethodParameter::type).toArray(TargetType[]::new)); + } + + public String getSignature() { + return getSignature(generics, parameters, returnType); + } + + public boolean isStatic() { + return (access & Opcodes.ACC_STATIC) != 0; + } +} + diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetAssign.java b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetAssign.java new file mode 100644 index 00000000..609de796 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetAssign.java @@ -0,0 +1,6 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record TargetAssign(TargetType type, TargetExpression left, TargetExpression right) implements TargetStatementExpression { +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBinaryOp.java b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBinaryOp.java new file mode 100644 index 00000000..12d56d5b --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBinaryOp.java @@ -0,0 +1,48 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.expression.TargetExpression; +import de.dhbwstuttgart.target.tree.type.TargetType; + +public sealed interface TargetBinaryOp extends TargetExpression { + TargetExpression left(); + TargetExpression right(); + + // Arithmetic + record Add(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} + record Sub(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} + record Div(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} + record Mul(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} + record Rem(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} + + // Bitwise + record BAnd(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} + record BOr(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} + record XOr(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} + record Shl(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} + record Shr(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} + record UShr(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} + + // Conditional + record And(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} + record Or(TargetType type, TargetExpression left, TargetExpression right) implements TargetBinaryOp {} + + sealed interface TargetRelationalOp extends TargetBinaryOp { + @Override + default TargetType type() { + return TargetType.Boolean; + } + TargetType exprType(); + } + + // Comparison + // exprType is the type that both arguments get converted to before comparison + record Equal(TargetType exprType, TargetExpression left, TargetExpression right) implements TargetRelationalOp {} + record Greater(TargetType exprType, TargetExpression left, TargetExpression right) implements TargetRelationalOp {} + record GreaterOrEqual(TargetType exprType, TargetExpression left, TargetExpression right) implements TargetRelationalOp {} + record Less(TargetType exprType, TargetExpression left, TargetExpression right) implements TargetRelationalOp {} + record LessOrEqual(TargetType exprType, TargetExpression left, TargetExpression right) implements TargetRelationalOp {} + record NotEqual(TargetType exprType, TargetExpression left, TargetExpression right) implements TargetRelationalOp {} + +} + + diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBlock.java b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBlock.java new file mode 100644 index 00000000..87cc3b5e --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBlock.java @@ -0,0 +1,12 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +import java.util.List; + +public record TargetBlock(List statements) implements TargetExpression { + @Override + public TargetType type() { + return null; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBreak.java b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBreak.java new file mode 100644 index 00000000..ae918c44 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetBreak.java @@ -0,0 +1,11 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record TargetBreak() implements TargetExpression { + + @Override + public TargetType type() { + return null; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetCast.java b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetCast.java new file mode 100644 index 00000000..f95bc9a8 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetCast.java @@ -0,0 +1,6 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record TargetCast(TargetType type, TargetExpression expr) implements TargetExpression { +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetClassName.java b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetClassName.java new file mode 100644 index 00000000..7131acac --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetClassName.java @@ -0,0 +1,6 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record TargetClassName(TargetType type) implements TargetExpression { +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetContinue.java b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetContinue.java new file mode 100644 index 00000000..42ebc995 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetContinue.java @@ -0,0 +1,11 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record TargetContinue() implements TargetExpression { + + @Override + public TargetType type() { + return null; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetExpression.java b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetExpression.java new file mode 100644 index 00000000..64146f7e --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetExpression.java @@ -0,0 +1,9 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.type.*; + +public sealed interface TargetExpression + permits TargetBinaryOp, TargetBlock, TargetBreak, TargetCast, TargetClassName, TargetContinue, TargetFieldVar, TargetFor, TargetForEach, TargetIf, TargetInstanceOf, TargetLambdaExpression, TargetLiteral, TargetLocalVar, TargetReturn, TargetStatementExpression, TargetSuper, TargetSwitch, TargetTernary, TargetThis, TargetUnaryOp, TargetVarDecl, TargetWhile { + + TargetType type(); +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetFieldVar.java b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetFieldVar.java new file mode 100644 index 00000000..5b82f22d --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetFieldVar.java @@ -0,0 +1,7 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.type.TargetRefType; +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record TargetFieldVar(TargetType type, TargetType owner, boolean isStatic, TargetExpression left, String right) implements TargetExpression { +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetFor.java b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetFor.java new file mode 100644 index 00000000..2ce402ab --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetFor.java @@ -0,0 +1,11 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record TargetFor(TargetExpression init, TargetExpression termination, TargetExpression increment, TargetExpression body) implements TargetExpression { + + @Override + public TargetType type() { + return null; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetForEach.java b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetForEach.java new file mode 100644 index 00000000..392b84e4 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetForEach.java @@ -0,0 +1,11 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record TargetForEach(TargetExpression vardecl, TargetExpression list) implements TargetExpression { + + @Override + public TargetType type() { + return null; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetIf.java b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetIf.java new file mode 100644 index 00000000..78bc766b --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetIf.java @@ -0,0 +1,10 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record TargetIf(TargetExpression cond, TargetExpression if_body, TargetExpression else_body) implements TargetExpression { + @Override + public TargetType type() { + return null; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetInstanceOf.java b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetInstanceOf.java new file mode 100644 index 00000000..c1f104e2 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetInstanceOf.java @@ -0,0 +1,12 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.syntaxtree.statement.Expression; +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record TargetInstanceOf(TargetExpression left, TargetType right) implements TargetExpression { + + @Override + public TargetType type() { + return TargetType.Boolean; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLambdaExpression.java b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLambdaExpression.java new file mode 100644 index 00000000..718fb663 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLambdaExpression.java @@ -0,0 +1,10 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.MethodParameter; +import de.dhbwstuttgart.target.tree.TargetField; +import de.dhbwstuttgart.target.tree.type.TargetType; + +import java.util.List; + +public record TargetLambdaExpression(TargetType type, List captures, List params, TargetType returnType, TargetBlock block) implements TargetExpression { +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLiteral.java b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLiteral.java new file mode 100644 index 00000000..c4673682 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLiteral.java @@ -0,0 +1,56 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +public sealed interface TargetLiteral extends TargetExpression { + Object value(); + + record BooleanLiteral(Boolean value) implements TargetLiteral { + @Override + public TargetType type() { + return TargetType.Boolean; + } + } + + record CharLiteral(Character value) implements TargetLiteral { + @Override + public TargetType type() { + return TargetType.Char; + } + } + + record IntLiteral(Integer value) implements TargetLiteral { + @Override + public TargetType type() { + return TargetType.Integer; + } + } + + record LongLiteral(Long value) implements TargetLiteral { + @Override + public TargetType type() { + return TargetType.Long; + } + } + + record FloatLiteral(Float value) implements TargetLiteral { + @Override + public TargetType type() { + return TargetType.Float; + } + } + + record DoubleLiteral(Double value) implements TargetLiteral { + @Override + public TargetType type() { + return TargetType.Double; + } + } + + record StringLiteral(String value) implements TargetLiteral { + @Override + public TargetType type() { + return TargetType.String; + } + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLocalVar.java b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLocalVar.java new file mode 100644 index 00000000..e4fa977f --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetLocalVar.java @@ -0,0 +1,6 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record TargetLocalVar(TargetType type, String name) implements TargetExpression { +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetMethodCall.java b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetMethodCall.java new file mode 100644 index 00000000..50a31471 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetMethodCall.java @@ -0,0 +1,19 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.MethodParameter; +import de.dhbwstuttgart.target.tree.TargetMethod; +import de.dhbwstuttgart.target.tree.type.TargetRefType; +import de.dhbwstuttgart.target.tree.type.TargetType; + +import java.util.List; + +public record TargetMethodCall(TargetType type, TargetType returnType, List parameterTypes, TargetExpression expr, List args, TargetType owner, String name, boolean isStatic, boolean isInterface) implements TargetStatementExpression { + public TargetMethodCall(TargetType type, TargetExpression expr, List args, TargetType owner, String name, boolean isStatic, boolean isInterface) { + this(type, type, args.stream().map(TargetExpression::type).toList(), expr, args, owner, name, isStatic, isInterface); + } + + + public String getDescriptor() { + return TargetMethod.getDescriptor(returnType, parameterTypes.toArray(TargetType[]::new)); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetNew.java b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetNew.java new file mode 100644 index 00000000..e9d4ce8c --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetNew.java @@ -0,0 +1,12 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.TargetMethod; +import de.dhbwstuttgart.target.tree.type.TargetType; + +import java.util.List; + +public record TargetNew(TargetType type, List params) implements TargetStatementExpression { + public String getDescriptor() { + return TargetMethod.getDescriptor(null, params.stream().map(TargetExpression::type).toArray(TargetType[]::new)); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetReturn.java b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetReturn.java new file mode 100644 index 00000000..c419cc1c --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetReturn.java @@ -0,0 +1,10 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record TargetReturn(TargetExpression expression) implements TargetExpression { + @Override + public TargetType type() { + return null; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetStatementExpression.java b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetStatementExpression.java new file mode 100644 index 00000000..2d804d6a --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetStatementExpression.java @@ -0,0 +1,4 @@ +package de.dhbwstuttgart.target.tree.expression; + +public sealed interface TargetStatementExpression extends TargetExpression permits TargetAssign, TargetMethodCall, TargetNew, TargetUnaryOp.PostDecrement, TargetUnaryOp.PostIncrement, TargetUnaryOp.PreDecrement, TargetUnaryOp.PreIncrement { +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetSuper.java b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetSuper.java new file mode 100644 index 00000000..ddffe386 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetSuper.java @@ -0,0 +1,6 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record TargetSuper(TargetType type) implements TargetExpression { +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetSwitch.java b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetSwitch.java new file mode 100644 index 00000000..a6823913 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetSwitch.java @@ -0,0 +1,16 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.syntaxtree.statement.Expression; +import de.dhbwstuttgart.target.tree.type.TargetType; + +import java.util.List; + +public record TargetSwitch(Expression expr, List cases, Expression default_) implements TargetExpression { + + @Override + public TargetType type() { + return null; + } + + record Case(Expression value, Expression body) {} +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetTernary.java b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetTernary.java new file mode 100644 index 00000000..17349489 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetTernary.java @@ -0,0 +1,6 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record TargetTernary(TargetType type, TargetExpression cond, TargetExpression ifTrue, TargetExpression ifFalse) implements TargetExpression { +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetThis.java b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetThis.java new file mode 100644 index 00000000..fe9b722c --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetThis.java @@ -0,0 +1,6 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record TargetThis(TargetType type) implements TargetExpression { +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetUnaryOp.java b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetUnaryOp.java new file mode 100644 index 00000000..92e57647 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetUnaryOp.java @@ -0,0 +1,16 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +public sealed interface TargetUnaryOp extends TargetExpression { + TargetExpression expr(); + + record Negate(TargetType type, TargetExpression expr) implements TargetUnaryOp {} + record Add(TargetType type, TargetExpression expr) implements TargetUnaryOp {} + record Not(TargetType type, TargetExpression expr) implements TargetUnaryOp {} + + record PreIncrement(TargetType type, TargetExpression expr) implements TargetStatementExpression, TargetUnaryOp {} + record PostIncrement(TargetType type, TargetExpression expr) implements TargetStatementExpression, TargetUnaryOp {} + record PreDecrement(TargetType type, TargetExpression expr) implements TargetStatementExpression, TargetUnaryOp {} + record PostDecrement(TargetType type, TargetExpression expr) implements TargetStatementExpression, TargetUnaryOp {} +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetVarDecl.java b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetVarDecl.java new file mode 100644 index 00000000..b1eda5e7 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetVarDecl.java @@ -0,0 +1,11 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record TargetVarDecl(TargetType varType, String name, TargetExpression value) implements TargetExpression { + + @Override + public TargetType type() { + return null; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetWhile.java b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetWhile.java new file mode 100644 index 00000000..62ff90dc --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetWhile.java @@ -0,0 +1,11 @@ +package de.dhbwstuttgart.target.tree.expression; + +import de.dhbwstuttgart.target.tree.type.TargetType; + +public record TargetWhile(TargetExpression cond, TargetExpression body) implements TargetExpression { + + @Override + public TargetType type() { + return null; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/type/TargetExtendsWildcard.java b/app/src/main/java/de/dhbwstuttgart/target/tree/type/TargetExtendsWildcard.java new file mode 100644 index 00000000..7e5ab002 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/type/TargetExtendsWildcard.java @@ -0,0 +1,24 @@ +package de.dhbwstuttgart.target.tree.type; + +public record TargetExtendsWildcard(TargetType innerType) implements TargetType { + @Override + public String toSignature() { + return innerType.toSignature(); + } + + @Override + public String toGenericSignature() { + return innerType.toGenericSignature(); + } + + @Override + public String getInternalName() { + return innerType.getInternalName(); + } + + @Override + public String name() { + return innerType.name(); + } +} + diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/type/TargetFunNType.java b/app/src/main/java/de/dhbwstuttgart/target/tree/type/TargetFunNType.java new file mode 100644 index 00000000..e9379de6 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/type/TargetFunNType.java @@ -0,0 +1,20 @@ +package de.dhbwstuttgart.target.tree.type; + +import java.util.List; + +public record TargetFunNType(int N, List params) implements TargetSpecializedType { + @Override + public String getInternalName() { + return "Fun" + N + "$$"; + } + + @Override + public String name() { + return getInternalName(); + } + + @Override + public String toSignature() { + return "L" + getInternalName() + ";"; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/type/TargetGenericType.java b/app/src/main/java/de/dhbwstuttgart/target/tree/type/TargetGenericType.java new file mode 100644 index 00000000..15900fb4 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/type/TargetGenericType.java @@ -0,0 +1,18 @@ +package de.dhbwstuttgart.target.tree.type; + +public record TargetGenericType(String name) implements TargetType { + @Override + public String toSignature() { + return "Ljava/lang/Object;"; // TODO Use bounds for this? + } + + @Override + public String toGenericSignature() { + return "T" + getInternalName() + ";"; + } + + @Override + public String getInternalName() { + return name; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/type/TargetPrimitiveType.java b/app/src/main/java/de/dhbwstuttgart/target/tree/type/TargetPrimitiveType.java new file mode 100644 index 00000000..9d3bbf46 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/type/TargetPrimitiveType.java @@ -0,0 +1,19 @@ +package de.dhbwstuttgart.target.tree.type; + +public record TargetPrimitiveType(String name) implements TargetType { + + @Override + public String toSignature() { + return getInternalName(); + } + + @Override + public String toGenericSignature() { + return toSignature(); + } + + @Override + public String getInternalName() { + return name; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/type/TargetRefType.java b/app/src/main/java/de/dhbwstuttgart/target/tree/type/TargetRefType.java new file mode 100644 index 00000000..0d043555 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/type/TargetRefType.java @@ -0,0 +1,33 @@ +package de.dhbwstuttgart.target.tree.type; + +import java.util.List; +import java.util.Objects; + +public record TargetRefType(String name, List params) implements TargetSpecializedType { + public TargetRefType(String name) { + this(name, List.of()); + } + + public String getInternalName() { + return this.name.replaceAll("\\.", "/"); + } + + @Override + public String toSignature() { + return "L" + getInternalName() + ";"; + } + + // Type erasure means we need to override hashCode and equals to only consider the name + @Override + public int hashCode() { + return Objects.hashCode(name); + } + + @Override + public boolean equals(Object other) { + if (other instanceof TargetRefType refType) { + return refType.name.equals(name); + } + return false; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSpecializedType.java b/app/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSpecializedType.java new file mode 100644 index 00000000..2a74307c --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSpecializedType.java @@ -0,0 +1,21 @@ +package de.dhbwstuttgart.target.tree.type; + +import java.util.List; + +public sealed interface TargetSpecializedType extends TargetType permits TargetFunNType, TargetRefType { + List params(); + + @Override + default String toGenericSignature() { + String ret = "L" + getInternalName(); + if (params().size() > 0) { + ret += "<"; + for (var param : params()) { + ret += param.toGenericSignature(); + } + ret += ">"; + } + ret += ";"; + return ret; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSuperWildcard.java b/app/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSuperWildcard.java new file mode 100644 index 00000000..bf16e143 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/type/TargetSuperWildcard.java @@ -0,0 +1,25 @@ +package de.dhbwstuttgart.target.tree.type; + +public record TargetSuperWildcard(TargetType innerType) implements TargetType { + @Override + public String toSignature() { + return innerType.toSignature(); + } + + @Override + public String toGenericSignature() { + return innerType.toGenericSignature(); + } + + @Override + public String getInternalName() { + return innerType.getInternalName(); + } + + @Override + public String name() { + return innerType.name(); + } +} + + diff --git a/app/src/main/java/de/dhbwstuttgart/target/tree/type/TargetType.java b/app/src/main/java/de/dhbwstuttgart/target/tree/type/TargetType.java new file mode 100644 index 00000000..36d71af1 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/target/tree/type/TargetType.java @@ -0,0 +1,59 @@ +package de.dhbwstuttgart.target.tree.type; + +public sealed interface TargetType + permits TargetExtendsWildcard, TargetGenericType, TargetSpecializedType, TargetSuperWildcard, TargetPrimitiveType { + + // Builtin types + TargetRefType Boolean = new TargetRefType("java.lang.Boolean"); + TargetRefType Char = new TargetRefType("java.lang.Character"); + TargetRefType Byte = new TargetRefType("java.lang.Byte"); + TargetRefType Short = new TargetRefType("java.lang.Short"); + TargetRefType Integer = new TargetRefType("java.lang.Integer"); + TargetRefType Long = new TargetRefType("java.lang.Long"); + TargetRefType Float = new TargetRefType("java.lang.Float"); + TargetRefType Double = new TargetRefType("java.lang.Double"); + TargetRefType String = new TargetRefType("java.lang.String"); + TargetRefType Object = new TargetRefType("java.lang.Object"); + + // Builtin types + TargetPrimitiveType boolean_ = new TargetPrimitiveType("Z"); + TargetPrimitiveType char_ = new TargetPrimitiveType("C"); + TargetPrimitiveType byte_ = new TargetPrimitiveType("B"); + TargetPrimitiveType short_ = new TargetPrimitiveType("S"); + TargetPrimitiveType int_ = new TargetPrimitiveType("I"); + TargetPrimitiveType long_ = new TargetPrimitiveType("J"); + TargetPrimitiveType float_ = new TargetPrimitiveType("F"); + TargetPrimitiveType double_ = new TargetPrimitiveType("D"); + + static TargetType toPrimitive(TargetType type) { + if (type.equals(Boolean)) return boolean_; + if (type.equals(Char)) return char_; + if (type.equals(Byte)) return byte_; + if (type.equals(Short)) return short_; + if (type.equals(Integer)) return int_; + if (type.equals(Long)) return long_; + if (type.equals(Float)) return float_; + if (type.equals(Double)) return double_; + return type; + } + + static TargetType toTargetType(Class clazz) { + if (clazz.isPrimitive()) { + if (clazz.equals(boolean.class)) return boolean_; + if (clazz.equals(char.class)) return char_; + if (clazz.equals(byte.class)) return byte_; + if (clazz.equals(short.class)) return short_; + if (clazz.equals(int.class)) return int_; + if (clazz.equals(long.class)) return long_; + if (clazz.equals(float.class)) return float_; + if (clazz.equals(double.class)) return double_; + } + if (clazz.equals(void.class)) return null; + return new TargetRefType(clazz.getName()); + } + + String toSignature(); + String toGenericSignature(); + String getInternalName(); + String name(); +} diff --git a/app/src/main/java/de/dhbwstuttgart/typedeployment/KindOfTypeInsertPoint.java b/app/src/main/java/de/dhbwstuttgart/typedeployment/KindOfTypeInsertPoint.java new file mode 100644 index 00000000..25b118e7 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typedeployment/KindOfTypeInsertPoint.java @@ -0,0 +1,7 @@ +package de.dhbwstuttgart.typedeployment; + +public enum KindOfTypeInsertPoint { + NORMAL_INSERT, + GENERIC_CLASS_INSERT, + GENERERIC_METHOD_INSERT +} diff --git a/app/src/main/java/de/dhbwstuttgart/typedeployment/TypeInsert.java b/app/src/main/java/de/dhbwstuttgart/typedeployment/TypeInsert.java new file mode 100644 index 00000000..131c9f9b --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typedeployment/TypeInsert.java @@ -0,0 +1,82 @@ +package de.dhbwstuttgart.typedeployment; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +import org.antlr.v4.parse.BlockSetTransformer.setAlt_return; + +import de.dhbwstuttgart.syntaxtree.statement.This; +import de.dhbwstuttgart.typeinference.result.ResultPair; + +public class TypeInsert { + /** + * point wird hauptsächlich zur Anzeige einer Annotation im Eclipse-plugin benutzt. + */ + public final TypeInsertPoint point; + Set inserts; + ResultPair resultPair; + + public TypeInsert(TypeInsertPoint point, Set additionalPoints, ResultPair resultPair){ + this.point = point; + inserts = additionalPoints; + this.resultPair = resultPair; + } + + public String insert(String intoSource){ + List offsets = new ArrayList<>(); + String ret = intoSource; + + List insertsSorted = new ArrayList<>(); + insertsSorted.add(point); + insertsSorted.addAll(inserts); + Collections.sort(insertsSorted, new TypeInsertPoint.TypeInsertPointPositionComparator().reversed()); + + for(TypeInsertPoint insertPoint : insertsSorted) { + ret = insertPoint.insert(ret, new ArrayList<>()); + offsets.add(insertPoint); + } + return ret; + } + + public String getInsertString(){ + return point.getInsertString(); + } + + public ResultPair getResultPair() { + return this.resultPair; + } + + /* PL 2018-06-18 + * Zwei TypeInsert's sind gleich, wenn ihre point's und ihre inserts' gleich sind + * eingefuegt damit man TypeReplaceMarker vergleichen kann + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) { + if(!(obj instanceof TypeInsert)) { + return false; + } + else { + return ((TypeInsert)obj).point.equals(this.point); + + } + } + + public Set getAdditionalPoints() { + TypeInsertPoint.TypeInsertPointPositionComparator comparator = new TypeInsertPoint.TypeInsertPointPositionComparator(); + TreeSet result = new TreeSet<>(comparator.reversed()); + result.addAll(inserts); + return result; + } + + public Set getAdditionalPointsUnsorted() { + return inserts; + } + + public String toString() { + return point.toString(); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/typedeployment/TypeInsertFactory.java b/app/src/main/java/de/dhbwstuttgart/typedeployment/TypeInsertFactory.java new file mode 100644 index 00000000..54a988c6 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typedeployment/TypeInsertFactory.java @@ -0,0 +1,236 @@ +package de.dhbwstuttgart.typedeployment; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Optional; +import java.util.Set; + +import org.antlr.v4.runtime.Token; +import org.objectweb.asm.Type; + +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericGenratorResultForSourceFile; +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericsGeneratorResult; +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericsGeneratorResultForClass; +import de.dhbwstuttgart.bytecode.utilities.MethodUtility; +import de.dhbwstuttgart.bytecode.utilities.Resolver; +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.syntaxtree.ClassOrInterface; +import de.dhbwstuttgart.syntaxtree.Method; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType; +import de.dhbwstuttgart.syntaxtree.type.GenericRefType; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.result.PairTPHEqualTPH; +import de.dhbwstuttgart.typeinference.result.PairTPHequalRefTypeOrWildcardType; +import de.dhbwstuttgart.typeinference.result.PairTPHsmallerTPH; +import de.dhbwstuttgart.typeinference.result.ResolvedType; +import de.dhbwstuttgart.typeinference.result.ResultSet; +import de.dhbwstuttgart.typeinference.result.ResultSetVisitor; + +/** + * TODO: + * Falls in Feldern Generics entstehen, dann werden diese als Klassenparameter eingesetzt + * Für die Instanzierung von Klassen kann man dann beispielsweise nur noch den Diamond-Operator verwenden + * + * Es müssen zu einem TPH alle in Beziehung stehenden Constraints gefunden werden + * + * Anmekung: Es wird nur ein RefType gleichzeitug eingesetzt. + * Steht dieser mit anderen Typen in Verbindung, so müssen diese nicht eingesetzt werden + * im Result set können nur TPHs mit <. Beziehung stehen + * Steht ein Typ A über TPHs mit anderen Typen B in Verbindung, so lassen sich diese auch im nächsten Durchgang + * inferieren, wenn A bereits eingesetzt wurde. Es werden dann eben zusätzliche Generics entstehen + */ +public class TypeInsertFactory { + + private static List newResults; + + public static Set createTypeInsertPoints(SourceFile forSourcefile, ResultSet withResults, List newResults, List simplifyResultsForAllSourceFiles){ + TypeInsertFactory.newResults = newResults; + return new TypeInsertPlacer().getTypeInserts(forSourcefile, withResults, simplifyResultsForAllSourceFiles); + } + + public static TypeInsert createInsertPoints(RefTypeOrTPHOrWildcardOrGeneric type, Token offset, ClassOrInterface cl, Method m, + ResultSet resultSet, List constraints, List classConstraints) { + + /* PL 2020-04-11 auskommentiert + * try { + */ + ResolvedType resolvedType = resultSet.resolveType(type); + TypeInsertPoint insertPoint = new TypeInsertPoint(offset, + new TypeToInsertString(resolvedType.resolvedType, constraints, classConstraints).insert, KindOfTypeInsertPoint.NORMAL_INSERT); + /* PL 2020-04-11 auskommentiert + List simplifyResults = JavaTXCompiler.INSTANCE.getGeneratedGenericResultsForAllSourceFiles(newResults); + for (GenericGenratorResultForSourceFile simplifyResultsEntries : simplifyResults) { + GenericsGeneratorResultForClass genericResultsForClass = simplifyResultsEntries.getSimplifyResultsByName(cl.getClassName()); + return new TypeInsert(insertPoint, createGenericInsert(genericResultsForClass, cl, m, resultSet, offset), resolvedType.getResultPair()); + } + + return new TypeInsert(insertPoint, new HashSet<>(), resolvedType.getResultPair()); + */ + //GenericsGeneratorResultForClass genericResultsForClass = genericResult.getSimplifyResultsByName("", cl.getClassName().toString()); + return new TypeInsert(insertPoint, createGenericInsert(constraints, classConstraints, cl, m, resultSet, offset), resolvedType.getResultPair()); + + /* PL 2020-04-11 auskommentiert + } catch (ClassNotFoundException e) { + e.printStackTrace(); + return null; + } + */ + } + + private static synchronized Set createGenericInsert(List methodConstraints, List classConstraints,ClassOrInterface cl, Method m, ResultSet resultSet, Token mOffset){ + Set result = createGenericClassInserts(classConstraints, cl); + + Resolver resolver = new Resolver(resultSet); + + if (m != null) { + //List methodConstraints = genericResult.getMethodConstraintsByID(MethodUtility.createID(resolver, m)); + result.addAll(createMethodConstraints(methodConstraints, m.getOffset() != null ? m.getOffset() : mOffset)); + } + + return result; + } + + private static Set createMethodConstraints(List constraints, Token mOffset) { + Set result = new HashSet<>(); + Token offset = mOffset; + + if (constraints.size() == 0) { + return result; + } + + String insert = " <"; + + for (GenericsGeneratorResult genericInsertConstraint : constraints) { + if (genericInsertConstraint.getConstraint().getRight().equals(Type.getInternalName(Object.class))) { + insert += genericInsertConstraint.getConstraint().getLeft(); + } else { + insert += genericInsertConstraint.getConstraint().getLeft() + " extends " + genericInsertConstraint.getConstraint().getRight(); + } + insert += ", "; + } + + insert = insert.substring(0, insert.length() -2); + insert += ">"; + + result.add(new TypeInsertPoint(offset, insert, KindOfTypeInsertPoint.GENERERIC_METHOD_INSERT)); + return result; + } + + private static Set createGenericClassInserts(List classConstraints, ClassOrInterface cl) { + Set result = new HashSet<>(); + Token offset = cl.getGenerics().getOffset(); + + //List classConstraints = genericResult.getClassConstraints(); + + if (classConstraints == null || classConstraints.size() == 0) { + return result; + } + + String insert = " <"; + + for (GenericsGeneratorResult genericInsertConstraint : classConstraints) { + if (genericInsertConstraint.getConstraint().getRight().equals(Type.getInternalName(Object.class))) { + insert += genericInsertConstraint.getConstraint().getLeft(); + } else { + insert += genericInsertConstraint.getConstraint().getLeft() + " extends " + genericInsertConstraint.getConstraint().getRight(); + } + insert += ", "; + } + + insert = insert.substring(0, insert.length() -2); + insert += ">"; + + result.add(new TypeInsertPoint(offset, insert, KindOfTypeInsertPoint.GENERIC_CLASS_INSERT)); + + return result; + } +} + +class TypeToInsertString implements ResultSetVisitor{ + String insert = ""; + private List constraints; + private List classConstraints; + + + TypeToInsertString(RefTypeOrTPHOrWildcardOrGeneric type, List constraints, List classConstraints){ + this.constraints = constraints; + this.classConstraints = classConstraints; + type.accept(this); + } + + @Override + public void visit(PairTPHsmallerTPH p) { + + } + + @Override + public void visit(PairTPHequalRefTypeOrWildcardType p) { + + } + + @Override + public void visit(PairTPHEqualTPH p) { + + } + + @Override + public void visit(RefType resolved) { + insert = resolved.getName().toString(); + if(resolved.getParaList().size() > 0){ + insert += "<"; + Iterator iterator = resolved.getParaList().iterator(); + while(iterator.hasNext()){ + RefTypeOrTPHOrWildcardOrGeneric typeParam = iterator.next(); + insert += new TypeToInsertString(typeParam, constraints, classConstraints).insert; + if(iterator.hasNext())insert += ", "; + } + insert += ">"; + } + } + + @Override + public void visit(GenericRefType genericRefType) { + insert += genericRefType.getParsedName(); + } + + @Override + public void visit(SuperWildcardType superWildcardType) { + insert += "? super " + new TypeToInsertString(superWildcardType.getInnerType(), constraints, classConstraints).insert; + } + + @Override + public void visit(TypePlaceholder typePlaceholder) { + String realName = typePlaceholder.getName(); + //String realName = sig2.substring(1, sig2.length() - 1); + //String toVisit = realName+SPECIAL_CHAR; + //if(!genericsAndBounds.containsKey(toVisit)) {//PL 202-04-1 vielleicht braucht man das, vgl. Signature.java + Optional equalTPH = getEqualTPHFromClassConstraints(classConstraints, realName); + if(equalTPH.isPresent()){ + insert += equalTPH.get().getConstraint().getLeft();// + SPECIAL_CHAR; + } else { + insert += getEqualTPH(constraints, realName);// + SPECIAL_CHAR; + } + } + + @Override + public void visit(ExtendsWildcardType extendsWildcardType) { + insert += "? extends " + new TypeToInsertString(extendsWildcardType.getInnerType(), constraints, classConstraints).insert; + } + + private Optional getEqualTPHFromClassConstraints(List listOfConstraints, String tph) { + return listOfConstraints.stream() + .filter(c -> c.getConstraint().getLeft().equals(tph) || c.getEqualsTPHs().contains(tph)) + .findFirst(); + } + + private String getEqualTPH(List constraints2, String tph) { + return constraints2.stream() + .filter(c -> c.getConstraint().getLeft().equals(tph) || c.getEqualsTPHs().contains(tph)) + .findFirst().get().getConstraint().getLeft(); + } +} \ No newline at end of file diff --git a/app/src/main/java/de/dhbwstuttgart/typedeployment/TypeInsertPlacer.java b/app/src/main/java/de/dhbwstuttgart/typedeployment/TypeInsertPlacer.java new file mode 100644 index 00000000..042a76eb --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typedeployment/TypeInsertPlacer.java @@ -0,0 +1,99 @@ +package de.dhbwstuttgart.typedeployment; + +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericGenratorResultForSourceFile; +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericsGeneratorResult; +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericsGeneratorResultForClass; +import de.dhbwstuttgart.bytecode.utilities.MethodUtility; +import de.dhbwstuttgart.bytecode.utilities.Resolver; +import de.dhbwstuttgart.syntaxtree.*; +import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.result.ResultSet; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class TypeInsertPlacer extends AbstractASTWalker{ + Set inserts = new HashSet<>(); + private ResultSet withResults; + String pkgName; + private List simplifyResultsForAllSourceFiles; + + public Set getTypeInserts(SourceFile forSourceFile, ResultSet withResults, List simplifyResultsForAllSourceFiles){ + this.withResults = withResults; + this.simplifyResultsForAllSourceFiles = simplifyResultsForAllSourceFiles; + pkgName = forSourceFile.getPkgName(); + forSourceFile.accept(this); + return inserts; + } + + @Override + public void visit(ClassOrInterface classOrInterface) { + GenericsGeneratorResultForClass generatedGenerics = simplifyResultsForAllSourceFiles + .stream() + .map(sr->sr.getSimplifyResultsByName(classOrInterface.getClassName())) + .findFirst() + .get(); + TypeInsertPlacerClass cl = new TypeInsertPlacerClass(classOrInterface, withResults, generatedGenerics); + this.inserts.addAll(cl.inserts); + } +} + +class TypeInsertPlacerClass extends AbstractASTWalker{ + protected final ResultSet results; + private GenericsGeneratorResultForClass generatedGenerics; + protected final ClassOrInterface cl; + public final Set inserts = new HashSet<>(); + private Method method; + + private Resolver resolver; + + List constraints; + List classConstraints; + + TypeInsertPlacerClass(ClassOrInterface forClass, ResultSet withResults, GenericsGeneratorResultForClass generatedGenerics){ + this.cl = forClass; + this.method = null; + this.results = withResults; + this.generatedGenerics = generatedGenerics; + resolver = new Resolver(withResults); //PL 2020-04-12 Ob das stimmt weiss ich nicht + forClass.accept(this); + } + + @Override + public void visit(Method method) { + this.method = method; + String id = MethodUtility.createID(resolver, method); + constraints = generatedGenerics.getMethodConstraintsByID(id); + classConstraints = generatedGenerics.getClassConstraints(); + if(method.getReturnType() instanceof TypePlaceholder) + inserts.add(TypeInsertFactory.createInsertPoints( + method.getReturnType(), method.getReturnType().getOffset(), cl, method, results, constraints, classConstraints)); + super.visit(method); + } + + @Override + public void visit(Field field) { + if(field.getType() instanceof TypePlaceholder){ + classConstraints = generatedGenerics.getClassConstraints(); + inserts.add(TypeInsertFactory.createInsertPoints( + field.getType(), field.getType().getOffset(), cl, method, results, new ArrayList<>(), classConstraints)); + } + super.visit(field); + } + + @Override + public void visit(FormalParameter param) { + if(param.getType() instanceof TypePlaceholder) + inserts.add(TypeInsertFactory.createInsertPoints( + param.getType(), param.getType().getOffset(), cl, method, results, constraints, classConstraints)); + super.visit(param); + } + + @Override + public void visit(LambdaExpression lambdaExpression) { + //Lambda-Ausdrücke brauchen keine Typeinsetzungen + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/typedeployment/TypeInsertPoint.java b/app/src/main/java/de/dhbwstuttgart/typedeployment/TypeInsertPoint.java new file mode 100644 index 00000000..0efb66e4 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typedeployment/TypeInsertPoint.java @@ -0,0 +1,93 @@ +package de.dhbwstuttgart.typedeployment; + +import java.util.Comparator; +import java.util.List; +import java.util.Set; + +import org.antlr.v4.runtime.Token; + +public class TypeInsertPoint { + public Token point; + private String insertString; + private int extraOffset = 0; + private KindOfTypeInsertPoint kind; + + public TypeInsertPoint(Token point, String toInsert, KindOfTypeInsertPoint kind){ + this.point = point; + this.kind = kind; + this.insertString = (toInsert.endsWith(" ")) ? toInsert : toInsert + " " ; + } + + public boolean isGenericClassInsertPoint() { + return kind == KindOfTypeInsertPoint.GENERIC_CLASS_INSERT; + } + + public String insert(String intoSource, List additionalOffset){ + return new StringBuilder(intoSource).insert(point.getStartIndex()+extraOffset, insertString).toString(); + } + + public String getInsertString() { + return insertString; + } + + public void addExtraOffset(int toAdd) { + this.extraOffset += toAdd; + } + + public int getPositionInCode() { + return point.getStartIndex() + extraOffset; + } + + /* PL 2018-06-19 + * Zwei TypeInsertPoint's sind gleich, wenn ihre point's gleich sind + * eingefuegt damit man TypeReplaceMarker vergleichen kann + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) { + return this == obj; + /* + if(!(obj instanceof TypeInsertPoint)) { + return false; + } + else { + return + ((TypeInsertPoint)obj).getPositionInCode() == this.getPositionInCode() && + ((TypeInsertPoint)obj).insertString.equals(this.insertString); + } + */ + } + + public int hashCode() { + return getPositionInCode() * 11 * insertString.hashCode(); + } + + public Set getAdditionalPoints() { + return this.getAdditionalPoints(); + } + + public String toString() { + return point.getLine() + ":" + point.getCharPositionInLine() + ":" + insertString; + } + + public static final class TypeInsertPointPositionComparator implements Comparator { + + @Override + public int compare(TypeInsertPoint o1, TypeInsertPoint o2) { + if (o1.point == null && o2.point == null) { + return 0; + } else if (o2.point == null) { + return 1; + } else if (o1.point == null) { + return -1; + } + + if (o1.getPositionInCode() > o2.getPositionInCode()) { + return 1; + } else if (o1.getPositionInCode() < o2.getPositionInCode()) { + return -1; + } + return 0; + } + + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/assumptions/Assumption.java b/app/src/main/java/de/dhbwstuttgart/typeinference/assumptions/Assumption.java new file mode 100644 index 00000000..2435f58b --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/assumptions/Assumption.java @@ -0,0 +1,15 @@ +package de.dhbwstuttgart.typeinference.assumptions; + +import de.dhbwstuttgart.syntaxtree.TypeScope; + +public class Assumption { + private final TypeScope typeScope; + + public Assumption(TypeScope typeScope) { + this.typeScope = typeScope; + } + + public TypeScope getTypeScope() { + return typeScope; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/assumptions/FieldAssumption.java b/app/src/main/java/de/dhbwstuttgart/typeinference/assumptions/FieldAssumption.java new file mode 100644 index 00000000..ee18ea7c --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/assumptions/FieldAssumption.java @@ -0,0 +1,49 @@ +package de.dhbwstuttgart.typeinference.assumptions; + +import de.dhbwstuttgart.exceptions.NotImplementedException; +import de.dhbwstuttgart.parser.NullToken; +import de.dhbwstuttgart.syntaxtree.ClassOrInterface; +import de.dhbwstuttgart.syntaxtree.GenericTypeVar; +import de.dhbwstuttgart.syntaxtree.TypeScope; +import de.dhbwstuttgart.syntaxtree.type.GenericRefType; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.typeinference.constraints.GenericsResolver; + +import java.util.ArrayList; +import java.util.List; + +public class FieldAssumption extends Assumption{ + private ClassOrInterface receiverClass; + private RefTypeOrTPHOrWildcardOrGeneric type; + private String name; + + public FieldAssumption(String fieldName, ClassOrInterface receiverType, + RefTypeOrTPHOrWildcardOrGeneric type, TypeScope scope){ + super(scope); + this.type = type; + this.receiverClass = receiverType; + this.name = fieldName; + } + + public ClassOrInterface getReceiverClass() { + return receiverClass; + } + + public RefTypeOrTPHOrWildcardOrGeneric getType(GenericsResolver resolver) { + return resolver.resolve(type); + } + + public RefTypeOrTPHOrWildcardOrGeneric getReceiverType(GenericsResolver resolver) { + List params = new ArrayList<>(); + for(GenericTypeVar gtv : receiverClass.getGenerics()){ + //Hier wird ein GenericRefType gebildet, welcher einen für dieses Feld eindeutigen Namen hat + GenericRefType genericRefType = + new GenericRefType(gtv.getName() + , new NullToken()); + //Dieser wird dann korrekt aufgelöst vom Resolver: + params.add(resolver.resolve(genericRefType)); + } + return new RefType(receiverClass.getClassName(), params, new NullToken()); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/assumptions/FunNClass.java b/app/src/main/java/de/dhbwstuttgart/typeinference/assumptions/FunNClass.java new file mode 100644 index 00000000..d41baa06 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/assumptions/FunNClass.java @@ -0,0 +1,44 @@ +package de.dhbwstuttgart.typeinference.assumptions; + +import de.dhbwstuttgart.parser.NullToken; +import de.dhbwstuttgart.parser.scope.JavaClassName; +import de.dhbwstuttgart.syntaxtree.ClassOrInterface; +import de.dhbwstuttgart.syntaxtree.GenericDeclarationList; +import de.dhbwstuttgart.syntaxtree.GenericTypeVar; +import de.dhbwstuttgart.syntaxtree.Method; +import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; +import de.dhbwstuttgart.syntaxtree.factory.NameGenerator; +import de.dhbwstuttgart.syntaxtree.type.GenericRefType; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; + +import org.antlr.v4.runtime.Token; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +public class FunNClass extends ClassOrInterface { + public FunNClass(List funNParams) { + super(0, new JavaClassName("Fun"+(funNParams.size()-1)), new ArrayList<>(), Optional.empty() /* eingefuegt PL 2018-11-24 */, + createMethods(funNParams), new ArrayList<>(), createGenerics(funNParams), + ASTFactory.createObjectType(), true, new ArrayList<>(), new NullToken()); + + + } + + private static GenericDeclarationList createGenerics(List funNParams) { + //PL 2018-06-22: so geaendert, dass generierte Generics den Namen der funParams entsprechen. + List generics = new ArrayList<>(); + for(GenericRefType param : funNParams){ + generics.add(new GenericTypeVar(param.getParsedName(),//NameGenerator.makeNewName(), + new ArrayList<>(), new NullToken(), new NullToken())); + } + return new GenericDeclarationList(generics, new NullToken()); + } + + private static List createMethods(List funNParams) { + return null; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/assumptions/MethodAssumption.java b/app/src/main/java/de/dhbwstuttgart/typeinference/assumptions/MethodAssumption.java new file mode 100644 index 00000000..6e6c5c5a --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/assumptions/MethodAssumption.java @@ -0,0 +1,79 @@ +package de.dhbwstuttgart.typeinference.assumptions; + +import de.dhbwstuttgart.parser.NullToken; +import de.dhbwstuttgart.parser.scope.JavaClassName; +import de.dhbwstuttgart.syntaxtree.ClassOrInterface; +import de.dhbwstuttgart.syntaxtree.GenericTypeVar; +import de.dhbwstuttgart.syntaxtree.TypeScope; +import de.dhbwstuttgart.syntaxtree.type.GenericRefType; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.typeinference.constraints.GenericsResolver; + +import java.util.ArrayList; +import java.util.List; + +public class MethodAssumption extends Assumption{ + private ClassOrInterface receiver; + private RefTypeOrTPHOrWildcardOrGeneric retType; + List params; + private final Boolean isInherited; + + public MethodAssumption(ClassOrInterface receiver, RefTypeOrTPHOrWildcardOrGeneric retType, + List params, TypeScope scope, Boolean isInherited){ + super(scope); + this.receiver = receiver; + this.retType = retType; + this.params = params; + this.isInherited = isInherited; + } + + /* + public RefType getReceiverType() { + + return receiver; + } + */ + + public ClassOrInterface getReceiver(){ + return receiver; + } + + public RefTypeOrTPHOrWildcardOrGeneric getReturnType(GenericsResolver resolver) { + return resolver.resolve(retType); + } + + public List getArgTypes(GenericsResolver resolver) { + List ret = new ArrayList<>(); + for(RefTypeOrTPHOrWildcardOrGeneric param : params){ + param = resolver.resolve(param); + ret.add(param); + } + return ret; + } + + /** + * + * @param resolver + * @return + */ + public RefTypeOrTPHOrWildcardOrGeneric getReceiverType(GenericsResolver resolver) { + List params = new ArrayList<>(); + for(GenericTypeVar gtv : receiver.getGenerics()){ + //Die Generics werden alle zu TPHs umgewandelt. + params.add(resolver.resolve(new GenericRefType(gtv.getName(), new NullToken()))); + } + RefTypeOrTPHOrWildcardOrGeneric receiverType; + if(receiver instanceof FunNClass){ + receiverType = new RefType(new JavaClassName(receiver.getClassName().toString()+"$$"), params, new NullToken()); // new FunN(params); + }else{ + receiverType = new RefType(receiver.getClassName(), params, new NullToken()); + } + + return receiverType; + } + + public Boolean isInherited() { + return isInherited; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/assumptions/TypeInferenceBlockInformation.java b/app/src/main/java/de/dhbwstuttgart/typeinference/assumptions/TypeInferenceBlockInformation.java new file mode 100644 index 00000000..df280d48 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/assumptions/TypeInferenceBlockInformation.java @@ -0,0 +1,36 @@ +package de.dhbwstuttgart.typeinference.assumptions; + +import com.google.common.collect.Iterables; +import com.google.common.collect.Iterators; +import de.dhbwstuttgart.syntaxtree.ClassOrInterface; +import de.dhbwstuttgart.syntaxtree.GenericTypeVar; +import de.dhbwstuttgart.syntaxtree.Method; +import de.dhbwstuttgart.syntaxtree.TypeScope; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Set; +import java.util.Stack; +import java.util.stream.Collectors; + +public class TypeInferenceBlockInformation extends TypeInferenceInformation { + private TypeScope methodContext; + private ClassOrInterface currentClass; + + public TypeInferenceBlockInformation(Collection availableClasses, + ClassOrInterface currentClass, TypeScope methodContext) { + super(availableClasses); + this.methodContext = new TypeScopeContainer(currentClass, methodContext); + this.currentClass = currentClass; + } + public TypeInferenceBlockInformation(TypeInferenceBlockInformation oldScope, TypeScope newScope) { + this(oldScope.getAvailableClasses(), oldScope.currentClass, new TypeScopeContainer(oldScope.methodContext, newScope)); + } + public ClassOrInterface getCurrentClass() { + return currentClass; + } + public TypeScope getCurrentTypeScope() { + return methodContext; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/assumptions/TypeInferenceInformation.java b/app/src/main/java/de/dhbwstuttgart/typeinference/assumptions/TypeInferenceInformation.java new file mode 100644 index 00000000..3a215bc3 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/assumptions/TypeInferenceInformation.java @@ -0,0 +1,61 @@ +package de.dhbwstuttgart.typeinference.assumptions; + +import de.dhbwstuttgart.exceptions.NotImplementedException; +import de.dhbwstuttgart.parser.NullToken; +import de.dhbwstuttgart.syntaxtree.*; +import de.dhbwstuttgart.syntaxtree.statement.ArgumentList; +import de.dhbwstuttgart.syntaxtree.type.GenericRefType; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.constraints.Constraint; +import de.dhbwstuttgart.typeinference.constraints.Pair; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Set; + +/* +Anmerkung: +Zwei Möglichkeiten, die TypeAssumptions zu speichern. +1. Die Klassen mit bedeutenden Informationen generieren diese und übergeben sie dann dieser Klasse. +2. Oder es werden nur Referenzen auf den SyntaxTree übergeben, welche diese Klasse hier dann verarbeitet. + +Bei Änderungen des SyntaxTrees müssen beide Methoden angepasst werden. +Zweiteres hat den Vorteil, dass bei der Entwicklung leichter Dinge hinzugefügt werden können. +Die ganze Logik steckt in dieser Klasse. + */ +public class TypeInferenceInformation { + private Collection classes; + + public TypeInferenceInformation(Collection availableClasses){ + classes = availableClasses; + } + + public RefTypeOrTPHOrWildcardOrGeneric checkGTV(RefTypeOrTPHOrWildcardOrGeneric type){ + if(type instanceof GenericRefType){ + return TypePlaceholder.fresh(new NullToken()); + }else{ + return type; + } + } + + public List getFields(String name){ + List ret = new ArrayList<>(); + for(ClassOrInterface cl : classes){ + for(Field m : cl.getFieldDecl()){ + if(m.getName().equals(name)){ + + ret.add(new FieldAssumption(name, cl, m.getType(), new TypeScopeContainer(cl, m))); + } + } + } + return ret; + } + + public Collection getAvailableClasses() { + return classes; + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/assumptions/TypeScopeContainer.java b/app/src/main/java/de/dhbwstuttgart/typeinference/assumptions/TypeScopeContainer.java new file mode 100644 index 00000000..c315fb52 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/assumptions/TypeScopeContainer.java @@ -0,0 +1,32 @@ +package de.dhbwstuttgart.typeinference.assumptions; + +import com.google.common.collect.Iterables; +import de.dhbwstuttgart.syntaxtree.GenericTypeVar; +import de.dhbwstuttgart.syntaxtree.TypeScope; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; + +import java.util.ArrayList; +import java.util.Stack; +import java.util.stream.Collectors; + +public class TypeScopeContainer implements TypeScope { + ArrayList scopes = new ArrayList<>(); + Stack types = new Stack<>(); + public TypeScopeContainer(TypeScope scope1, TypeScope scope2){ + scopes.add(scope1); + scopes.add(scope2); + types.push(scope1.getReturnType()); + types.push(scope2.getReturnType()); + } + + @Override + public Iterable getGenerics() { + return Iterables.concat(scopes.stream(). + map(TypeScope::getGenerics).collect(Collectors.toList()).toArray(new Iterable[0])); + } + + @Override + public RefTypeOrTPHOrWildcardOrGeneric getReturnType() { + return types.peek(); + } +} \ No newline at end of file diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/constraints/Constraint.java b/app/src/main/java/de/dhbwstuttgart/typeinference/constraints/Constraint.java new file mode 100644 index 00000000..6ebb9404 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/constraints/Constraint.java @@ -0,0 +1,59 @@ +package de.dhbwstuttgart.typeinference.constraints; + +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +public class Constraint
extends HashSet { + private static final long serialVersionUID = 1L; + private Boolean isInherited = false;//wird nur für die Method-Constraints benoetigt + + /* es darf kein Constraint für den Return-Type erstellt werden, sonst gibt + * es Probleme beim Generated Generics + */ + public boolean isStatement = false; + + private Constraint extendConstraint = null; + + public Constraint() { + super(); + } + + public Constraint(Boolean isInherited) { + this.isInherited = isInherited; + } + + public Constraint(Boolean isInherited, Constraint extendConstraint) { + this.isInherited = isInherited; + this.extendConstraint = extendConstraint; + } + + public void setIsInherited(Boolean isInherited) { + this.isInherited = isInherited; + } + + public Boolean isInherited() { + return isInherited; + } + + public Constraint getExtendConstraint() { + return extendConstraint; + } + + public void setExtendConstraint(Constraint c) { + extendConstraint = c; + } + + public String toString() { + return super.toString() + "\nisInherited = " + isInherited + "\nisStatement = " + isStatement + //" + extendsContraint: " + (extendConstraint != null ? extendConstraint.toStringBase() : "null" ) + + "\n" ; + } + + public String toStringBase() { + return super.toString(); + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/constraints/ConstraintSet.java b/app/src/main/java/de/dhbwstuttgart/typeinference/constraints/ConstraintSet.java new file mode 100644 index 00000000..1c7b7439 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/constraints/ConstraintSet.java @@ -0,0 +1,127 @@ +package de.dhbwstuttgart.typeinference.constraints; + + +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.unify.GuavaSetOperations; +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; + +import java.util.*; +import java.util.function.BinaryOperator; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.stream.Collectors; + +public class ConstraintSet { + Constraint undConstraints = new Constraint<>(); + List>> oderConstraints = new ArrayList<>(); + + public void addUndConstraint(A p){ + undConstraints.add(p); + } + + public void addOderConstraint(Set> methodConstraints) { + oderConstraints.add(methodConstraints); + } + + public void addAllUndConstraint(Constraint allUndConstraints){ + undConstraints.addAll(allUndConstraints); + } + + public void addAllOderConstraint(List>> allOderConstraints){ + this.oderConstraints.addAll(allOderConstraints); + } + + public void addAll(ConstraintSet constraints) { + this.addAllUndConstraint(constraints.undConstraints); + this.addAllOderConstraint(constraints.oderConstraints); + } + + @Override + public String toString(){ + BinaryOperator b = (x,y) -> x+y; + return "\nUND:" + this.undConstraints.toString() + "\n" + + "ODER:" + this.oderConstraints.stream().reduce("", (x,y) -> x.toString()+ "\n" +y, b); + //cartesianProduct().toString(); + } + + public Set>> cartesianProduct(){ + Set> toAdd = new HashSet<>(); + toAdd.add(undConstraints); + List>> allConstraints = new ArrayList<>(); + allConstraints.add(toAdd); + allConstraints.addAll(oderConstraints); + return new GuavaSetOperations().cartesianProduct(allConstraints); + } + + public ConstraintSet map(Function o) { + Hashtable,Constraint> CSA2CSB = new Hashtable<>(); + ConstraintSet ret = new ConstraintSet<>(); + ret.undConstraints = undConstraints.stream().map(o).collect(Collectors.toCollection(Constraint::new)); + List>> newOder = new ArrayList<>(); + /* + for(Set> oderConstraint : oderConstraints){ + oderConstraint.forEach(as -> { + Constraint newConst = as.stream() + .map(o) + .collect(Collectors.toCollection( + () -> new Constraint (as.isInherited()))); + CSA2CSB.put(as, newConst);} ); + } + */ + + for(Set> oderConstraint : oderConstraints){ + newOder.add( + oderConstraint.parallelStream().map((Constraint as) -> { + + Constraint newConst = as.stream() + .map(o) + .collect(Collectors.toCollection((as.getExtendConstraint() != null) + ? () -> new Constraint (as.isInherited(), + as.getExtendConstraint().stream().map(o).collect(Collectors.toCollection(Constraint::new))) + : () -> new Constraint (as.isInherited()) + )); + + //CSA2CSB.put(as, newConst); + + return newConst; + + /* + Constraint bs = CSA2CSB.get(as); + if (as.getExtendConstraint() != null) { + bs.setExtendConstraint(CSA2CSB.get(as.getExtendConstraint())); + } + return bs; + */ + }).collect(Collectors.toSet()) + ); + } + + ret.oderConstraints = newOder; + return ret; + } + + public void forEach (Consumer c) { + undConstraints.stream().forEach(c); + for(Set> oderConstraint : oderConstraints){ + oderConstraint.parallelStream().forEach((Constraint as) -> + as.stream().forEach(c)); + } + } + + public Set getAll () { + Set ret = new HashSet<>(); + ret.addAll(undConstraints); + for(Set> oderConstraint : oderConstraints){ + oderConstraint.parallelStream().forEach((Constraint as) -> ret.addAll(as)); + } + return ret; + } + + public List>> getOderConstraints() { + return oderConstraints; + } + + public Set getUndConstraints() { + return undConstraints; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/constraints/GenericsResolver.java b/app/src/main/java/de/dhbwstuttgart/typeinference/constraints/GenericsResolver.java new file mode 100644 index 00000000..59bcd4b4 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/constraints/GenericsResolver.java @@ -0,0 +1,14 @@ +package de.dhbwstuttgart.typeinference.constraints; + +import de.dhbwstuttgart.syntaxtree.GenericTypeVar; +import de.dhbwstuttgart.syntaxtree.type.GenericRefType; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; + +/** + * Wird für Generics benötigt + * TODO: Erklörung! + */ +public interface GenericsResolver { + public RefTypeOrTPHOrWildcardOrGeneric resolve(RefTypeOrTPHOrWildcardOrGeneric generic); +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/constraints/Pair.java b/app/src/main/java/de/dhbwstuttgart/typeinference/constraints/Pair.java new file mode 100644 index 00000000..0c8ad7a5 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/constraints/Pair.java @@ -0,0 +1,132 @@ +package de.dhbwstuttgart.typeinference.constraints; +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.unify.model.PairOperator; + + +public class Pair implements Serializable +{ + public final RefTypeOrTPHOrWildcardOrGeneric TA1; + public final RefTypeOrTPHOrWildcardOrGeneric TA2; + + private PairOperator eOperator = PairOperator.SMALLER; + + + public Pair(RefTypeOrTPHOrWildcardOrGeneric TA1, RefTypeOrTPHOrWildcardOrGeneric TA2 ) + { + this.TA1 = TA1; + this.TA2 = TA2; + if(TA1 == null || TA2 == null) + throw new NullPointerException(); + eOperator = PairOperator.SMALLER; + } + + public Pair(RefTypeOrTPHOrWildcardOrGeneric TA1, RefTypeOrTPHOrWildcardOrGeneric TA2, PairOperator eOp) + { + // Konstruktor + this(TA1,TA2); + this.eOperator = eOp; + } + + public String toString() + { + // otth: Gibt ein Paar als String aus --> zum Debuggen und Vergleichen + String strElement1 = "NULL"; + String strElement2 = "NULL"; + String Operator = "<."; + + if( TA1 != null ) + strElement1 = TA1.toString(); + + if( TA2 != null ) + strElement2 = TA2.toString(); + + /* PL ausskommentiert 2018-05-24 + if(OperatorEqual()) + Operator = "="; + if(OperatorSmaller()) + Operator = "<."; + if(OperatorSmallerExtends()) + Operator = "Author: J�rg B�uerle + * @param obj + * @return + */ + public boolean equals(Object obj) + { + boolean ret = true; + ret &= (obj instanceof Pair); + if(!ret)return ret; + ret &= ((Pair)obj).TA1.equals(this.TA1); + ret &= ((Pair)obj).TA2.equals(this.TA2); + return ret; + } + + /** + * Author: Arne Lüdtke
+ * Abfrage, ob Operator vom Typ Equal ist. + */ + public boolean OperatorEqual() + { + return eOperator == PairOperator.EQUALSDOT; + } + + /** + * Author: Arne Lüdtke
+ * Abfrage, ob Operator vom Typ Smaller ist. + */ + public boolean OperatorSmaller() + { + return eOperator == PairOperator.SMALLER; + } + + /** + * Author: Arne Lüdtke
+ * Abfrage, ob Operator vom Typ SmallerExtends ist. + */ + public boolean OperatorSmallerExtends() + { + return eOperator == PairOperator.SMALLERDOTWC; + } + + /** + * Author: Arne Lüdtke
+ * Gibt den Operator zurück. + */ + public PairOperator GetOperator() + { + return eOperator; + } + + public boolean OperatorSmallerDot() { + return eOperator == PairOperator.SMALLERDOT; + } + + + static public Map generateTPHMap(ConstraintSet constraints) { + HashMap ret = new HashMap<>(); + constraints.map((Pair p) -> { + if (p.TA1 instanceof TypePlaceholder) { + ret.put(((TypePlaceholder) p.TA1).getName(), (TypePlaceholder) p.TA1); + } + if (p.TA2 instanceof TypePlaceholder) { + ret.put(((TypePlaceholder) p.TA2).getName(), (TypePlaceholder) p.TA2); + } + return null; + }); + return ret; + } +} +// ino.end diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/result/GenericInsertPair.java b/app/src/main/java/de/dhbwstuttgart/typeinference/result/GenericInsertPair.java new file mode 100644 index 00000000..f864905d --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/result/GenericInsertPair.java @@ -0,0 +1,31 @@ +package de.dhbwstuttgart.typeinference.result; + +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.constraints.Pair; + +public class GenericInsertPair { + public TypePlaceholder TA1; + public TypePlaceholder TA2; + + public GenericInsertPair(TypePlaceholder additionalTPH, TypePlaceholder superType) { + TA1 = additionalTPH; + TA2 = superType; + } + + public GenericInsertPair(Pair pair) { + TA1 = (TypePlaceholder) pair.TA1; + TA2 = (TypePlaceholder) pair.TA2; + } + + public boolean contains(TypePlaceholder additionalTPH) { + if(TA1.equals(additionalTPH))return true; + if(TA2.equals(additionalTPH))return true; + return false; + } + + @Override + public String toString() { + return "GenIns(" + TA1.toString() + " < " + TA2.toString() + ")"; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/result/PairNoResult.java b/app/src/main/java/de/dhbwstuttgart/typeinference/result/PairNoResult.java new file mode 100644 index 00000000..63b3137c --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/result/PairNoResult.java @@ -0,0 +1,32 @@ +package de.dhbwstuttgart.typeinference.result; + +import de.dhbwstuttgart.exceptions.NotImplementedException; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; + +/** + * enthaelt alle Paare, die in einem Ergebnis nicht vorkommen koennen + * sie sind noetig fuer origPairs in PairTPHsmallerTPH, da hier auch + * Paare vorkommen koennen die keine Result sind (z.B. bei FunN$$) + */ +public class PairNoResult extends ResultPair{ + //public final TypePlaceholder left; + //public final TypePlaceholder right; + + /* + * urspruengliches Paar aus diesem dieses Resultpair erzeugt wurde + * wichtig fuer generated Generics + */ + ResultPair origPair; + + public PairNoResult(RefTypeOrTPHOrWildcardOrGeneric left, RefTypeOrTPHOrWildcardOrGeneric right){ + super(left, right); + } + + /* noch nicht implementiert. */ + @Override + public void accept(ResultPairVisitor visitor) { + throw new NotImplementedException(); + //visitor.visit(this); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/result/PairTPHEqualTPH.java b/app/src/main/java/de/dhbwstuttgart/typeinference/result/PairTPHEqualTPH.java new file mode 100644 index 00000000..c24fe211 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/result/PairTPHEqualTPH.java @@ -0,0 +1,15 @@ +package de.dhbwstuttgart.typeinference.result; + +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; + +public class PairTPHEqualTPH extends ResultPair { + public PairTPHEqualTPH(TypePlaceholder tl, TypePlaceholder tr) { + super(tl, tr); + } + + @Override + public void accept(ResultPairVisitor visitor) { + visitor.visit(this); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/result/PairTPHequalRefTypeOrWildcardType.java b/app/src/main/java/de/dhbwstuttgart/typeinference/result/PairTPHequalRefTypeOrWildcardType.java new file mode 100644 index 00000000..0c0a5872 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/result/PairTPHequalRefTypeOrWildcardType.java @@ -0,0 +1,29 @@ +package de.dhbwstuttgart.typeinference.result; + +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; + +/** + * Steht für A =. RefType + */ +public class PairTPHequalRefTypeOrWildcardType extends ResultPair{ + public final TypePlaceholder left; + public final RefTypeOrTPHOrWildcardOrGeneric right; + + public PairTPHequalRefTypeOrWildcardType(TypePlaceholder left, RefTypeOrTPHOrWildcardOrGeneric right){ + super(left, right); + this.left = left; + this.right = right; + } + + @Override + public void accept(ResultPairVisitor visitor) { + visitor.visit(this); + } + + @Override + public String toString() { + return "(" + left.toString() + " = " + right.toString() + ")"; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/result/PairTPHsmallerTPH.java b/app/src/main/java/de/dhbwstuttgart/typeinference/result/PairTPHsmallerTPH.java new file mode 100644 index 00000000..1df94e6b --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/result/PairTPHsmallerTPH.java @@ -0,0 +1,39 @@ +package de.dhbwstuttgart.typeinference.result; + +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; + +/** + * Steht für: A <. B + */ +public class PairTPHsmallerTPH extends ResultPair{ + public final TypePlaceholder left; + public final TypePlaceholder right; + + /* + * urspruengliches Paar aus diesem dieses Resultpair erzeugt wurde + * wichtig fuer generated Generics + */ + ResultPair origPair; + + public PairTPHsmallerTPH(TypePlaceholder left, TypePlaceholder right){ + super(left, right); + this.left = left; + this.right = right; + } + + public PairTPHsmallerTPH(TypePlaceholder left, TypePlaceholder right, ResultPair origPair){ + this(left, right); + this.origPair = origPair; + } + + @Override + public void accept(ResultPairVisitor visitor) { + visitor.visit(this); + } + + @Override + public String toString() { + return "(" + left.toString() + " < " + right.toString() + ")"; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/result/ResolvedType.java b/app/src/main/java/de/dhbwstuttgart/typeinference/result/ResolvedType.java new file mode 100644 index 00000000..8e7e8451 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/result/ResolvedType.java @@ -0,0 +1,27 @@ +package de.dhbwstuttgart.typeinference.result; + +import de.dhbwstuttgart.syntaxtree.type.GenericRefType; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; + +import java.util.Set; + +public class ResolvedType{ + private ResultPair resultPair; + + public final RefTypeOrTPHOrWildcardOrGeneric resolvedType; + //public final Set additionalGenerics; + + public ResolvedType(RefTypeOrTPHOrWildcardOrGeneric resolvedType, Set additionalGenerics){ + this.resolvedType = resolvedType; + //this.additionalGenerics = additionalGenerics; + } + + public void setResultPair(ResultPair resultPair) { + this.resultPair = resultPair; + } + + public ResultPair getResultPair() { + return resultPair; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/result/ResultPair.java b/app/src/main/java/de/dhbwstuttgart/typeinference/result/ResultPair.java new file mode 100644 index 00000000..490e6f95 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/result/ResultPair.java @@ -0,0 +1,62 @@ +package de.dhbwstuttgart.typeinference.result; + +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; + +/** + * Paare, welche das Unifikationsergebnis darstellen + */ +public abstract class ResultPair
{ + private final A left; + private final B right; + + public abstract void accept(ResultPairVisitor visitor); + + public ResultPair(A left, B right){ + this.left = left; + this.right = right; + } + + public A getLeft() { + return left; + } + + public B getRight() { + return right; + } + + public String toString() { + return "(" + left.toString() + ", " + right.toString() + ")"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((left == null) ? 0 : left.getOffset().hashCode()); + result = prime * result + ((right == null) ? 0 : right.getOffset().hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ResultPair other = (ResultPair) obj; + if (left == null) { + if (other.left != null) + return false; + } else if (!left.getOffset().equals(other.left.getOffset())) + return false; + if (right == null) { + if (other.right != null) + return false; + } else if (!right.getOffset().equals(other.right.getOffset())) + return false; + return true; + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/result/ResultPairVisitor.java b/app/src/main/java/de/dhbwstuttgart/typeinference/result/ResultPairVisitor.java new file mode 100644 index 00000000..e1372336 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/result/ResultPairVisitor.java @@ -0,0 +1,10 @@ +package de.dhbwstuttgart.typeinference.result; + +public interface ResultPairVisitor { + void visit(PairTPHsmallerTPH p); + void visit(PairTPHequalRefTypeOrWildcardType p); + void visit(PairTPHEqualTPH p); + + //bisher nicht umgesetzt + //void visit(PairNoResult p); +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/result/ResultSet.java b/app/src/main/java/de/dhbwstuttgart/typeinference/result/ResultSet.java new file mode 100644 index 00000000..a46b9ed2 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/result/ResultSet.java @@ -0,0 +1,309 @@ +package de.dhbwstuttgart.typeinference.result; + +import java.util.HashSet; +import java.util.Set; + +import de.dhbwstuttgart.exceptions.NotImplementedException; +import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType; +import de.dhbwstuttgart.syntaxtree.type.GenericRefType; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; + +@SuppressWarnings("rawtypes") +public class ResultSet { + + public final Set results; + public Set> genIns; + + public ResultSet(Set set){ + this.results = set; + this.genIns = new HashSet<>(); + results.forEach(x -> { if (x instanceof PairTPHsmallerTPH) { this.genIns.add(x);}} ); + } + + public boolean contains(ResultPair toCheck) { + return this.results.contains(toCheck); + } + + public void remove(ResultPair toCheck) { + results.remove(toCheck); + } + + public ResolvedType resolveType(RefTypeOrTPHOrWildcardOrGeneric type) { + if(type instanceof TypePlaceholder) + return new Resolver(this).resolve((TypePlaceholder)type); + if(type instanceof GenericRefType)return new ResolvedType(type, new HashSet<>()); + if(type instanceof RefType) { + RelatedTypeWalker related = new RelatedTypeWalker(null, this); + type.accept(related); + return new ResolvedType(type, related.relatedTPHs); + } else { + throw new NotImplementedException(); + //return new ResolvedType(type,new HashSet<>()); + } + } + + public String toString() { + return results.toString(); + } + + @Override + public boolean equals(Object o) { + if (o instanceof ResultSet) { + ResultSet other = (ResultSet)o; + return this.results.equals(other.results); + } else { + return false; + } + } + + @Override + public int hashCode() { + return results.hashCode(); + } +} + +class Resolver implements ResultSetVisitor { + private final ResultSet result; + private TypePlaceholder toResolve; + private RefTypeOrTPHOrWildcardOrGeneric resolved; + private final Set additionalTPHs = new HashSet<>(); + private ResultPair currentPair; + + public Resolver(ResultSet resultPairs){ + this.result = resultPairs; + } + + public ResolvedType resolve(TypePlaceholder tph){ + toResolve = tph; + resolved = null; + System.out.println(tph.toString()); + for(ResultPair resultPair : result.results) { + if(resultPair instanceof PairTPHEqualTPH && ((PairTPHEqualTPH) resultPair).getLeft().equals(toResolve)){ + currentPair = resultPair; + return resolve(((PairTPHEqualTPH) resultPair).getRight()); + } + } + for(ResultPair resultPair : result.results){ + currentPair = resultPair; + resultPair.accept(this); + } + if(resolved==null){//TPH kommt nicht im Result vor: + resolved = tph; + } + + ResolvedType result = new ResolvedType(resolved, additionalTPHs);//resolved; + result.setResultPair(currentPair); + return result; + } + + @Override + public void visit(PairTPHsmallerTPH p) { + currentPair = p; + if(p.left.equals(toResolve)){ + additionalTPHs.add(new GenericInsertPair(p.left, p.right)); + additionalTPHs.addAll(new RelatedTypeWalker(p.right, result).relatedTPHs); + } + if(p.right.equals(toResolve)) + additionalTPHs.addAll(new RelatedTypeWalker(p.left, result).relatedTPHs); + } + + @Override + public void visit(PairTPHequalRefTypeOrWildcardType p) { + currentPair = p; + if(p.left.equals(toResolve)){ + resolved = p.right; + RelatedTypeWalker related = new RelatedTypeWalker(null, result); + p.right.accept(related); + additionalTPHs.addAll(related.relatedTPHs); + } + } + + @Override + public void visit(PairTPHEqualTPH p) { + //Do nothing. Dieser Fall wird in der resolve-Methode abgefangen + } + + @Override + public void visit(RefType refType) { + + } + + @Override + public void visit(GenericRefType genericRefType) { + + } + + @Override + public void visit(SuperWildcardType superWildcardType) { + + } + + @Override + public void visit(TypePlaceholder typePlaceholder) { + + } + + @Override + public void visit(ExtendsWildcardType extendsWildcardType) { + + } + + + +} + +/** + * Sucht aus dem Result Set den Sub/supertyp für einen TPH + */ +@SuppressWarnings("rawtypes") +class TPHResolver implements ResultSetVisitor { + + private final TypePlaceholder tph; + Set resolved = new HashSet<>(); + private final ResultSet resultSet; + + TPHResolver(TypePlaceholder tph, ResultSet resultSet){ + this.resultSet = resultSet; + this.tph = tph; + for(ResultPair p : resultSet.results){ + p.accept(this); + } + if(resolved.size() == 0){ + resolved.add(new GenericInsertPair(tph, null)); + } + } + + @Override + public void visit(PairTPHsmallerTPH p) { + if(p.left.equals(tph) || p.right.equals(tph)){ + resolved.add(new GenericInsertPair(p.left, p.right)); + } + } + + @Override + public void visit(PairTPHequalRefTypeOrWildcardType p) { + TypePlaceholder otherSide = null; + if(p.right.equals(tph)){ + otherSide = p.left; + } + if(otherSide != null){ + Set newResultSet = new HashSet<>(this.resultSet.results); + newResultSet.remove(p); + resolved.addAll(new TPHResolver(otherSide, new ResultSet(newResultSet)).resolved); + } + } + + @Override + public void visit(PairTPHEqualTPH p) { + //ignorieren. Wird vom Resolver behandelt + } + + @Override + public void visit(RefType refType) { + + } + + @Override + public void visit(GenericRefType genericRefType) { + + } + + @Override + public void visit(SuperWildcardType superWildcardType) { + + } + + @Override + public void visit(TypePlaceholder typePlaceholder) { + + } + + @Override + public void visit(ExtendsWildcardType extendsWildcardType) { + + } +} + +@SuppressWarnings("rawtypes") +class RelatedTypeWalker implements ResultSetVisitor { + + final Set relatedTPHs = new HashSet<>(); + private final TypePlaceholder toResolve; + private final ResultSet resultSet; + + /** + * Läuft über das resultSet und speichert alle TPHs, welche mit start in Verbindung stehen + * @param start - kann null sein, wenn der Walker für einen RefType benutzt wird + * @param resultSet + */ + RelatedTypeWalker(TypePlaceholder start, ResultSet resultSet){ + this.toResolve = start; + this.resultSet = resultSet; + int resolved = 0; + do{ + resolved = relatedTPHs.size(); + for(ResultPair p : resultSet.results){ + p.accept(this); + p.accept(this); + } + }while(resolved - relatedTPHs.size() > 0); + } + + @Override + public void visit(PairTPHsmallerTPH p) { + if(p.getRight().equals(toResolve)){ + relatedTPHs.addAll(new TPHResolver(p.right, resultSet).resolved); + //relatedTPHs.addAll(new RelatedTypeWalker(p.right, resultSet).relatedTPHs); + } + if(p.getLeft().equals(toResolve)){ + relatedTPHs.addAll(new TPHResolver(p.left, resultSet).resolved); + //relatedTPHs.addAll(new RelatedTypeWalker(p.left, resultSet).relatedTPHs); + } + } + + @Override + public void visit(PairTPHequalRefTypeOrWildcardType p) { + if(p.getLeft().equals(toResolve)){ + p.getRight().accept(this); + } + } + + @Override + public void visit(PairTPHEqualTPH p) { + //Kann ignoriert werden. Diese Fälle werden vom Resolver behandelt + } + + /* + Die folgenden Funktionen fügen alle TPHs an die relatedTPHs an, denen sie begegnen: + Das wird verwendet, wenn alle relatedTPHs aus den Parametern eines RefTypes angefügt werden sollen + */ + + @Override + public void visit(RefType refType) { + for(RefTypeOrTPHOrWildcardOrGeneric param : refType.getParaList()){ + param.accept(this); + } + } + + @Override + public void visit(SuperWildcardType superWildcardType) { + superWildcardType.getInnerType().accept(this); + } + + @Override + public void visit(TypePlaceholder typePlaceholder) { + relatedTPHs.addAll(new TPHResolver(typePlaceholder, resultSet).resolved); + } + + @Override + public void visit(ExtendsWildcardType extendsWildcardType) { + extendsWildcardType.getInnerType().accept(this); + } + + @Override + public void visit(GenericRefType genericRefType) { + } +} \ No newline at end of file diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/result/ResultSetVisitor.java b/app/src/main/java/de/dhbwstuttgart/typeinference/result/ResultSetVisitor.java new file mode 100644 index 00000000..105fc8af --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/result/ResultSetVisitor.java @@ -0,0 +1,17 @@ +package de.dhbwstuttgart.typeinference.result; + +import de.dhbwstuttgart.syntaxtree.type.*; + +public interface ResultSetVisitor extends ResultPairVisitor{ + + void visit(RefType refType); + + void visit(GenericRefType genericRefType); + + void visit(SuperWildcardType superWildcardType); + + void visit(TypePlaceholder typePlaceholder); + + void visit(ExtendsWildcardType extendsWildcardType); + +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/GenericsResolverSameName.java b/app/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/GenericsResolverSameName.java new file mode 100644 index 00000000..2bb131f1 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/GenericsResolverSameName.java @@ -0,0 +1,56 @@ +package de.dhbwstuttgart.typeinference.typeAlgo; + +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.type.*; +import de.dhbwstuttgart.typeinference.constraints.GenericsResolver; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +/** + * Ein GenericsResolver, welcher Generics mit dem selben Namen den selben TPH zuordnet + */ +public class GenericsResolverSameName implements GenericsResolver, TypeVisitor{ + + HashMap map = new HashMap<>(); + + @Override + public RefTypeOrTPHOrWildcardOrGeneric resolve(RefTypeOrTPHOrWildcardOrGeneric generic) { + return generic.acceptTV(this); + } + + @Override + public RefTypeOrTPHOrWildcardOrGeneric visit(RefType refType) { + List params = new ArrayList<>(); + for(RefTypeOrTPHOrWildcardOrGeneric param : refType.getParaList()){ + params.add(param.acceptTV(this)); + } + RefType ret = new RefType(refType.getName(), params, refType.getOffset()); + return ret; + } + + @Override + public RefTypeOrTPHOrWildcardOrGeneric visit(SuperWildcardType superWildcardType) { + return new SuperWildcardType(superWildcardType.getInnerType().acceptTV(this), superWildcardType.getOffset()); + } + + @Override + public RefTypeOrTPHOrWildcardOrGeneric visit(TypePlaceholder typePlaceholder) { + return typePlaceholder; + } + + @Override + public RefTypeOrTPHOrWildcardOrGeneric visit(ExtendsWildcardType extendsWildcardType) { + return new ExtendsWildcardType(extendsWildcardType.getInnerType().acceptTV(this), extendsWildcardType.getOffset()); + } + + @Override + public RefTypeOrTPHOrWildcardOrGeneric visit(GenericRefType genericRefType) { + String name = genericRefType.getParsedName(); + if(!map.containsKey(name)){ + map.put(name, TypePlaceholder.fresh(genericRefType.getOffset())); + } + return map.get(name); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPE.java b/app/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPE.java new file mode 100644 index 00000000..685ac9f6 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPE.java @@ -0,0 +1,86 @@ +package de.dhbwstuttgart.typeinference.typeAlgo; + +import de.dhbwstuttgart.exceptions.DebugException; +import de.dhbwstuttgart.parser.scope.JavaClassName; +import de.dhbwstuttgart.syntaxtree.*; +import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; +import de.dhbwstuttgart.syntaxtree.statement.Statement; +import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; +import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation; +import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; +import java.util.*; + +public class TYPE { + + private final Collection sfs; + private final TypeInferenceInformation typeInferenceInformation; + + public TYPE(Collection sourceFiles, Collection allAvailableClasses){ + sfs = sourceFiles; + this.typeInferenceInformation = new TypeInferenceInformation(allAvailableClasses); + } + + + public ConstraintSet getConstraints() { + ConstraintSet ret = new ConstraintSet(); + for(SourceFile sf : sfs) + for (ClassOrInterface cl : sf.KlassenVektor) { + ret.addAll(getConstraintsClass(cl ,typeInferenceInformation)); + } + return ret; + } + + private ConstraintSet getConstraintsClass(ClassOrInterface cl, TypeInferenceInformation info) { + ConstraintSet ret = new ConstraintSet(); + ConstraintSet methConstrains; + for(Method m : cl.getMethods()){ + ret.addAll(methConstrains = getConstraintsMethod(m,info, cl)); + m.constraints.addAll(methConstrains); + } + for(Constructor m : cl.getConstructors()){ + ret.addAll(getConstraintsConstructor(m,info, cl)); + } + if (cl.getfieldInitializations().isPresent()) { + ret.addAll(getConstraintsConstructor(cl.getfieldInitializations().get(), info, cl)); + } + return ret; + } + /* + TODO: Hier eine Information erstellen nur mit den importierte Klassen einer einzigen SourceFile + private TypeInferenceInformation getTypeInferenceInformation(sourceFile) { + DirectoryClassLoader classLoader = DirectoryClassLoader.getSystemClassLoader(); + Set classes = new HashSet<>(); + + for(SourceFile sourceFile : sfs){ + for(JavaClassName importName : sourceFile.imports){ + System.out.println(importName); + try { + classes.add(ASTFactory.createClass(classLoader.loadClass(importName.toString()))); + } catch (ClassNotFoundException e) { + throw new DebugException("Klasse " + importName + " konnte nicht geladen werden"); + } + } + classes.addAll(sourceFile.KlassenVektor); + } + + return new TypeInferenceInformation(classes); + } + */ + + private ConstraintSet getConstraintsMethod(Method m, TypeInferenceInformation info, ClassOrInterface currentClass) { + if(m.block == null)return new ConstraintSet(); //Abstrakte Methoden generieren keine Constraints + TypeInferenceBlockInformation blockInfo = new TypeInferenceBlockInformation(info.getAvailableClasses(), currentClass, m); + TYPEStmt methodScope = new TYPEStmt(blockInfo); + m.block.accept(methodScope); + return methodScope.getConstraints(); + } + + private ConstraintSet getConstraintsConstructor(Constructor m, TypeInferenceInformation info, ClassOrInterface currentClass) { + TypeInferenceBlockInformation blockInfo = new TypeInferenceBlockInformation(info.getAvailableClasses(), currentClass, m); + TYPEStmt methodScope = new TYPEStmt(blockInfo); + //for(Statement stmt : m.fieldInitializations)stmt.accept(methodScope); + ConstraintSet ret = this.getConstraintsMethod(m, info, currentClass); + ret.addAll(methodScope.getConstraints()); + return ret; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java b/app/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java new file mode 100644 index 00000000..ddc2dc92 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java @@ -0,0 +1,711 @@ +//PL 2018-12-19: Merge chekcen +package de.dhbwstuttgart.typeinference.typeAlgo; + +import de.dhbwstuttgart.exceptions.NotImplementedException; +import de.dhbwstuttgart.exceptions.TypeinferenceException; +import de.dhbwstuttgart.parser.NullToken; +import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; +import de.dhbwstuttgart.parser.scope.JavaClassName; +import de.dhbwstuttgart.syntaxtree.*; +import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; +import de.dhbwstuttgart.syntaxtree.factory.NameGenerator; +import de.dhbwstuttgart.syntaxtree.statement.*; +import de.dhbwstuttgart.syntaxtree.type.*; +import de.dhbwstuttgart.syntaxtree.type.Void; +import de.dhbwstuttgart.typeinference.assumptions.FieldAssumption; +import de.dhbwstuttgart.typeinference.assumptions.FunNClass; +import de.dhbwstuttgart.typeinference.assumptions.MethodAssumption; +import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; +import de.dhbwstuttgart.typeinference.constraints.*; +import de.dhbwstuttgart.typeinference.unify.model.ExtendsType; +import de.dhbwstuttgart.typeinference.unify.model.PairOperator; +import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType; +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; + +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class TYPEStmt implements StatementVisitor{ + + private final TypeInferenceBlockInformation info; + private final ConstraintSet constraintsSet = new ConstraintSet(); + + public TYPEStmt(TypeInferenceBlockInformation info){ + this.info = info; + } + + public ConstraintSet getConstraints() { + return constraintsSet; + } + + /** + * Erstellt einen neuen GenericResolver + * Die Idee dieser Datenstruktur ist es, GTVs einen eindeutigen TPH zuzuweisen. + * Bei Methodenaufrufen oder anderen Zugriffen, bei denen alle benutzten GTVs jeweils einen einheitlichen TPH bekommen müssen + * kann diese Klasse eingesetzt werden. Wichtig ist, dass hierfür jeweils eine frische Instanz benutzt wird. + * @return + */ + private static GenericsResolver getResolverInstance(){ + return new GenericsResolverSameName(); + } + + private static TypeScope createTypeScope(ClassOrInterface cl, Method method) { + return null; + } + + @Override + public void visit(ArgumentList arglist) { + for(int i = 0;i lambdaParams = lambdaExpression.params.getFormalparalist().stream().map((formalParameter -> formalParameter.getType())).collect(Collectors.toList()); + lambdaParams.add(tphRetType); + //lambdaParams.add(0,tphRetType); + constraintsSet.addUndConstraint( + new Pair(lambdaExpression.getType(), + new RefType(new JavaClassName("Fun"+(lambdaParams.size()-1)+"$$"), lambdaParams, new NullToken()), + //new FunN(lambdaParams), + PairOperator.EQUALSDOT)); + constraintsSet.addUndConstraint( + new Pair(lambdaExpression.getReturnType(), + tphRetType,PairOperator.EQUALSDOT)); + + //Constraints des Bodys generieren: + TYPEStmt lambdaScope = new TYPEStmt(new TypeInferenceBlockInformation(info, lambdaExpression)); + lambdaExpression.methodBody.accept(lambdaScope); + constraintsSet.addAll(lambdaScope.getConstraints()); + } + + @Override + public void visit(Assign assign) { + assign.lefSide.accept(this); + assign.rightSide.accept(this); + constraintsSet.addUndConstraint(new Pair( + assign.rightSide.getType(), assign.lefSide.getType(), PairOperator.SMALLERDOT)); + } + + @Override + public void visit(Block block) { + for(Statement stmt : block.getStatements()){ + stmt.accept(this); + } + } + + @Override + public void visit(CastExpr castExpr) { + throw new NotImplementedException(); + } + + @Override + public void visit(EmptyStmt emptyStmt) { + //Nothing :) + } + + @Override + public void visit(FieldVar fieldVar) { + fieldVar.receiver.accept(this); + Set oderConstraints = new HashSet<>(); + for(FieldAssumption fieldAssumption : info.getFields(fieldVar.fieldVarName)){ + Constraint constraint = new Constraint(); + GenericsResolver resolver = getResolverInstance(); + constraint.add(new Pair(fieldVar.receiver.getType(), fieldAssumption.getReceiverType(resolver), PairOperator.SMALLERDOT)); //PL 2019-12-09: SMALLERDOT eingefuegt, EQUALSDOT entfernt, wenn ds Field privat ist muesste es EQUALSDOT lauten + constraint.add(new Pair( + fieldVar.getType(), fieldAssumption.getType(resolver), PairOperator.EQUALSDOT)); + oderConstraints.add(constraint); + } + if(oderConstraints.size() == 0) + throw new TypeinferenceException("Kein Feld "+fieldVar.fieldVarName+ " gefunden", fieldVar.getOffset()); + constraintsSet.addOderConstraint(oderConstraints); + } + + @Override + public void visit(ForStmt forStmt) { + throw new NotImplementedException(); + } + + @Override + public void visit(IfStmt ifStmt) { + RefType booleanType = new RefType(ASTFactory.createClass(java.lang.Boolean.class).getClassName(), new NullToken()); + //Expression inferieren: + ifStmt.expr.accept(this); + //Expression muss boolean sein: + constraintsSet.addUndConstraint(new Pair(ifStmt.expr.getType(), booleanType, PairOperator.EQUALSDOT)); + //Blöcke inferieren: + ifStmt.then_block.accept(this); + //Beide Blöcke müssen den gleichen Supertyp haben, welcher den Rückgabetyp des If-Stmts darstellt + constraintsSet.addUndConstraint(new Pair(ifStmt.else_block.getType(), ifStmt.getType(), PairOperator.SMALLERDOT)); + if(ifStmt.else_block != null){ + ifStmt.else_block.accept(this); + constraintsSet.addUndConstraint(new Pair(ifStmt.else_block.getType(), ifStmt.getType(), PairOperator.SMALLERDOT)); + } + + } + + @Override + public void visit(InstanceOf instanceOf) { + throw new NotImplementedException(); + } + + @Override + public void visit(LocalVar localVar) { + // Es werden nur bei Feldvariablen Constraints generiert. Lokale Variablen sind eindeutig + } + + @Override + public void visit(LocalVarDecl localVarDecl) { + //Hier ist nichts zu tun. Allen lokalen Variablen bekommen beim parsen schon den korrekten Typ + } + + @Override + //Es wird in OderConstraints davon ausgegangen dass die Bedingungen für die Typen der Argumente links stehen + //und die Typen der Rückgabewerte immer rechts stehen (vgl. JavaTXCompiler) + public void visit(MethodCall methodCall) { + methodCall.receiver.accept(this); + //Overloading: + Set> methodConstraints = new HashSet<>(); + for(MethodAssumption m : this.getMethods(methodCall.name, methodCall.arglist, info)){ + GenericsResolver resolver = getResolverInstance(); + Constraint oneMethodConstraint = generateConstraint(methodCall, m, info, resolver); + methodConstraints.add(oneMethodConstraint); + + Constraint extendsOneMethodConstraint = oneMethodConstraint.stream() + .map(x -> (x.TA1 instanceof TypePlaceholder && + x.GetOperator() == PairOperator.EQUALSDOT && + !(x.TA2 instanceof TypePlaceholder)) + ? new Pair(x.TA1, new ExtendsWildcardType(x.TA2, x.TA2.getOffset()), PairOperator.EQUALSDOT) + : x) + .collect(Collectors.toCollection(() -> new Constraint(oneMethodConstraint.isInherited()))); + extendsOneMethodConstraint.isStatement = oneMethodConstraint.isStatement; + oneMethodConstraint.setExtendConstraint(extendsOneMethodConstraint); + extendsOneMethodConstraint.setExtendConstraint(oneMethodConstraint); + methodConstraints.add(extendsOneMethodConstraint); + } + if(methodConstraints.size()<1){ + throw new TypeinferenceException("Methode "+methodCall.name+" ist nicht vorhanden!",methodCall.getOffset()); + } + constraintsSet.addOderConstraint(methodConstraints); + } + + @Override + public void visit(NewClass methodCall) { + //Overloading: + Set methodConstraints = new HashSet<>(); + for(MethodAssumption m : this.getConstructors(info, (RefType) methodCall.getType(), methodCall.getArgumentList())){ + methodConstraints.add(generateConstructorConstraint(methodCall, m, info, getResolverInstance())); + } + if(methodConstraints.size()<1){ + throw new TypeinferenceException("Konstruktor in Klasse "+methodCall.getType().toString()+" ist nicht vorhanden!",methodCall.getOffset()); + } + constraintsSet.addOderConstraint(methodConstraints); + } + + @Override + public void visit(NewArray newArray) { + throw new NotImplementedException(); + } + + @Override + public void visit(ExpressionReceiver receiver) { + receiver.expr.accept(this); + } + + private final RefType number = new RefType(ASTFactory.createClass(Number.class).getClassName(), new NullToken()); + private final RefType longg = new RefType(ASTFactory.createClass(Long.class).getClassName(), new NullToken()); + private final RefType integer = new RefType(ASTFactory.createClass(Integer.class).getClassName(), new NullToken()); + private final RefType shortt = new RefType(ASTFactory.createClass(Short.class).getClassName(), new NullToken()); + private final RefType bytee = new RefType(ASTFactory.createClass(Byte.class).getClassName(), new NullToken()); + private final RefType floatt = new RefType(ASTFactory.createClass(Float.class).getClassName(), new NullToken()); + private final RefType doublee = new RefType(ASTFactory.createClass(Double.class).getClassName(), new NullToken()); + private final RefType string = new RefType(ASTFactory.createClass(String.class).getClassName(), new NullToken()); + private final RefType bool = new RefType(ASTFactory.createClass(Boolean.class).getClassName(), new NullToken()); + @Override + public void visit(UnaryExpr unaryExpr) { + if(unaryExpr.operation == UnaryExpr.Operation.POSTDECREMENT || + unaryExpr.operation == UnaryExpr.Operation.POSTINCREMENT || + unaryExpr.operation == UnaryExpr.Operation.PREDECREMENT || + unaryExpr.operation == UnaryExpr.Operation.PREINCREMENT){ + //@see: https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.14.2 + //Expression muss zu Numeric Convertierbar sein. also von Numeric erben + constraintsSet.addUndConstraint(new Pair(unaryExpr.expr.getType(), number, PairOperator.SMALLERNEQDOT)); + //The type of the postfix increment expression is the type of the variable + constraintsSet.addUndConstraint(new Pair(unaryExpr.expr.getType(), unaryExpr.getType(), PairOperator.EQUALSDOT)); + }else{ + throw new NotImplementedException(); + } + } + + @Override + //Es wird in OderConstraints davon ausgegangen dass die Bedingungen für die Typen der Argumente links stehen + //und die Typen der Rückgabewerte immer rechts stehen (vgl. JavaTXCompiler) + public void visit(BinaryExpr binary) { + binary.lexpr.accept(this); + binary.rexpr.accept(this); + if(binary.operation.equals(BinaryExpr.Operator.DIV) || + binary.operation.equals(BinaryExpr.Operator.MUL)|| + binary.operation.equals(BinaryExpr.Operator.MOD)|| + binary.operation.equals(BinaryExpr.Operator.ADD)|| + binary.operation.equals(BinaryExpr.Operator.SUB)) { + Set> numericAdditionOrStringConcatenation = new HashSet<>(); + +// TODO PL 2018-11-06 + + // Auf importierte Typen einschraenken + // pruefen, ob Typen richtig bestimmt werden. + + + + //Zuerst der Fall für Numerische AusdrücPairOpnumericeratorke, das sind Mul, Mod und Div immer: + //see: https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.17 + //Expression muss zu Numeric Convertierbar sein. also von Numeric erben + Constraint numeric; + //PL eingefuegt 2018-07-17 + if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(bytee.getName())) { + numeric = new Constraint<>(); + numeric.add(new Pair(binary.lexpr.getType(), bytee, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.rexpr.getType(), bytee, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.getType(), integer, PairOperator.EQUALSDOT)); + numericAdditionOrStringConcatenation.add(numeric); + } + //PL eingefuegt 2018-07-17 + if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(shortt.getName())) { + numeric = new Constraint<>(); + numeric.add(new Pair(binary.lexpr.getType(), shortt, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.rexpr.getType(), shortt, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.getType(), integer, PairOperator.EQUALSDOT)); + numericAdditionOrStringConcatenation.add(numeric); + } + //PL eingefuegt 2018-07-17 + if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(integer.getName())) { + numeric = new Constraint<>(); + numeric.add(new Pair(binary.lexpr.getType(), integer, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.rexpr.getType(), integer, PairOperator.SMALLERDOT)); + numeric.add(new Pair(integer, binary.getType(), PairOperator.EQUALSDOT)); + numericAdditionOrStringConcatenation.add(numeric); + } + //PL eingefuegt 2018-07-17 + if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(longg.getName())) { + numeric = new Constraint<>(); + numeric.add(new Pair(binary.lexpr.getType(), longg, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.rexpr.getType(), longg, PairOperator.SMALLERDOT)); + numeric.add(new Pair(longg, binary.getType(), PairOperator.EQUALSDOT)); + numericAdditionOrStringConcatenation.add(numeric); + } + //PL eingefuegt 2018-07-17 + if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(floatt.getName())) { + numeric = new Constraint<>(); + numeric.add(new Pair(binary.lexpr.getType(), floatt, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.rexpr.getType(), floatt, PairOperator.SMALLERDOT)); + numeric.add(new Pair(floatt, binary.getType(), PairOperator.EQUALSDOT)); + numericAdditionOrStringConcatenation.add(numeric); + } + //PL eingefuegt 2018-07-17 + if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(doublee.getName())) { + numeric = new Constraint<>(); + numeric.add(new Pair(binary.lexpr.getType(), doublee, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.rexpr.getType(), doublee, PairOperator.SMALLERDOT)); + numeric.add(new Pair(doublee, binary.getType(), PairOperator.EQUALSDOT)); + numericAdditionOrStringConcatenation.add(numeric); + } + /* PL auskommentiert Anfang 2018-07-17 + /* + In Java passiert bei den binären Operatoren eine sogenannte Type Promotion: + https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.6.2 + Das bedeutet, dass Java die Typen je nach belieben castet, so lange sie nur von Number erben + + numeric = new Constraint<>(); + numeric.add(new Pair(binary.getType(), number, PairOperator.SMALLERDOT)); + numericAdditionOrStringConcatenation.add(numeric); + * PL auskommentiert Ende 2018-07-17 */ + + if(binary.operation.equals(BinaryExpr.Operator.ADD)) { + //Dann kann der Ausdruck auch das aneinanderfügen zweier Strings sein: ("a" + "b") oder (1 + 2) + if (info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)).contains(string.getName())) { + Constraint stringConcat = new Constraint<>(); + stringConcat.add(new Pair(binary.lexpr.getType(), string, PairOperator.EQUALSDOT)); + stringConcat.add(new Pair(binary.rexpr.getType(), string, PairOperator.EQUALSDOT)); + stringConcat.add(new Pair(string, binary.getType(), PairOperator.EQUALSDOT)); + numericAdditionOrStringConcatenation.add(stringConcat); + } + } + if(numericAdditionOrStringConcatenation.size()<1){ + throw new TypeinferenceException("Kein Typ für " + binary.operation.toString() + " vorhanden", binary.getOffset()); + } + constraintsSet.addOderConstraint(numericAdditionOrStringConcatenation); + }else if(binary.operation.equals(BinaryExpr.Operator.LESSEQUAL) || + binary.operation.equals(BinaryExpr.Operator.BIGGEREQUAL) || + binary.operation.equals(BinaryExpr.Operator.BIGGERTHAN) || + binary.operation.equals(BinaryExpr.Operator.LESSTHAN)) { + /* //eingefuegt PL 2018-05-24 + Set> numericRelationConcatenation = new HashSet<>(); + Constraint numeric = new Constraint<>(); + numeric.add(new Pair(binary.lexpr.getType(), bytee, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.rexpr.getType(), bytee, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.getType(), bool, PairOperator.SMALLERDOT)); + numericRelationConcatenation.add(numeric); + numeric = new Constraint<>(); + numeric.add(new Pair(binary.lexpr.getType(), shortt, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.rexpr.getType(), shortt, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.getType(), bool, PairOperator.SMALLERDOT)); + numericRelationConcatenation.add(numeric); + numeric = new Constraint<>(); + numeric.add(new Pair(binary.lexpr.getType(), integer, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.rexpr.getType(), integer, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.getType(), bool, PairOperator.SMALLERDOT)); + numericRelationConcatenation.add(numeric); + numeric = new Constraint<>(); + numeric.add(new Pair(binary.lexpr.getType(), longg, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.rexpr.getType(), longg, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.getType(), bool, PairOperator.SMALLERDOT)); + numericRelationConcatenation.add(numeric); + numeric = new Constraint<>(); + numeric.add(new Pair(binary.lexpr.getType(), floatt, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.rexpr.getType(), floatt, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.getType(), bool, PairOperator.SMALLERDOT)); + numericRelationConcatenation.add(numeric); + numeric = new Constraint<>(); + numeric.add(new Pair(binary.lexpr.getType(), doublee, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.rexpr.getType(), doublee, PairOperator.SMALLERDOT)); + numeric.add(new Pair(binary.getType(), bool, PairOperator.SMALLERDOT)); + numericRelationConcatenation.add(numeric); + + //***ACHTUNG: Moeglicherweise oder und und-Contraint falsch + constraintsSet.addOderConstraint(numericRelationConcatenation); + //***ACHTUNG: Moeglicherweise oder und und-Contraint falsch + */ + //Testeise eingefuegt PL 2018-05-24 + //Hier sollte evtl. noch importe angefragt werden PL 2019-05-07 + constraintsSet.addUndConstraint(new Pair(binary.lexpr.getType(), number, PairOperator.SMALLERNEQDOT)); + constraintsSet.addUndConstraint(new Pair(binary.rexpr.getType(), number, PairOperator.SMALLERNEQDOT)); + //Rückgabetyp ist Boolean + constraintsSet.addUndConstraint(new Pair(bool, binary.getType(), PairOperator.EQUALSDOT)); + + //auskommentiert PL 2018-05-24 + //constraintsSet.addUndConstraint(new Pair(binary.lexpr.getType(), number, PairOperator.SMALLERDOT)); + //constraintsSet.addUndConstraint(new Pair(binary.rexpr.getType(), number, PairOperator.SMALLERDOT)); + //Rückgabetyp ist Boolean + //constraintsSet.addUndConstraint(new Pair(bool, binary.getType(), PairOperator.EQUALSDOT)); + }else if(binary.operation.equals(BinaryExpr.Operator.EQUAL) || binary.operation.equals(BinaryExpr.Operator.NOTEQUAL)){ + /*Auszug aus https://docs.oracle.com/javase/specs/jls/se9/html/jls-15.html#jls-15.21 + The equality operators may be used to compare two operands that are convertible (§5.1.8) to numeric type, or two operands of type boolean or Boolean, or two operands that are each of either reference type or the null type. All other cases result in a compile-time error. + */ + //Der Equals Operator geht mit fast allen Typen, daher werden hier keine Constraints gesetzt + constraintsSet.addUndConstraint(new Pair(bool, binary.getType(), PairOperator.EQUALSDOT)); + }else{ + throw new NotImplementedException(); + } + } + + @Override + public void visit(Literal literal) { + //Nothing to do here. Literale erzeugen keine Constraints + //PL 2018-06-23 Sie haben einen Typ. Der muesste hier eingefuegt werden + //wie hier fuer double gezeigt. Im Momment auskommentiert, weil zu wenige Literaltypen + //funktionieren + if (literal.value instanceof Short) { + constraintsSet.addUndConstraint(new Pair(literal.getType(), shortt, PairOperator.EQUALSDOT)); + return; + } + if (literal.value instanceof Byte) { + constraintsSet.addUndConstraint(new Pair(literal.getType(), bytee, PairOperator.EQUALSDOT)); + return; + } + if (literal.value instanceof Float) { + constraintsSet.addUndConstraint(new Pair(literal.getType(), floatt, PairOperator.EQUALSDOT)); + return; + } + if (literal.value instanceof Double) { + constraintsSet.addUndConstraint(new Pair(literal.getType(), doublee, PairOperator.EQUALSDOT)); + return; + } + if (literal.value instanceof Long) { + constraintsSet.addUndConstraint(new Pair(literal.getType(), longg, PairOperator.EQUALSDOT)); + return; + } + if (literal.value instanceof Integer) { + //constraintsSet.addUndConstraint(new Pair(literal.getType(),integer, PairOperator.EQUALSDOT)); + // /* + HashSet clNames = info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)); + Set oderConstraints = new HashSet<>(); + Constraint constraint = new Constraint(); + constraint.add(new Pair(literal.getType(), integer, PairOperator.EQUALSDOT)); + oderConstraints.add(constraint); + if (clNames.stream().filter(x -> x.toString().equals("java.lang.Double")).findAny().isPresent()) { + constraint = new Constraint(); + constraint.add(new Pair(literal.getType(), doublee, PairOperator.EQUALSDOT)); + oderConstraints.add(constraint); + } + if (clNames.stream().filter(x -> x.toString().equals("java.lang.Long")).findAny().isPresent()) { + constraint = new Constraint(); + constraint.add(new Pair(literal.getType(), longg, PairOperator.EQUALSDOT)); + oderConstraints.add(constraint); + } + if (clNames.stream().filter(x -> x.toString().equals("java.lang.Float")).findAny().isPresent()) { + constraint = new Constraint(); + constraint.add(new Pair(literal.getType(), floatt, PairOperator.EQUALSDOT)); + oderConstraints.add(constraint); + } + if (clNames.stream().filter(x -> x.toString().equals("java.lang.Short")).findAny().isPresent()) { + constraint = new Constraint(); + constraint.add(new Pair(literal.getType(), shortt, PairOperator.EQUALSDOT)); + oderConstraints.add(constraint); + } + if (clNames.stream().filter(x -> x.toString().equals("java.lang.Byte")).findAny().isPresent()) { + constraint = new Constraint(); + constraint.add(new Pair(literal.getType(), bytee, PairOperator.EQUALSDOT)); + oderConstraints.add(constraint); + } + constraintsSet.addOderConstraint(oderConstraints); + // */ + return; + } + if (literal.value instanceof Short) { + constraintsSet.addUndConstraint(new Pair(literal.getType(),shortt, PairOperator.EQUALSDOT)); + return; + } + if (literal.value instanceof Byte) { + constraintsSet.addUndConstraint(new Pair(literal.getType(),bytee, PairOperator.EQUALSDOT)); + return; + } + if (literal.value instanceof Float) { + constraintsSet.addUndConstraint(new Pair(literal.getType(),floatt, PairOperator.EQUALSDOT)); + return; + } + if (literal.value instanceof String) { + constraintsSet.addUndConstraint(new Pair(literal.getType(),string, PairOperator.EQUALSDOT)); + return; + } + if (literal.value instanceof Boolean) { + constraintsSet.addUndConstraint(new Pair(literal.getType(),bool, PairOperator.EQUALSDOT)); + return; + } + else { + throw new NotImplementedException(); + } + } + + @Override + public void visit(Return returnExpr) { + returnExpr.retexpr.accept(this); + constraintsSet.addUndConstraint(new Pair(returnExpr.getType(),info.getCurrentTypeScope().getReturnType(), PairOperator.EQUALSDOT)); + } + + @Override + public void visit(ReturnVoid aReturn) { + visit((Return) aReturn); + } + + @Override + public void visit(StaticClassName staticClassName) { + //Hier entstehen keine Constraints + } + + @Override + public void visit(Super aSuper) { + throw new NotImplementedException(); + } + + @Override + public void visit(This aThis) { + //Im Falle von this, müssen die Generics in der Klasse als RefTypes behandelt werden. + ClassOrInterface currentClass = info.getCurrentClass(); + List params = new ArrayList<>(); + for(GenericTypeVar gtv : currentClass.getGenerics()){ + params.add(new GenericRefType(gtv.getName(), aThis.getOffset())); + } + RefType thisType = new RefType(currentClass.getClassName(), params, aThis.getOffset()); + constraintsSet.addUndConstraint(new Pair( + aThis.getType(), thisType, PairOperator.EQUALSDOT)); + } + + private static TypeScope createNullTypeScope() { + return new TypeScope() { + @Override + public Iterable getGenerics() { + return new ArrayList<>(); + } + + @Override + public RefTypeOrTPHOrWildcardOrGeneric getReturnType() { + return null; + } + }; + } + + @Override + public void visit(WhileStmt whileStmt) { + RefType booleanType = new RefType(ASTFactory.createClass(java.lang.Boolean.class).getClassName(), new NullToken()); + //Expression inferieren: + whileStmt.expr.accept(this); + //Expression muss boolean sein: + constraintsSet.addUndConstraint(new Pair(whileStmt.expr.getType(), booleanType, PairOperator.EQUALSDOT)); + //LoopBlock inferieren: + whileStmt.loopBlock.accept(this); + } + + @Override + public void visit(DoStmt whileStmt) { + throw new NotImplementedException(); + } + + @Override + public void visit(AssignToField assignLeftSide) { + //Hier ist kein Code nötig. Es werden keine extra Constraints generiert + //HIER muss Code rein PL 2018-10-24 + assignLeftSide.field.accept(this); + } + + @Override + public void visit(AssignToLocal assignLeftSide) { + //Hier ist kein Code nötig. Es werden keine extra Constraints generiert + } + + @Override + public void visit(SuperCall superCall) { + //TODO: Für einen super-Call werden keine Constraints erzeugt bisher + } + + /* + METHOD CALL Section: + */ + + protected Constraint generateConstraint(MethodCall forMethod, MethodAssumption assumption, + TypeInferenceBlockInformation info, GenericsResolver resolver){ + Constraint methodConstraint = new Constraint<>(assumption.isInherited()); + ClassOrInterface receiverCl = assumption.getReceiver(); + /* + List params = new ArrayList<>(); + for(GenericTypeVar gtv : receiverCl.getGenerics()){ + //Die Generics werden alle zu TPHs umgewandelt. + params.add(resolver.resolve(gtv.getName())); + } + + RefTypeOrTPHOrWildcardOrGeneric receiverType = new RefType(assumption.getReceiver().getClassName(), params, forMethod.getOffset()); + */ + + RefTypeOrTPHOrWildcardOrGeneric retType = assumption.getReceiverType(resolver); + methodConstraint.add(new Pair(forMethod.receiver.getType(), retType, + PairOperator.EQUALSDOT));//PL 2020-03-17 SMALLERDOT in EQUALSDOT umgewandelt, weil alle geerbten Methoden in den jeweilen Klassen enthalten sind. + + //Fuer Bytecodegenerierung PL 2020-03-09 wird derzeit nicht benutzt ANFANG + //methodConstraint.add(new Pair(forMethod.receiverType, retType, + // PairOperator.EQUALSDOT)); + //Fuer Bytecodegenerierung PL 2020-03-09 wird derzeit nicht benutzt ENDE + + + methodConstraint.isStatement = forMethod.getStatement(); + methodConstraint.add(new Pair(assumption.getReturnType(resolver), forMethod.getType(), + PairOperator.EQUALSDOT)); + methodConstraint.addAll(generateParameterConstraints(forMethod, assumption, info, resolver)); + return methodConstraint; + } + + protected Set generateParameterConstraints(MethodCall foMethod, MethodAssumption assumption, + TypeInferenceBlockInformation info, GenericsResolver resolver) { + Set ret = new HashSet<>(); + for(int i = 0;i getMethods(String name, int numArgs, TypeInferenceBlockInformation info) { + List ret = new ArrayList<>(); + //TODO: apply Methoden wieder anfügen. Diese könnten möglicherweise auch in den Assumptions auftauchen (überdenken) + if(name.equals("apply")){ + List funNParams = new ArrayList<>(); + for(int i = 0; i< numArgs + 1 ; i++){ + //funNParams.add(TypePlaceholder.fresh(new NullToken())); + funNParams.add(new GenericRefType(NameGenerator.makeNewName(), + new NullToken())); + } + funNParams.get(funNParams.size()-1); + ret.add(new MethodAssumption(new FunNClass(funNParams), funNParams.get(funNParams.size()-1), funNParams.subList(0, funNParams.size()-1), + new TypeScope() { + @Override + public Iterable getGenerics() { + throw new NotImplementedException(); + } + + @Override + public RefTypeOrTPHOrWildcardOrGeneric getReturnType() { + throw new NotImplementedException(); + } + }, false)); + } + for(ClassOrInterface cl : info.getAvailableClasses()){ + for(Method m : cl.getMethods()){ + if(m.getName().equals(name) && + m.getParameterList().getFormalparalist().size() == numArgs){ + RefTypeOrTPHOrWildcardOrGeneric retType = m.getReturnType();//info.checkGTV(m.getReturnType()); + + ret.add(new MethodAssumption(cl, retType, convertParams(m.getParameterList(),info), + createTypeScope(cl, m), m.isInherited)); + } + } + } + return ret; + } + + public static List getMethods(String name, ArgumentList arglist, TypeInferenceBlockInformation info) { + return getMethods(name, arglist.getArguments().size(), info); + } + + protected static List convertParams(ParameterList parameterList, TypeInferenceBlockInformation info){ + //TODO: Hier müssen die Parameter mit den TPHs in den GEnerics des Receivers verknüpft werden + /* + BEispiel: + auto test = new List(); + test.add("hallo"); + + Hier kriegt der Receiver ja den COnstraint TPH REceiver <. List + Dann mus bei dem Parameter der COnstraint entstehen: TPH A <. String + */ + List params = new ArrayList<>(); + for(FormalParameter fp : parameterList.getFormalparalist()){ + params.add(fp.getType()); //info.checkGTV(fp.getType())); //PL 2018-06-22 GTV sollen in Argumenten erhalten bleiben + } + return params; + } + + public List getConstructors(TypeInferenceBlockInformation info, RefType ofType, ArgumentList argList){ + List ret = new ArrayList<>(); + for(ClassOrInterface cl : info.getAvailableClasses()){ + if(cl.getClassName().equals(ofType.getName())){ + for(Method m : cl.getConstructors()){ + if(m.getParameterList().getFormalparalist().size() == argList.getArguments().size()){ + ret.add(new MethodAssumption(cl, cl.generateTypeOfThisClass(), convertParams(m.getParameterList(), + info), createTypeScope(cl, m), m.isInherited)); + } + } + } + } + return ret; + } + + protected Constraint generateConstructorConstraint(NewClass forConstructor, MethodAssumption assumption, + TypeInferenceBlockInformation info, GenericsResolver resolver){ + Constraint methodConstraint = new Constraint(); + //WELCHEN SINN MACHT DIESER CONSTRAINT??? + //Ist er nicht immer classname <. classname und damit redundant? + methodConstraint.add(new Pair(assumption.getReturnType(resolver), forConstructor.getType(), + PairOperator.SMALLERDOT)); + //WELCHEN SINN MACHT DIESER CONSTRAINT??? + methodConstraint.addAll(generateParameterConstraints(forConstructor, assumption, info, resolver)); + return methodConstraint; + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/unify/GuavaSetOperations.java b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/GuavaSetOperations.java new file mode 100644 index 00000000..19e7c48f --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/GuavaSetOperations.java @@ -0,0 +1,23 @@ +package de.dhbwstuttgart.typeinference.unify; + +import java.util.List; +import java.util.Set; + +import com.google.common.collect.Sets; + +import de.dhbwstuttgart.typeinference.unify.interfaces.ISetOperations; + +/** + * Implements set operations using google guava. + * @author DH10STF + * + */ +public class GuavaSetOperations implements ISetOperations { + + @Override + public Set> cartesianProduct(List> sets) { + // Wraps the call to google guava + return Sets.cartesianProduct(sets); + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/unify/MartelliMontanariUnify.java b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/MartelliMontanariUnify.java new file mode 100644 index 00000000..2fceb245 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/MartelliMontanariUnify.java @@ -0,0 +1,108 @@ +package de.dhbwstuttgart.typeinference.unify; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import de.dhbwstuttgart.typeinference.unify.interfaces.IUnify; +import de.dhbwstuttgart.typeinference.unify.model.PairOperator; +import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType; +import de.dhbwstuttgart.typeinference.unify.model.TypeParams; +import de.dhbwstuttgart.typeinference.unify.model.Unifier; +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; +import de.dhbwstuttgart.typeinference.unify.model.UnifyType; + +/** + * Implementation of the Martelli-Montanari unification algorithm. + * @author Florian Steurer + */ +public class MartelliMontanariUnify implements IUnify { + + @Override + public Optional unify(Set terms) { + // Sets with less than 2 terms are trivially unified + if(terms.size() < 2) + return Optional.of(Unifier.identity()); + + // For the the set of terms {t1,...,tn}, + // build a list of equations {(t1 = t2), (t2 = t3), (t3 = t4), ....} + ArrayList termsList = new ArrayList(); + Iterator iter = terms.iterator(); + UnifyType prev = iter.next(); + while(iter.hasNext()) { + UnifyType next = iter.next(); + termsList.add(new UnifyPair(prev, next, PairOperator.EQUALSDOT)); + prev = next; + } + + // Start with the identity unifier. Substitutions will be added later. + Unifier mgu = Unifier.identity(); + + // Apply rules while possible + int idx = 0; + while(idx < termsList.size()) { + UnifyPair pair = termsList.get(idx); + UnifyType rhsType = pair.getRhsType(); + UnifyType lhsType = pair.getLhsType(); + TypeParams rhsTypeParams = rhsType.getTypeParams(); + TypeParams lhsTypeParams = lhsType.getTypeParams(); + + // REDUCE - Rule + if(!(rhsType instanceof PlaceholderType) && !(lhsType instanceof PlaceholderType)) { + Set result = new HashSet<>(); + + // f<...> = g<...> with f != g are not unifiable + if(!rhsType.getName().equals(lhsType.getName())) + return Optional.empty(); // conflict + // f = f are not unifiable + if(rhsTypeParams.size() != lhsTypeParams.size()) + return Optional.empty(); // conflict + // f = g is not unifiable (cannot be f = f because erase rule would have been applied) + //if(rhsTypeParams.size() == 0) + //return Optional.empty(); + + // Unpack the arguments + for(int i = 0; i < rhsTypeParams.size(); i++) + result.add(new UnifyPair(rhsTypeParams.get(i), lhsTypeParams.get(i), PairOperator.EQUALSDOT)); + + termsList.remove(idx); + termsList.addAll(result); + continue; + } + + // DELETE - Rule + if(pair.getRhsType().equals(pair.getLhsType())) { + termsList.remove(idx); + continue; + } + + // SWAP - Rule + if(!(lhsType instanceof PlaceholderType) && (rhsType instanceof PlaceholderType)) { + termsList.remove(idx); + termsList.add(new UnifyPair(rhsType, lhsType, PairOperator.EQUALSDOT)); + continue; + } + + // OCCURS-CHECK + if(pair.getLhsType() instanceof PlaceholderType + && pair.getRhsType().getTypeParams().occurs((PlaceholderType) pair.getLhsType())) + return Optional.empty(); + + // SUBST - Rule + if(lhsType instanceof PlaceholderType) { + mgu.add((PlaceholderType) lhsType, rhsType); + //PL 2018-04-01 nach checken, ob es richtig ist, dass keine Substitutionen uebergeben werden muessen. + termsList = termsList.stream().map(x -> mgu.apply(x)).collect(Collectors.toCollection(ArrayList::new)); + idx = idx+1 == termsList.size() ? 0 : idx+1; + continue; + } + + idx++; + } + + return Optional.of(mgu); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/unify/Match.java b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/Match.java new file mode 100644 index 00000000..91406612 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/Match.java @@ -0,0 +1,92 @@ +package de.dhbwstuttgart.typeinference.unify; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import de.dhbwstuttgart.typeinference.unify.interfaces.IMatch; +import de.dhbwstuttgart.typeinference.unify.model.PairOperator; +import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType; +import de.dhbwstuttgart.typeinference.unify.model.TypeParams; +import de.dhbwstuttgart.typeinference.unify.model.Unifier; +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; +import de.dhbwstuttgart.typeinference.unify.model.UnifyType; + +/** + * Implementation of match derived from unification algorithm. + * @author Martin Pluemicke + */ +public class Match implements IMatch { + + @Override + //vorne muss das Pattern stehen + //A =. A ==> True + //A =. A ==> False + public Optional match(ArrayList termsList) { + + // Start with the identity unifier. Substitutions will be added later. + Unifier mgu = Unifier.identity(); + + // Apply rules while possible + int idx = 0; + while(idx < termsList.size()) { + UnifyPair pair = termsList.get(idx); + UnifyType rhsType = pair.getRhsType(); + UnifyType lhsType = pair.getLhsType(); + TypeParams rhsTypeParams = rhsType.getTypeParams(); + TypeParams lhsTypeParams = lhsType.getTypeParams(); + + // REDUCE - Rule + if(!(rhsType instanceof PlaceholderType) && !(lhsType instanceof PlaceholderType)) { + Set result = new HashSet<>(); + + // f<...> = g<...> with f != g are not unifiable + if(!rhsType.getName().equals(lhsType.getName())) + return Optional.empty(); // conflict + // f = f are not unifiable + if(rhsTypeParams.size() != lhsTypeParams.size()) + return Optional.empty(); // conflict + // f = g is not unifiable (cannot be f = f because erase rule would have been applied) + //if(rhsTypeParams.size() == 0) + //return Optional.empty(); + + // Unpack the arguments + for(int i = 0; i < rhsTypeParams.size(); i++) + result.add(new UnifyPair(lhsTypeParams.get(i), rhsTypeParams.get(i), PairOperator.EQUALSDOT)); + + termsList.remove(idx); + termsList.addAll(result); + continue; + } + + // DELETE - Rule + if(pair.getRhsType().equals(pair.getLhsType())) { + termsList.remove(idx); + continue; + } + + // SWAP - Rule + if(!(lhsType instanceof PlaceholderType) && (rhsType instanceof PlaceholderType)) { + return Optional.empty(); // conflict + } + + // OCCURS-CHECK + //deleted + + // SUBST - Rule + if(lhsType instanceof PlaceholderType) { + mgu.add((PlaceholderType) lhsType, rhsType); + termsList = termsList.stream().map(mgu::applyleft).collect(Collectors.toCollection(ArrayList::new)); + idx = idx+1 == termsList.size() ? 0 : idx+1; + continue; + } + + idx++; + } + + return Optional.of(mgu); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/unify/RuleSet.java b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/RuleSet.java new file mode 100644 index 00000000..50ea9a2e --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/RuleSet.java @@ -0,0 +1,1024 @@ +package de.dhbwstuttgart.typeinference.unify; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; +import java.util.Queue; +import java.util.Set; +import java.util.Stack; +import java.util.function.Function; +import java.util.stream.Collectors; + +import de.dhbwstuttgart.exceptions.DebugException; +import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; +import de.dhbwstuttgart.typeinference.unify.interfaces.IRuleSet; +import de.dhbwstuttgart.typeinference.unify.model.ExtendsType; +import de.dhbwstuttgart.typeinference.unify.model.FunNType; +import de.dhbwstuttgart.typeinference.unify.model.PairOperator; +import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType; +import de.dhbwstuttgart.typeinference.unify.model.ReferenceType; +import de.dhbwstuttgart.typeinference.unify.model.SuperType; +import de.dhbwstuttgart.typeinference.unify.model.TypeParams; +import de.dhbwstuttgart.typeinference.unify.model.Unifier; +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; +import de.dhbwstuttgart.typeinference.unify.model.UnifyType; +import de.dhbwstuttgart.typeinference.unify.model.WildcardType; +import de.dhbwstuttgart.typeinference.constraints.Constraint; +import de.dhbwstuttgart.typeinference.unify.distributeVariance; + +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; +import java.io.OutputStreamWriter; + +import org.apache.commons.io.output.NullOutputStream; + +/** + * Implementation of the type inference rules. + * @author Florian Steurer + * + */ +public class RuleSet implements IRuleSet{ + + Writer logFile; + + public RuleSet() { + super(); + logFile = new OutputStreamWriter(new NullOutputStream()); + } + + RuleSet(Writer logFile) { + this.logFile = logFile; + } + + @Override + public Optional reduceUp(UnifyPair pair) { + // Check if reduce up is applicable + if(pair.getPairOp() != PairOperator.SMALLERDOT) + return Optional.empty(); + + UnifyType rhsType = pair.getRhsType(); + if(!(rhsType instanceof SuperType)) + return Optional.empty(); + + UnifyType lhsType = pair.getLhsType(); + if(!(lhsType instanceof ReferenceType) && !(lhsType instanceof PlaceholderType)) + return Optional.empty(); + + // Rule is applicable, unpack the SuperType + return Optional.of(new UnifyPair(lhsType, ((SuperType) rhsType).getSuperedType(), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); + } + + @Override + public Optional reduceLow(UnifyPair pair) { + // Check if rule is applicable + if(pair.getPairOp() != PairOperator.SMALLERDOT) + return Optional.empty(); + + UnifyType lhsType = pair.getLhsType(); + if(!(lhsType instanceof ExtendsType)) + return Optional.empty(); + + UnifyType rhsType = pair.getRhsType(); + if(!(rhsType instanceof ReferenceType) && !(rhsType instanceof PlaceholderType)) + return Optional.empty(); + + // Rule is applicable, unpack the ExtendsType + return Optional.of(new UnifyPair(((ExtendsType) lhsType).getExtendedType(), rhsType, PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); + } + + @Override + public Optional reduceUpLow(UnifyPair pair) { + // Check if rule is applicable + if(pair.getPairOp() != PairOperator.SMALLERDOT) + return Optional.empty(); + + UnifyType lhsType = pair.getLhsType(); + if(!(lhsType instanceof ExtendsType)) + return Optional.empty(); + + UnifyType rhsType = pair.getRhsType(); + if(!(rhsType instanceof SuperType)) + return Optional.empty(); + + // Rule is applicable, unpack both sides + return Optional.of(new UnifyPair(((ExtendsType) lhsType).getExtendedType(),((SuperType) rhsType).getSuperedType(), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); + } + + @Override + public Optional> reduceExt(UnifyPair pair, IFiniteClosure fc) { + if(pair.getPairOp() != PairOperator.SMALLERDOTWC) + return Optional.empty(); + + UnifyType x = pair.getLhsType(); + UnifyType sTypeX; + + if(x instanceof ReferenceType) + sTypeX = x; + else if(x instanceof ExtendsType) + sTypeX = ((ExtendsType) x).getExtendedType(); + else + return Optional.empty(); + + UnifyType extY = pair.getRhsType(); + + if(!(extY instanceof ExtendsType)) + return Optional.empty(); + + if(x.getTypeParams().empty() || extY.getTypeParams().size() != x.getTypeParams().size()) + return Optional.empty(); + + UnifyType xFromFc = fc.getLeftHandedType(sTypeX.getName()).orElse(null); + + if(xFromFc == null || !xFromFc.getTypeParams().arePlaceholders()) + return Optional.empty(); + + if(x instanceof ExtendsType) + xFromFc = new ExtendsType(xFromFc); + + UnifyType extYFromFc = fc.grArg(xFromFc, new HashSet<>()).stream().filter(t -> t.getName().equals(extY.getName())).filter(t -> t.getTypeParams().arePlaceholders()).findAny().orElse(null); + + if(extYFromFc == null || extYFromFc.getTypeParams() != xFromFc.getTypeParams()) + return Optional.empty(); + + TypeParams extYParams = extY.getTypeParams(); + TypeParams xParams = x.getTypeParams(); + + int[] pi = pi(xParams, extYParams); + + if(pi.length == 0) + return Optional.empty(); + + Set result = new HashSet<>(); + + for(int rhsIdx = 0; rhsIdx < extYParams.size(); rhsIdx++) + result.add(new UnifyPair(xParams.get(pi[rhsIdx]), extYParams.get(rhsIdx), PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair.getBasePair())); + + return Optional.of(result); + } + + @Override + public Optional> reduceSup(UnifyPair pair, IFiniteClosure fc) { + if(pair.getPairOp() != PairOperator.SMALLERDOTWC) + return Optional.empty(); + + UnifyType x = pair.getLhsType(); + UnifyType sTypeX; + + if(x instanceof ReferenceType) + sTypeX = x; + else if(x instanceof SuperType) + sTypeX = ((SuperType) x).getSuperedType(); + else + return Optional.empty(); + + UnifyType supY = pair.getRhsType(); + + if(!(supY instanceof SuperType)) + return Optional.empty(); + + if(x.getTypeParams().empty() || supY.getTypeParams().size() != x.getTypeParams().size()) + return Optional.empty(); + + UnifyType xFromFc = fc.getLeftHandedType(sTypeX.getName()).orElse(null); + + if(xFromFc == null || !xFromFc.getTypeParams().arePlaceholders()) + return Optional.empty(); + + if(x instanceof SuperType) + xFromFc = new SuperType(xFromFc); + + UnifyType supYFromFc = fc.grArg(xFromFc, new HashSet<>()).stream().filter(t -> t.getName().equals(supY.getName())).filter(t -> t.getTypeParams().arePlaceholders()).findAny().orElse(null); + + if(supYFromFc == null || supYFromFc.getTypeParams() != xFromFc.getTypeParams()) + return Optional.empty(); + + TypeParams supYParams = supY.getTypeParams(); + TypeParams xParams = x.getTypeParams(); + Set result = new HashSet<>(); + + int[] pi = pi(xParams, supYParams); + + if(pi.length == 0) + return Optional.empty(); + + for(int rhsIdx = 0; rhsIdx < supYParams.size(); rhsIdx++) + result.add(new UnifyPair(supYParams.get(rhsIdx), xParams.get(pi[rhsIdx]), PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair.getBasePair())); + + return Optional.of(result); + } + + @Override + public Optional> reduceEq(UnifyPair pair) { + if(pair.getPairOp() != PairOperator.SMALLERDOTWC) + return Optional.empty(); + + UnifyType lhsType = pair.getLhsType(); + if(lhsType instanceof PlaceholderType || lhsType.getTypeParams().empty()) + return Optional.empty(); + + UnifyType rhsType = pair.getRhsType(); + + if(!rhsType.getName().equals(lhsType.getName())) + return Optional.empty(); + + if(rhsType instanceof PlaceholderType || lhsType instanceof PlaceholderType || rhsType.getTypeParams().empty()) + return Optional.empty(); + + if(rhsType.getTypeParams().size() != lhsType.getTypeParams().size()) + return Optional.empty(); + + // Keine Permutation wie im Paper nötig + Set result = new HashSet<>(); + TypeParams lhsTypeParams = lhsType.getTypeParams(); + TypeParams rhsTypeParams = rhsType.getTypeParams(); + + for(int i = 0; i < lhsTypeParams.size(); i++) + result.add(new UnifyPair(lhsTypeParams.get(i), rhsTypeParams.get(i), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); + + return Optional.of(result); + } + + @Override + public Optional> reduce1(UnifyPair pair, IFiniteClosure fc) { + if(pair.getPairOp() != PairOperator.SMALLERDOT) + return Optional.empty(); + + UnifyType c = pair.getLhsType(); + if(!(c instanceof ReferenceType)) + return Optional.empty(); + + UnifyType d = pair.getRhsType(); + if(!(d instanceof ReferenceType)) + return Optional.empty(); + + ReferenceType lhsSType = (ReferenceType) c; + ReferenceType rhsSType = (ReferenceType) d; + + //try { + // logFile.write("PAIR Rules: " + pair + "\n"); + // logFile.flush(); + //} + //catch (IOException e) { } + + if(lhsSType.getTypeParams().empty() || lhsSType.getTypeParams().size() != rhsSType.getTypeParams().size()) + return Optional.empty(); + + UnifyType cFromFc = fc.getLeftHandedType(c.getName()).orElse(null); + //2018-02-23: liefert Vector>: Das kann nicht sein. + + //NOCHMAL UEBERPRUEFEN + //PL 18-02-09 Eingfuegt Anfang + //C und D koennen auch gleich sein. + if (c.getName().equals(d.getName())) { + Set result = new HashSet<>(); + TypeParams rhsTypeParams = d.getTypeParams(); + TypeParams lhsTypeParams = c.getTypeParams(); + for(int rhsIdx = 0; rhsIdx < c.getTypeParams().size(); rhsIdx++) + result.add(new UnifyPair(lhsTypeParams.get(rhsIdx), rhsTypeParams.get(rhsIdx), PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair.getBasePair())); + + return Optional.of(result); + } + //PL 18-02-09 Eingfuegt ENDE + + //try { + // logFile.write("cFromFc: " + cFromFc); + // logFile.flush(); + //} + //catch (IOException e) { } + + if(cFromFc == null || !cFromFc.getTypeParams().arePlaceholders()) + return Optional.empty(); + + UnifyType dFromFc = fc.getAncestors(cFromFc).stream().filter(x -> x.getName().equals(d.getName())).findAny().orElse(null); + + //try { + // logFile.write("cFromFc: " + cFromFc); + // logFile.flush(); + //} + //catch (IOException e) { } + + if(dFromFc == null || !dFromFc.getTypeParams().arePlaceholders() || dFromFc.getTypeParams().size() != cFromFc.getTypeParams().size()) + return Optional.empty(); + //System.out.println("cFromFc: " + cFromFc); + //System.out.println("dFromFc: " + dFromFc); + int[] pi = pi(cFromFc.getTypeParams(), dFromFc.getTypeParams()); + + if(pi.length == 0) + return Optional.empty(); + + TypeParams rhsTypeParams = d.getTypeParams(); + TypeParams lhsTypeParams = c.getTypeParams(); + Set result = new HashSet<>(); + + for(int rhsIdx = 0; rhsIdx < rhsTypeParams.size(); rhsIdx++) + result.add(new UnifyPair(lhsTypeParams.get(pi[rhsIdx]), rhsTypeParams.get(rhsIdx), PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair.getBasePair())); + + return Optional.of(result); + } + + @Override + public Optional> reduce2(UnifyPair pair) { + if(pair.getPairOp() != PairOperator.EQUALSDOT) + return Optional.empty(); + + UnifyType lhsType = pair.getLhsType(); + ReferenceType lhsSType; + UnifyType rhsType = pair.getRhsType(); + ReferenceType rhsSType; + + if ((lhsType instanceof ReferenceType) && (rhsType instanceof ReferenceType)) { + lhsSType = (ReferenceType) lhsType; + rhsSType = (ReferenceType) rhsType; + } + else if (((lhsType instanceof ExtendsType) && (rhsType instanceof ExtendsType)) + || ((lhsType instanceof SuperType) && (rhsType instanceof SuperType))) { + UnifyType lhsSTypeRaw = ((WildcardType) lhsType).getWildcardedType(); + UnifyType rhsSTypeRaw = ((WildcardType) rhsType).getWildcardedType(); + if ((lhsSTypeRaw instanceof ReferenceType) && (rhsSTypeRaw instanceof ReferenceType)) { + lhsSType = (ReferenceType) lhsSTypeRaw; + rhsSType = (ReferenceType) rhsSTypeRaw; + } + else + return Optional.empty(); + } + else + return Optional.empty(); + + if(lhsSType.getTypeParams().empty()) + return Optional.empty(); + + /* PL 2018-01-22 in obere Teil integriert + UnifyType rhsType = pair.getRhsType(); + ReferenceType rhsSType; + + if(rhsType instanceof ReferenceType) + rhsSType = (ReferenceType) rhsType; + else if(rhsType instanceof WildcardType) { + UnifyType rhsSTypeRaw = ((WildcardType) rhsType).getWildcardedType(); + if(rhsSTypeRaw instanceof ReferenceType) + rhsSType = (ReferenceType) rhsSTypeRaw; + else + return Optional.empty(); + } + else + return Optional.empty(); + */ + + if(!rhsSType.getName().equals(lhsSType.getName())) + return Optional.empty(); + + if(!(lhsSType.getTypeParams().size()==rhsSType.getTypeParams().size()))throw new DebugException("Fehler in Unifizierung"+ " " + lhsSType.toString() + " " + rhsSType.toString()); + //if(rhsSType.getTypeParams().size() != lhsSType.getTypeParams().size()) + // return Optional.empty(); + + Set result = new HashSet<>(); + + TypeParams rhsTypeParams = rhsSType.getTypeParams(); + TypeParams lhsTypeParams = lhsSType.getTypeParams(); + for(int i = 0; i < rhsTypeParams.size(); i++) + result.add(new UnifyPair(lhsTypeParams.get(i), rhsTypeParams.get(i), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); + + return Optional.of(result); + } + + @Override + public boolean erase1(UnifyPair pair, IFiniteClosure fc) { + if((pair.getPairOp() != PairOperator.SMALLERDOT) && (pair.getPairOp() != PairOperator.SMALLERNEQDOT)) + return false; + + if (pair.getPairOp() == PairOperator.SMALLERNEQDOT) { + UnifyType lhs = pair.getLhsType(); + UnifyType rhs = pair.getRhsType(); + if (lhs instanceof WildcardType) { + lhs = ((WildcardType)lhs).getWildcardedType(); + } + if (rhs instanceof WildcardType) { + rhs = ((WildcardType)rhs).getWildcardedType(); + } + + if (lhs.equals(rhs)){ + return false; + } + } + + UnifyType lhsType = pair.getLhsType(); + if(!(lhsType instanceof ReferenceType) && !(lhsType instanceof PlaceholderType)) + return false; + + UnifyType rhsType = pair.getRhsType(); + if(!(rhsType instanceof ReferenceType) && !(rhsType instanceof PlaceholderType)) + return false; + + return fc.greater(lhsType, new HashSet<>()).contains(rhsType); + } + + @Override + public boolean erase2(UnifyPair pair, IFiniteClosure fc) { + if(pair.getPairOp() != PairOperator.SMALLERDOTWC) + return false; + + UnifyType lhsType = pair.getLhsType(); + UnifyType rhsType = pair.getRhsType(); + + return fc.grArg(lhsType, new HashSet<>()).contains(rhsType); + } + + @Override + public boolean erase3(UnifyPair pair) { + if(pair.getPairOp() != PairOperator.EQUALSDOT) + return false; + + return pair.getLhsType().equals(pair.getRhsType()); + } + + @Override + public Optional swap(UnifyPair pair) { + if(pair.getPairOp() != PairOperator.EQUALSDOT) + return Optional.empty(); + + if(pair.getLhsType() instanceof PlaceholderType) + return Optional.empty(); + + if(!(pair.getRhsType() instanceof PlaceholderType)) + return Optional.empty(); + + return Optional.of(new UnifyPair(pair.getRhsType(), pair.getLhsType(), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); + } + + @Override + public Optional adapt(UnifyPair pair, IFiniteClosure fc) { + if(pair.getPairOp() != PairOperator.SMALLERDOT) + return Optional.empty(); + + UnifyType typeD = pair.getLhsType(); + if(!(typeD instanceof ReferenceType)) + return Optional.empty(); + + UnifyType typeDs = pair.getRhsType(); + if(!(typeDs instanceof ReferenceType)) + return Optional.empty(); + + /*if(typeD.getTypeParams().size() == 0 || typeDs.getTypeParams().size() == 0) + return Optional.empty();*/ + + if(typeD.getName().equals(typeDs.getName())) + return Optional.empty(); + + + Optional opt = fc.getLeftHandedType(typeD.getName()); + if(!opt.isPresent()) + return Optional.empty(); + + // The generic Version of Type D (D) + UnifyType typeDgen = opt.get(); + + // Actually greater+ because the types are ensured to have different names + Set greater = fc.getAncestors(typeDgen); + opt = greater.stream().filter(x -> x.getName().equals(typeDs.getName())).findAny(); + + if(!opt.isPresent()) + return Optional.empty(); + + UnifyType newLhs = opt.get(); + + TypeParams typeDParams = typeD.getTypeParams(); + TypeParams typeDgenParams = typeDgen.getTypeParams(); + + //System.out.println("Pair: " +pair); + //System.out.println("typeD: " +typeD); + //System.out.println("typeDParams: " +typeDParams); + //System.out.println("typeDgen: " +typeD); + //System.out.println("typeDgenParams: " +typeDgenParams); + Unifier unif = Unifier.identity(); + for(int i = 0; i < typeDParams.size(); i++) { + //System.out.println("ADAPT" +typeDgenParams); + if (typeDgenParams.get(i) instanceof PlaceholderType) + unif.add((PlaceholderType) typeDgenParams.get(i), typeDParams.get(i)); + else System.out.println("ERROR"); + } + return Optional.of(new UnifyPair(unif.apply(newLhs), typeDs, PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); + } + + @Override + public Optional adaptExt(UnifyPair pair, IFiniteClosure fc) { + if(pair.getPairOp() != PairOperator.SMALLERDOTWC) + return Optional.empty(); + + UnifyType typeD = pair.getLhsType(); + if(!(typeD instanceof ReferenceType) && !(typeD instanceof ExtendsType)) + return Optional.empty(); + + UnifyType typeExtDs = pair.getRhsType(); + if(!(typeExtDs instanceof ExtendsType)) + return Optional.empty(); + + if(typeD.getTypeParams().size() == 0 || typeExtDs.getTypeParams().size() == 0) + return Optional.empty(); + + UnifyType typeDgen; + if(typeD instanceof ReferenceType) + typeDgen = fc.getLeftHandedType(typeD.getName()).orElse(null); + else { + Optional opt = fc.getLeftHandedType(((ExtendsType) typeD).getExtendedType().getName()); + typeDgen = opt.isPresent() ? new ExtendsType(opt.get()) : null; + } + + if(typeDgen == null) + return Optional.empty(); + + Set grArg = fc.grArg(typeDgen, new HashSet<>()); + + Optional opt = grArg.stream().filter(x -> x.getName().equals(typeExtDs.getName())).findAny(); + + if(!opt.isPresent()) + return Optional.empty(); + + UnifyType newLhs = ((ExtendsType) opt.get()).getExtendedType(); + + TypeParams typeDParams = typeD.getTypeParams(); + TypeParams typeDgenParams = typeDgen.getTypeParams(); + + Unifier unif = new Unifier((PlaceholderType) typeDgenParams.get(0), typeDParams.get(0)); + for(int i = 1; i < typeDParams.size(); i++) + unif.add((PlaceholderType) typeDgenParams.get(i), typeDParams.get(i)); + + return Optional.of(new UnifyPair(unif.apply(newLhs), typeExtDs, PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair.getBasePair())); + } + + @Override + public Optional adaptSup(UnifyPair pair, IFiniteClosure fc) { + if(pair.getPairOp() != PairOperator.SMALLERDOTWC) + return Optional.empty(); + + UnifyType typeDs = pair.getLhsType(); + if(!(typeDs instanceof ReferenceType) && !(typeDs instanceof SuperType)) + return Optional.empty(); + + UnifyType typeSupD = pair.getRhsType(); + if(!(typeSupD instanceof SuperType)) + return Optional.empty(); + + if(typeDs.getTypeParams().size() == 0 || typeSupD.getTypeParams().size() == 0) + return Optional.empty(); + + + Optional opt = fc.getLeftHandedType(((SuperType) typeSupD).getSuperedType().getName()); + + if(!opt.isPresent()) + return Optional.empty(); + + UnifyType typeDgen = opt.get(); + UnifyType typeSupDgen = new SuperType(typeDgen); + + // Use of smArg instead of grArg because + // a in grArg(b) => b in smArg(a) + Set smArg = fc.smArg(typeSupDgen, new HashSet<>()); + opt = smArg.stream().filter(x -> x.getName().equals(typeDs.getName())).findAny(); + + if(!opt.isPresent()) + return Optional.empty(); + + // New RHS + UnifyType newRhs = null; + if(typeDs instanceof ReferenceType) + newRhs = new ExtendsType(typeDs); + else + newRhs = new ExtendsType(((SuperType) typeDs).getSuperedType()); + + // New LHS + UnifyType newLhs = opt.get(); + TypeParams typeDParams = typeSupD.getTypeParams(); + TypeParams typeSupDsgenParams = typeSupDgen.getTypeParams(); + + Unifier unif = new Unifier((PlaceholderType) typeSupDsgenParams.get(0), typeDParams.get(0)); + for(int i = 1; i < typeDParams.size(); i++) + unif.add((PlaceholderType) typeSupDsgenParams.get(i), typeDParams.get(i)); + + return Optional.of(new UnifyPair(unif.apply(newLhs), newRhs, PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair.getBasePair())); + } + + /** + * Finds the permutation pi of the type arguments of two types based on the finite closure + * @param cArgs The type which arguments are permuted + * @param dArgs The other type + * @return An array containing the values of pi for every type argument of C or an empty array if the search failed. + */ + private int[] pi(TypeParams cArgs, TypeParams dArgs) { + if(!(cArgs.size()==dArgs.size()))throw new DebugException("Fehler in Unifizierung"); + + int[] permutation = new int[dArgs.size()]; + + boolean succ = true; + for (int dArgIdx = 0; dArgIdx < dArgs.size() && succ; dArgIdx++) { + UnifyType dArg = dArgs.get(dArgIdx); + succ = false; + for (int pi = 0; pi < cArgs.size(); pi++) + if (cArgs.get(pi).getName().equals(dArg.getName())) { + permutation[dArgIdx] = pi; + succ = true; + break; + } + } + + return succ ? permutation : new int[0]; + } + + public Optional> subst(Set pairs) { + return subst(pairs, new ArrayList<>()); + } + + @Override + public Optional> subst(Set pairs, List>> oderConstraints) { + HashMap typeMap = new HashMap<>(); + + Stack occuringTypes = new Stack<>(); + + for(UnifyPair pair : pairs) { + occuringTypes.push(pair.getLhsType()); + occuringTypes.push(pair.getRhsType()); + } + + while(!occuringTypes.isEmpty()) { + UnifyType t1 = occuringTypes.pop(); + if(!typeMap.containsKey(t1)) + typeMap.put(t1, 0); + typeMap.put(t1, typeMap.get(t1)+1); + + if(t1 instanceof ExtendsType) + occuringTypes.push(((ExtendsType) t1).getExtendedType()); + if(t1 instanceof SuperType) + occuringTypes.push(((SuperType) t1).getSuperedType()); + else + t1.getTypeParams().forEach(x -> occuringTypes.push(x)); + } + Queue result1 = new LinkedList(pairs); + ArrayList result = new ArrayList(); + boolean applied = false; + + while(!result1.isEmpty()) { + UnifyPair pair = result1.poll(); + PlaceholderType lhsType = null; + UnifyType rhsType; + + if(pair.getPairOp() == PairOperator.EQUALSDOT + && pair.getLhsType() instanceof PlaceholderType) + lhsType = (PlaceholderType) pair.getLhsType(); + rhsType = pair.getRhsType(); //PL eingefuegt 2017-09-29 statt !((rhsType = pair.getRhsType()) instanceof PlaceholderType) + + if(lhsType != null + //&& !((rhsType = pair.getRhsType()) instanceof PlaceholderType) //PL geloescht am 2017-09-29 Begründung: auch Typvariablen muessen ersetzt werden. + && typeMap.get(lhsType) > 1 // The type occurs in more pairs in the set than just the recent pair. + && !rhsType.getTypeParams().occurs(lhsType) + && !((rhsType instanceof WildcardType) && ((WildcardType)rhsType).getWildcardedType().equals(lhsType))) //PL eigefuegt 2018-02-18 + { + Unifier uni = new Unifier(lhsType, rhsType); + result = result.stream().map(x -> uni.apply(pair,x)).collect(Collectors.toCollection(ArrayList::new)); + result1 = result1.stream().map(x -> uni.apply(pair,x)).collect(Collectors.toCollection(LinkedList::new)); + + Function,? extends Constraint> applyUni = b -> b.stream().map( + x -> uni.apply(pair,x)).collect(Collectors.toCollection((b.getExtendConstraint() != null) + ? () -> new Constraint( + b.isInherited(), + b.getExtendConstraint().stream().map(x -> uni.apply(pair,x)).collect(Collectors.toCollection(Constraint::new))) + : () -> new Constraint(b.isInherited()) + )); + oderConstraints.replaceAll(oc -> oc.stream().map(applyUni).collect(Collectors.toCollection(HashSet::new))); + /* + oderConstraints = oderConstraints.stream().map( + a -> a.stream().map(applyUni + //b -> b.stream().map( + // x -> uni.apply(pair,x)).collect(Collectors.toCollection(HashSet::new) ) + ).collect(Collectors.toCollection(HashSet::new)) + ).collect(Collectors.toList(ArrayList::new)); + } + */ + applied = true; + } + result.add(pair); + } + + return applied ? Optional.of(new HashSet<>(result)) : Optional.empty(); + } + + @Override + public Optional reduceWildcardLow(UnifyPair pair) { + if(pair.getPairOp() != PairOperator.SMALLERDOTWC) + return Optional.empty(); + + UnifyType lhsType = pair.getLhsType(); + UnifyType rhsType = pair.getRhsType(); + if(!(lhsType instanceof ExtendsType) || !(rhsType instanceof ExtendsType)) + return Optional.empty(); + + return Optional.of(new UnifyPair(((ExtendsType) lhsType).getExtendedType(), ((ExtendsType) rhsType).getExtendedType(), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); + } + + @Override + public Optional reduceWildcardLowRight(UnifyPair pair) { + if(pair.getPairOp() != PairOperator.SMALLERDOTWC) + return Optional.empty(); + + UnifyType lhsType = pair.getLhsType(); + UnifyType rhsType = pair.getRhsType(); + if(!(lhsType instanceof ReferenceType) || !(rhsType instanceof ExtendsType)) + return Optional.empty(); + + return Optional.of(new UnifyPair(lhsType, ((ExtendsType) rhsType).getExtendedType(), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); + } + + @Override + public Optional reduceWildcardUp(UnifyPair pair) { + if(pair.getPairOp() != PairOperator.SMALLERDOTWC) + return Optional.empty(); + + UnifyType lhsType = pair.getLhsType(); + UnifyType rhsType = pair.getRhsType(); + if(!(lhsType instanceof SuperType) || !(rhsType instanceof SuperType)) + return Optional.empty(); + + return Optional.of(new UnifyPair(((SuperType) rhsType).getSuperedType(), ((SuperType) lhsType).getSuperedType(), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); + } + + @Override + public Optional reduceWildcardUpRight(UnifyPair pair) { + if(pair.getPairOp() != PairOperator.SMALLERDOTWC) + return Optional.empty(); + + UnifyType lhsType = pair.getLhsType(); + UnifyType rhsType = pair.getRhsType(); + if(!(lhsType instanceof ReferenceType) || !(rhsType instanceof SuperType)) + return Optional.empty(); + + return Optional.of(new UnifyPair(((SuperType) rhsType).getSuperedType(), lhsType, PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair.getBasePair())); + } + + /* PL 2018-03-06 auskommentiert sind mutmaßlich falsch + * vgl. JAVA_BSP/Wildcard6.java + @Override + public Optional reduceWildcardLowUp(UnifyPair pair) { + if(pair.getPairOp() != PairOperator.SMALLERDOTWC) + return Optional.empty(); + + UnifyType lhsType = pair.getLhsType(); + UnifyType rhsType = pair.getRhsType(); + if(!(lhsType instanceof ExtendsType) || !(rhsType instanceof SuperType)) + return Optional.empty(); + + return Optional.of(new UnifyPair(((ExtendsType) lhsType).getExtendedType(), ((SuperType) rhsType).getSuperedType(), PairOperator.EQUALSDOT)); + } + + @Override + public Optional reduceWildcardUpLow(UnifyPair pair) { + if(pair.getPairOp() != PairOperator.SMALLERDOTWC) + return Optional.empty(); + + UnifyType lhsType = pair.getLhsType(); + UnifyType rhsType = pair.getRhsType(); + if(!(lhsType instanceof SuperType) || !(rhsType instanceof ExtendsType)) + return Optional.empty(); + + return Optional.of(new UnifyPair(((SuperType) lhsType).getSuperedType(), ((ExtendsType) rhsType).getExtendedType(), PairOperator.EQUALSDOT)); + } + + + @Override + public Optional reduceWildcardLeft(UnifyPair pair) { + if(pair.getPairOp() != PairOperator.SMALLERDOTWC) + return Optional.empty(); + + UnifyType rhsType = pair.getRhsType(); + if(!(rhsType instanceof ReferenceType)) + return Optional.empty(); + + UnifyType lhsType = pair.getLhsType(); + + if(lhsType instanceof WildcardType) + return Optional.of(new UnifyPair(((WildcardType) lhsType).getWildcardedType(), rhsType, PairOperator.EQUALSDOT)); + + return Optional.empty(); + } + */ + @Override + public Optional> reduceFunN(UnifyPair pair) { + if((pair.getPairOp() != PairOperator.SMALLERDOT) + && (pair.getPairOp() != PairOperator.EQUALSDOT)) //PL 2017-10-03 hinzugefuegt + //da Regel auch fuer EQUALSDOT anwendbar + //TODO: fuer allen anderen Relationen noch pruefen + return Optional.empty(); + + UnifyType lhsType = pair.getLhsType(); + UnifyType rhsType = pair.getRhsType(); + + if(!(lhsType instanceof FunNType) || !(rhsType instanceof FunNType)) + return Optional.empty(); + + FunNType funNLhsType = (FunNType) lhsType; + FunNType funNRhsType = (FunNType) rhsType; + + if(funNLhsType.getN() != funNRhsType.getN()) + return Optional.empty(); + + Set result = new HashSet(); + if (pair.getPairOp() == PairOperator.SMALLERDOT) { + result.add(new UnifyPair(funNLhsType.getTypeParams().get(funNLhsType.getTypeParams().size()-1), funNRhsType.getTypeParams().get(funNRhsType.getTypeParams().size()-1), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); + for(int i = 0; i < funNLhsType.getTypeParams().size()-1; i++) { + result.add(new UnifyPair(funNRhsType.getTypeParams().get(i), funNLhsType.getTypeParams().get(i), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); + } + } + else {// pair.getPairOp() == PairOperator.EQUALDOT + result.add(new UnifyPair(funNLhsType.getTypeParams().get(funNLhsType.getTypeParams().size()-1), funNRhsType.getTypeParams().get(funNRhsType.getTypeParams().size()-1), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); + for(int i = 0; i < funNLhsType.getTypeParams().size()-1; i++) { + result.add(new UnifyPair(funNRhsType.getTypeParams().get(i), funNLhsType.getTypeParams().get(i), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); + } + } + result.stream().forEach(x -> { UnifyType l = x.getLhsType(); + if (l instanceof PlaceholderType) { ((PlaceholderType)l).disableWildcardtable(); } + UnifyType r = x.getRhsType(); + if (r instanceof PlaceholderType) { ((PlaceholderType)r).disableWildcardtable(); } + } ); + try { + logFile.write("FUNgreater: " + pair + "\n"); + logFile.write("FUNred: " + result + "\n"); + logFile.flush(); + } + catch (IOException e) { + System.out.println("logFile-Error"); + } + return Optional.of(result); + } + + + @Override + public Optional> greaterFunN(UnifyPair pair) { + if(pair.getPairOp() != PairOperator.SMALLERDOT) + return Optional.empty(); + + UnifyType lhsType = pair.getLhsType(); + UnifyType rhsType = pair.getRhsType(); + + if(!(lhsType instanceof FunNType) || !(rhsType instanceof PlaceholderType)) + return Optional.empty(); + + FunNType funNLhsType = (FunNType) lhsType; + + Set result = new HashSet(); + + Integer variance = ((PlaceholderType)rhsType).getVariance(); + Integer inversVariance = distributeVariance.inverseVariance(variance); + + UnifyType[] freshPlaceholders = new UnifyType[funNLhsType.getTypeParams().size()]; + for(int i = 0; i < freshPlaceholders.length-1; i++) { + freshPlaceholders[i] = PlaceholderType.freshPlaceholder(); + ((PlaceholderType)freshPlaceholders[i]).setVariance(inversVariance); + } + freshPlaceholders[freshPlaceholders.length-1] = PlaceholderType.freshPlaceholder(); + ((PlaceholderType)freshPlaceholders[freshPlaceholders.length-1]).setVariance(variance); + result.add(new UnifyPair(funNLhsType.getTypeParams().get(funNLhsType.getTypeParams().size()-1), freshPlaceholders[funNLhsType.getTypeParams().size()-1], PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); + + for(int i = 0; i < funNLhsType.getTypeParams().size()-1; i++) { + result.add(new UnifyPair(freshPlaceholders[i], funNLhsType.getTypeParams().get(i), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); + } + + result.add(new UnifyPair(rhsType, funNLhsType.setTypeParams(new TypeParams(freshPlaceholders)), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); + + result.stream().forEach(x -> { UnifyType l = x.getLhsType(); + if (l instanceof PlaceholderType) { ((PlaceholderType)l).disableWildcardtable(); } + UnifyType r = x.getRhsType(); + if (r instanceof PlaceholderType) { ((PlaceholderType)r).disableWildcardtable(); } + } ); + try { + logFile.write("FUNgreater: " + pair + "\n"); + logFile.write("FUNgreater: " + result + "\n"); + logFile.flush(); + } + catch (IOException e) { + System.out.println("lofFile-Error"); + } + return Optional.of(result); + } + + @Override + public Optional> smallerFunN(UnifyPair pair) { + if(pair.getPairOp() != PairOperator.SMALLERDOT) + return Optional.empty(); + + UnifyType lhsType = pair.getLhsType(); + UnifyType rhsType = pair.getRhsType(); + + if(!(lhsType instanceof PlaceholderType) || !(rhsType instanceof FunNType)) + return Optional.empty(); + + FunNType funNRhsType = (FunNType) rhsType; + + Set result = new HashSet(); + + Integer variance = ((PlaceholderType)lhsType).getVariance(); + Integer inversVariance = distributeVariance.inverseVariance(variance); + + UnifyType[] freshPlaceholders = new UnifyType[funNRhsType.getTypeParams().size()]; + for(int i = 0; i < freshPlaceholders.length-1; i++) { + freshPlaceholders[i] = PlaceholderType.freshPlaceholder(); + ((PlaceholderType)freshPlaceholders[i]).setVariance(inversVariance); + } + freshPlaceholders[freshPlaceholders.length-1] = PlaceholderType.freshPlaceholder(); + ((PlaceholderType)freshPlaceholders[freshPlaceholders.length-1]).setVariance(variance); + + result.add(new UnifyPair(freshPlaceholders[funNRhsType.getTypeParams().size()-1], funNRhsType.getTypeParams().get(funNRhsType.getTypeParams().size()-1), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); + + for(int i = 0; i < funNRhsType.getTypeParams().size()-1; i++) { + result.add(new UnifyPair(funNRhsType.getTypeParams().get(i), freshPlaceholders[i], PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); + } + + result.add(new UnifyPair(lhsType, funNRhsType.setTypeParams(new TypeParams(freshPlaceholders)), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); + + result.stream().forEach(x -> { UnifyType l = x.getLhsType(); + if (l instanceof PlaceholderType) { ((PlaceholderType)l).disableWildcardtable(); } + UnifyType r = x.getRhsType(); + if (r instanceof PlaceholderType) { ((PlaceholderType)r).disableWildcardtable(); } + } ); + try { + logFile.write("FUNgreater: " + pair + "\n"); + logFile.write("FUNsmaller: " + result + "\n"); + logFile.flush(); + } + catch (IOException e) { + System.out.println("lofFile-Error"); + } + return Optional.of(result); + } + + @Override + public Optional reduceTph(UnifyPair pair) { + if(pair.getPairOp() != PairOperator.SMALLERDOTWC) + return Optional.empty(); + + UnifyType lhsType = pair.getLhsType(); + UnifyType rhsType = pair.getRhsType(); + if(!(lhsType instanceof PlaceholderType) || !(rhsType instanceof ReferenceType)) + return Optional.empty(); + + return Optional.of(new UnifyPair(lhsType, rhsType, PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); + } + + @Override + public Optional> reduceTphExt(UnifyPair pair) { + if(pair.getPairOp() != PairOperator.SMALLERDOTWC) + return Optional.empty(); + + UnifyType lhsType = pair.getLhsType(); + UnifyType rhsType = pair.getRhsType(); + if(!(lhsType instanceof ExtendsType) || !(rhsType instanceof PlaceholderType)) + return Optional.empty(); + + UnifyType extendedType = ((ExtendsType)lhsType).getExtendedType(); + + if (extendedType.equals(rhsType)) return Optional.empty(); //PL 2019-02-18 eingefügt ? extends a <.? a + + boolean isGen = extendedType instanceof PlaceholderType && !((PlaceholderType) extendedType).isGenerated(); + + Set result = new HashSet<>(); + if(isGen) + result.add(new UnifyPair(rhsType, lhsType, PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); + else { + UnifyType freshTph = PlaceholderType.freshPlaceholder(); + result.add(new UnifyPair(rhsType, new ExtendsType(freshTph), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); + result.add(new UnifyPair(extendedType, freshTph, PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); + } + + return Optional.of(result); + } + + @Override + public Optional> reduceTphSup(UnifyPair pair) { + if(pair.getPairOp() != PairOperator.SMALLERDOTWC) + return Optional.empty(); + + UnifyType lhsType = pair.getLhsType(); + UnifyType rhsType = pair.getRhsType(); + if(!(lhsType instanceof SuperType) || !(rhsType instanceof PlaceholderType)) + return Optional.empty(); + + UnifyType superedType = ((SuperType)lhsType).getSuperedType(); + + if (superedType.equals(rhsType)) return Optional.empty(); //PL 2019-02-18 eingefügt ? super a <.? a + + boolean isGen = superedType instanceof PlaceholderType && !((PlaceholderType) superedType).isGenerated(); + + Set result = new HashSet<>(); + if(isGen) + result.add(new UnifyPair(rhsType, lhsType, PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); + else { + UnifyType freshTph = PlaceholderType.freshPlaceholder(); + result.add(new UnifyPair(rhsType, new SuperType(freshTph), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); + Set fBounded = pair.getfBounded(); + fBounded.add(lhsType); + result.add(new UnifyPair(freshTph, superedType, PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair(), fBounded)); + } + + return Optional.of(result); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnify.java b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnify.java new file mode 100644 index 00000000..d78d8c8d --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnify.java @@ -0,0 +1,121 @@ +package de.dhbwstuttgart.typeinference.unify; + +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.concurrent.ForkJoinPool; + +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.typeinference.constraints.Constraint; +import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; +import de.dhbwstuttgart.typeinference.constraints.Pair; +import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; +import de.dhbwstuttgart.typeinference.unify.model.FiniteClosure; +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; + +public class TypeUnify { + + /** + * unify parallel ohne result modell + * @param undConstrains + * @param oderConstraints + * @param fc + * @param logFile + * @param log + * @param cons + * @return + */ + public Set> unify(Set undConstrains, List>> oderConstraints, IFiniteClosure fc, Writer logFile, Boolean log, UnifyResultModel ret, UnifyTaskModel usedTasks) { + TypeUnifyTask unifyTask = new TypeUnifyTask(undConstrains, oderConstraints, fc, true, logFile, log, 0, ret, usedTasks); + ForkJoinPool pool = new ForkJoinPool(); + pool.invoke(unifyTask); + Set> res = unifyTask.join(); + try { + logFile.write("\nnoShortendElements: " + unifyTask.noShortendElements + "\n"); + logFile.flush(); + } + catch (IOException e) { + System.err.println("no log-File"); + } + return res; + } + + /** + * unify asynchron mit Rückgabe UnifyResultModel ohne dass alle results gesammelt sind + * @param undConstrains + * @param oderConstraints + * @param fc + * @param logFile + * @param log + * @param cons + * @param ret + * @return + */ + public UnifyResultModel unifyAsync(Set undConstrains, List>> oderConstraints, IFiniteClosure fc, Writer logFile, Boolean log, UnifyResultModel ret, UnifyTaskModel usedTasks) { + TypeUnifyTask unifyTask = new TypeUnifyTask(undConstrains, oderConstraints, fc, true, logFile, log, 0, ret, usedTasks); + ForkJoinPool pool = new ForkJoinPool(); + pool.invoke(unifyTask); + return ret; + } + + /** + * unify parallel mit Rückgabe UnifyResultModel nachdem alle results gesammelt sind + * @param undConstrains + * @param oderConstraints + * @param fc + * @param logFile + * @param log + * @param cons + * @param ret + * @return + */ + public UnifyResultModel unifyParallel(Set undConstrains, List>> oderConstraints, IFiniteClosure fc, Writer logFile, Boolean log, UnifyResultModel ret, UnifyTaskModel usedTasks) { + TypeUnifyTask unifyTask = new TypeUnifyTask(undConstrains, oderConstraints, fc, true, logFile, log, 0, ret, usedTasks); + ForkJoinPool pool = new ForkJoinPool(); + pool.invoke(unifyTask); + Set> res = unifyTask.join(); + try { + logFile.write("\nnoShortendElements: " + unifyTask.noShortendElements +"\n"); + logFile.flush(); + } + catch (IOException e) { + System.err.println("no log-File"); + } + return ret; + } + + /* + public Set> unifySequential(Set eq, IFiniteClosure fc, FileWriter logFile, Boolean log) { + TypeUnifyTask unifyTask = new TypeUnifyTask(eq, fc, false, logFile, log); + Set> res = unifyTask.compute(); + return res; + } + */ + + /** + * unify sequentiell mit oderconstraints + * @param undConstrains + * @param oderConstraints + * @param fc + * @param logFile + * @param log + * @param cons + * @return + */ + public Set> unifyOderConstraints(Set undConstrains, List>> oderConstraints, IFiniteClosure fc, Writer logFile, Boolean log, UnifyResultModel ret, UnifyTaskModel usedTasks) { + TypeUnifyTask unifyTask = new TypeUnifyTask(undConstrains, oderConstraints, fc, false, logFile, log, 0, ret, usedTasks); + Set> res = unifyTask.compute(); + try { + logFile.write("\nnoShortendElements: " + unifyTask.noShortendElements +"\n"); + logFile.flush(); + } + catch (IOException e) { + System.err.println("no log-File"); + } + return res; + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnify2Task.java b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnify2Task.java new file mode 100644 index 00000000..317f3660 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnify2Task.java @@ -0,0 +1,64 @@ +package de.dhbwstuttgart.typeinference.unify; + +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import de.dhbwstuttgart.typeinference.constraints.Constraint; +import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; +import de.dhbwstuttgart.typeinference.constraints.Pair; +import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; + +public class TypeUnify2Task extends TypeUnifyTask { + + Set> setToFlatten; + + public TypeUnify2Task(Set> setToFlatten, Set eq, List>> oderConstraints, Set nextSetElement, IFiniteClosure fc, boolean parallel, Writer logFile, Boolean log, int rekTiefe, UnifyResultModel urm, UnifyTaskModel usedTasks) { + super(eq, oderConstraints, fc, parallel, logFile, log, rekTiefe, urm, usedTasks); + this.setToFlatten = setToFlatten; + this.nextSetElement = nextSetElement; + } + + Set getNextSetElement() { + return nextSetElement; + } + + @Override + protected Set> compute() { + if (one) { + System.out.println("two"); + } + one = true; + Set> res = unify2(setToFlatten, eq, oderConstraintsField, fc, parallel, rekTiefeField); + /*if (isUndefinedPairSetSet(res)) { + return new HashSet<>(); } + else + */ + //writeLog("xxx"); + //noOfThread--; + synchronized (usedTasks) { + if (this.myIsCancelled()) { + return new HashSet<>(); + } + else { + return res; + } + } + } + + public void closeLogFile() { + + try { + logFile.close(); + } + catch (IOException ioE) { + System.err.println("no log-File" + thNo); + } + + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java new file mode 100644 index 00000000..abe48103 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/TypeUnifyTask.java @@ -0,0 +1,2547 @@ +//PL 2018-12-19: Merge checken +package de.dhbwstuttgart.typeinference.unify; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map.Entry; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.RecursiveTask; +import java.util.function.BiFunction; +import java.util.function.BinaryOperator; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.apache.commons.io.output.NullOutputStream; + +import de.dhbwstuttgart.exceptions.TypeinferenceException; +import de.dhbwstuttgart.parser.NullToken; +import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory; +import de.dhbwstuttgart.typeinference.constraints.Constraint; +import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; +import de.dhbwstuttgart.typeinference.result.ResultSet; +import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; +import de.dhbwstuttgart.typeinference.unify.interfaces.IMatch; +import de.dhbwstuttgart.typeinference.unify.interfaces.IRuleSet; +import de.dhbwstuttgart.typeinference.unify.interfaces.ISetOperations; +import de.dhbwstuttgart.typeinference.unify.interfaces.IUnify; +import de.dhbwstuttgart.typeinference.unify.model.ExtendsType; +import de.dhbwstuttgart.typeinference.unify.model.FunNType; +import de.dhbwstuttgart.typeinference.unify.model.OrderingExtend; +import de.dhbwstuttgart.typeinference.unify.model.PairOperator; +import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType; +import de.dhbwstuttgart.typeinference.unify.model.ReferenceType; +import de.dhbwstuttgart.typeinference.unify.model.SuperType; +import de.dhbwstuttgart.typeinference.unify.model.TypeParams; +import de.dhbwstuttgart.typeinference.unify.model.Unifier; +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; +import de.dhbwstuttgart.typeinference.unify.model.UnifyType; +import de.dhbwstuttgart.typeinference.unify.model.WildcardType; +import de.dhbwstuttgart.typeinference.unify.model.OrderingUnifyPair; +import de.dhbwstuttgart.typeinference.unify.model.Pair; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.Writer; + +import com.google.common.collect.Ordering; + + +/** + * Implementation of the type unification algorithm + * @author Florian Steurer + */ +public class TypeUnifyTask extends RecursiveTask>> { + + private static final long serialVersionUID = 1L; + private static int i = 0; + private boolean printtag = false; + Boolean log = true; //gibt an ob ein Log-File nach System.getProperty("user.dir")+"/test/logFiles/log" geschrieben werden soll? + + /** + * Element, das aus dem nextSet den Gleichunen dieses Threads hinzugefuegt wurde + */ + Set nextSetElement; + + /** + * Fuer die Threads + */ + UnifyResultModel urm; + protected static int noOfThread = 0; + private static int totalnoOfThread = 0; + int thNo; + protected boolean one = false; + Integer MaxNoOfThreads = 8; + + public static final String rootDirectory = System.getProperty("user.dir")+"/test/logFiles/"; + Writer logFile; + + /** + * The implementation of setOps that will be used during the unification + */ + protected ISetOperations setOps = new GuavaSetOperations(); + + /** + * The implementation of the standard unify that will be used during the unification + */ + protected IUnify stdUnify = new MartelliMontanariUnify(); + + /** + * The implementation of the rules that will be used during the unification. + */ + protected IRuleSet rules; + + protected Set eq; //und-constraints + + protected List>> oderConstraintsField; + + protected IFiniteClosure fc; + + protected OrderingExtend> oup; + + protected boolean parallel; + + //Gives if unify is not called from checkA + private boolean finalresult = true; + + int rekTiefeField; + + Integer nOfUnify = 0; + + Integer noUndefPair = 0; + + Integer noAllErasedElements = 0; + + static Integer noou = 0; + + static int noBacktracking; + + static Integer noShortendElements = 0; + + Boolean myIsCanceled = false; + + volatile UnifyTaskModel usedTasks; + + public TypeUnifyTask() { + rules = new RuleSet(); + } + + /* + public TypeUnifyTask(Set eq, IFiniteClosure fc, boolean parallel, FileWriter logFile, Boolean log) { + this.eq = eq; + this.fc = fc; + this.oup = new OrderingUnifyPair(fc); + this.parallel = parallel; + this.logFile = logFile; + this.log = log; + rules = new RuleSet(logFile); + noOfThread++; + thNo = noOfThread; + } + */ + + + public TypeUnifyTask(Set eq, List>> oderConstraints, IFiniteClosure fc, boolean parallel, Writer logFile, Boolean log, int rekTiefe, UnifyResultModel urm, UnifyTaskModel usedTasks) { + synchronized (this) { + this.eq = eq; + //this.oderConstraints = oderConstraints.stream().map(x -> x.stream().map(y -> new HashSet<>(y)).collect(Collectors.toSet(HashSet::new))).collect(Collectors.toList(ArrayList::new)); + this.oderConstraintsField = oderConstraints; /*.stream().map(x -> { + Set> ret = new HashSet<>(); + for (Constraint y : x) { + ret.add(new HashSet<>(y)); + } + return ret; + }).collect(Collectors.toCollection(ArrayList::new)); + */ + + //x.stream().map(y -> new HashSet<>(y)).collect(Collectors.toSet(HashSet::new))).collect(Collectors.toList(ArrayList::new)); + this.nextSetElement = nextSetElement; + this.fc = fc; + this.oup = new OrderingUnifyPair(fc); + this.parallel = parallel; + this.logFile = logFile; + this.log = log; + + noOfThread++; + totalnoOfThread++; + //writeLog("thNo1 " + thNo); + thNo = totalnoOfThread; + writeLog("thNo2 " + thNo); + try { + this.logFile = //new OutputStreamWriter(new NullOutputStream()); + //new FileWriter(new File(System.getProperty("user.dir")+"/resources/logFiles/"+"Thread_"+thNo)); + new FileWriter(new File(System.getProperty("user.dir")+"/logFiles/"+"Thread_"+thNo)); + logFile.write(""); + } + catch (IOException e) { + System.err.println("log-File nicht vorhanden"); + } + /*Abbruchtest + if (thNo > 10) { + System.out.println("cancel"); + usedTasks.cancel(); + writeLog(nOfUnify.toString() + "cancel"); + System.out.println("cancel"); + try { + logFile.write("Abbruch"); + } + catch (IOException e) { + System.err.println("log-File nicht vorhanden"); + } + } + */ + rules = new RuleSet(logFile); + this.rekTiefeField = rekTiefe; + this.urm = urm; + this.usedTasks = usedTasks; + this.usedTasks.add(this); + } + } + + /** + * Vererbt alle Variancen + * @param eq The set of constraints + */ + /* PL 2018-05- 17 verschoben nach JavaTXCompiler + private void varianceInheritance(Set eq) { + Set usedTPH = new HashSet<>(); + Set phSet = eq.stream().map(x -> { + Set pair = new HashSet<>(); + if (x.getLhsType() instanceof PlaceholderType) pair.add((PlaceholderType)x.getLhsType()); + if (x.getRhsType() instanceof PlaceholderType) pair.add((PlaceholderType)x.getRhsType()); + return pair; + }).reduce(new HashSet<>(), (a,b) -> { a.addAll(b); return a;} , (c,d) -> { c.addAll(d); return c;}); + + ArrayList phSetVariance = new ArrayList<>(phSet); + phSetVariance.removeIf(x -> (x.getVariance() == 0)); + while(!phSetVariance.isEmpty()) { + PlaceholderType a = phSetVariance.remove(0); + usedTPH.add(a); + //HashMap ht = new HashMap<>(); + //ht.put(a, a.getVariance()); + Set eq1 = new HashSet<>(eq); + eq1.removeIf(x -> !(x.getLhsType() instanceof PlaceholderType && ((PlaceholderType)x.getLhsType()).equals(a))); + eq1.stream().forEach(x -> { x.getRhsType().accept(new distributeVariance(), a.getVariance());}); + eq1 = new HashSet<>(eq); + eq1.removeIf(x -> !(x.getRhsType() instanceof PlaceholderType && ((PlaceholderType)x.getRhsType()).equals(a))); + eq1.stream().forEach(x -> { x.getLhsType().accept(new distributeVariance(), a.getVariance());}); + phSetVariance = new ArrayList<>(phSet); + phSetVariance.removeIf(x -> (x.getVariance() == 0 || usedTPH.contains(x))); + } +} +*/ + void myCancel(Boolean b) { + myIsCanceled = true; + } + + public boolean myIsCancelled() { + return myIsCanceled; + } + + protected Set> compute() { + if (one) { + System.out.println("two"); + } + one = true; + Set neweq = new HashSet<>(eq); + /* 1-elementige Oder-Constraints werden in und-Constraints umgewandelt */ + oderConstraintsField.stream() + .filter(x -> x.size()==1) + .map(y -> y.stream().findFirst().get()).forEach(x -> neweq.addAll(x)); + ArrayList>> remainingOderconstraints = oderConstraintsField.stream() + .filter(x -> x.size()>1) + .collect(Collectors.toCollection(ArrayList::new)); + Set> res = unify(neweq, remainingOderconstraints, fc, parallel, rekTiefeField); + noOfThread--; + try { + logFile.close(); + } + catch (IOException ioE) { + System.err.println("no log-File"); + } + if (isUndefinedPairSetSet(res)) { + //fuer debug-Zwecke + ArrayList al = res.stream().map(x -> x.stream().collect(Collectors.toCollection(ArrayList::new))) + .collect(Collectors.toCollection(ArrayList::new)); + throw new TypeinferenceException("Unresolved constraints: " + res.toString(), new NullToken()); //return new HashSet<>(); + } + else { + synchronized (usedTasks) { + if (this.myIsCancelled()) { + return new HashSet<>(); + } + else { + return res; + } + } + } + } +/* + @Override + protected Set> compute() { + Set> fstElems = new HashSet<>(); + fstElems.add(eq); + Set> res = computeCartesianRecursiveOderConstraints(fstElems, oderConstraints, fc, parallel); + if (isUndefinedPairSetSet(res)) { return new HashSet<>(); } + else return res; + } +*/ + + + + + /** + * Computes all principal type unifiers for a set of constraints. + * @param eq The set of constraints + * @param fc The finite closure + * @return The set of all principal type unifiers + */ + protected Set> unify(final Set eq, List>> oderConstraints, IFiniteClosure fc, boolean parallel, int rekTiefe) { + //Set aas = eq.stream().filter(x -> x.getLhsType().getName().equals("AA") //&& x.getPairOp().equals(PairOperator.SMALLERDOT) + // ).collect(Collectors.toCollection(HashSet::new)); + //writeLog(nOfUnify.toString() + " AA: " + aas.toString()); + //if (aas.isEmpty()) { + // System.out.println(""); + //} + + //.collect(Collectors.toCollection(HashSet::new))); + + synchronized (usedTasks) { + if (this.myIsCancelled()) { + return new HashSet<>(); + } + } + + rekTiefe++; + nOfUnify++; + writeLog(nOfUnify.toString() + " Unifikation: " + eq.toString()); + writeLog(nOfUnify.toString() + " Oderconstraints: " + oderConstraints.toString()); + + /* + * Variancen auf alle Gleichungen vererben + */ + //PL 2018-05-17 nach JavaTXCompiler verschoben + //varianceInheritance(eq); + + /* + * ? extends ? extends Theta rausfiltern + */ + Set doubleExt = eq.stream().filter(x -> (x.wrongWildcard())).map(x -> { x.setUndefinedPair(); return x;}) + .collect(Collectors.toCollection(HashSet::new)); + if (doubleExt.size() > 0) { + Set> ret = new HashSet<>(); + ret.add(doubleExt); + return ret; + } + + /* + * Occurs-Check durchfuehren + */ + + Set ocurrPairs = eq.stream().filter(x -> { + UnifyType lhs, rhs; + return (lhs = x.getLhsType()) instanceof PlaceholderType + && !((rhs = x.getRhsType()) instanceof PlaceholderType) + && rhs.getTypeParams().occurs((PlaceholderType)lhs);}) + .map(x -> { x.setUndefinedPair(); return x;}) + .collect(Collectors.toCollection(HashSet::new)); + writeLog("ocurrPairs: " + ocurrPairs); + if (ocurrPairs.size() > 0) { + Set> ret = new HashSet<>(); + ret.add(ocurrPairs); + return ret; + } + + + + /* + * Step 1: Repeated application of reduce, adapt, erase, swap + */ + Set eq0; + Set eq0Prime; + Optional> eqSubst = Optional.of(eq); + do { + eq0Prime = eqSubst.get(); + eq0 = applyTypeUnificationRules(eq0Prime, fc); + eqSubst = rules.subst(eq0, oderConstraints); + } while (eqSubst.isPresent()); + + eq0.forEach(x -> x.disableCondWildcards()); + + writeLog(nOfUnify.toString() + " Unifikation nach applyTypeUnificationRules: " + eq.toString()); + writeLog(nOfUnify.toString() + " Oderconstraints nach applyTypeUnificationRules: " + oderConstraints.toString()); + + /* + * Step 2 and 3: Create a subset eq1s of pairs where both sides are TPH and eq2s of the other pairs + */ + Set eq1s = new HashSet<>(); + Set eq2s = new HashSet<>(); + splitEq(eq0, eq1s, eq2s); + + /* + * Step 4: Create possible typings + * + * "Manche Autoren identifizieren die Paare (a, (b,c)) und ((a,b),c) + * mit dem geordneten Tripel (a,b,c), wodurch das kartesische Produkt auch assoziativ wird." - Wikipedia + */ + + // There are up to 10 toplevel set. 8 of 10 are the result of the + // cartesian product of the sets created by pattern matching. + List>> topLevelSets = new ArrayList<>(); + + //System.out.println(eq2s); + + if(eq1s.size() != 0) { // Do not add empty sets or the cartesian product will always be empty. + Set> wrap = new HashSet<>(); + wrap.add(eq1s); + topLevelSets.add(wrap); // Add Eq1' + } + + // Add the set of [a =. Theta | (a=. Theta) in Eq2'] + //TODO: Occurscheck anwenden als Fehler identifizieren + Set bufferSet = eq2s.stream() + .filter(x -> x.getPairOp() == PairOperator.EQUALSDOT && x.getLhsType() instanceof PlaceholderType) + .collect(Collectors.toSet()); + + if(bufferSet.size() != 0) { // Do not add empty sets or the cartesian product will always be empty. + Set> wrap = new HashSet<>(); + wrap.add(bufferSet); + topLevelSets.add(wrap); + eq2s.removeAll(bufferSet); + } + + // Sets that originate from pair pattern matching + // Sets of the "second level" + Set undefinedPairs = new HashSet<>(); + if (printtag) System.out.println("eq2s " + eq2s); + //writeLog("BufferSet: " + bufferSet.toString()+"\n"); + List>> oderConstraintsOutput = new ArrayList<>();//new ArrayList<>(oderConstraints); + Set>>> secondLevelSets = calculatePairSets(eq2s, oderConstraints, fc, undefinedPairs, oderConstraintsOutput); + //PL 2017-09-20: Im calculatePairSets wird möglicherweise O .< java.lang.Integer + //nicht ausgewertet Faculty Beispiel im 1. Schritt + //PL 2017-10-03 geloest, muesste noch mit FCs mit kleineren + //Typen getestet werden. + writeLog(nOfUnify.toString() + " Oderconstraints2: " + oderConstraintsOutput.toString()); + if (printtag) System.out.println("secondLevelSets:" +secondLevelSets); + // If pairs occured that did not match one of the cartesian product cases, + // those pairs are contradictory and the unification is impossible. + if(!undefinedPairs.isEmpty()) { + noUndefPair++; + for (UnifyPair up : undefinedPairs) { + writeLog(noUndefPair.toString() + " UndefinedPairs; " + up); + writeLog("BasePair; " + up.getBasePair()); + } + Set> error = new HashSet<>(); + undefinedPairs = undefinedPairs.stream().map(x -> { x.setUndefinedPair(); return x;}).collect(Collectors.toCollection(HashSet::new)); + error.add(undefinedPairs); + undefinedPairs.forEach(x -> writeLog("AllSubst: " +x.getAllSubstitutions().toString())); + return error; + } + + /* Up to here, no cartesian products are calculated. + * filters for pairs and sets can be applied here */ + + // Alternative: Sub cartesian products of the second level (pattern matched) sets + // "the big (x)" + /* for(Set>> secondLevelSet : secondLevelSets) { + //System.out.println("secondLevelSet "+secondLevelSet.size()); + List>> secondLevelSetList = new ArrayList<>(secondLevelSet); + Set>> cartResult = setOps.cartesianProduct(secondLevelSetList); + //System.out.println("CardResult: "+cartResult.size()); + // Flatten and add to top level sets + Set> flat = new HashSet<>(); + int j = 0; + for(List> s : cartResult) { + j++; + //System.out.println("s from CardResult: "+cartResult.size() + " " + j); + Set flat1 = new HashSet<>(); + for(Set s1 : s) + flat1.addAll(s1); + flat.add(flat1); + } + //topLevelSets.add(flat); + } + */ + + //Alternative KEIN KARTESISCHES PRODUKT der secondlevel Ebene bilden + for(Set>> secondLevelSet : secondLevelSets) { + for (Set> secondlevelelem : secondLevelSet) { + topLevelSets.add(secondlevelelem); + } + } + //System.out.println(topLevelSets); + //System.out.println(); + + + //Aufruf von computeCartesianRecursive ANFANG + //writeLog("topLevelSets: " + topLevelSets.toString()); + return computeCartesianRecursive(new ArrayList<>(topLevelSets), eq, oderConstraintsOutput, fc, parallel, rekTiefe); + + } + + + Set> unify2(Set> setToFlatten, Set eq, List>> oderConstraints, IFiniteClosure fc, boolean parallel, int rekTiefe) { + //Aufruf von computeCartesianRecursive ENDE + + //keine Ahnung woher das kommt + //Set> setToFlatten = topLevelSets.stream().map(x -> x.iterator().next()).collect(Collectors.toCollection(HashSet::new)); + + //Muss auskommentiert werden, wenn computeCartesianRecursive ANFANG + // Cartesian product over all (up to 10) top level sets + //Set>> eqPrimeSet = setOps.cartesianProduct(topLevelSets) + // .stream().map(x -> new HashSet<>(x)) + // .collect(Collectors.toCollection(HashSet::new)); + //Muss auskommentiert werden, wenn computeCartesianRecursive ENDE + + synchronized (usedTasks) { + if (this.myIsCancelled()) { + return new HashSet<>(); + } + } + + Set> eqPrimePrimeSet = new HashSet<>(); + + Set forks = new HashSet<>(); + + //Muss auskommentiert werden, wenn computeCartesianRecursive ANFANG + //for(Set> setToFlatten : eqPrimeSet) { + // Flatten the cartesian product + //Muss auskommentiert werden, wenn computeCartesianRecursive ENDE + Set eqPrime = new HashSet<>(); + setToFlatten.stream().forEach(x -> eqPrime.addAll(x)); + + /* + * Step 5: Substitution + */ + //writeLog("vor Subst: " + eqPrime); + writeLog("vor Subst: " + oderConstraints); + String ocString = oderConstraints.toString(); + List>> newOderConstraints = new ArrayList<>(oderConstraints); + Optional> eqPrimePrime = rules.subst(eqPrime, newOderConstraints); + Set> unifyres1 = null; + Set> unifyres2 = null; + if (!ocString.equals(newOderConstraints.toString())) writeLog("nach Subst: " + newOderConstraints); + //writeLog("nach Subst: " + eqPrimePrime); + /* + * Step 6 a) Restart (fork) for pairs where subst was applied + */ + /* + if(parallel) { + if (eqPrime.equals(eq) && !eqPrimePrime.isPresent() + && oderConstraints.isEmpty()) //PL 2017-09-29 //(!eqPrimePrime.isPresent()) auskommentiert und durch + //PL 2017-09-29 dies ersetzt //(!eqPrimePrime.isPresent()) + //PL 2018-05-18 beide Bedingungen muessen gelten, da eqPrime Veränderungen in allem ausser subst + //eqPrimePrime Veraenderungen in subst repraesentieren. + eqPrimePrimeSet.add(eqPrime); + else if(eqPrimePrime.isPresent()) { + //System.out.println("nextStep: " + eqPrimePrime.get()); + TypeUnifyTask fork = new TypeUnifyTask(eqPrimePrime.get(), fc, true, logFile, log); + forks.add(fork); + fork.fork(); + } + else { + //System.out.println("nextStep: " + eqPrime); + TypeUnifyTask fork = new TypeUnifyTask(eqPrime, fc, true, logFile, log); + forks.add(fork); + fork.fork(); + } + } + else */ + {// sequentiell (Step 6b is included) + if (printtag) System.out.println("nextStep: " + eqPrimePrime); + if (eqPrime.equals(eq) && !eqPrimePrime.isPresent() + && oderConstraints.isEmpty()) { //PL 2017-09-29 //(!eqPrimePrime.isPresent()) auskommentiert und durch + //PL 2017-09-29 dies ersetzt //(!eqPrimePrime.isPresent()) + //PL 2018-05-18 beide Bedingungen muessen gelten, da eqPrime Veränderungen in allem ausser subst + //eqPrimePrime Veraenderungen in subst repraesentieren. + //try { + //if (isSolvedForm(eqPrime)) { + // writeLog("eqPrime:" + eqPrime.toString()+"\n"); + //} + //} + //catch (IOException e) { + // System.err.println("log-File nicht vorhanden"); + //} + eqPrimePrimeSet.add(eqPrime); + if (finalresult && isSolvedForm(eqPrime)) { + writeLog("eqPrime:" + eqPrime.toString()+"\n"); + urm.notify(eqPrimePrimeSet); + } + } + else if(eqPrimePrime.isPresent()) { + Set> unifyres = unifyres1 = unify(eqPrimePrime.get(), newOderConstraints, fc, parallel, rekTiefe); + + eqPrimePrimeSet.addAll(unifyres); + } + else { + Set> unifyres = unifyres2 = unify(eqPrime, newOderConstraints, fc, parallel, rekTiefe); + + + eqPrimePrimeSet.addAll(unifyres); + } + } + //Muss auskommentiert werden, wenn computeCartesianRecursive ANFANG + //} + //Muss auskommentiert werden, wenn computeCartesianRecursive ENDE + + /* + * Step 6 b) Build the union over everything. + */ + /* + * PL 2019-01-22: geloescht + + if(parallel) + for(TypeUnifyTask fork : forks) + eqPrimePrimeSet.addAll(fork.join()); + */ + /* + * Step 7: Filter empty sets; + */ + eqPrimePrimeSet = eqPrimePrimeSet.stream().filter(x -> isSolvedForm(x) || this.isUndefinedPairSet(x)).collect(Collectors.toCollection(HashSet::new)); + if (!eqPrimePrimeSet.isEmpty() && !isUndefinedPairSetSet(eqPrimePrimeSet)) { + writeLog("Result1 " + eqPrimePrimeSet.toString()); + } + return eqPrimePrimeSet; + } + + + /** + * Computes the cartesian product of topLevelSets step by step. + * @param topLevelSets List of Sets of Sets, where a cartesian product have to be built + * Ex.: [{{a =. Integer}, {a = Object}}, {{a = Vector, b =. Integer}, {a = Vector, b =. Object}}] + * @param eq Original set of equations which should be unified + * @param oderConstraints Remaining or-constraints + * @param fc The finite closure + * @param parallel If the algorithm should be parallelized run + * @param rekTiefe Deep of recursive calls + * @return The set of all principal type unifiers + */ + Set> computeCartesianRecursive(ArrayList>> topLevelSets, Set eq, List>> oderConstraints, IFiniteClosure fc, boolean parallel, int rekTiefe) { + + //oneElems: Alle 1-elementigen Mengen, die nur ein Paar + //a <. theta, theta <. a oder a =. theta enthalten + Set> oneElems = new HashSet<>(); + oneElems.addAll(topLevelSets.stream() + .filter(x -> x.size()==1) + .map(y -> y.stream().findFirst().get()) + .collect(Collectors.toCollection(HashSet::new))); + + //optNextSet: Eine mehrelementige Menge, wenn vorhanden + Optional>> optNextSet = topLevelSets.stream().filter(x -> x.size()>1).findAny(); + + if (!optNextSet.isPresent()) {//Alle Elemente sind 1-elementig + Set> result = unify2(oneElems, eq, oderConstraints, fc, parallel, rekTiefe); + return result; + } + + Set> nextSet = optNextSet.get(); + //writeLog("nextSet: " + nextSet.toString()); + List> nextSetasList =new ArrayList<>(nextSet); + /* + try { + //List> + //nextSetasList = oup.sortedCopy(nextSet);//new ArrayList<>(nextSet); + } + catch (java.lang.IllegalArgumentException e) { + System.out.print(""); + } + */ + Set> result = new HashSet<>(); + int variance = 0; + + /* Varianzbestimmung Anfang + * Oderconstraint, wenn entweder kein Basepair oder unterschiedliche Basepairs => oderConstraint = true; + * Varianz = 1 => Argumentvariable + * Varianz = -1 => Rückgabevariable + * Varianz = 0 => unklar + * Varianz = 2 => Operatoren oderConstraints */ + ArrayList zeroNextElem = new ArrayList<>(nextSetasList.get(0)); + UnifyPair fstBasePair = zeroNextElem.remove(0).getBasePair(); + Boolean oderConstraint = false; + + if (fstBasePair != null) { + Boolean sameBase = true; + for (UnifyPair ele : nextSetasList.get(0)) {//check ob a <. ty base oder ob Ueberladung + sameBase = sameBase && ele.getBasePair() != null && ele.getBasePair().equals(fstBasePair); + } + if (sameBase) { //angefuegt PL 2020-02-30 + Optional xi = nextSetasList.stream().map(x -> x.stream().filter(y -> (y.getLhsType() instanceof PlaceholderType && !(y.getRhsType() instanceof PlaceholderType))) + .filter(z -> ((PlaceholderType)z.getLhsType()).getVariance() != 0) + .map(c -> ((PlaceholderType)c.getLhsType()).getVariance()) + .reduce((a,b)-> {if (a==b) return a; else return 0; })) //2 kommt insbesondere bei Oder-Constraints vor + .filter(d -> d.isPresent()) + .map(e -> e.get()) + .findAny(); + if (xi.isPresent()) { + variance = xi.get(); + } + } + else { + oderConstraint = true; + } + } + else { + oderConstraint = true; + } + + //Varianz-Bestimmung Oder-Constraints + if (oderConstraint) { + if (printtag) System.out.println("nextSetasList " + nextSetasList); + Optional optVariance = + nextSetasList.iterator() + .next() + .stream() + .filter(x -> x.getGroundBasePair().getLhsType() instanceof PlaceholderType && + ! (x.getRhsType() instanceof PlaceholderType) && + x.getPairOp() == PairOperator.EQUALSDOT) + .map(x -> + ((PlaceholderType)x.getGroundBasePair().getLhsType()).getVariance()) + .findAny(); + //Fuer Operatorenaufrufe wird variance auf 2 gesetzt. + //da kein Receiver existiert also kein x.getGroundBasePair().getLhsType() instanceof PlaceholderType + //Bei Varianz = 2 werden alle Elemente des Kartesischen Produkts abgearbeitet + variance = optVariance.isPresent() ? optVariance.get() : 2; + } + /* Varianzbestimmung Ende */ + + //writeLog("nextSetasList: " + nextSetasList.toString()); + Set nextSetElem = nextSetasList.get(0); + //writeLog("BasePair1: " + nextSetElem + " " + nextSetElem.iterator().next().getBasePair()); + + /* sameEqSet-Bestimmung: Wenn a = ty \in nextSet dann enthaelt sameEqSet + * alle Paare a < ty1 oder ty2 < a aus oneElems */ + Set sameEqSet = new HashSet<>(); + + //optOrigPair enthaelt ggf. das Paar a = ty \in nextSet + Optional optOrigPair = null; + if (!oderConstraint) { + optOrigPair = nextSetElem.stream().filter(x -> ( + //x.getBasePair() != null && ist gegeben wenn variance != 2 + //x.getBasePair().getPairOp().equals(PairOperator.SMALLERDOT) && + (x.getPairOp().equals(PairOperator.EQUALSDOT) + /* + (x.getBasePair().getLhsType() instanceof PlaceholderType + && x.getLhsType().equals(x.getBasePair().getLhsType())) + || (x.getBasePair().getRhsType() instanceof PlaceholderType + && x.getLhsType().equals(x.getBasePair().getRhsType()) + */ + ))).filter(x -> //Sicherstellen, dass bei a = ty a auch wirklich die gesuchte Typvariable ist + x.getLhsType().equals(x.getBasePair().getLhsType()) || + x.getLhsType().equals(x.getBasePair().getRhsType()) + ).findFirst(); + writeLog("optOrigPair: " + optOrigPair); + if (optOrigPair.isPresent()) { + UnifyPair origPair = optOrigPair.get(); + UnifyType tyVar; + if (!((tyVar = origPair.getLhsType()) instanceof PlaceholderType)) { + tyVar = origPair.getRhsType(); + } + UnifyType tyVarEF = tyVar; + sameEqSet = oneElems.stream().map(xx -> xx.iterator().next()) + .filter(x -> (((x.getLhsType().equals(tyVarEF) && !(x.getRhsType() instanceof PlaceholderType)) + || (x.getRhsType().equals(tyVarEF) && !(x.getLhsType() instanceof PlaceholderType))))) + .collect(Collectors.toCollection(HashSet::new)); + } + } + /* sameEqSet-Bestimmung Ende */ + + Set a = null; + while (nextSetasList.size() > 0) { + Set a_last = a; + + /* Liste der Faelle für die parallele Verarbeitung + * Enthaelt Elemente, die nicht in Relation zu aktuellem Fall in der + * Variablen a stehen. Diese muesse auf alle Faelle bearbeitet werden, + * Deshalb wird ihre Berechnung parallel angestossen. + */ + List> nextSetasListRest = new ArrayList<>(); + + /* Liste der Faelle, bei dem Receiver jeweils "? extends" enthaelt bzw. nicht enthaelt + * In der Regel ist dies genau ein Element + * Dieses Element wird später aus nextSetasList geloescht, wenn das jeweils andere Element zum Erfolg + * gefuehrt hat. + */ + List> nextSetasListOderConstraints = new ArrayList<>(); + + writeLog("nextSet: " + nextSet.toString()); + writeLog("nextSetasList: " + nextSetasList.toString()); + if (variance == 1) { + a = oup.max(nextSetasList.iterator()); + nextSetasList.remove(a); + if (oderConstraint) { + nextSetasListOderConstraints.add(((Constraint)a).getExtendConstraint()); + } + writeLog("nextSetasListOderConstraints 1: " + nextSetasListOderConstraints); + nextSetasListRest = new ArrayList<>(nextSetasList); + Iterator> nextSetasListItRest = new ArrayList>(nextSetasListRest).iterator(); + while (nextSetasListItRest.hasNext()) { + Set a_next = nextSetasListItRest.next(); + if (//a.equals(a_next) || + (oup.compare(a, a_next) == 1)) { + nextSetasListRest.remove(a_next); + } + } + + //Alle maximale Elemente in nextSetasListRest bestimmen + //nur für diese wird parallele Berechnung angestossen. + nextSetasListRest = oup.maxElements(nextSetasListRest); + } + else if (variance == -1) { + a = oup.min(nextSetasList.iterator()); + writeLog("Min: a in " + variance + " "+ a); + if (oderConstraint) { + nextSetasListOderConstraints.add(((Constraint)a).getExtendConstraint()); + } + writeLog("nextSetasListOderConstraints -1: " + nextSetasListOderConstraints); + nextSetasList.remove(a); + nextSetasListRest = new ArrayList<>(nextSetasList); + Iterator> nextSetasListItRest = new ArrayList>(nextSetasListRest).iterator(); + while (nextSetasListItRest.hasNext()) { + Set a_next = nextSetasListItRest.next(); + if (//a.equals(a_next) || + (oup.compare(a, a_next) == -1)) { + nextSetasListRest.remove(a_next); + } + } + //Alle minimalen Elemente in nextSetasListRest bestimmen + //nur für diese wird parallele Berechnung angestossen. + nextSetasListRest = oup.minElements(nextSetasListRest); + } + else if (variance == 2) { + a = nextSetasList.remove(0); + + //Fuer alle Elemente wird parallele Berechnung angestossen. + nextSetasListRest = new ArrayList<>(nextSetasList); + } + else if (variance == 0) { + //wenn a <. theta dann ist ein maximales Element sehr wahrscheinlich + //wenn theta <. a dann ist ein minimales Element sehr wahrscheinlich + if (!oderConstraint && optOrigPair != null && optOrigPair.isPresent()) { + if (optOrigPair.get().getBasePair().getLhsType() instanceof PlaceholderType) { + a = oup.max(nextSetasList.iterator()); + } + else { + a = oup.min(nextSetasList.iterator()); + } + nextSetasList.remove(a); + } + else { + if (oderConstraint) { + a = oup.max(nextSetasList.iterator()); + nextSetasList.remove(a); + nextSetasListOderConstraints.add(((Constraint)a).getExtendConstraint()); + } + else { + a = nextSetasList.remove(0); + } + } + } + + i++; + Set> elems = new HashSet>(oneElems); + writeLog("a1: " + rekTiefe + " "+ "variance: "+ variance + " " + a.toString()+ "\n"); + + //Ergebnisvariable für den aktuelle Thread + Set> res = new HashSet<>(); + + //Menge der Ergebnisse der geforkten Threads + Set>> add_res = new HashSet<>(); + + + Set> aParDef = new HashSet<>(); + + /* Wenn bei (a \in theta) \in a zu Widerspruch in oneElems wird + * a verworfen und zu nächstem Element von nextSetasList gegangen + */ + if (!oderConstraint && !sameEqSet.isEmpty() && !checkNoContradiction(a, sameEqSet, result)) { + a = null; + noShortendElements++; + continue; + } + + /* Wenn parallel gearbeitet wird, wird je nach Varianz ein neuer Thread + * gestartet, der parallel weiterarbeitet. + */ + if(parallel && (variance == 1) && noOfThread <= MaxNoOfThreads) { + Set forks = new HashSet<>(); + Set newEqOrig = new HashSet<>(eq); + Set> newElemsOrig = new HashSet<>(elems); + List>> newOderConstraintsOrig = new ArrayList<>(oderConstraints); + newElemsOrig.add(a); + + /* FORK ANFANG */ + TypeUnify2Task forkOrig = new TypeUnify2Task(newElemsOrig, newEqOrig, newOderConstraintsOrig, a, fc, parallel, logFile, log, rekTiefe, urm, usedTasks); + //forks.add(forkOrig); + synchronized(usedTasks) { + if (this.myIsCancelled()) { + return new HashSet<>(); + } + forkOrig.fork(); + } + /* FORK ENDE */ + + synchronized (this) { + writeLog("a in " + variance + " "+ a); + writeLog("nextSetasListRest: " + nextSetasListRest.toString()); + } + while (!nextSetasListRest.isEmpty()) { + Set nSaL = nextSetasListRest.remove(0); + synchronized (this) { nextSetasList.remove(nSaL); + writeLog("1 RM" + nSaL.toString()); + } + + if (!oderConstraint) { + //ueberpruefung ob zu a =. ty \in nSaL in sameEqSet ein Widerspruch besteht + if (!sameEqSet.isEmpty() && !checkNoContradiction(nSaL, sameEqSet, result)) { + nSaL = null; + noShortendElements++; + continue; + } + } + else { + nextSetasListOderConstraints.add(((Constraint)nSaL).getExtendConstraint()); + } + Set newEq = new HashSet<>(eq); + Set> newElems = new HashSet<>(elems); + List>> newOderConstraints = new ArrayList<>(oderConstraints); + newElems.add(nSaL); + TypeUnify2Task fork = new TypeUnify2Task(newElems, newEq, newOderConstraints, nSaL, fc, parallel, logFile, log, rekTiefe, urm, usedTasks); + forks.add(fork); + synchronized(usedTasks) { + if (this.myIsCancelled()) { + return new HashSet<>(); + } + fork.fork(); + } + } + //res = unify2(newElemsOrig, newEqOrig, newOderConstraintsOrig, fc, parallel, rekTiefe); + + /* FORK ANFANG */ + synchronized (this) { + writeLog("wait "+ forkOrig.thNo); + noOfThread--; + res = forkOrig.join(); + synchronized (usedTasks) { + if (this.myIsCancelled()) { + return new HashSet<>(); + } + } + //noOfThread++; + forkOrig.writeLog("final Orig 1"); + forkOrig.closeLogFile(); + //Set> fork_res = forkOrig.join(); + writeLog("JoinOrig " + new Integer(forkOrig.thNo).toString()); + //noOfThread--; an das Ende von compute verschoben + //add_res.add(fork_res); + }; + /* FORK ENDE */ + + forks.forEach(x -> writeLog("wait: " + x.thNo)); + for(TypeUnify2Task fork : forks) { + synchronized (this) { + noOfThread--; + Set> fork_res = fork.join(); + synchronized (usedTasks) { + if (this.myIsCancelled()) { + return new HashSet<>(); + } + } + //noOfThread++; + writeLog("Join " + new Integer(fork.thNo).toString()); + //noOfThread--; an das Ende von compute verschoben + writeLog("fork_res: " + fork_res.toString()); + writeLog(new Boolean((isUndefinedPairSetSet(fork_res))).toString()); + add_res.add(fork_res); + if (!isUndefinedPairSetSet(fork_res)) { + aParDef.add(fork.getNextSetElement()); + } + fork.writeLog("final 1"); + fork.closeLogFile(); + }; + } + //noOfThread++; + } else { + if(parallel && (variance == -1) && noOfThread <= MaxNoOfThreads) { + Set forks = new HashSet<>(); + Set newEqOrig = new HashSet<>(eq); + Set> newElemsOrig = new HashSet<>(elems); + List>> newOderConstraintsOrig = new ArrayList<>(oderConstraints); + newElemsOrig.add(a); + + /* FORK ANFANG */ + TypeUnify2Task forkOrig = new TypeUnify2Task(newElemsOrig, newEqOrig, newOderConstraintsOrig, a, fc, parallel, logFile, log, rekTiefe, urm, usedTasks); + //forks.add(forkOrig); + synchronized(usedTasks) { + if (this.myIsCancelled()) { + return new HashSet<>(); + } + forkOrig.fork(); + } + /* FORK ENDE */ + + synchronized (this) { + writeLog("a in " + variance + " "+ a); + writeLog("nextSetasListRest: " + nextSetasListRest.toString()); + } + while (!nextSetasListRest.isEmpty()) { + Set nSaL = nextSetasListRest.remove(0); + synchronized (this) { nextSetasList.remove(nSaL); + writeLog("-1 RM" + nSaL.toString()); + } + + if (!oderConstraint) { + //ueberpruefung ob zu a =. ty \in nSaL in sameEqSet ein Widerspruch besteht + if (!sameEqSet.isEmpty() && !checkNoContradiction(nSaL, sameEqSet, result)) { + nSaL = null; + noShortendElements++; + continue; + } + } + else { + nextSetasListOderConstraints.add(((Constraint)nSaL).getExtendConstraint()); + } + Set newEq = new HashSet<>(eq); + Set> newElems = new HashSet<>(elems); + List>> newOderConstraints = new ArrayList<>(oderConstraints); + newElems.add(nSaL); + TypeUnify2Task fork = new TypeUnify2Task(newElems, newEq, newOderConstraints, nSaL, fc, parallel, logFile, log, rekTiefe, urm, usedTasks); + forks.add(fork); + synchronized(usedTasks) { + if (this.myIsCancelled()) { + return new HashSet<>(); + } + fork.fork(); + } + } + //res = unify2(newElemsOrig, newEqOrig, newOderConstraintsOrig, fc, parallel, rekTiefe); + + /* FORK ANFANG */ + synchronized (this) { + writeLog("wait "+ forkOrig.thNo); + noOfThread--; + res = forkOrig.join(); + synchronized (usedTasks) { + if (this.myIsCancelled()) { + return new HashSet<>(); + } + } + //noOfThread++; + forkOrig.writeLog("final Orig -1"); + forkOrig.closeLogFile(); + //Set> fork_res = forkOrig.join(); + writeLog("JoinOrig " + new Integer(forkOrig.thNo).toString()); + //noOfThread--; an das Ende von compute verschoben + //add_res.add(fork_res); + }; + /* FORK ENDE */ + + forks.forEach(x -> writeLog("wait: " + x.thNo)); + for(TypeUnify2Task fork : forks) { + synchronized (this) { + noOfThread--; + Set> fork_res = fork.join(); + synchronized (usedTasks) { + if (this.myIsCancelled()) { + return new HashSet<>(); + } + } + //noOfThread++; + writeLog("Join " + new Integer(fork.thNo).toString()); + //noOfThread--; an das Ende von compute verschoben + writeLog("fork_res: " + fork_res.toString()); + writeLog(new Boolean((isUndefinedPairSetSet(fork_res))).toString()); + add_res.add(fork_res); + if (!isUndefinedPairSetSet(fork_res)) { + aParDef.add(fork.getNextSetElement()); + } + fork.writeLog("final -1"); + fork.closeLogFile(); + }; + } + //noOfThread++; + } else { + if(parallel && (variance == 2) && noOfThread <= MaxNoOfThreads) { + writeLog("var2einstieg"); + Set forks = new HashSet<>(); + Set newEqOrig = new HashSet<>(eq); + Set> newElemsOrig = new HashSet<>(elems); + List>> newOderConstraintsOrig = new ArrayList<>(oderConstraints); + newElemsOrig.add(a); + + /* FORK ANFANG */ + TypeUnify2Task forkOrig = new TypeUnify2Task(newElemsOrig, newEqOrig, newOderConstraintsOrig, a, fc, parallel, logFile, log, rekTiefe, urm, usedTasks); + //forks.add(forkOrig); + synchronized(usedTasks) { + if (this.myIsCancelled()) { + return new HashSet<>(); + } + forkOrig.fork(); + } + /* FORK ENDE */ + + synchronized (this) { + writeLog("a in " + variance + " "+ a); + writeLog("nextSetasListRest: " + nextSetasListRest.toString()); + } + while (!nextSetasListRest.isEmpty()) { + Set nSaL = nextSetasListRest.remove(0); + nextSetasList.remove(nSaL); //PL einkommentiert 20-02-03 + Set newEq = new HashSet<>(eq); + Set> newElems = new HashSet<>(elems); + List>> newOderConstraints = new ArrayList<>(oderConstraints); + newElems.add(nSaL); + TypeUnify2Task fork = new TypeUnify2Task(newElems, newEq, newOderConstraints, nSaL, fc, parallel, logFile, log, rekTiefe, urm, usedTasks); + forks.add(fork); + synchronized(usedTasks) { + if (this.myIsCancelled()) { + return new HashSet<>(); + } + fork.fork(); + } + } + //res = unify2(newElemsOrig, newEqOrig, newOderConstraintsOrig, fc, parallel, rekTiefe); + + /* FORK ANFANG */ + synchronized (this) { + writeLog("wait "+ forkOrig.thNo); + noOfThread--; + res = forkOrig.join(); + synchronized (usedTasks) { + if (this.myIsCancelled()) { + return new HashSet<>(); + } + } + //noOfThread++; + forkOrig.writeLog("final Orig 2"); + forkOrig.closeLogFile(); + //Set> fork_res = forkOrig.join(); + writeLog("JoinOrig " + new Integer(forkOrig.thNo).toString()); + //noOfThread--; an das Ende von compute verschoben + //add_res.add(fork_res); //vermutlich falsch + }; + /* FORK ENDE */ + forks.forEach(x -> writeLog("wait: " + x.thNo)); + for(TypeUnify2Task fork : forks) { + synchronized (this) { + noOfThread--; + Set> fork_res = fork.join(); + synchronized (usedTasks) { + if (this.myIsCancelled()) { + return new HashSet<>(); + } + } + //noOfThread++; + writeLog("Join " + new Integer(fork.thNo).toString()); + //noOfThread--; an das Ende von compute verschoben + add_res.add(fork_res); + fork.writeLog("final 2"); + fork.closeLogFile(); + }; + } + //noOfThread++; + } else {//parallel = false oder MaxNoOfThreads ist erreicht, sequentiell weiterarbeiten + elems.add(a); //PL 2019-01-16 muss das wirklich hin steht schon in Zeile 859 ja braucht man siehe Zeile 859 + res = unify2(elems, eq, oderConstraints, fc, parallel, rekTiefe); + }}} + + //Ab hier alle parallele Berechnungen wieder zusammengeführt. + if (!isUndefinedPairSetSet(res) && isUndefinedPairSetSet(result)) { + //wenn korrektes Ergebnis gefunden alle Fehlerfaelle loeschen + result = res; + } + else { + if ((isUndefinedPairSetSet(res) && isUndefinedPairSetSet(result)) + || (!isUndefinedPairSetSet(res) && !isUndefinedPairSetSet(result)) + || result.isEmpty()) { + + if ((!result.isEmpty() && !res.isEmpty() && !isUndefinedPairSetSet(res) && !isUndefinedPairSetSet(result)) //korrekte Loesungen aus und-constraints + && (a.stream().map(x-> (x.getBasePair() != null)).reduce(true, (x, y) -> (x && y)))) //bei oder-Constraints nicht ausfuehren + { + //TODO: PL 2019-01-15: Bug 129: Im Moment wird nur das Maximum und das Minimum des aktuellen Elements betrachtet. + //Die zu vereinigenden Mengen können mehrere Elemente enthalten. Das ist bisher nicht berücksichtigt + + //Alle Variablen bestimmen die nicht hinzugefügt wurden in a + //PL 2018-12-28: Hier gab es eine ClassCastException, war nicht reproduzierbar + System.out.println(""); + List vars_a = + a.stream().filter(x -> ((x.getLhsType().getName().equals(x.getBasePair().getLhsType().getName()) + && (x.getLhsType() instanceof PlaceholderType) && (x.getBasePair().getLhsType() instanceof PlaceholderType)) + || ((x.getLhsType().getName().equals(x.getBasePair().getRhsType().getName())) + && (x.getLhsType() instanceof PlaceholderType) && (x.getBasePair().getRhsType() instanceof PlaceholderType))) + ) + .map(y -> (PlaceholderType)y.getLhsType()).collect(Collectors.toCollection(ArrayList::new)); + Set fstElemRes = res.iterator().next(); + Set compRes = fstElemRes.stream().filter(x -> vars_a.contains(((PlaceholderType)x.getLhsType()))).collect(Collectors.toCollection(HashSet::new)); + + //Alle Variablen bestimmen die nicht hinzugefügt wurden in a_last + //System.out.println(a_last); + + try {//PL eingefuegt 2019-03-06 da bei map mmer wieder Nullpointer kamen + a_last.forEach(x -> {writeLog("a_last_elem:" + x + " basepair: " + x.getBasePair());});//PL 2019-05-13 ins try hinzugefuegt Nullpointer-Exception ist in der Zeile aufgetaucht. + List varsLast_a = + a_last.stream().filter(x -> ((x.getLhsType().getName().equals(x.getBasePair().getLhsType().getName()) + && (x.getLhsType() instanceof PlaceholderType) && (x.getBasePair().getLhsType() instanceof PlaceholderType)) + || ((x.getLhsType().getName().equals(x.getBasePair().getRhsType().getName()))) + && (x.getLhsType() instanceof PlaceholderType) && (x.getBasePair().getRhsType() instanceof PlaceholderType))) + .map(y -> (PlaceholderType)y.getLhsType()).collect(Collectors.toCollection(ArrayList::new)); + //[(java.util.Vector <. gen_aq, , 1), (CEK =. ? extends gen_aq, 1)] KANN VORKOMMEN + //erstes Element genügt, da vars immer auf die gleichen Elemente zugeordnet werden muessen + Set fstElemResult = result.iterator().next(); + Set compResult = fstElemResult.stream().filter(x -> varsLast_a.contains(((PlaceholderType)x.getLhsType()))).collect(Collectors.toCollection(HashSet::new));; + if (variance == 1) { + writeLog("a_last:" + a_last + " a: " + a); + writeLog("varsLast_a:" + varsLast_a + " vars_a: " + vars_a); + writeLog("compResult:" + compResult + " compRes: " + compRes); + int resOfCompare = oup.compare(compResult, compRes); + if (resOfCompare == -1) { + writeLog("Geloescht result: " + result); + result = res; + } else { + if (resOfCompare == 0) { + result.addAll(res); + } //else { + if (resOfCompare == 1) { + writeLog("Geloescht res: " + res); + //result = result; + }}} + else { if (variance == -1) { + writeLog("a_last:" + a_last + " a: " + a); + writeLog("varsLast_a:" + varsLast_a + " vars_a: " + vars_a); + writeLog("compResult:" + compResult + " compRes: " + compRes); + int resOfCompare = oup.compare(compResult, compRes); + if (resOfCompare == 1) { + writeLog("Geloescht result: " + result); + result = res; + } else { + if (resOfCompare == 0) { + result.addAll(res); + } else { + if (resOfCompare == -1) { + writeLog("Geloescht res: " + res); + //result = result; + }}}} + else { if (variance == 0) { + writeLog("RES var=1 ADD:" + result.toString() + " " + res.toString()); + result.addAll(res); + }}} + } + catch (NullPointerException e) { + writeLog("NullPointerException: " + a_last.toString()); + } + } + else { + //alle Fehlerfaelle und alle korrekten Ergebnis jeweils adden + writeLog("RES Fst: result: " + result.toString() + " res: " + res.toString()); + result.addAll(res); + } + } + //else { + //wenn Korrekte Ergebnisse da und Feherfälle dazukommen Fehlerfälle ignorieren + // if (isUndefinedPairSetSet(res) && !isUndefinedPairSetSet(result)) { + // result = result; + // } + //} + } + + if (parallel) { + for (Set> par_res : add_res) { + if (!isUndefinedPairSetSet(par_res) && isUndefinedPairSetSet(result)) { + //wenn korrektes Ergebnis gefunden alle Fehlerfaelle loeschen + result = par_res; + if (!par_res.isEmpty() && par_res.iterator().next() instanceof WildcardType) { + System.out.println(""); + } + } + else { + if ((isUndefinedPairSetSet(par_res) && isUndefinedPairSetSet(result)) + || (!isUndefinedPairSetSet(par_res) && !isUndefinedPairSetSet(result)) + || result.isEmpty()) { + //alle Fehlerfaelle und alle korrekten Ergebnis jeweils adden + writeLog("RES var1 ADD:" + result.toString() + " " + par_res.toString()); + result.addAll(par_res); + } + } + } + //break; + } + + /* auskommentiert um alle Max und min Betrachtung auszuschalten ANFANG */ + if (!result.isEmpty() && (!isUndefinedPairSetSet(res) || !aParDef.isEmpty())) { + if (nextSetasList.iterator().hasNext() && nextSetasList.iterator().next().stream().filter(x -> x.getLhsType().getName().equals("B")).findFirst().isPresent() && nextSetasList.size()>1) + System.out.print(""); + Iterator> nextSetasListIt = new ArrayList>(nextSetasList).iterator(); + if (variance == 1) { + System.out.println(""); + writeLog("a: " + rekTiefe + " variance: " + variance + a.toString()); + writeLog("aParDef: " + aParDef.toString()); + aParDef.add(a); + Iterator> aParDefIt = aParDef.iterator(); + if (oderConstraint) { + nextSetasList.removeAll(nextSetasListOderConstraints); + nextSetasListOderConstraints = new ArrayList<>(); + writeLog("Removed: " + nextSetasListOderConstraints); + while(aParDefIt.hasNext()) { + Set a_new = aParDefIt.next(); + List> smallerSetasList = oup.smallerThan(a_new, nextSetasList); + List> notInherited = smallerSetasList.stream() + .filter(x -> !((Constraint)x).isInherited()) + .collect(Collectors.toCollection(ArrayList::new)); + List> notErased = new ArrayList<>(); + notInherited.stream().forEach(x -> { notErased.addAll(oup.smallerEqThan(x, smallerSetasList)); }); + List> erased = new ArrayList<>(smallerSetasList); + erased.removeAll(notErased); + nextSetasList.removeAll(erased); + + writeLog("Removed: " + erased); + + writeLog("Not Removed: " + nextSetasList); + + } + } + else { + while(aParDefIt.hasNext()) { + //nextSetasListIt = nextSetasList.iterator(); Sollte eingefuegt werden PL 2020-04-28 + Set a_new = aParDefIt.next(); + List> erased = oup.smallerEqThan(a_new, nextSetasList); + nextSetasList.removeAll(erased); + + writeLog("Removed: " + erased); + + writeLog("Not Removed: " + nextSetasList); + } + } + } + else { if (variance == -1) { + System.out.println(""); + writeLog("a: " + rekTiefe + " variance: " + variance + a.toString()); + writeLog("aParDef: " + aParDef.toString()); + aParDef.add(a); + Iterator> aParDefIt = aParDef.iterator(); + if (oderConstraint) { + nextSetasList.removeAll(nextSetasListOderConstraints); + writeLog("Removed: " + nextSetasListOderConstraints); + nextSetasListOderConstraints = new ArrayList<>(); + while(aParDefIt.hasNext()) { + Set a_new = aParDefIt.next(); + List> greaterSetasList = oup.greaterThan(a_new, nextSetasList); + + //a_new muss hingefuegt werden, wenn es nicht vererbt ist, dann wird es spaeter wieder geloescht + if (!((Constraint)a_new).isInherited()) { + greaterSetasList.add(a_new); + } + List> notInherited = greaterSetasList.stream() + .filter(x -> !((Constraint)x).isInherited()) + .collect(Collectors.toCollection(ArrayList::new)); + List> notErased = new ArrayList<>(); + + //Wenn x nicht vererbt ist, beginnt beim naechstgroesseren Element die naechste Ueberladung + notInherited.stream().forEach(x -> { notErased.addAll(oup.greaterEqThan(x, greaterSetasList)); }); + + //das kleineste Element ist das Element von dem a_new geerbt hat + //muss deshalb geloescht werden + Iterator> notErasedIt = notErased.iterator(); + if (notErasedIt.hasNext()) { + Set min = oup.min(notErasedIt); + notErased.remove(min); + notErased.remove(((Constraint)min).getExtendConstraint()); + } + + List> erased = new ArrayList<>(greaterSetasList); + erased.removeAll(notErased); + nextSetasList.removeAll(erased); + + writeLog("Removed: " + erased); + + writeLog("Not Removed: " + nextSetasList); + + } + } + else { + while(aParDefIt.hasNext()) { + //nextSetasListIt = nextSetasList.iterator(); Sollte eingefuegt werden PL 2020-04-28 + Set a_new = aParDefIt.next(); + List> erased = oup.greaterEqThan(a_new, nextSetasList); + + nextSetasList.removeAll(erased); + + writeLog("Removed: " + erased); + + writeLog("Not Removed: " + nextSetasList); + } + } + } + else { if (variance == 0) { + writeLog("a: " + rekTiefe + " variance: " + variance + a.toString()); + if (!oderConstraint) { + break; + } + else { + nextSetasList.removeAll(nextSetasListOderConstraints); + nextSetasListOderConstraints = new ArrayList<>(); + writeLog("Removed: " + nextSetasListOderConstraints); + List> smallerSetasList = oup.smallerThan(a, nextSetasList); + List> notInherited = smallerSetasList.stream() + .filter(x -> !((Constraint)x).isInherited()) + .collect(Collectors.toCollection(ArrayList::new)); + List> notErased = new ArrayList<>(); + notInherited.stream().forEach(x -> { notErased.addAll(oup.smallerEqThan(x, smallerSetasList)); }); + List> erased = new ArrayList<>(smallerSetasList); + erased.removeAll(notErased); + nextSetasList.removeAll(erased); + + writeLog("Removed: " + erased); + + writeLog("Not Removed: " + nextSetasList); + + } + + } + else { if (variance == 2) { + }}} + writeLog("a: " + rekTiefe + " variance: " + variance + a.toString()); + } + } + /* auskommentiert um alle Max und min Betrachtung auszuschalten ENDE */ + + if (isUndefinedPairSetSet(res) && aParDef.isEmpty()) { + int nofstred= 0; + Set abhSubst = res.stream() + .map(b -> + b.stream() + .map(x -> x.getAllSubstitutions()) + .reduce((y,z) -> { y.addAll(z); return y;}).get()) + .reduce((y,z) -> { y.addAll(z); return y;}).get(); + abhSubst.addAll( + res.stream() + .map(b -> + b.stream() + .map(x -> x.getThisAndAllBases()) //getAllBases durch getThisAndAllBases ersetzt, weil auch im UnifyPair selbst schon ein Fehler liegen kann. + .reduce((y,z) -> { y.addAll(z); return y;}).get()) + .reduce((y,z) -> { y.addAll(z); return y;}).get() + ); + Set b = a;//effective final a + Set durchschnitt = abhSubst.stream() + .filter(x -> b.contains(x)) + //.filter(y -> abhSubst.contains(y)) + .collect(Collectors.toCollection(HashSet::new)); + //Set vars = durchschnitt.stream().map(x -> (PlaceholderType)x.getLhsType()).collect(Collectors.toCollection(HashSet::new)); + int len = nextSetasList.size(); + Set undefRes = res.stream().reduce((y,z) -> { y.addAll(z); return y;}).get(); //flatten aller undef results + Set, UnifyPair>> reducedUndefResSubstGroundedBasePair = undefRes.stream() + .map(x -> { Set su = x.getAllSubstitutions(); //alle benutzten Substitutionen + su.add(x.getGroundBasePair()); // urspruengliches Paar + su.removeAll(durchschnitt); //alle aktuell genänderten Paare entfernen + return new Pair<>(su, x.getGroundBasePair());}) + .collect(Collectors.toCollection(HashSet::new)); + if (res.size() > 1) { + System.out.println(); + } + writeLog("nextSetasList vor filter-Aufruf: " + nextSetasList); + nextSetasList = nextSetasList.stream().filter(x -> { + //Boolean ret = false; + //for (PlaceholderType var : vars) { + // ret = ret || x.stream().map(b -> b.getLhsType().equals(var)).reduce((c,d) -> c || d).get(); + //} + return (!x.containsAll(durchschnitt)); + })//.filter(y -> couldBecorrect(reducedUndefResSubstGroundedBasePair, y)) //fuer testzwecke auskommentiert um nofstred zu bestimmen PL 2018-10-10 + .collect(Collectors.toCollection(ArrayList::new)); + writeLog("nextSetasList nach filter-Aufruf: " + nextSetasList); + nofstred = nextSetasList.size(); + //NOCH NICHT korrekt PL 2018-10-12 + //nextSetasList = nextSetasList.stream().filter(y -> couldBecorrect(reducedUndefResSubstGroundedBasePair, y)) + // .collect(Collectors.toCollection(ArrayList::new)); + writeLog("res (undef): " + res.toString()); + writeLog("abhSubst: " + abhSubst.toString()); + writeLog("a2: " + rekTiefe + " " + a.toString()); + writeLog("Durchschnitt: " + durchschnitt.toString()); + writeLog("nextSet: " + nextSet.toString()); + writeLog("nextSetasList: " + nextSetasList.toString()); + writeLog("Number first erased Elements (undef): " + (len - nofstred)); + writeLog("Number second erased Elements (undef): " + (nofstred- nextSetasList.size())); + writeLog("Number erased Elements (undef): " + (len - nextSetasList.size())); + noAllErasedElements = noAllErasedElements + (len - nextSetasList.size()); + writeLog("Number of all erased Elements (undef): " + noAllErasedElements.toString()); + noBacktracking++; + writeLog("Number of Backtracking: " + noBacktracking); + System.out.println(""); + } + //if (nextSetasList.size() == 0 && isUndefinedPairSetSet(result) && nextSet.size() > 1) { + // return result; + //} + //else { + // result.removeIf(y -> isUndefinedPairSet(y)); + //} + //else result.stream().filter(y -> !isUndefinedPairSet(y)); + writeLog("res: " + res.toString()); + } + //2020-02-02: if (variance ==2) Hier Aufruf von filterOverriding einfuegen + writeLog("Return computeCR: " + result.toString()); + return result; + } + + /** + * checks if there is for (a = ty) \in a in sameEqSet a constradiction + * @param a Set of actual element of constraints with a =. ty \in a + * @param sameEqSet Set of constraints where a <. ty' and ty' <. a + * @param result set of results which contains correct solution s and the + * the error constraints. Error constraints are added + * @result contradiction of (a = ty) in sameEqSet + */ + protected Boolean checkNoContradiction(Set a, Set sameEqSet, Set> result) { + + //optAPair enthaelt ggf. das Paar a = ty' \in a + //unterscheidet sich von optOrigPair, da dort a = ty + Optional optAPair = + a.stream().filter(x -> (x.getPairOp().equals(PairOperator.EQUALSDOT))) + .filter(x -> //Sicherstellen, dass bei a = ty a auch wirklich die gesuchte Typvariable ist + x.getLhsType().equals(x.getBasePair().getLhsType()) || + x.getLhsType().equals(x.getBasePair().getRhsType())) + .findFirst(); + + if (optAPair.isPresent()) {//basepair ist entweder a <. Ty oder ty <. a + UnifyPair aPair = optAPair.get(); + //writeLog("optOrigPair: " + optOrigPair + " " + "aPair: " + aPair+ " " + "aPair.basePair(): " + aPair.getBasePair()); + + writeLog("checkA: " + aPair + "sameEqSet: " + sameEqSet); + for (UnifyPair sameEq : sameEqSet) { + if (sameEq.getLhsType() instanceof PlaceholderType) { + Set localEq = new HashSet<>(); + Set unitedSubst = new HashSet<>(aPair.getAllSubstitutions()); + unitedSubst.addAll(aPair.getAllBases()); + unitedSubst.addAll(sameEq.getAllSubstitutions()); + unitedSubst.addAll(sameEq.getAllBases()); + localEq.add(new UnifyPair(aPair.getRhsType(), sameEq.getRhsType(), sameEq.getPairOp(), unitedSubst, null)); + finalresult = false; + Set> localRes = unify(localEq, new ArrayList<>(), fc, false, 0); + finalresult = true; + if (isUndefinedPairSetSet(localRes)) { + if (result.isEmpty() || isUndefinedPairSetSet(result)) { + result.addAll(localRes); + } + writeLog("FALSE: " + aPair + "sameEqSet: " + sameEqSet); + return false; + } + } + else { + Set localEq = new HashSet<>(); + Set unitedSubst = new HashSet<>(aPair.getAllSubstitutions()); + unitedSubst.addAll(aPair.getAllBases()); + unitedSubst.addAll(sameEq.getAllSubstitutions()); + unitedSubst.addAll(sameEq.getAllBases()); + localEq.add(new UnifyPair(sameEq.getLhsType(), aPair.getRhsType(), sameEq.getPairOp(), unitedSubst, null)); + finalresult = false; + Set> localRes = unify(localEq, new ArrayList<>(), fc, false, 0); + finalresult = true; + if (isUndefinedPairSetSet(localRes)) { + if (result.isEmpty() || isUndefinedPairSetSet(result)) { + result.addAll(localRes); + } + writeLog("FALSE: " + aPair + "sameEqSet: " + sameEqSet); + return false; + } + } + } + writeLog("TRUE: " + aPair + "sameEqSet: " + sameEqSet); + return true; + } + return true; + } + + + protected boolean couldBecorrect(Set, UnifyPair>> reducedUndefResSubstGroundedBasePair, Set nextElem) { + return reducedUndefResSubstGroundedBasePair.stream() + .map(pair -> { + Set reducedAbhSubst = pair.getKey(); + reducedAbhSubst.addAll(nextElem); + Optional> substRes = rules.subst(reducedAbhSubst); + if (!substRes.isPresent()) { + return true; + } + //PL 2018-10-12 + //Evtl. zurest applyTypeUnification aufrufen + //evtl auch unify aufrufen + else { + UnifyPair checkPair = substRes.get().stream() + .filter(x -> x.getGroundBasePair().equals(pair.getValue().get())).findFirst().get(); + if (((checkPair.getLhsType() instanceof PlaceholderType) || (checkPair.getRhsType() instanceof PlaceholderType)) + && (checkPair.getPairOp() == PairOperator.SMALLERDOT || checkPair.getPairOp() == PairOperator.SMALLERDOTWC)) + { + /* + Set setCheckPair = new HashSet<>(); + setCheckPair.add(checkPair); + Set setReturnCheckPair = applyTypeUnificationRules(setCheckPair, fc); + UnifyPair checkPair1 = setReturnCheckPair.iterator().next(); + Set up = new HashSet<>(); + up.add(checkPair1); + Set undef = new HashSet<>(); + */ + PairOperator pairOp = checkPair.getPairOp(); + UnifyType lhsType = checkPair.getLhsType(); + UnifyType rhsType = checkPair.getRhsType(); + ///* Case 1: (a <. Theta') + if ((((pairOp == PairOperator.SMALLERDOT) || (pairOp == PairOperator.SMALLERNEQDOT)) && lhsType instanceof PlaceholderType) + // Case 2: (a <.? ? ext Theta') + || (pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof PlaceholderType && rhsType instanceof ExtendsType) + // Case 3: (a <.? ? sup Theta') + || (pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof PlaceholderType && rhsType instanceof SuperType) + + // Case 4 was replaced by an inference rule + // Case 4: (a <.? Theta') + || (pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof PlaceholderType) + // Case 5: (Theta <. a) + || ((pairOp == PairOperator.SMALLERDOT) && rhsType instanceof PlaceholderType) + // Case 6 was replaced by an inference rule. + // Case 6: (? ext Theta <.? a) + || (pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof ExtendsType && rhsType instanceof PlaceholderType) + // Case 7 was replaced by an inference rule + // Case 7: (? sup Theta <.? a) + || (pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof SuperType && rhsType instanceof PlaceholderType) + // Case 8: (Theta <.? a) + || (pairOp == PairOperator.SMALLERDOTWC && rhsType instanceof PlaceholderType) + //reduceWildcardLow + || (pairOp == PairOperator.SMALLERDOTWC && (lhsType instanceof ExtendsType) && (rhsType instanceof ExtendsType)) + //reduceWildcardLowRight + || ((pairOp == PairOperator.SMALLERDOTWC) && (lhsType instanceof ReferenceType) && (rhsType instanceof ExtendsType)) + //reduceWildcardUp + || ((pairOp == PairOperator.SMALLERDOTWC) && (lhsType instanceof SuperType) && (rhsType instanceof SuperType)) + //reduceWildcardUpRight + || ((pairOp == PairOperator.SMALLERDOTWC) && (lhsType instanceof ReferenceType) && (rhsType instanceof SuperType)) + //reduceFunN + || (((pairOp == PairOperator.SMALLERDOT) || (pairOp == PairOperator.EQUALSDOT)) + //PL 2017-10-03 hinzugefuegt + //da Regel auch fuer EQUALSDOT anwendbar + && (lhsType instanceof FunNType) && (rhsType instanceof FunNType)) + //greaterFunN + || ((pairOp== PairOperator.SMALLERDOT) && (lhsType instanceof FunNType) && (rhsType instanceof PlaceholderType)) + //smallerFunN + || ((pairOp == PairOperator.SMALLERDOT) && (lhsType instanceof PlaceholderType && rhsType instanceof FunNType)) + //reduceTph + || ((pairOp == PairOperator.SMALLERDOTWC) && (lhsType instanceof PlaceholderType && rhsType instanceof ReferenceType)) + //reduceTphExt + || ((pairOp == PairOperator.SMALLERDOTWC) && (lhsType instanceof ExtendsType) && rhsType instanceof PlaceholderType) + //reduceTphSup + || ((pairOp == PairOperator.SMALLERDOTWC) && (lhsType instanceof SuperType) && rhsType instanceof PlaceholderType)) { + return true; + } + // Case unknown: If a pair fits no other case, then the type unification has failed. + // Through application of the rules, every pair should have one of the above forms. + // Pairs that do not have one of the aboves form are contradictory. + else { + writeLog("Second erase:" +checkPair.toString()); + return false; + } + //*/ + } else { + //Pair type <. ? extends ? extends type betrachten TODO PL 2018-10-09 + }} + return true;}).reduce((xx, yy) -> xx || yy).get(); + } + + protected boolean isUndefinedPairSet(Set s) { + if (s.size() >= 1 ) { + Boolean ret = s.stream().map(x -> x.isUndefinedPair()).reduce(true, (x,y)-> (x && y)); + return ret; + } + else { + return false; + } + } + + protected boolean isUndefinedPairSetSet(Set> s) { + if (s.size() >= 1) { + Boolean ret = s.stream(). map(x -> isUndefinedPairSet(x)).reduce(true, (x,y)-> (x && y)); + return ret; + } + return false; + + } + /** + * Checks whether a set of pairs is in solved form. + * @param eqPrimePrime The set of pair + * @return True if in solved form, false otherwise. + */ + protected boolean isSolvedForm(Set eqPrimePrime) { + for(UnifyPair pair : eqPrimePrime) { + UnifyType lhsType = pair.getLhsType(); + UnifyType rhsType = pair.getRhsType(); + + if(!(lhsType instanceof PlaceholderType)) + return false; + + // If operator is not equals, both sides must be placeholders + if(pair.getPairOp() != PairOperator.EQUALSDOT && !(rhsType instanceof PlaceholderType)) + return false; + } + return true; + } + + /** + * Repeatedly applies type unification rules to a set of equations. + * This is step one of the unification algorithm. + * @return The set of pairs that results from repeated application of the inference rules. + */ + public Set applyTypeUnificationRules(Set eq, IFiniteClosure fc) { + + /* + * Rule Application Strategy: + * + * 1. Swap all pairs and erase all erasable pairs + * 2. Apply all possible rules to a single pair, then move it to the result set. + * Iterating over pairs first, then iterating over rules prevents the application + * of rules to a "finished" pair over and over. + * 2.1 Apply all rules repeatedly except for erase rules. If + * the application of a rule creates new pairs, check immediately + * against the erase rules. + */ + + + LinkedHashSet targetSet = new LinkedHashSet(); + LinkedList eqQueue = new LinkedList<>(); + + /* + * Swap all pairs and erase all erasable pairs + */ + eq.forEach(x -> swapAddOrErase(x, fc, eqQueue)); + + /* + * Apply rules until the queue is empty + */ + while(!eqQueue.isEmpty()) { + UnifyPair pair = eqQueue.pollFirst(); + + // ReduceUp, ReduceLow, ReduceUpLow + Optional opt = rules.reduceUpLow(pair); + opt = opt.isPresent() ? opt : rules.reduceLow(pair); + opt = opt.isPresent() ? opt : rules.reduceUp(pair); + opt = opt.isPresent() ? opt : rules.reduceWildcardLow(pair); + opt = opt.isPresent() ? opt : rules.reduceWildcardLowRight(pair); + opt = opt.isPresent() ? opt : rules.reduceWildcardUp(pair); + opt = opt.isPresent() ? opt : rules.reduceWildcardUpRight(pair); + //PL 2018-03-06 auskommentiert muesste falsch sein vgl. JAVA_BSP/Wildcard6.java + //opt = opt.isPresent() ? opt : rules.reduceWildcardLowUp(pair); + //opt = opt.isPresent() ? opt : rules.reduceWildcardUpLow(pair); + //opt = opt.isPresent() ? opt : rules.reduceWildcardLeft(pair); + + // Reduce TPH + opt = opt.isPresent() ? opt : rules.reduceTph(pair); + + // One of the rules has been applied + if(opt.isPresent()) { + swapAddOrErase(opt.get(), fc, eqQueue); + continue; + } + + // Reduce1, Reduce2, ReduceExt, ReduceSup, ReduceEq + //try { + // logFile.write("PAIR1 " + pair + "\n"); + // logFile.flush(); + //} + //catch (IOException e) { } + + Optional> optSet = rules.reduce1(pair, fc); + optSet = optSet.isPresent() ? optSet : rules.reduce2(pair); + optSet = optSet.isPresent() ? optSet : rules.reduceExt(pair, fc); + optSet = optSet.isPresent() ? optSet : rules.reduceSup(pair, fc); + optSet = optSet.isPresent() ? optSet : rules.reduceEq(pair); + + // ReduceTphExt, ReduceTphSup + optSet = optSet.isPresent() ? optSet : rules.reduceTphExt(pair); + optSet = optSet.isPresent() ? optSet : rules.reduceTphSup(pair); + + + // FunN Rules + optSet = optSet.isPresent() ? optSet : rules.reduceFunN(pair); + optSet = optSet.isPresent() ? optSet : rules.greaterFunN(pair); + optSet = optSet.isPresent() ? optSet : rules.smallerFunN(pair); + + // One of the rules has been applied + if(optSet.isPresent()) { + optSet.get().forEach(x -> swapAddOrErase(x, fc, eqQueue)); + continue; + } + + // Adapt, AdaptExt, AdaptSup + //try { + // logFile.write("PAIR2 " + pair + "\n"); + // logFile.flush(); + //} + //catch (IOException e) { } + opt = rules.adapt(pair, fc); + opt = opt.isPresent() ? opt : rules.adaptExt(pair, fc); + opt = opt.isPresent() ? opt : rules.adaptSup(pair, fc); + + // One of the rules has been applied + if(opt.isPresent()) { + swapAddOrErase(opt.get(), fc, eqQueue); + continue; + } + + // None of the rules has been applied + targetSet.add(pair); + } + + return targetSet; + } + + /** + * Applies the rule swap to a pair if possible. Then adds the pair to the set if no erase rule applies. + * If an erase rule applies, the pair is not added (erased). + * @param pair The pair to swap and add or erase. + * @param collection The collection to which the pairs are added. + */ + protected void swapAddOrErase(UnifyPair pair, IFiniteClosure fc, Collection collection) { + Optional opt = rules.swap(pair); + UnifyPair pair2 = opt.isPresent() ? opt.get() : pair; + + if(rules.erase1(pair2, fc) || rules.erase3(pair2) || rules.erase2(pair2, fc)) + return; + + collection.add(pair2); + } + + /** + * Splits the equation eq into a set eq1s where both terms are type variables, + * and a set eq2s where one of both terms is not a type variable. + * @param eq Set of pairs to be splitted. + * @param eq1s Subset of eq where both terms are type variables. + * @param eq2s eq/eq1s. + */ + protected void splitEq(Set eq, Set eq1s, Set eq2s) { + for(UnifyPair pair : eq) + if(pair.getLhsType() instanceof PlaceholderType && pair.getRhsType() instanceof PlaceholderType) + eq1s.add(pair); + else + eq2s.add(pair); + } + + /** + * Creates sets of pairs specified in the fourth step. Does not calculate cartesian products. + * @param undefined All pairs that did not match one of the 8 cases are added to this set. + * @return The set of the eight cases (without empty sets). Each case is a set, containing sets generated + * from the pairs that matched the case. Each generated set contains singleton sets or sets with few elements + * (as in case 1 where sigma is added to the innermost set). + */ + protected Set>>> calculatePairSets(Set eq2s, List>> oderConstraintsInput, IFiniteClosure fc, Set undefined, List>> oderConstraintsOutput) { + writeLog("eq2s: " + eq2s.toString()); + oderConstraintsOutput.addAll(oderConstraintsInput); + List>>> result = new ArrayList<>(9); + + // Init all 8 cases + 9. Case: oderConstraints + for(int i = 0; i < 9; i++) + result.add(new HashSet<>()); + + ArrayList eq2sprime = new ArrayList<>(eq2s); + Iterator eq2sprimeit = eq2sprime.iterator(); + ArrayList eq2sAsListFst = new ArrayList<>(); + ArrayList eq2sAsListSnd = new ArrayList<>(); + ArrayList eq2sAsListThird = new ArrayList<>(); + ArrayList eq2sAsListFourth = new ArrayList<>(); + ArrayList eq2sAsListBack = new ArrayList<>(); + ArrayList eq2sAsList = new ArrayList<>(); + Boolean first = true; + while(eq2sprimeit.hasNext()) {// alle mit Variance != 0 nach vorne schieben + UnifyPair up = eq2sprimeit.next(); + if ((up.getLhsType() instanceof PlaceholderType && + ((PlaceholderType)up.getLhsType()).getVariance() == 1 && + !((PlaceholderType)up.getLhsType()).isInnerType()) || + (up.getRhsType() instanceof PlaceholderType && + ((PlaceholderType)up.getRhsType()).getVariance() == -1) && + !((PlaceholderType)up.getRhsType()).isInnerType()) + { + eq2sAsListFst.add(up); + eq2s.remove(up); + } + else if ((up.getLhsType() instanceof PlaceholderType && ((PlaceholderType)up.getLhsType()).getVariance() == 1 && ((PlaceholderType)up.getLhsType()).isInnerType()) + || (up.getRhsType() instanceof PlaceholderType && ((PlaceholderType)up.getRhsType()).getVariance() == -1) && ((PlaceholderType)up.getRhsType()).isInnerType()) { + eq2sAsListSnd.add(up); + eq2s.remove(up); + } + else if ((up.getLhsType() instanceof PlaceholderType && + ((PlaceholderType)up.getLhsType()).getVariance() == -1 && + !((PlaceholderType)up.getLhsType()).isInnerType()) || + (up.getRhsType() instanceof PlaceholderType && + ((PlaceholderType)up.getRhsType()).getVariance() == -1) && + !((PlaceholderType)up.getRhsType()).isInnerType()) + { + eq2sAsListThird.add(up); + eq2s.remove(up); + } + else if ((up.getLhsType() instanceof PlaceholderType && ((PlaceholderType)up.getLhsType()).getVariance() == -1 && ((PlaceholderType)up.getLhsType()).isInnerType()) + || (up.getRhsType() instanceof PlaceholderType && ((PlaceholderType)up.getRhsType()).getVariance() == 1) && ((PlaceholderType)up.getRhsType()).isInnerType()) { + eq2sAsListFourth.add(up); + eq2s.remove(up); + } + else if ((up.getLhsType() instanceof PlaceholderType && ((PlaceholderType)up.getLhsType()).isInnerType()) + || (up.getRhsType() instanceof PlaceholderType && ((PlaceholderType)up.getRhsType()).isInnerType())) { + eq2sAsListBack.add(up); + eq2s.remove(up); + } + } + //if (eq2sAsListFst.isEmpty()) + { + List>> oderConstraintsVariance = oderConstraintsOutput.stream() //Alle Elemente rauswerfen, die Variance 0 haben oder keine TPH in LHS oder RHS sind + .filter(x -> x.stream() + .filter(y -> + y.stream().filter(z -> ((z.getLhsType() instanceof PlaceholderType) + && (((PlaceholderType)(z.getLhsType())).getVariance() != 0)) + || ((z.getRhsType() instanceof PlaceholderType) + && (((PlaceholderType)(z.getRhsType())).getVariance() != 0)) + ).findFirst().isPresent() + ).findFirst().isPresent()).collect(Collectors.toList()); + if (!oderConstraintsVariance.isEmpty()) { + Set> ret = oderConstraintsVariance.get(0); + oderConstraintsOutput.remove(ret); + //Set retFlat = new HashSet<>(); + //ret.stream().forEach(x -> retFlat.addAll(x)); + + //Alle wildcard Faelle rausfiltern bei not wildcardable + ret = ret.stream().filter(x -> { Optional optElem; + return !((optElem=x.stream().filter(y -> (y.getLhsType()) instanceof PlaceholderType + && !((PlaceholderType)y.getLhsType()).isWildcardable() + && y.getPairOp() == PairOperator.EQUALSDOT + && !(y.getRhsType() instanceof PlaceholderType)) + .findAny()).isPresent() + && optElem.get().getRhsType() instanceof ExtendsType);}) + .collect(Collectors.toSet()); + ret.stream().forEach(x -> x.stream().forEach(y -> { Set x_new = new HashSet<>(x); //PL 2020-03-18: y selbst darf nicht in die Substitutionen + x_new.remove(y); + y.addSubstitutions(x_new); + })); + result.get(8).add(ret); + first = false; + } + } + + writeLog("eq2s: " + eq2s.toString()); + writeLog("eq2sAsListFst: " + eq2sAsListFst.toString()); + writeLog("eq2sAsListSnd: " + eq2sAsListSnd.toString()); + writeLog("eq2sAsListBack: " + eq2sAsListBack.toString()); + + eq2sAsList.addAll(eq2sAsListFst); + eq2sAsList.addAll(eq2sAsListSnd); + eq2sAsList.addAll(eq2sAsListThird); + eq2sAsList.addAll(eq2sAsListFourth); + eq2sAsList.addAll(eq2s); + eq2sAsList.addAll(eq2sAsListBack); + + if (eq2sAsList.isEmpty() && first) {//Alle eq2s sind empty und alle oderConstraints mit Variance != 0 sind bearbeitet + if (!oderConstraintsOutput.isEmpty()) { + Set> ret = oderConstraintsOutput.remove(0); + //if (ret.iterator().next().iterator().next().getLhsType().getName().equals("M")) + // System.out.println("M"); + //Set retFlat = new HashSet<>(); + //ret.stream().forEach(x -> retFlat.addAll(x)); + + //Alle wildcard Faelle rausfiltern bei not wildcardable + ret = ret.stream().filter(x -> { Optional optElem; + return !((optElem=x.stream().filter(y -> (y.getLhsType()) instanceof PlaceholderType + && !((PlaceholderType)y.getLhsType()).isWildcardable() + && y.getPairOp() == PairOperator.EQUALSDOT + && !(y.getRhsType() instanceof PlaceholderType)) + .findAny()).isPresent() + && optElem.get().getRhsType() instanceof ExtendsType);}) + .collect(Collectors.toSet()); + ret.stream().forEach(x -> x.stream().forEach(y -> { Set x_new = new HashSet<>(x); //PL 2020-03-18: y selbst darf nicht in die Substitutionen + x_new.remove(y); + y.addSubstitutions(x_new); + })); + result.get(8).add(ret); + first = false; + } + } + /* + Bei allen die Abhaengigkeit der Elemente aus eq2sAsList als evtl. als Substitution + hinzufuegen + */ + Set consideredElements = new HashSet<>(); + for(UnifyPair pair : eq2sAsList) { + if (consideredElements.contains(pair)) { + continue; + } + PairOperator pairOp = pair.getPairOp(); + UnifyType lhsType = pair.getLhsType(); + UnifyType rhsType = pair.getRhsType(); + + // Case 1: (a <. Theta') + if (((pairOp == PairOperator.SMALLERDOT) || (pairOp == PairOperator.SMALLERNEQDOT)) && lhsType instanceof PlaceholderType) { + //System.out.println(pair); + if (first) { //writeLog(pair.toString()+"\n"); + if (((PlaceholderType)(pair.getLhsType())).getName().equals("AR")) { + System.out.println("AR"); + } + Set> x1 = unifyCase1(pair, fc); + if (pairOp == PairOperator.SMALLERNEQDOT) { + Set remElem = new HashSet<>(); + remElem.add(new UnifyPair(pair.getLhsType(), pair.getRhsType(), PairOperator.EQUALSDOT)); + x1.remove(remElem); + remElem = new HashSet<>(); + remElem.add(new UnifyPair(pair.getLhsType(), new ExtendsType(pair.getRhsType()), PairOperator.EQUALSDOT)); + x1.remove(remElem); + remElem = new HashSet<>(); + remElem.add(new UnifyPair(pair.getLhsType(), new SuperType(pair.getRhsType()), PairOperator.EQUALSDOT)); + x1.remove(remElem); + } + /* ZU LOESCHEN ANFANG + //System.out.println(x1); + Set sameEqSet = eq2sAsList.stream() + .filter(x -> ((x.getLhsType().equals(lhsType) || x.getRhsType().equals(lhsType)) && !x.equals(pair))) + .collect(Collectors.toCollection(HashSet::new)); + consideredElements.addAll(sameEqSet); + Set> x2 = x1; + Set> x1Res = new HashSet<>(); + writeLog("pair:\n" + pair.toString()); + writeLog("x1 Start:\n" + x1.toString()); + writeLog("sameEqSet:\n" + sameEqSet.toString()); + for (UnifyPair sameEq : sameEqSet) { + writeLog("x1 Original:\n" + x1.toString()); + if (sameEq.getLhsType() instanceof PlaceholderType) { + x1 = x1.stream().filter(y -> { + UnifyPair type = y.stream().filter(z -> z.getLhsType().equals(lhsType)).findFirst().get(); + Set localEq = new HashSet<>(); + Set unitedSubst = new HashSet<>(type.getSubstitution()); + unitedSubst.addAll(sameEq.getSubstitution()); + localEq.add(new UnifyPair(type.getRhsType(), sameEq.getRhsType(), sameEq.getPairOp(), unitedSubst, null)); + Set> localRes = unify(localEq, new ArrayList<>(), fc, false, 0, false); + Boolean localCorr = !isUndefinedPairSetSet(localRes); + if (!localCorr) { + collectErr.addAll(localRes); + } + else { + localRes.forEach(z -> z.addAll(y)); + x1Res.addAll(localRes); + } + return localCorr; + } + ).collect(Collectors.toCollection(HashSet::new)); + } + else { + x1 = x1.stream().filter(y -> { + UnifyPair type = y.stream().filter(z -> z.getLhsType().equals(lhsType)).findFirst().get(); + Set localEq = new HashSet<>(); + Set unitedSubst = new HashSet<>(type.getSubstitution()); + unitedSubst.addAll(sameEq.getSubstitution()); + localEq.add(new UnifyPair(sameEq.getLhsType(), type.getRhsType(), sameEq.getPairOp(), unitedSubst, null)); + Set> localRes = unify(localEq, new ArrayList<>(), fc, false, 0, false); + Boolean localCorr = !isUndefinedPairSetSet(localRes); + if (!localCorr) { + collectErr.addAll(localRes); + } + else { + localRes.forEach(z -> z.addAll(y)); + x1Res.addAll(localRes); + } + return localCorr; + } + ).collect(Collectors.toCollection(HashSet::new)); + } + writeLog("x1 nach Loeschung von " + sameEq.toString()+" :\n" + x1.toString()); + } + Set> x1ResPrime; + if (sameEqSet.isEmpty()) { + x1ResPrime = x1; + } + else { + x1ResPrime = x1Res; + } + result.get(0).add(x1ResPrime); + ZU LOESCHEN ENDE */ + result.get(0).add(x1); + if (x1.isEmpty()) { + undefined.add(pair); //Theta ist nicht im FC => Abbruch + } + } + else { + Set s1 = new HashSet<>(); + s1.add(pair); + Set> s2 = new HashSet<>(); + s2.add(s1); + result.get(0).add(s2); + } + + } + // Case 2: (a <.? ? ext Theta') + else if(pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof PlaceholderType && rhsType instanceof ExtendsType) + if (first) { //writeLog(pair.toString()+"\n"); + Set> x1 = unifyCase2(pair, fc); + result.get(1).add(x1); + if (x1.isEmpty()) { + undefined.add(pair); //Theta ist nicht im FC + } + } + else { + Set s1 = new HashSet<>(); + s1.add(pair); + Set> s2 = new HashSet<>(); + s2.add(s1); + result.get(1).add(s2); + } + + // Case 3: (a <.? ? sup Theta') + else if(pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof PlaceholderType && rhsType instanceof SuperType) + if (first) { //writeLog(pair.toString()+"\n"); + Set> x1 = unifyCase3(pair, fc); + result.get(2).add(x1); + if (x1.isEmpty()) { + undefined.add(pair); //Theta ist nicht im FC + } + } + else { + Set s1 = new HashSet<>(); + s1.add(pair); + Set> s2 = new HashSet<>(); + s2.add(s1); + result.get(2).add(s2); + } + + // Case 4 was replaced by an inference rule + // Case 4: (a <.? Theta') + //else if(pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof PlaceholderType) + // result.get(3).add(unifyCase4((PlaceholderType) lhsType, rhsType, fc)); + + // Case 5: (Theta <. a) + else if ((pairOp == PairOperator.SMALLERDOT) && rhsType instanceof PlaceholderType) + if (first) { //writeLog(pair.toString()+"\n"); + Set> x1 = unifyCase5(pair, fc); + result.get(4).add(x1); + if (x1.isEmpty()) { + undefined.add(pair); //Theta ist nicht im FC + } + } + else { + Set s1 = new HashSet<>(); + s1.add(pair); + Set> s2 = new HashSet<>(); + s2.add(s1); + result.get(4).add(s2); + } + + // Case 6 was replaced by an inference rule. + // Case 6: (? ext Theta <.? a) + //else if(pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof ExtendsType && rhsType instanceof PlaceholderType) + // result.get(5).add(unifyCase6((ExtendsType) lhsType, (PlaceholderType) rhsType, fc)); + + // Case 7 was replaced by an inference rule + // Case 7: (? sup Theta <.? a) + //else if(pairOp == PairOperator.SMALLERDOTWC && lhsType instanceof SuperType && rhsType instanceof PlaceholderType) + // result.get(6).add(unifyCase7((SuperType) lhsType, (PlaceholderType) rhsType, fc)); + + // Case 8: (Theta <.? a) + else if(pairOp == PairOperator.SMALLERDOTWC && rhsType instanceof PlaceholderType) + if (first) { //writeLog(pair.toString()+"\n"); + Set> x1 = unifyCase8(pair, fc); + result.get(7).add(x1); + if (x1.isEmpty()) { + undefined.add(pair); //Theta ist nicht im FC + } + } + else { + Set s1 = new HashSet<>(); + s1.add(pair); + Set> s2 = new HashSet<>(); + s2.add(s1); + result.get(7).add(s2); + } + // Case unknown: If a pair fits no other case, then the type unification has failed. + // Through application of the rules, every pair should have one of the above forms. + // Pairs that do not have one of the aboves form are contradictory. + else { + // If a pair is not defined, the unificiation will fail, so the loop can be stopped here. + undefined.add(pair); + break; + } + first = false; + } + + // Filter empty sets or sets that only contain an empty set. + return result.stream().map(x -> x.stream().filter(y -> y.size() > 0).collect(Collectors.toCollection(HashSet::new))) + .filter(x -> x.size() > 0).collect(Collectors.toCollection(HashSet::new)); + } + + //TODO: Wenn Theta' nicht im FC muss ein Fehler produziert werden PL 18-04-20 + /** + * Cartesian product Case 1: (a <. Theta') + */ + protected Set> unifyCase1(UnifyPair pair, IFiniteClosure fc) { + PlaceholderType a = (PlaceholderType)pair.getLhsType(); + UnifyType thetaPrime = pair.getRhsType(); + + if (thetaPrime instanceof ExtendsType) { + thetaPrime = ((ExtendsType)thetaPrime).getExtendedType(); + } + + if (thetaPrime instanceof SuperType) { + //HIER MUSS NOCH WAS UEBERLEGT WERDEN + } + + Set> result = new HashSet<>(); + + if (thetaPrime instanceof ReferenceType && ((ReferenceType)thetaPrime).isGenTypeVar()) { + Set resultOne = new HashSet<>(); + resultOne.add(new UnifyPair (a, thetaPrime, PairOperator.EQUALSDOT, pair.getSubstitution(), pair)); + result.add(resultOne); + } + + boolean allGen = thetaPrime.getTypeParams().size() > 0; + for(UnifyType t : thetaPrime.getTypeParams()) + if(!(t instanceof PlaceholderType) || !((PlaceholderType) t).isGenerated()) { + allGen = false; + break; + } + //if (thetaPrime.getName().equals("java.util.Vector") //Fuer Bug 127 + // && thetaPrime instanceof ReferenceType + // && ((ReferenceType)thetaPrime).getTypeParams().iterator().next() instanceof PlaceholderType) //.getName().equals("java.util.Vector")) + // && ((ReferenceType)((ReferenceType)thetaPrime).getTypeParams().iterator().next()).getTypeParams().iterator().next().getName().equals("java.lang.Integer")) { + // { + // System.out.println(""); + //} + Set cs = fc.getAllTypesByName(thetaPrime.getName());//cs= [java.util.Vector, java.util.Vector>, ????java.util.Vector???] + + writeLog("cs: " + cs.toString()); + //PL 18-02-06 entfernt, kommt durch unify wieder rein + //cs.add(thetaPrime); + //PL 18-02-06 entfernt + + //cs muessen fresh Typvars gesetzt werden PL 2018-03-18 + Set csPHRenamed = cs.stream().map(x -> { + BinaryOperator> combiner = (aa,b) -> { aa.putAll(b); return aa;}; + HashMap hm = x.getInvolvedPlaceholderTypes().stream() + .reduce(new HashMap(), + (aa, b)-> { aa.put(b,PlaceholderType.freshPlaceholder()); return aa; }, combiner); + return x.accept(new freshPlaceholder(), hm); + }).collect(Collectors.toCollection(HashSet::new)); + + IMatch match = new Match(); + for(UnifyType c : csPHRenamed) { + //PL 18-02-05 getChildren durch smaller ersetzt in getChildren werden die Varianlen nicht ersetzt. + Set thetaQs = new HashSet<>(); + //TODO smaller wieder reinnehmen? + //thetaQs.add(c);// + thetaQs = fc.smaller(c, new HashSet<>()).stream().collect(Collectors.toCollection(HashSet::new)); + ArrayList ml = new ArrayList<>(); + ml.add(new UnifyPair(c, thetaPrime, PairOperator.EQUALSDOT)); + if (!(match.match(ml)).isPresent()) { + thetaQs.remove(c); + } + writeLog("thetaQs von " + c + ": " + thetaQs.toString()); + //Set thetaQs = fc.getChildren(c).stream().collect(Collectors.toCollection(HashSet::new)); + //thetaQs.add(thetaPrime); //PL 18-02-05 wieder geloescht + //PL 2017-10-03: War auskommentiert habe ich wieder einkommentiert, + //da children offensichtlich ein echtes kleiner und kein kleinergleich ist + + //PL 18-02-06: eingefuegt, thetaQs der Form V> <. V'> werden entfernt + //TODO PL 19-01-14 wieder reinnehmen kurzfristig auskommentiert + //thetaQs = thetaQs.stream().filter(ut -> ut.getTypeParams().arePlaceholders()).collect(Collectors.toCollection(HashSet::new)); + //PL 18-02-06: eingefuegt + + Set thetaQPrimes = new HashSet<>(); + TypeParams cParams = c.getTypeParams(); + if(cParams.size() == 0) + thetaQPrimes.add(c); + else { + ArrayList> candidateParams = new ArrayList<>(); + + for(UnifyType param : cParams) + candidateParams.add(fc.grArg(param, new HashSet<>())); + + for(TypeParams tp : permuteParams(candidateParams)) + thetaQPrimes.add(c.setTypeParams(tp)); + } + writeLog("thetaQPrimes von " + c + ": " + thetaQPrimes.toString()); + for(UnifyType tqp : thetaQPrimes) {//PL 2020-03-08 umbauen in der Schleife wird nur unifizierbarer Typ gesucht break am Ende + Collection tphs = tqp.getInvolvedPlaceholderTypes(); + Optional opt = stdUnify.unify(tqp, thetaPrime); + if (!opt.isPresent()) { + continue; + } + Unifier unifier = opt.get(); + unifier.swapPlaceholderSubstitutions(thetaPrime.getTypeParams()); + Set substitutionSet = new HashSet<>(); + for (Entry sigma : unifier) { + if (!tphs.contains(sigma.getKey())) {//eingefuegt PL 2019-02-02 Bug 127 + substitutionSet.add(new UnifyPair(sigma.getKey(), sigma.getValue(), PairOperator.EQUALSDOT, + //TODO: nochmals ueberlegen ob hier pair.getSubstitution() korrekt ist, oder ob leere Menge hin müsste + //alle folgenden New UnifyPair ebenfalls ueberpruefen PL 2018-04-19 + pair.getSubstitution(), pair)); + } + } + //List freshTphs = new ArrayList<>(); PL 18-02-06 in die For-Schleife verschoben + for (UnifyType tq : thetaQs) { + //geaendert PL 20-03-07 + Set smaller = new HashSet<>(); + smaller.add(unifier.apply(tq)); + //Set smaller = fc.smaller(unifier.apply(tq), new HashSet<>()); + //eingefuegt PL 2018-03-29 Anfang ? ext. theta hinzufuegen + if (a.isWildcardable()) { + Set smaller_ext = smaller.stream().filter(x -> !(x instanceof ExtendsType) && !(x instanceof SuperType)) + .map(x -> { + //BinaryOperator> combiner = (aa,b) -> { aa.putAll(b); return aa;}; //Variablenumbenennung rausgenommen + //HashMap hm = x.getInvolvedPlaceholderTypes().stream() //Variablen muessen wahrscheinlich erhalten bleiben + // .reduce(new HashMap(), + // (aa, b)-> { aa.put(b,PlaceholderType.freshPlaceholder()); return aa; }, combiner); + return new ExtendsType (x);})//.accept(new freshPlaceholder(), hm));} + .collect(Collectors.toCollection(HashSet::new)); + smaller.addAll(smaller_ext); + } + //eingefuegt PL 2018-03-29 Ende ? ext. theta hinzufuegen + for(UnifyType theta : smaller) { + List freshTphs = new ArrayList<>(); + Set resultPrime = new HashSet<>(); + + for(int i = 0; !allGen && i < theta.getTypeParams().size(); i++) { + if(freshTphs.size()-1 < i)//IST DAS RICHTIG??? PL 2018-12-12 + freshTphs.add(PlaceholderType.freshPlaceholder()); + freshTphs.forEach(x -> ((PlaceholderType)x).setInnerType(true)); + resultPrime.add(new UnifyPair(freshTphs.get(i), theta.getTypeParams().get(i), PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair)); + } + + if(allGen) { + UnifyPair up = new UnifyPair(a, theta, PairOperator.EQUALSDOT, pair.getSubstitution(), pair); + Iterator upit = up.getRhsType().getTypeParams().iterator(); + //TODO PL 2019-01-24: upit.next() ist nicht unbedingt ein PlaceholderType -> Visitor erledigt + while (upit.hasNext()) upit.next().accept(new distributeVariance(), a.getVariance());//((PlaceholderType)upit.next()).setVariance(a.getVariance()); + resultPrime.add(up); + } + else { + UnifyPair up = new UnifyPair(a, theta.setTypeParams(new TypeParams(freshTphs.toArray(new UnifyType[0]))), PairOperator.EQUALSDOT, pair.getSubstitution(), pair); + Iterator upit = up.getRhsType().getTypeParams().iterator(); + distributeVariance dv = new distributeVariance(); + //TODO PL 2019-01-24: upit.next() ist nicht unbedingt ein PlaceholderType -> Visitor erledigt + while (upit.hasNext()) upit.next().accept(new distributeVariance(), a.getVariance()); //((PlaceholderType)upit.next()).setVariance(a.getVariance()); + resultPrime.add(up); + } + resultPrime.addAll(substitutionSet); + //writeLog("Substitution: " + substitutionSet.toString()); + result.add(resultPrime); + //writeLog("Result: " + resultPrime.toString()); + //writeLog("MAX: " + oup.max(resultPrime.iterator()).toString()); + } + } + } + } + writeLog("result von " + pair + ": " + result.toString()); + return result; + } + + /** + * Cartesian Product Case 2: (a <.? ? ext Theta') + */ + private Set> unifyCase2(UnifyPair pair, IFiniteClosure fc) { + PlaceholderType a = (PlaceholderType) pair.getLhsType(); + ExtendsType extThetaPrime = (ExtendsType) pair.getRhsType(); + Set> result = new HashSet<>(); + + UnifyType aPrime = PlaceholderType.freshPlaceholder(); + ((PlaceholderType)aPrime).setVariance(((PlaceholderType)a).getVariance()); + ((PlaceholderType)aPrime).disableWildcardtable(); + UnifyType extAPrime = new ExtendsType(aPrime); + UnifyType thetaPrime = extThetaPrime.getExtendedType(); + Set resultPrime = new HashSet<>(); + resultPrime.add(new UnifyPair(a, thetaPrime, PairOperator.SMALLERDOT, pair.getSubstitution(), pair)); + result.add(resultPrime); + + resultPrime = new HashSet<>(); + resultPrime.add(new UnifyPair(a, extAPrime, PairOperator.EQUALSDOT, pair.getSubstitution(), pair)); + resultPrime.add(new UnifyPair(aPrime, thetaPrime, PairOperator.SMALLERDOT, pair.getSubstitution(), pair)); + result.add(resultPrime); + //writeLog("Result: " + resultPrime.toString()); + return result; + } + + /** + * Cartesian Product Case 3: (a <.? ? sup Theta') + */ + private Set> unifyCase3(UnifyPair pair, IFiniteClosure fc) { + PlaceholderType a = (PlaceholderType) pair.getLhsType(); + a.reversVariance(); + SuperType subThetaPrime = (SuperType) pair.getRhsType(); + Set> result = new HashSet<>(); + + UnifyType aPrime = PlaceholderType.freshPlaceholder(); + ((PlaceholderType)aPrime).setVariance(((PlaceholderType)a).getVariance()); + ((PlaceholderType)aPrime).disableWildcardtable(); + UnifyType supAPrime = new SuperType(aPrime); + UnifyType thetaPrime = subThetaPrime.getSuperedType(); + Set resultPrime = new HashSet<>(); + resultPrime.add(new UnifyPair(thetaPrime, a, PairOperator.SMALLERDOT, pair.getSubstitution(), pair, pair.getfBounded())); + result.add(resultPrime); + //writeLog(resultPrime.toString()); + + resultPrime = new HashSet<>(); + resultPrime.add(new UnifyPair(a, supAPrime, PairOperator.EQUALSDOT, pair.getSubstitution(), pair)); + resultPrime.add(new UnifyPair(thetaPrime, aPrime, PairOperator.SMALLERDOT, pair.getSubstitution(), pair)); + result.add(resultPrime); + //writeLog(resultPrime.toString()); + + return result; + } + + /** + * Cartesian Product Case 5: (Theta <. a) + */ + private Set> unifyCase5(UnifyPair pair, IFiniteClosure fc) { + UnifyType theta = pair.getLhsType(); + PlaceholderType a = (PlaceholderType) pair.getRhsType(); + Set> result = new HashSet<>(); + + boolean allGen = theta.getTypeParams().size() > 0; + for(UnifyType t : theta.getTypeParams()) + if(!(t instanceof PlaceholderType) || !((PlaceholderType) t).isGenerated()) { + allGen = false; + break; + } + + //eingefuegt PL 2019-01-03 ANFANG + //fc.setLogTrue(); + //writeLog("FBOUNDED: " + pair.getfBounded()); + //writeLog("Pair: " + pair); + Set greater = fc.greater(theta, pair.getfBounded()); + //writeLog("GREATER: " + greater + pair + "THETA: " + theta + "FBOUNDED: " + pair.getfBounded() + " "); + if (a.isWildcardable()) { + Set greater_ext = greater.stream().filter(x -> !(x instanceof ExtendsType) && !(x instanceof SuperType)) + .map(x -> { + //BinaryOperator> combiner = (aa,b) -> { aa.putAll(b); return aa;}; //Variablenumbenennung rausgenommen + //HashMap hm = x.getInvolvedPlaceholderTypes().stream() //Variablen muessen wahrscheinlich erhalten bleiben + // .reduce(new HashMap(), + // (aa, b)-> { aa.put(b,PlaceholderType.freshPlaceholder()); return aa; }, combiner); + return new SuperType (x);})//.accept(new freshPlaceholder(), hm));} + .collect(Collectors.toCollection(HashSet::new)); + greater.addAll(greater_ext); + } + //eingefuegt PL 2019-01-03 ENDE + + //for(UnifyType thetaS : fc.greater(theta, pair.getfBounded())) { + for(UnifyType thetaS : greater) { + Set resultPrime = new HashSet<>(); + Match match = new Match(); + + UnifyType[] freshTphs = new UnifyType[thetaS.getTypeParams().size()]; + for(int i = 0; !allGen && i < freshTphs.length; i++) { + freshTphs[i] = PlaceholderType.freshPlaceholder(); + ((PlaceholderType)freshTphs[i]).setVariance(((PlaceholderType)a).getVariance()); + Set fBounded = new HashSet<>(pair.getfBounded()); //PL 2019-01-09 new HashSet eingefuegt + + int i_ef = i; + BiFunction f = (x,y) -> + { + ArrayList termList = new ArrayList(); + termList.add(new UnifyPair(y,thetaS.getTypeParams().get(i_ef), PairOperator.EQUALSDOT)); + return ((match.match(termList).isPresent()) || x); + }; + //if (parai.getName().equals("java.lang.Integer")) { + // System.out.println(""); + //} + BinaryOperator bo = (x,y) -> (x || y); + if (fBounded.stream().reduce(false,f,bo)) { + resultPrime.add(new UnifyPair(freshTphs[i], thetaS.getTypeParams().get(i), PairOperator.EQUALSDOT, pair.getSubstitution(), pair)); + } + else { + fBounded.add(thetaS.getTypeParams().get(i)); + resultPrime.add(new UnifyPair(thetaS.getTypeParams().get(i), freshTphs[i], PairOperator.SMALLERDOTWC, pair.getSubstitution(), pair, fBounded)); + } + } + + if(allGen) + resultPrime.add(new UnifyPair(a, thetaS, PairOperator.EQUALSDOT, pair.getSubstitution(), pair)); + else + resultPrime.add(new UnifyPair(a, thetaS.setTypeParams(new TypeParams(freshTphs)), PairOperator.EQUALSDOT, pair.getSubstitution(), pair)); + result.add(resultPrime); + //writeLog("FBOUNDED2: " + pair.getfBounded()); + //writeLog("resultPrime Theta < a: " + greater + pair + "THETA: " + theta + "FBOUNDED: " + pair.getfBounded() + " " + resultPrime.toString()); + } + + return result; + } + + /** + * Cartesian Product Case 8: (Theta <.? a) + */ + private Set> unifyCase8(UnifyPair pair, IFiniteClosure fc) { + UnifyType theta = pair.getLhsType(); + PlaceholderType a = (PlaceholderType) pair.getRhsType(); + Set> result = new HashSet<>(); + //for(UnifyType thetaS : fc.grArg(theta)) { + Set resultPrime = new HashSet<>(); + resultPrime.add(new UnifyPair(a, theta, PairOperator.EQUALSDOT, pair.getSubstitution(), pair)); + result.add(resultPrime); + //writeLog(resultPrime.toString()); + + UnifyType freshTph = PlaceholderType.freshPlaceholder(); + + ((PlaceholderType)freshTph).setVariance(a.getVariance()); + ((PlaceholderType)freshTph).disableWildcardtable(); + resultPrime = new HashSet<>(); + resultPrime.add(new UnifyPair(a, new ExtendsType(freshTph), PairOperator.EQUALSDOT, pair.getSubstitution(), pair)); + resultPrime.add(new UnifyPair(theta, freshTph, PairOperator.SMALLERDOT, pair.getSubstitution(), pair, pair.getfBounded())); + result.add(resultPrime); + //writeLog("resultPrime: " + resultPrime.toString()); + + resultPrime = new HashSet<>(); + resultPrime.add(new UnifyPair(a, new SuperType(freshTph), PairOperator.EQUALSDOT, pair.getSubstitution(), pair)); + resultPrime.add(new UnifyPair(freshTph, theta, PairOperator.SMALLERDOT, pair.getSubstitution(), pair)); + result.add(resultPrime); + //writeLog(resultPrime.toString()); + //} + + return result; + } + + /** + * Takes a set of candidates for each position and computes all possible permutations. + * @param candidates The length of the list determines the number of type params. Each set + * contains the candidates for the corresponding position. + */ + protected Set permuteParams(ArrayList> candidates) { + Set result = new HashSet<>(); + permuteParams(candidates, 0, result, new UnifyType[candidates.size()]); + return result; + } + + /** + * Takes a set of candidates for each position and computes all possible permutations. + * @param candidates The length of the list determines the number of type params. Each set + * contains the candidates for the corresponding position. + * @param idx Idx for the current permutatiton. + * @param result Set of all permutations found so far + * @param current The permutation of type params that is currently explored + */ + private void permuteParams(ArrayList> candidates, int idx, Set result, UnifyType[] current) { + if(candidates.size() == idx) { + result.add(new TypeParams(Arrays.copyOf(current, current.length))); + return; + } + + Set localCandidates = candidates.get(idx); + + for(UnifyType t : localCandidates) { + current[idx] = t; + permuteParams(candidates, idx+1, result, current); + } + } + + void writeLog(String str) { + synchronized ( this ) { + if (log && finalresult) { + try { + logFile.write("Thread no.:" + thNo + "\n"); + logFile.write("noOfThread:" + noOfThread + "\n"); + logFile.write("parallel:" + parallel + "\n"); + logFile.write(str+"\n\n"); + logFile.flush(); + + } + catch (IOException e) { + System.err.println("kein LogFile"); + } + } + } + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/unify/Unifikationsalgorithmus.java b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/Unifikationsalgorithmus.java new file mode 100644 index 00000000..39c25e57 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/Unifikationsalgorithmus.java @@ -0,0 +1,11 @@ +package de.dhbwstuttgart.typeinference.unify; + +import java.util.Set; + +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; + +public interface Unifikationsalgorithmus { + + public Set> apply (Set E); + +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/unify/UnifyResultEvent.java b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/UnifyResultEvent.java new file mode 100644 index 00000000..a79e34ec --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/UnifyResultEvent.java @@ -0,0 +1,18 @@ +package de.dhbwstuttgart.typeinference.unify; + +import java.util.List; + +import de.dhbwstuttgart.typeinference.result.ResultSet; + +public class UnifyResultEvent { + + private List newTypeResult; + + public UnifyResultEvent(List newTypeResult) { + this.newTypeResult = newTypeResult; + } + + public List getNewTypeResult() { + return newTypeResult; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/unify/UnifyResultListener.java b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/UnifyResultListener.java new file mode 100644 index 00000000..f490ccde --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/UnifyResultListener.java @@ -0,0 +1,7 @@ +package de.dhbwstuttgart.typeinference.unify; + +public interface UnifyResultListener { + + void onNewTypeResultFound(UnifyResultEvent evt); + +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/unify/UnifyResultListenerImpl.java b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/UnifyResultListenerImpl.java new file mode 100644 index 00000000..ea34728b --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/UnifyResultListenerImpl.java @@ -0,0 +1,21 @@ +package de.dhbwstuttgart.typeinference.unify; + +import java.util.ArrayList; +import java.util.List; + +import de.dhbwstuttgart.typeinference.result.ResultSet; +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; + +public class UnifyResultListenerImpl implements UnifyResultListener { + + List results = new ArrayList<>(); + + public synchronized void onNewTypeResultFound(UnifyResultEvent evt) { + results.addAll(evt.getNewTypeResult()); + } + + public List getResults() { + return results; + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/unify/UnifyResultModel.java b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/UnifyResultModel.java new file mode 100644 index 00000000..7a4f0ccf --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/UnifyResultModel.java @@ -0,0 +1,59 @@ +package de.dhbwstuttgart.typeinference.unify; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import de.dhbwstuttgart.syntaxtree.factory.UnifyTypeFactory; +import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; +import de.dhbwstuttgart.typeinference.result.ResultSet; +import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; +import de.dhbwstuttgart.typeinference.unify.model.PairOperator; +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; + +public class UnifyResultModel { + + ConstraintSet cons; + + IFiniteClosure fc; + + public UnifyResultModel(ConstraintSet cons, + IFiniteClosure fc) { + this.cons = cons; + this.fc = fc; + } + + private List listeners = new ArrayList<>(); + + public void addUnifyResultListener(UnifyResultListener listenerToAdd) { + listeners.add(listenerToAdd); + } + + public void removeUnifyResultListener(UnifyResultListener listenerToRemove) { + listeners.remove(listenerToRemove); + } + + public void notify(Set> eqPrimePrimeSet) { + Set> eqPrimePrimeSetRet = eqPrimePrimeSet.stream().map(x -> { + Optional> res = new RuleSet().subst(x.stream().map(y -> { + if (y.getPairOp() == PairOperator.SMALLERDOTWC) y.setPairOp(PairOperator.EQUALSDOT); + return y; //alle Paare a <.? b erden durch a =. b ersetzt + }).collect(Collectors.toCollection(HashSet::new))); + if (res.isPresent()) {//wenn subst ein Erg liefert wurde was veraendert + return new TypeUnifyTask().applyTypeUnificationRules(res.get(), fc); + } + else return x; //wenn nichts veraendert wurde wird x zurueckgegeben + }).collect(Collectors.toCollection(HashSet::new)); + List newResult = eqPrimePrimeSetRet.stream().map(unifyPairs -> + new ResultSet(UnifyTypeFactory.convert(unifyPairs, de.dhbwstuttgart.typeinference.constraints.Pair.generateTPHMap(cons)))) + .collect(Collectors.toList()); + UnifyResultEvent evt = new UnifyResultEvent(newResult); + + for (UnifyResultListener listener : listeners) { + listener.onNewTypeResultFound(evt); + } + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/unify/UnifyTaskModel.java b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/UnifyTaskModel.java new file mode 100644 index 00000000..e60054f0 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/UnifyTaskModel.java @@ -0,0 +1,18 @@ +package de.dhbwstuttgart.typeinference.unify; + +import java.util.ArrayList; + +public class UnifyTaskModel { + + ArrayList usedTasks = new ArrayList<>(); + + public synchronized void add(TypeUnifyTask t) { + usedTasks.add(t); + } + + public synchronized void cancel() { + for(TypeUnifyTask t : usedTasks) { + t.myCancel(true); + } + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/unify/distributeVariance.java b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/distributeVariance.java new file mode 100644 index 00000000..1779c941 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/distributeVariance.java @@ -0,0 +1,54 @@ +package de.dhbwstuttgart.typeinference.unify; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import de.dhbwstuttgart.typeinference.unify.model.FunNType; +import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType; +import de.dhbwstuttgart.typeinference.unify.model.TypeParams; +import de.dhbwstuttgart.typeinference.unify.model.UnifyType; + +public class distributeVariance extends visitUnifyTypeVisitor { + + public static int inverseVariance(int variance) { + Integer ret = 0; + if (variance == 1) { + ret = -1; + } + if (variance == -1) { + ret = 1; + } + return ret; + } + + + @Override + public PlaceholderType visit(PlaceholderType phty, Integer ht) { + if (ht != 0) { + if (phty.getVariance() == 0) { + phty.setVariance(ht); + } + //PL 2018-05-17 urspruengliche Variance nicht veraendern + //else if (phty.getVariance() != ht) { + // phty.setVariance(0); + //} + } + return phty; + } + + public FunNType visit(FunNType funnty, Integer ht) { + List param = new ArrayList<>(funnty.getTypeParams().get().length); + param.addAll(Arrays.asList(funnty.getTypeParams().get())); + UnifyType resultType = param.remove(param.size()-1); + Integer htInverse = inverseVariance(ht); + param = param.stream() + .map(x -> x.accept(this, htInverse)) + .collect(Collectors.toCollection(ArrayList::new)); + param.add(resultType.accept(this, ht)); + return FunNType.getFunNType(new TypeParams(param)); + } + + +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/unify/freshPlaceholder.java b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/freshPlaceholder.java new file mode 100644 index 00000000..69870bd5 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/freshPlaceholder.java @@ -0,0 +1,15 @@ +package de.dhbwstuttgart.typeinference.unify; + + +import java.util.HashMap; + +import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType; + + +public class freshPlaceholder extends visitUnifyTypeVisitor> { + + @Override + public PlaceholderType visit(PlaceholderType phty, HashMap ht) { + return ht.get(phty); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/unify/interfaces/IFiniteClosure.java b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/interfaces/IFiniteClosure.java new file mode 100644 index 00000000..50371d34 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/interfaces/IFiniteClosure.java @@ -0,0 +1,68 @@ +package de.dhbwstuttgart.typeinference.unify.interfaces; + +import java.util.Optional; +import java.util.Set; + +import de.dhbwstuttgart.typeinference.unify.model.ExtendsType; +import de.dhbwstuttgart.typeinference.unify.model.FunNType; +import de.dhbwstuttgart.typeinference.unify.model.PairOperator; +import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType; +import de.dhbwstuttgart.typeinference.unify.model.ReferenceType; +import de.dhbwstuttgart.typeinference.unify.model.SuperType; +import de.dhbwstuttgart.typeinference.unify.model.UnifyType; + +/** + * + * @author Florian Steurer + */ +public interface IFiniteClosure { + + public void setLogTrue(); + /** + * Returns all types of the finite closure that are subtypes of the argument. + * @return The set of subtypes of the argument. + */ + public Set smaller(UnifyType type, Set fBounded); + + /** + * Returns all types of the finite closure that are supertypes of the argument. + * @return The set of supertypes of the argument. + */ + public Set greater(UnifyType type, Set fBounded); + + /** + * Wo passt Type rein? + * @param type + * @return + */ + public Set grArg(UnifyType type, Set fBounded); + + /** + * Was passt in Type rein? + * @param type + * @return + */ + public Set smArg(UnifyType type, Set fBounded); + + public Set grArg(ReferenceType type, Set fBounded); + public Set smArg(ReferenceType type, Set fBounded); + + public Set grArg(ExtendsType type, Set fBounded); + public Set smArg(ExtendsType type, Set fBounded); + + public Set grArg(SuperType type, Set fBounded); + public Set smArg(SuperType type, Set fBounded); + + public Set grArg(PlaceholderType type, Set fBounded); + public Set smArg(PlaceholderType type, Set fBounded); + + public Set grArg(FunNType type, Set fBounded); + public Set smArg(FunNType type, Set fBounded); + + public Optional getLeftHandedType(String typeName); + public Set getAncestors(UnifyType t); + public Set getChildren(UnifyType t); + public Set getAllTypesByName(String typeName); + + public int compare(UnifyType rhsType, UnifyType rhsType2, PairOperator pairop); +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/unify/interfaces/IMatch.java b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/interfaces/IMatch.java new file mode 100644 index 00000000..a60de878 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/interfaces/IMatch.java @@ -0,0 +1,29 @@ +package de.dhbwstuttgart.typeinference.unify.interfaces; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import de.dhbwstuttgart.typeinference.unify.model.UnifyType; +import de.dhbwstuttgart.typeinference.unify.model.Unifier; +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; + +/** + * Match + * @author Martin Pluemicke + * abgeleitet aus IUnify.java + */ +public interface IMatch { + + /** + * Finds the most general matcher sigma of the set {t1 =. t1',...,tn =. tn'} so that + * sigma(t1) = t1' , ... sigma(tn) = tn'. + * @param terms The set of terms to be matched + * @return An optional of the most general matcher if it exists or an empty optional if there is no matcher. + */ + public Optional match(ArrayList termsList); + + +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/unify/interfaces/IRuleSet.java b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/interfaces/IRuleSet.java new file mode 100644 index 00000000..bac6bcb0 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/interfaces/IRuleSet.java @@ -0,0 +1,103 @@ +package de.dhbwstuttgart.typeinference.unify.interfaces; + +import java.util.List; +import java.util.Optional; +import java.util.Set; + +import de.dhbwstuttgart.typeinference.constraints.Constraint; +import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; + +/** + * Contains the inference rules that are applied to the set Eq. + * @author Florian Steurer + */ +public interface IRuleSet { + + public Optional reduceUp(UnifyPair pair); + public Optional reduceLow(UnifyPair pair); + public Optional reduceUpLow(UnifyPair pair); + public Optional> reduceExt(UnifyPair pair, IFiniteClosure fc); + public Optional> reduceSup(UnifyPair pair, IFiniteClosure fc); + public Optional> reduceEq(UnifyPair pair); + public Optional> reduce1(UnifyPair pair, IFiniteClosure fc); + public Optional> reduce2(UnifyPair pair); + + /* + * Missing Reduce-Rules for Wildcards + */ + public Optional reduceWildcardLow(UnifyPair pair); + public Optional reduceWildcardLowRight(UnifyPair pair); + public Optional reduceWildcardUp(UnifyPair pair); + public Optional reduceWildcardUpRight(UnifyPair pair); + + /* + * vgl. JAVA_BSP/Wildcard6.java + public Optional reduceWildcardLowUp(UnifyPair pair); + public Optional reduceWildcardUpLow(UnifyPair pair); + public Optional reduceWildcardLeft(UnifyPair pair); + */ + + /* + * Additional Rules which replace cases of the cartesian product + */ + + /** + * Rule that replaces the fourth case of the cartesian product where (a <.? Theta) + */ + public Optional reduceTph(UnifyPair pair); + + /** + * Rule that replaces the sixth case of the cartesian product where (? ext Theta <.? a) + */ + public Optional> reduceTphExt(UnifyPair pair); + + /** + * Rule that replaces the fourth case of the cartesian product where (? sup Theta <.? a) + */ + public Optional> reduceTphSup(UnifyPair pair); + + /* + * FunN Rules + */ + public Optional> reduceFunN(UnifyPair pair); + public Optional> greaterFunN(UnifyPair pair); + public Optional> smallerFunN(UnifyPair pair); + + /** + * Checks whether the erase1-Rule applies to the pair. + * @return True if the pair is erasable, false otherwise. + */ + public boolean erase1(UnifyPair pair, IFiniteClosure fc); + + /** + * Checks whether the erase2-Rule applies to the pair. + * @return True if the pair is erasable, false otherwise. + */ + public boolean erase2(UnifyPair pair, IFiniteClosure fc); + + /** + * Checks whether the erase3-Rule applies to the pair. + * @return True if the pair is erasable, false otherwise. + */ + public boolean erase3(UnifyPair pair); + + public Optional swap(UnifyPair pair); + + public Optional adapt(UnifyPair pair, IFiniteClosure fc); + public Optional adaptExt(UnifyPair pair, IFiniteClosure fc); + public Optional adaptSup(UnifyPair pair, IFiniteClosure fc); + + /** + * Applies the subst-Rule to a set of pairs (usually Eq'). + * @param pairs The set of pairs where the subst rule should apply. + * @return An optional of the modified set, if there were any substitutions. An empty optional if there were no substitutions. + */ + public Optional> subst(Set pairs, List>> oderConstraints); + + /** + * Applies the subst-Rule to a set of pairs (usually Eq'). + * @param pairs The set of pairs where the subst rule should apply. + * @return An optional of the modified set, if there were any substitutions. An empty optional if there were no substitutions. + */ + public Optional> subst(Set pairs); +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/unify/interfaces/ISetOperations.java b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/interfaces/ISetOperations.java new file mode 100644 index 00000000..cf0def37 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/interfaces/ISetOperations.java @@ -0,0 +1,16 @@ +package de.dhbwstuttgart.typeinference.unify.interfaces; + +import java.util.List; +import java.util.Set; + +/** + * Contains operations on sets. + * @author Florian Steurer + */ +public interface ISetOperations { + /** + * Calculates the cartesian product of the sets. + * @return The cartesian product + */ + Set> cartesianProduct(List> sets); +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/unify/interfaces/IUnify.java b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/interfaces/IUnify.java new file mode 100644 index 00000000..5647e189 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/interfaces/IUnify.java @@ -0,0 +1,35 @@ +package de.dhbwstuttgart.typeinference.unify.interfaces; + +import java.util.Arrays; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import de.dhbwstuttgart.typeinference.unify.model.UnifyType; +import de.dhbwstuttgart.typeinference.unify.model.Unifier; + +/** + * Standard unification algorithm (e.g. Robinson, Paterson-Wegman, Martelli-Montanari) + * @author Florian Steurer + */ +public interface IUnify { + + /** + * Finds the most general unifier sigma of the set {t1 =. t1',...,tn =. tn'} so that + * sigma(t1) = sigma(t1') , ... sigma(tn) = sigma(tn'). + * @param terms The set of terms to be unified + * @return An optional of the most general unifier if it exists or an empty optional if there is no unifier. + */ + public Optional unify(Set terms); + + /** + * Finds the most general unifier sigma of the set {t1 =. t1',...,tn =. tn'} so that + * sigma(t1) = sigma(t1') , ... sigma(tn) = sigma(tn'). + * @param terms The set of terms to be unified + * @return An optional of the most general unifier if it exists or an empty optional if there is no unifier. + */ + default public Optional unify(UnifyType... terms) { + return unify(Arrays.stream(terms).collect(Collectors.toSet())); + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/unify/interfaces/UnifyTypeVisitor.java b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/interfaces/UnifyTypeVisitor.java new file mode 100644 index 00000000..8d06b3e1 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/interfaces/UnifyTypeVisitor.java @@ -0,0 +1,23 @@ +package de.dhbwstuttgart.typeinference.unify.interfaces; + +import java.util.HashMap; + +import de.dhbwstuttgart.typeinference.unify.model.ExtendsType; +import de.dhbwstuttgart.typeinference.unify.model.FunNType; +import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType; +import de.dhbwstuttgart.typeinference.unify.model.ReferenceType; +import de.dhbwstuttgart.typeinference.unify.model.SuperType; + +public interface UnifyTypeVisitor { + + public ReferenceType visit(ReferenceType refty, T ht); + + public PlaceholderType visit(PlaceholderType phty, T ht); + + public FunNType visit(FunNType funnty, T ht); + + public SuperType visit(SuperType suty, T ht); + + public ExtendsType visit(ExtendsType extty, T ht); + +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/ExtendsType.java b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/ExtendsType.java new file mode 100644 index 00000000..ef7e950e --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/ExtendsType.java @@ -0,0 +1,96 @@ +package de.dhbwstuttgart.typeinference.unify.model; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Set; + +import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; +import de.dhbwstuttgart.typeinference.unify.interfaces.UnifyTypeVisitor; + +/** + * An extends wildcard type "? extends T". + */ +public final class ExtendsType extends WildcardType { + + public UnifyType accept(UnifyTypeVisitor visitor, T ht) { + return visitor.visit(this, ht); + } + + /** + * Creates a new extends wildcard type. + * @param extendedType The extended type e.g. Integer in "? extends Integer" + */ + public ExtendsType(UnifyType extendedType) { + super("? extends " + extendedType.getName(), extendedType); + if (extendedType instanceof ExtendsType) { + System.out.print(""); + } + } + + /** + * The extended type e.g. Integer in "? extends Integer" + */ + public UnifyType getExtendedType() { + return wildcardedType; + } + + /** + * Sets the type parameters of the wildcarded type and returns a new extendstype that extends that type. + */ + @Override + public UnifyType setTypeParams(TypeParams newTp) { + UnifyType newType = wildcardedType.setTypeParams(newTp); + if(newType == wildcardedType) + return this; // Reduced the amount of objects created + return new ExtendsType(wildcardedType.setTypeParams(newTp)); + } + + @Override + Set smArg(IFiniteClosure fc, Set fBounded) { + return fc.smArg(this, fBounded); + } + + @Override + Set grArg(IFiniteClosure fc, Set fBounded) { + return fc.grArg(this, fBounded); + } + + @Override + UnifyType apply(Unifier unif) { + UnifyType newType = wildcardedType.apply(unif); + if(newType.hashCode() == wildcardedType.hashCode() && newType.equals(wildcardedType)) + return this; // Reduced the amount of objects created + return new ExtendsType(newType); + } + + @Override + public int hashCode() { + /* + * It is important that the prime that is added is different to the prime added in hashCode() of SuperType. + * Otherwise ? extends T and ? super T have the same hashCode() for every Type T. + */ + return wildcardedType.hashCode() + 229; + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof ExtendsType)) + return false; + + if(obj.hashCode() != this.hashCode()) + return false; + + ExtendsType other = (ExtendsType) obj; + + + return other.getWildcardedType().equals(wildcardedType); + } + + @Override + public String toString() { + return "? extends " + wildcardedType; + } + + +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java new file mode 100644 index 00000000..a48db2aa --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/FiniteClosure.java @@ -0,0 +1,771 @@ +package de.dhbwstuttgart.typeinference.unify.model; + +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.function.BiFunction; +import java.util.function.BinaryOperator; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import com.google.common.collect.Ordering; + +//PL 18-02-05/18-04-05 Unifier durch Matcher ersetzt +//muss greater noch ersetzt werden ja erledigt 18--04-05 +import de.dhbwstuttgart.typeinference.unify.MartelliMontanariUnify; + +import de.dhbwstuttgart.typeinference.unify.Match; +import de.dhbwstuttgart.typeinference.unify.TypeUnifyTask; +import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; +import de.dhbwstuttgart.typeinference.unify.interfaces.IUnify; + +/** + * The finite closure for the type unification + * @author Florian Steurer + */ +public class FiniteClosure //extends Ordering //entfernt PL 2018-12-11 +implements IFiniteClosure { + + Writer logFile; + static Boolean log = false; + public void setLogTrue() { + log = true; + } + /** + * A map that maps every type to the node in the inheritance graph that contains that type. + */ + private HashMap> inheritanceGraph; + + /** + * A map that maps every typename to the nodes of the inheritance graph that contain a type with that name. + */ + private HashMap>> strInheritanceGraph; + + + /** + * The initial pairs of that define the inheritance tree + */ + private Set pairs; + + /** + * Hastable fuer die greater-Werte, damit sie nicht doppelt berechnet werden muessen + */ + Hashtable> greaterHash = new Hashtable<>(); + + /** + * Hastable fuer die smaller-Werte, damit sie nicht doppelt berechnet werden muessen + */ + Hashtable> smallerHash = new Hashtable<>(); + + /** + * Creates a new instance using the inheritance tree defined in the pairs. + */ + public FiniteClosure(Set pairs, Writer logFile) { + this.logFile = logFile; + this.pairs = new HashSet<>(pairs); + inheritanceGraph = new HashMap>(); + + // Build the transitive closure of the inheritance tree + for(UnifyPair pair : pairs) { + + /* + try { + logFile.write("Pair: " + pair + "\n"); + logFile.flush(); + } + catch (IOException e) { + System.err.println("no LogFile"); + } + */ + + if(pair.getPairOp() != PairOperator.SMALLER) + continue; + + //VERSUCH PL 18-02-06 + //koennte ggf. die FC reduzieren + //TO DO: Ueberpruefen, ob das sinnvll und korrekt ist + //if (!pair.getLhsType().getTypeParams().arePlaceholders() + // && !pair.getRhsType().getTypeParams().arePlaceholders()) + // continue; +; + // Add nodes if not already in the graph + if(!inheritanceGraph.containsKey(pair.getLhsType())) + inheritanceGraph.put(pair.getLhsType(), new Node(pair.getLhsType())); + if(!inheritanceGraph.containsKey(pair.getRhsType())) + inheritanceGraph.put(pair.getRhsType(), new Node(pair.getRhsType())); + + Node childNode = inheritanceGraph.get(pair.getLhsType()); + Node parentNode = inheritanceGraph.get(pair.getRhsType()); + + // Add edge + parentNode.addDescendant(childNode); + + // Add edges to build the transitive closure + parentNode.getPredecessors().stream().forEach(x -> x.addDescendant(childNode)); + childNode.getDescendants().stream().forEach(x -> x.addPredecessor(parentNode)); + + //PL eingefuegt 2020-05-07 File UnitTest InheritTest.java + this.inheritanceGraph.forEach((x,y) -> { if (y.getDescendants().contains(parentNode)) { y.addDescendant(childNode); y.addAllDescendant(childNode.getDescendants());}; + if (y.getPredecessors().contains(childNode)) { y.addPredecessor(parentNode); y.addAllPredecessor(parentNode.getPredecessors());};} ); + } + + // Build the alternative representation with strings as keys + strInheritanceGraph = new HashMap<>(); + for(UnifyType key : inheritanceGraph.keySet()) { + if(!strInheritanceGraph.containsKey(key.getName())) + strInheritanceGraph.put(key.getName(), new HashSet<>()); + + strInheritanceGraph.get(key.getName()).add(inheritanceGraph.get(key)); + } + } + + void testSmaller() { + UnifyType tq1, tq2, tq3; + tq1 = new ExtendsType(PlaceholderType.freshPlaceholder()); + List l1 = new ArrayList<>(); + List l2 = new ArrayList<>(); + l1.add(tq1); + tq2 = new ReferenceType("java.util.Vector", new TypeParams(l1)); + l2.add(tq2); + tq3 = new ReferenceType("java.util.Vector", new TypeParams(l2)); + Set smaller = smaller(tq3, new HashSet<>()); + } + + /** + * Returns all types of the finite closure that are subtypes of the argument. + * @return The set of subtypes of the argument. + */ + @Override + public Set smaller(UnifyType type, Set fBounded) { + + Set ret; + if ((ret = smallerHash.get(new hashKeyType(type))) != null) { + //System.out.println(greaterHash); + return new HashSet<>(ret); + } + + if(type instanceof FunNType) + return computeSmallerFunN((FunNType) type, fBounded); + + Set>> ts = new HashSet<>(); + ts.add(new Pair<>(type, fBounded)); + Set result = computeSmaller(ts); + smallerHash.put(new hashKeyType(type), result); + /* + try { + logFile.write("\ntype: " + type + "\nret: " + ret + "\nresult: " + result);//"smallerHash: " + greaterHash.toString()); + logFile.flush(); + } + catch (IOException e) { + System.err.println("no LogFile"); + }*/ + return result; + } + + /** + * Computes the smaller functions for every type except FunNTypes. + */ + private Set computeSmaller(Set>> types) { + Set>> result = new HashSet<>(); + + //PL 18-02-05 Unifier durch Matcher ersetzt + //IUnify unify = new MartelliMontanariUnify(); + Match match = new Match(); + + for(Pair> pt : types) { + UnifyType t = pt.getKey(); + Set fBounded = pt.getValue().get(); + + // if T = T' then T <* T' + try { + result.add(new Pair<>(t, fBounded)); + } + catch (StackOverflowError e) { + System.out.println(""); + } + + // if C<...> <* C<...> then ... (third case in definition of <*) + if(t.getTypeParams().size() > 0) { + ArrayList> paramCandidates = new ArrayList<>(); + for (int i = 0; i < t.getTypeParams().size(); i++) + paramCandidates.add(smArg(t.getTypeParams().get(i), fBounded)); + permuteParams(paramCandidates).forEach(x -> result.add(new Pair<>(t.setTypeParams(x), fBounded))); + } + + if(!strInheritanceGraph.containsKey(t.getName())) + continue; + + // if T <* T' then sigma(T) <* sigma(T') + Set> candidates = strInheritanceGraph.get(t.getName()); //cadidates= [???Node(java.util.Vector>)??? + // , Node(java.util.Vector) + //] + for(Node candidate : candidates) { + UnifyType theta2 = candidate.getContent(); + //PL 18-02-05 Unifier durch Matcher ersetzt ANFANG + ArrayList termList= new ArrayList(); + termList.add(new UnifyPair(theta2,t, PairOperator.EQUALSDOT)); + Optional optSigma = match.match(termList); + //PL 18-02-05 Unifier durch Matcher ersetzt ENDE + if(!optSigma.isPresent()) + continue; + + Unifier sigma = optSigma.get(); + sigma.swapPlaceholderSubstitutions(t.getTypeParams()); + + Set theta1Set = candidate.getContentOfDescendants(); + + for(UnifyType theta1 : theta1Set) + result.add(new Pair<>(theta1.apply(sigma), fBounded)); + } + } + + HashSet resut = result.stream().map(x -> x.getKey()).collect(Collectors.toCollection(HashSet::new)); + if(resut.equals(types.stream().map(x -> x.getKey()).collect(Collectors.toCollection(HashSet::new)))) + return resut; + return computeSmaller(result); + } + + /** + * Computes the smaller-Function for FunNTypes. + */ + private Set computeSmallerFunN(FunNType type, Set fBounded) { + Set result = new HashSet<>(); + + // if T = T' then T <=* T' + result.add(type); + + // Because real function types are implicitly variant + // it is enough to permute the params with the values of greater / smaller. + ArrayList> paramCandidates = new ArrayList<>(); + paramCandidates.add(smaller(type.getTypeParams().get(0), fBounded)); + for (int i = 1; i < type.getTypeParams().size(); i++) + paramCandidates.add(greater(type.getTypeParams().get(i), new HashSet<>())); + + permuteParams(paramCandidates).forEach(x -> result.add(type.setTypeParams(x))); + return result; + } + + /** + * Returns all types of the finite closure that are supertypes of the argument. + * @return The set of supertypes of the argument. + */ + @Override + //Eingefuegt PL 2018-05-24 F-Bounded Problematik + public Set greater(UnifyType type, Set fBounded) { + + Set ret; + if ((ret = greaterHash.get(new hashKeyType(type))) != null) { + //System.out.println(greaterHash); + return new HashSet<>(ret); + } + + + if(type instanceof FunNType) { + return computeGreaterFunN((FunNType) type, fBounded); + } + + Set result = new HashSet<>(); + Set>> PairResultFBounded = new HashSet<>(); + + Match match = new Match(); + + + // if T = T' then T <=* T' + result.add(type); + if(!strInheritanceGraph.containsKey(type.getName())) + return result; + + // if T <* T' then sigma(T) <* sigma(T') + Set> candidates = strInheritanceGraph.get(type.getName()); + + /* + try { + if (log) logFile.write(candidates.toString()); + //log = false; + } + catch (IOException e) { + System.err.println("no LogFile"); + } + */ + + for(Node candidate : candidates) { + UnifyType theta1 = candidate.getContent(); + + //PL 18-04-05 Unifier durch Matcher ersetzt ANFANG + ArrayList termList= new ArrayList(); + termList.add(new UnifyPair(theta1,type, PairOperator.EQUALSDOT)); + Optional optSigma = match.match(termList); + //PL 18-04-05 Unifier durch Matcher ersetzt ENDE + if(!optSigma.isPresent()) { + continue; + } + Unifier sigma = optSigma.get(); + sigma.swapPlaceholderSubstitutionsReverse(theta1.getTypeParams()); + + Set fBoundedNew = new HashSet<>(fBounded); + fBoundedNew.add(theta1); + Set theta2Set = candidate.getContentOfPredecessors(); + //System.out.println(""); + for(UnifyType theta2 : theta2Set) { + result.add(theta2.apply(sigma)); + PairResultFBounded.add(new Pair<>(theta2.apply(sigma), fBoundedNew)); + } + } + /* + try { + if (log) logFile.write(PairResultFBounded.toString()); + log = false; + } + catch (IOException e) { + System.err.println("no LogFile"); + } + */ + for(Pair> pt : PairResultFBounded) { + UnifyType t = pt.getKey(); + Set lfBounded = pt.getValue().get(); + + // if C<...> <* C<...> then ... (third case in definition of <*) + //TypeParams typeparams = t.getTypeParams(); + if(t.getTypeParams().size() > 0) { + ArrayList> paramCandidates = new ArrayList<>(); + + for (int i = 0; i < t.getTypeParams().size(); i++) { + //UnifyType parai = t.getTypeParams().get(i); + int i_ef = i; + BiFunction f = (x,y) -> + { + ArrayList termList = new ArrayList(); + termList.add(new UnifyPair(y,t.getTypeParams().get(i_ef), PairOperator.EQUALSDOT)); + return ((match.match(termList).isPresent()) || x); + }; + //if (parai.getName().equals("java.lang.Integer")) { + // System.out.println(""); + //} + BinaryOperator bo = (a,b) -> (a || b); + if (lfBounded.stream().reduce(false,f,bo)) { + //F-Bounded Endlosrekursion + HashSet res = new HashSet(); + paramCandidates.add(res); + } + else { + paramCandidates.add(grArg(t.getTypeParams().get(i), new HashSet<>(fBounded) )); + } + } + permuteParams(paramCandidates).forEach(x -> result.add(t.setTypeParams(x))); + //System.out.println(""); + } + } + + greaterHash.put(new hashKeyType(type), result); + /* + try { + logFile.write("\ntype: " + type + "\nret: " + ret + "\nresult: " + result);//"greaterHash: " + greaterHash.toString()); + logFile.flush(); + } + catch (IOException e) { + System.err.println("no LogFile"); + }*/ + return result; + } + + /* auskommentiert PL 2018-05-24 + /** + * Returns all types of the finite closure that are supertypes of the argument. + * @return The set of supertypes of the argument. + * + //@Override + public Set oldgreater(UnifyType type, Set fBounded) { + if(type instanceof FunNType) + return computeGreaterFunN((FunNType) type, fBounded); + + Set>> ts = new HashSet<>(); + ts.add(new Pair<>(type, fBounded)); + return computeGreater(ts); + } + + /** + * Computes the greater function for all types except function types. + * + protected Set computeGreater(Set>> types) { + Set>> result = new HashSet<>(); + + //PL 18-04-05 Unifier durch Matcher ersetzt + //IUnify unify = new MartelliMontanariUnify(); + Match match = new Match(); + + for(Pair> pt : types) { + UnifyType t = pt.getKey(); + Set fBounded = pt.getValue().get(); + // if T = T' then T <=* T' + result.add(pt); + + // if C<...> <* C<...> then ... (third case in definition of <*) + if(t.getTypeParams().size() > 0) { + ArrayList> paramCandidates = new ArrayList<>(); + for (int i = 0; i < t.getTypeParams().size(); i++) { + UnifyType parai = t.getTypeParams().get(i); + int i_ef = i; + BiFunction f = (x,y) -> + { + ArrayList termList = new ArrayList(); + termList.add(new UnifyPair(y,t.getTypeParams().get(i_ef), PairOperator.EQUALSDOT)); + return ((match.match(termList).isPresent()) || x); + }; + if (parai.getName().equals("java.lang.Integer")) { + System.out.println(""); + } + BinaryOperator bo = (a,b) -> (a || b); + if (fBounded.stream().reduce(false,f,bo)) continue; //F-Bounded Endlosrekursion + paramCandidates.add(grArg(t.getTypeParams().get(i), new HashSet<>(fBounded) )); + } + permuteParams(paramCandidates).forEach(x -> result.add(new Pair<>(t.setTypeParams(x), new HashSet<>(fBounded)))); + } + + if(!strInheritanceGraph.containsKey(t.getName())) + continue; + + // if T <* T' then sigma(T) <* sigma(T') + Set> candidates = strInheritanceGraph.get(t.getName()); + for(Node candidate : candidates) { + UnifyType theta1 = candidate.getContent(); + + //PL 18-04-05 Unifier durch Matcher ersetzt ANFANG + ArrayList termList= new ArrayList(); + termList.add(new UnifyPair(theta1,t, PairOperator.EQUALSDOT)); + Optional optSigma = match.match(termList); + //PL 18-04-05 Unifier durch Matcher ersetzt ENDE + if(!optSigma.isPresent()) + continue; + + Unifier sigma = optSigma.get(); + sigma.swapPlaceholderSubstitutionsReverse(theta1.getTypeParams()); + + Set fBoundedNew = new HashSet<>(fBounded); + fBoundedNew.add(theta1); + Set theta2Set = candidate.getContentOfPredecessors(); + + for(UnifyType theta2 : theta2Set) + result.add(new Pair<>(theta2.apply(sigma), fBoundedNew)); + } + + } + + HashSet resut = result.stream().map(x -> x.getKey()).collect(Collectors.toCollection(HashSet::new)); + System.out.println(resut); + if(resut.equals(types.stream().map(x -> x.getKey()).collect(Collectors.toCollection(HashSet::new)))) + return resut; + return computeGreater(result); + } + */ + + /** + * Computes the greater function for FunN-Types + */ + protected Set computeGreaterFunN(FunNType type, Set fBounded) { + Set result = new HashSet<>(); + + // if T = T' then T <=* T' + result.add(type); + + // Because real function types are implicitly variant + // it is enough to permute the params with the values of greater / smaller. + ArrayList> paramCandidates = new ArrayList<>(); + paramCandidates.add(greater(type.getTypeParams().get(0), new HashSet<>())); + for (int i = 1; i < type.getTypeParams().size(); i++) + paramCandidates.add(smaller(type.getTypeParams().get(i), fBounded)); + permuteParams(paramCandidates).forEach(x -> result.add(type.setTypeParams(x))); + return result; + } + + + @Override + public Set grArg(UnifyType type, Set fBounded) { + return type.grArg(this, fBounded); + } + + @Override + public Set grArg(ReferenceType type, Set fBounded) { + Set result = new HashSet(); + result.add(type); + smaller(type, fBounded).forEach(x -> result.add(new SuperType(x))); + greater(type,fBounded).forEach(x -> result.add(new ExtendsType(x))); + return result; + } + + @Override + public Set grArg(FunNType type, Set fBounded) { + Set result = new HashSet(); + result.add(type); + smaller(type, fBounded).forEach(x -> result.add(new SuperType(x))); + greater(type, fBounded).forEach(x -> result.add(new ExtendsType(x))); + return result; + } + + @Override + public Set grArg(ExtendsType type, Set fBounded) { + Set result = new HashSet(); + result.add(type); + UnifyType t = type.getExtendedType(); + greater(t, fBounded).forEach(x -> result.add(new ExtendsType(x))); + return result; + } + + @Override + public Set grArg(SuperType type, Set fBounded) { + Set result = new HashSet(); + result.add(type); + UnifyType t = type.getSuperedType(); + smaller(t, fBounded).forEach(x -> result.add(new SuperType(x))); + return result; + } + + @Override + public Set grArg(PlaceholderType type, Set fBounded) { + HashSet result = new HashSet<>(); + result.add(type); + return result; + } + + @Override + public Set smArg(UnifyType type, Set fBounded) { + return type.smArg(this, fBounded); + } + + @Override + public Set smArg(ReferenceType type, Set fBounded) { + Set result = new HashSet(); + result.add(type); + return result; + } + + @Override + public Set smArg(FunNType type, Set fBounded) { + Set result = new HashSet(); + result.add(type); + return result; + } + + @Override + public Set smArg(ExtendsType type, Set fBounded) { + Set result = new HashSet(); + result.add(type); + UnifyType t = type.getExtendedType(); + result.add(t); + smaller(t, fBounded).forEach(x -> { + result.add(new ExtendsType(x)); + result.add(x); + }); + return result; + } + + + @Override + public Set smArg(SuperType type, Set fBounded) { + Set result = new HashSet(); + result.add(type); + UnifyType t = type.getSuperedType(); + result.add(t); +//*** ACHTUNG das koennte FALSCH sein PL 2018-05-23 evtl. HashSet durch smArg durchschleifen + greater(t, fBounded).forEach(x -> { + result.add(new SuperType(x)); + result.add(x); + }); + return result; + } + + @Override + public Set smArg(PlaceholderType type, Set fBounded) { + HashSet result = new HashSet<>(); + result.add(type); + return result; + } + + @Override + public Set getAllTypesByName(String typeName) { + if(!strInheritanceGraph.containsKey(typeName)) + return new HashSet<>(); + return strInheritanceGraph.get(typeName).stream().map(x -> x.getContent()).collect(Collectors.toCollection(HashSet::new)); + } + + @Override + public Optional getLeftHandedType(String typeName) { + if(!strInheritanceGraph.containsKey(typeName)) + return Optional.empty(); + + for(UnifyPair pair : pairs) + if(pair.getLhsType().getName().equals(typeName) && pair.getLhsType().typeParams.arePlaceholders()) + return Optional.of(pair.getLhsType()); + + return Optional.empty(); + } + + @Override + public Set getAncestors(UnifyType t) { + if(!inheritanceGraph.containsKey(t)) + return new HashSet<>(); + Set result = inheritanceGraph.get(t).getContentOfPredecessors(); + result.add(t); + return result; + } + + @Override + public Set getChildren(UnifyType t) { + if(!inheritanceGraph.containsKey(t)) + return new HashSet<>(); + Set result = inheritanceGraph.get(t).getContentOfDescendants(); + result.add(t); + return result; + } + + /** + * Takes a set of candidates for each position and computes all possible permutations. + * @param candidates The length of the list determines the number of type params. Each set + * contains the candidates for the corresponding position. + */ + protected Set permuteParams(ArrayList> candidates) { + Set result = new HashSet<>(); + permuteParams(candidates, 0, result, new UnifyType[candidates.size()]); + return result; + } + + /** + * Takes a set of candidates for each position and computes all possible permutations. + * @param candidates The length of the list determines the number of type params. Each set + * contains the candidates for the corresponding position. + * @param idx Idx for the current permutatiton. + * @param result Set of all permutations found so far + * @param current The permutation of type params that is currently explored + */ + protected void permuteParams(ArrayList> candidates, int idx, Set result, UnifyType[] current) { + if(candidates.size() == idx) { + result.add(new TypeParams(Arrays.copyOf(current, current.length))); + return; + } + + Set localCandidates = candidates.get(idx); + + for(UnifyType t : localCandidates) { + current[idx] = t; + permuteParams(candidates, idx+1, result, current); + } + } + + @Override + public String toString(){ + return this.inheritanceGraph.toString(); + } + + /* entfernt PL 2018-12-11 + public int compare (UnifyType left, UnifyType right) { + return compare(left, right, PairOperator.SMALLERDOT); + } + */ + + public int compare (UnifyType left, UnifyType right, PairOperator pairop) { + //try {logFile.write("left: "+ left + " right: " + right + " pairop: " + pairop);} catch (IOException ie) {} + if (left.getName().equals("Matrix") || right.getName().equals("Matrix")) + System.out.println(""); + /* + pairop = PairOperator.SMALLERDOTWC; + List al = new ArrayList<>(); + PlaceholderType xx =new PlaceholderType("xx"); + al.add(xx); + left = new ExtendsType(new ReferenceType("Vector", new TypeParams(al))); + + List alr = new ArrayList<>(); + UnifyType exx = new ExtendsType(xx); + alr.add(exx); + right = new ExtendsType(new ReferenceType("Vector", new TypeParams(alr))); + */ + /* + List al = new ArrayList<>(); + PlaceholderType xx =new PlaceholderType("xx"); + al.add(xx); + left = new ExtendsType(xx); + right = xx; + */ + /* + List al = new ArrayList<>(); + PlaceholderType xx =new PlaceholderType("xx"); + PlaceholderType yy =new PlaceholderType("yy"); + al.add(xx); + left = yy; + right = new ExtendsType(xx); + */ + //Die Faelle abfangen, bei den Variablen verglichen werden PL 2018-12-11 + UnifyType ex; + if (left instanceof PlaceholderType) { + if ((right instanceof WildcardType) + && ((ex = ((WildcardType)right).wildcardedType) instanceof PlaceholderType) + && ((PlaceholderType)left).getName().equals(((PlaceholderType)ex).getName())) {// a <.? ? extends a oder a <.? ? super a + return -1; + } + else { + return 0; + } + } + if (right instanceof PlaceholderType) {//&& (left instanceof WildcardType)) {PL geloescht 2019-01-15 analog zu oben + if ((left instanceof WildcardType) //PL eingefuegt 2019-01-15 analog zu oben + && ((ex = ((WildcardType)left).wildcardedType) instanceof PlaceholderType) + && ((PlaceholderType)right).getName().equals(((PlaceholderType)ex).getName())) {// ? extends a <. a oder ? super a <. a + return 1; + } + else { + return 0; + } + } + UnifyPair up = new UnifyPair(left, right, pairop); + TypeUnifyTask unifyTask = new TypeUnifyTask(); + HashSet hs = new HashSet<>(); + hs.add(up); + Set smallerRes = unifyTask.applyTypeUnificationRules(hs, this); + /* + //if (left.getName().equals("Matrix") || right.getName().equals("Matrix")) + {try { + logFile.write("\nsmallerRes: " + smallerRes);//"smallerHash: " + greaterHash.toString()); + logFile.flush(); + } + catch (IOException e) { + System.err.println("no LogFile");}} + */ + //Gleichungen der Form a <./=. Theta oder Theta <./=. a oder a <./=. b sind ok. + Predicate delFun = x -> !((x.getLhsType() instanceof PlaceholderType || + x.getRhsType() instanceof PlaceholderType) + && !((x.getLhsType() instanceof WildcardType) && //? extends/super a <.? a + ((WildcardType)x.getLhsType()).getWildcardedType().equals(x.getRhsType())) + ); + long smallerLen = smallerRes.stream().filter(delFun).count(); + if (smallerLen == 0) return -1; + else { + up = new UnifyPair(right, left, pairop); + //TypeUnifyTask unifyTask = new TypeUnifyTask(); + hs = new HashSet<>(); + hs.add(up); + Set greaterRes = unifyTask.applyTypeUnificationRules(hs, this); + /* + //if (left.getName().equals("Matrix") || right.getName().equals("Matrix")) + {try { + logFile.write("\ngreaterRes: " + greaterRes);//"smallerHash: " + greaterHash.toString()); + logFile.flush(); + } + catch (IOException e) { + System.err.println("no LogFile");}} + */ + //Gleichungen der Form a <./=. Theta oder Theta <./=. a oder a <./=. b sind ok. + long greaterLen = greaterRes.stream().filter(delFun).count(); + if (greaterLen == 0) return 1; + else { + //try {logFile.write("0 left: "+ left + " right: " + right + " pairop: " + pairop);} catch (IOException ie) {} + return 0; + } + } + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/FunNType.java b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/FunNType.java new file mode 100644 index 00000000..f46ac918 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/FunNType.java @@ -0,0 +1,103 @@ +package de.dhbwstuttgart.typeinference.unify.model; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Set; + +import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; +import de.dhbwstuttgart.typeinference.unify.interfaces.UnifyTypeVisitor; + +/** + * A real function type in java. + * @author Florian Steurer + */ +public class FunNType extends UnifyType { + + public UnifyType accept(UnifyTypeVisitor visitor, T ht) { + return visitor.visit(this, ht); + } + + /** + * Creates a FunN-Type with the specified TypeParameters. + */ + protected FunNType(TypeParams p) { + super("Fun"+(p.size()-1)+"$$", p); + } + + /** + * Creates a new FunNType. + * @param tp The parameters of the type. + * @return A FunNType. + * @throws IllegalArgumentException is thrown when there are to few type parameters or there are wildcard-types. + */ + public static FunNType getFunNType(TypeParams tp) throws IllegalArgumentException { + if(tp.size() == 0) + throw new IllegalArgumentException("FunNTypes need at least one type parameter"); + for(UnifyType t : tp) + if(t instanceof WildcardType) + throw new IllegalArgumentException("Invalid TypeParams for a FunNType: " + tp); + return new FunNType(tp); + } + + /** + * Returns the degree of the function type, e.g. 2 for FunN. + */ + public int getN() { + return typeParams.size()-1; + } + + @Override + public UnifyType setTypeParams(TypeParams newTp) { + if(newTp.hashCode() == typeParams.hashCode() && newTp.equals(typeParams)) + return this; + return getFunNType(newTp); + } + + @Override + Set smArg(IFiniteClosure fc, Set fBounded) { + return fc.smArg(this, fBounded); + } + + @Override + Set grArg(IFiniteClosure fc, Set fBounded) { + return fc.grArg(this, fBounded); + } + + @Override + UnifyType apply(Unifier unif) { + // TODO this bypasses the validation of the type parameters. + // Wildcard types can be unified into FunNTypes. + TypeParams newParams = typeParams.apply(unif); + if(newParams.hashCode() == typeParams.hashCode() && newParams.equals(typeParams)) + return this; + + return new FunNType(newParams); + } + + @Override + public Boolean wrongWildcard() { + return (new ArrayList(Arrays.asList(getTypeParams() + .get())).stream().filter(x -> (x instanceof WildcardType)).findFirst().isPresent()); + } + + @Override + public int hashCode() { + return 181 + typeParams.hashCode(); + } + + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof FunNType)) + return false; + + if(obj.hashCode() != this.hashCode()) + return false; + + FunNType other = (FunNType) obj; + + return other.getTypeParams().equals(typeParams); + } + +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/Node.java b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/Node.java new file mode 100644 index 00000000..031130cf --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/Node.java @@ -0,0 +1,118 @@ +package de.dhbwstuttgart.typeinference.unify.model; + +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * A node of a directed graph. + * @author Florian Steurer + * + * @param The type of the content of the node. + */ +class Node { + + /** + * The content of the node. + */ + private T content; + + /** + * The set of predecessors + */ + private HashSet> predecessors = new HashSet<>(); + + /** + * The set of descendants + */ + private HashSet> descendants = new HashSet<>(); + + /** + * Creates a node containing the specified content. + */ + public Node(T content) { + this.content = content; + } + + /** + * Adds a directed edge from this node to the descendant (this -> descendant) + */ + public void addDescendant(Node descendant) { + if(descendants.contains(descendant)) + return; + + descendants.add(descendant); + descendant.addPredecessor(this); + } + + /** + * Adds some directed edges from this node to the descendant (this -> descendant) + */ + public void addAllDescendant(Set> allDescendants) { + for(Node descendant: allDescendants) { + addDescendant(descendant); + } + } + + /** + * Adds a directed edge from the predecessor to this node (predecessor -> this) + */ + public void addPredecessor(Node predecessor) { + if(predecessors.contains(predecessor)) + return; + + predecessors.add(predecessor); + predecessor.addDescendant(this); + } + + /** + * Adds some directed edges from the predecessor to this node (predecessor -> this) + */ + public void addAllPredecessor(Set> allPredecessors) { + for(Node predecessor: allPredecessors) { + addPredecessor(predecessor); + } + } + + /** + * The content of this node. + */ + public T getContent() { + return content; + } + + /** + * Returns all predecessors (nodes that have a directed edge to this node) + */ + public Set> getPredecessors() { + return predecessors; + } + + /** + * Returns all descendants. All nodes M, where there is a edge from this node to the node M. + * @return + */ + public Set> getDescendants() { + return descendants; + } + + /** + * Retrieves the content of all descendants. + */ + public Set getContentOfDescendants() { + return descendants.stream().map(x -> x.getContent()).collect(Collectors.toSet()); + } + + /** + * Retrieves the content of all predecessors. + */ + public Set getContentOfPredecessors() { + return predecessors.stream().map(x -> x.getContent()).collect(Collectors.toSet()); + } + + @Override + public String toString() { + return "Elem: Node(" + content.toString() + ")\nPrec: " + getContentOfPredecessors().toString() + + "\nDesc: " + getContentOfDescendants().toString() + "\n\n"; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/OrderingExtend.java b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/OrderingExtend.java new file mode 100644 index 00000000..8fa32343 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/OrderingExtend.java @@ -0,0 +1,89 @@ +package de.dhbwstuttgart.typeinference.unify.model; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +public abstract class OrderingExtend extends com.google.common.collect.Ordering { + + public List maxElements(Iterable iterable) { + ArrayList ret = new ArrayList<>(); + while (iterable.iterator().hasNext()) { + Set believe = new HashSet<>(); + + T max = max(iterable); + ret.add(max); + + Iterator it = iterable.iterator(); + while (it.hasNext()) { + T elem = it.next(); + if (!(compare(max, elem) == 1) && !max.equals(elem)) { + believe.add(elem); + } + } + iterable = believe; + } + return ret; + } + + public List minElements(Iterable iterable) { + ArrayList ret = new ArrayList<>(); + while (iterable.iterator().hasNext()) { + Set believe = new HashSet<>(); + + T min = min(iterable); + ret.add(min); + + Iterator it = iterable.iterator(); + while (it.hasNext()) { + T elem = it.next(); + if (!(compare(min, elem) == -1) && !min.equals(elem)) { + believe.add(elem); + } + } + iterable = believe; + } + return ret; + } + + + public List smallerEqThan(T elem, Iterable iterable) { + List ret = smallerThan(elem, iterable); + ret.add(elem); + return ret; + + } + + public List smallerThan(T elem, Iterable iterable) { + ArrayList ret = new ArrayList<>(); + Iterator it = iterable.iterator(); + while (it.hasNext()) { + T itElem = it.next(); + if (!itElem.equals(elem) && compare(elem, itElem) == 1) { + ret.add(itElem); + } + } + return ret; + } + + public List greaterEqThan(T elem, Iterable iterable) { + List ret = greaterThan(elem, iterable); + ret.add(elem); + return ret; + + } + + public List greaterThan(T elem, Iterable iterable) { + ArrayList ret = new ArrayList<>(); + Iterator it = iterable.iterator(); + while (it.hasNext()) { + T itElem = it.next(); + if (!itElem.equals(elem) && (compare(elem, itElem) == -1)) { + ret.add(itElem); + } + } + return ret; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/OrderingUnifyPair.java b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/OrderingUnifyPair.java new file mode 100644 index 00000000..ce2fbd21 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/OrderingUnifyPair.java @@ -0,0 +1,448 @@ +package de.dhbwstuttgart.typeinference.unify.model; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import com.google.common.collect.Ordering; + +import de.dhbwstuttgart.typeinference.unify.Match; +import de.dhbwstuttgart.typeinference.unify.TypeUnifyTask; +import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; + + + +public class OrderingUnifyPair extends OrderingExtend> { + + protected IFiniteClosure fc; + + public OrderingUnifyPair(IFiniteClosure fc) { + this.fc = fc; + } + + /* + * vergleicht Paare (a =. Theta) und (a =. Theta') + * in dem compare(Theta, Theta') aufgerufen wird. + */ + public int compareEq (UnifyPair left, UnifyPair right) { + try { + //if (left.getRhsType() instanceof WildcardType || right.getRhsType() instanceof WildcardType) {//PL 2019-01-12 ausgetauscht + if (((PlaceholderType)left.getLhsType()).isInnerType() && ((PlaceholderType)right.getLhsType()).isInnerType()) { + return fc.compare(left.getRhsType(), right.getRhsType(), PairOperator.SMALLERDOTWC); + } + else { + return fc.compare(left.getRhsType(), right.getRhsType(), PairOperator.SMALLERDOT); + }} + catch (ClassCastException e) { + try { + ((FiniteClosure)fc).logFile.write("ClassCastException: " + left.toString() + " " + left.getGroundBasePair() + "\n\n"); + ((FiniteClosure)fc).logFile.flush(); + } + catch (IOException ie) { + } + return -99; + } + } + + /* + public int compareEq (UnifyPair left, UnifyPair right) { + if (left == null || right == null) + System.out.println("Fehler"); + if (left.getLhsType() instanceof PlaceholderType) { + return fc.compare(left.getRhsType(), right.getRhsType(), left.getPairOp()); + } + else { + return fc.compare(left.getLhsType(), right.getLhsType(), left.getPairOp()); + } + } + */ + + public Pair> compare (UnifyType left, UnifyType right) { + UnifyPair up; + if (left instanceof WildcardType || right instanceof WildcardType) { + up = new UnifyPair(left, right, PairOperator.SMALLERDOTWC); + if (((left instanceof ExtendsType) + && (((ExtendsType)left).getExtendedType().getName().equals("java.util.Vector")) + && (((ReferenceType)((ExtendsType)left).getExtendedType()).getTypeParams().iterator().next() instanceof ExtendsType)) || + ((right instanceof ExtendsType) + && (((ExtendsType)right).getExtendedType().getName().equals("java.util.Vector")) + && (((ReferenceType)((ExtendsType)right).getExtendedType()).getTypeParams().iterator().next() instanceof ExtendsType))) + { + System.out.println(""); + } + if (((right instanceof SuperType) && (((SuperType)right).getSuperedType().getName().equals("java.lang.Object"))) + ||((left instanceof SuperType) && (((SuperType)left).getSuperedType().getName().equals("java.lang.Object")))) +{ + System.out.println(""); + } + } + else { + up = new UnifyPair(left, right, PairOperator.SMALLERDOT); + } + TypeUnifyTask unifyTask = new TypeUnifyTask(); + HashSet hs = new HashSet<>(); + hs.add(up); + Set smallerRes = unifyTask.applyTypeUnificationRules(hs, fc); + long smallerLen = smallerRes.stream().filter(x -> !(x.getLhsType() instanceof PlaceholderType && x.getRhsType() instanceof PlaceholderType)).count(); + if (smallerLen == 0) return new Pair<>(-1, smallerRes); + else { + if (left instanceof WildcardType || right instanceof WildcardType) { + up = new UnifyPair(right, left, PairOperator.SMALLERDOTWC); + if (((left instanceof ExtendsType) + && (((ExtendsType)left).getExtendedType().getName().equals("java.util.Vector")) + && (((ReferenceType)((ExtendsType)left).getExtendedType()).getTypeParams().iterator().next() instanceof ExtendsType)) || + ((right instanceof ExtendsType) + && (((ExtendsType)right).getExtendedType().getName().equals("java.util.Vector")) + && (((ReferenceType)((ExtendsType)right).getExtendedType()).getTypeParams().iterator().next() instanceof ExtendsType))) + { + System.out.println(""); + } + if (right instanceof SuperType) + { + System.out.println(""); + } + } + else { + up = new UnifyPair(right, left, PairOperator.SMALLERDOT); + } + //TypeUnifyTask unifyTask = new TypeUnifyTask(); + hs = new HashSet<>(); + hs.add(up); + Set greaterRes = unifyTask.applyTypeUnificationRules(hs, fc); + long greaterLen = greaterRes.stream().filter(x -> !(x.getLhsType() instanceof PlaceholderType && x.getRhsType() instanceof PlaceholderType)).count(); + if (greaterLen == 0) return new Pair<>(1, greaterRes); + else return new Pair<>(0, new HashSet<>()); + } + } + + /* TODO muss noch verifiziert werden PL 2018-03-21 + * (non-Javadoc) + * fuehrt zu Fehlern bei Arrays.sort (contract nicht erfuellt) + * @see com.google.common.collect.Ordering#compare(java.lang.Object, java.lang.Object) + */ + public int compare (Set left, Set right) { + /* + //pairop = PairOperator.SMALLERDOTWC; + List al = new ArrayList<>(); + PlaceholderType xx = PlaceholderType.freshPlaceholder(); + al.add(xx); + UnifyType t1 = new ExtendsType(new ReferenceType("Vector", new TypeParams(al))); + + //PlaceholderType yy =new PlaceholderType("yy"); + List alr = new ArrayList<>(); + UnifyType exx = new ExtendsType(xx); + alr.add(exx); + UnifyType t2 = new ExtendsType(new ReferenceType("Vector", new TypeParams(alr))); + + PlaceholderType a = PlaceholderType.freshPlaceholder(); + a.setInnerType(true); + UnifyPair p1 = new UnifyPair(a, t1, PairOperator.SMALLERDOTWC); + PlaceholderType b = PlaceholderType.freshPlaceholder(); + b.setInnerType(true); + UnifyPair p2 = new UnifyPair(b, t2, PairOperator.SMALLERDOTWC); + + List al3 = new ArrayList<>(); + al3.add(a); + + List al4 = new ArrayList<>(); + al4.add(b); + + UnifyPair p3 = new UnifyPair(new PlaceholderType("c"), new ReferenceType("Vector", new TypeParams(al3)), PairOperator.EQUALSDOT); + UnifyPair p4 = new UnifyPair(new PlaceholderType("c"), new ReferenceType("Vector", new TypeParams(al4)), PairOperator.EQUALSDOT); + + right = new HashSet<>(); + right.add(p1); + right.add(p3); + left = new HashSet<>(); + left.add(p2); + left.add(p4); + */ + + + Set lefteq = left.stream() + .filter(x -> (x.getLhsType() instanceof PlaceholderType && x.getPairOp() == PairOperator.EQUALSDOT)) + .collect(Collectors.toCollection(HashSet::new)); + Set righteq = right.stream() + .filter(x -> (x.getLhsType() instanceof PlaceholderType && x.getPairOp() == PairOperator.EQUALSDOT)) + .collect(Collectors.toCollection(HashSet::new)); + Set leftle = left.stream() + .filter(x -> ((x.getLhsType() instanceof PlaceholderType || x.getRhsType() instanceof PlaceholderType) + && x.getPairOp() == PairOperator.SMALLERDOT)) + .collect(Collectors.toCollection(HashSet::new)); + Set rightle = right.stream() + .filter(x -> ((x.getLhsType() instanceof PlaceholderType || x.getRhsType() instanceof PlaceholderType) + && x.getPairOp() == PairOperator.SMALLERDOT)) + .collect(Collectors.toCollection(HashSet::new)); + Set leftlewc = left.stream() + .filter(x -> ((x.getLhsType() instanceof PlaceholderType || x.getRhsType() instanceof PlaceholderType) + && x.getPairOp() == PairOperator.SMALLERDOTWC)) + .collect(Collectors.toCollection(HashSet::new)); + Set rightlewc = right.stream() + .filter(x -> ((x.getLhsType() instanceof PlaceholderType || x.getRhsType() instanceof PlaceholderType) + && x.getPairOp() == PairOperator.SMALLERDOTWC)) + .collect(Collectors.toCollection(HashSet::new)); + //System.out.println(left.toString()); + //Fall 2 + //if (lefteq.iterator().next().getLhsType().getName().equals("AJO")) { + // System.out.print(""); + //} + + //ODER-CONSTRAINT + Set leftBase = left.stream().map(x -> x.getGroundBasePair()).collect(Collectors.toCollection(HashSet::new)); + Set rightBase = right.stream().map(x -> x.getGroundBasePair()).collect(Collectors.toCollection(HashSet::new)); + + Set lefteqOder = left.stream() + .filter(x -> { UnifyPair y = x.getGroundBasePair(); + /*try { + ((FiniteClosure)fc).logFile.write("leftBase: " + leftBase.toString() +"\n"); + ((FiniteClosure)fc).logFile.write("rightBase: " + rightBase.toString() +"\n\n"); + ((FiniteClosure)fc).logFile.write("left: " + left.toString() +"\n"); + ((FiniteClosure)fc).logFile.write("right: " + right.toString() +"\n\n"); + ((FiniteClosure)fc).logFile.write("y: " + y.toString() +"\n"); + ((FiniteClosure)fc).logFile.write("y.getLhsType() : " + y.getLhsType() .toString() +"\n\n"); + ((FiniteClosure)fc).logFile.write("y.getRhsType(): " + y.getRhsType().toString() +"\n"); + ((FiniteClosure)fc).logFile.write("x.getPairOp(): " + x.getPairOp().toString() +"\n\n"); + } + catch (IOException ie) { + } */ + return (y.getLhsType() instanceof PlaceholderType && + !(y.getRhsType() instanceof PlaceholderType) && + x.getPairOp() == PairOperator.EQUALSDOT);}) + .collect(Collectors.toCollection(HashSet::new)); + Set righteqOder = right.stream() + .filter(x -> { UnifyPair y = x.getGroundBasePair(); + return (y.getLhsType() instanceof PlaceholderType && + !(y.getRhsType() instanceof PlaceholderType) && + x.getPairOp() == PairOperator.EQUALSDOT);}) + .collect(Collectors.toCollection(HashSet::new)); + Set lefteqRet = left.stream() + .filter(x -> { UnifyPair y = x.getGroundBasePair(); + return (y.getRhsType() instanceof PlaceholderType && + x.getPairOp() == PairOperator.EQUALSDOT);}) + .collect(Collectors.toCollection(HashSet::new)); + Set righteqRet = right.stream() + .filter(x -> { UnifyPair y = x.getGroundBasePair(); + return (y.getRhsType() instanceof PlaceholderType && + x.getPairOp() == PairOperator.EQUALSDOT);}) + .collect(Collectors.toCollection(HashSet::new)); + Set leftleOder = left.stream() + .filter(x -> (x.getPairOp() == PairOperator.SMALLERDOT)) + .collect(Collectors.toCollection(HashSet::new)); + Set rightleOder = right.stream() + .filter(x -> (x.getPairOp() == PairOperator.SMALLERDOT)) + .collect(Collectors.toCollection(HashSet::new)); + + /* + synchronized(this) { + try { + ((FiniteClosure)fc).logFile.write("leftBase: " + leftBase.toString() +"\n"); + ((FiniteClosure)fc).logFile.write("rightBase: " + rightBase.toString() +"\n\n"); + ((FiniteClosure)fc).logFile.write("left: " + left.toString() +"\n"); + ((FiniteClosure)fc).logFile.write("right: " + right.toString() +"\n\n"); + ((FiniteClosure)fc).logFile.write("lefteqOder: " + lefteqOder.toString() +"\n"); + ((FiniteClosure)fc).logFile.write("righteqOder: " + righteqOder.toString() +"\n\n"); + ((FiniteClosure)fc).logFile.write("lefteqRet: " + lefteqRet.toString() +"\n"); + ((FiniteClosure)fc).logFile.write("righteqRet: " + righteqRet.toString() +"\n\n"); + ((FiniteClosure)fc).logFile.write("leftleOder: " + leftleOder.toString() +"\n"); + ((FiniteClosure)fc).logFile.write("rightleOder: " + rightleOder.toString() +"\n\n"); + ((FiniteClosure)fc).logFile.flush(); + } + catch (IOException ie) { + } + } + */ + + + Integer compareEq; + if (lefteqOder.size() == 1 && righteqOder.size() == 1 && lefteqRet.size() == 1 && righteqRet.size() == 1) { + Match m = new Match(); + if ((compareEq = compareEq(lefteqOder.iterator().next().getGroundBasePair(), righteqOder.iterator().next().getGroundBasePair())) == -1) { + ArrayList matchList = + rightleOder.stream().map(x -> { + UnifyPair leftElem = leftleOder.stream() + .filter(y -> y.getGroundBasePair().getLhsType().equals(x.getGroundBasePair().getLhsType())) + .findAny().get(); + return new UnifyPair(x.getRhsType(), leftElem.getRhsType(), PairOperator.EQUALSDOT);}) + .collect(Collectors.toCollection(ArrayList::new)); + if (m.match(matchList).isPresent()) { + //try { ((FiniteClosure)fc).logFile.write("result1: -1 \n\n"); } catch (IOException ie) {} + return -1; + } + else { + //try { ((FiniteClosure)fc).logFile.write("result1: 0 \n\n"); } catch (IOException ie) {} + return 0; + } + } else if (compareEq == 1) { + ArrayList matchList = + leftleOder.stream().map(x -> { + UnifyPair rightElem = rightleOder.stream() + .filter(y -> + y.getGroundBasePair().getLhsType().equals(x.getGroundBasePair().getLhsType())) + .findAny().get(); + return new UnifyPair(x.getRhsType(), rightElem.getRhsType(), PairOperator.EQUALSDOT);}) + .collect(Collectors.toCollection(ArrayList::new)); + if (m.match(matchList).isPresent()) { + //try { ((FiniteClosure)fc).logFile.write("result2: 1 \n\n"); } catch (IOException ie) {} + return 1; + } + else { + //try { ((FiniteClosure)fc).logFile.write("result2: 0 \n\n"); } catch (IOException ie) {} + return 0; + } + } else { + /* + synchronized(this) { + try { + ((FiniteClosure)fc).logFile.write("leftBase: " + leftBase.toString() +"\n"); + ((FiniteClosure)fc).logFile.write("rightBase: " + rightBase.toString() +"\n\n"); + ((FiniteClosure)fc).logFile.write("left: " + left.toString() +"\n"); + ((FiniteClosure)fc).logFile.write("right: " + right.toString() +"\n\n"); + ((FiniteClosure)fc).logFile.write("lefteqOder: " + lefteqOder.toString() +"\n"); + ((FiniteClosure)fc).logFile.write("righteqOder: " + righteqOder.toString() +"\n\n"); + ((FiniteClosure)fc).logFile.write("lefteqRet: " + lefteqRet.toString() +"\n"); + ((FiniteClosure)fc).logFile.write("righteqRet: " + righteqRet.toString() +"\n\n"); + ((FiniteClosure)fc).logFile.write("leftleOder: " + leftleOder.toString() +"\n"); + ((FiniteClosure)fc).logFile.write("rightleOder: " + rightleOder.toString() +"\n\n"); + ((FiniteClosure)fc).logFile.write("result3: 0 \n\n"); + ((FiniteClosure)fc).logFile.flush(); + } + catch (IOException ie) { + } + } + */ + return 0; + } + } + + + if (lefteq.size() == 1 && lefteq.iterator().next().getRhsType() instanceof ExtendsType && leftle.size() == 1 && righteq.size() == 0 && rightle.size() == 1) { + return 1; + } + //Fall 2 + if (lefteq.size() == 0 && leftle.size() == 1 && righteq.size() == 1 && righteq.iterator().next().getRhsType() instanceof ExtendsType && rightle.size() == 1) { + return -1; + } + //Fall 3 + if (lefteq.size() == 1 && lefteq.iterator().next().getRhsType() instanceof SuperType && leftle.size() == 1 && righteq.size() == 0 && rightle.size() == 1) { + return -1; + } + //Fall 3 + if (lefteq.size() == 0 && leftle.size() == 1 && righteq.size() == 1 && righteq.iterator().next().getRhsType() instanceof SuperType && rightle.size() == 1) { + return 1; + } + //Fall 5 + if (lefteq.size() == 1 && leftle.size() == 0 && righteq.size() == 1 && rightle.size() == 1) { + return -1; + } + //Fall 5 + if (lefteq.size() == 1 && leftle.size() == 1 && righteq.size() == 1 && rightle.size() == 0) { + return 1; + } + //Fall 5 + if (lefteq.size() == 1 && leftle.size() == 1 && righteq.size() == 1 && rightle.size() == 1) { + return 0; + } + // Nur Paare a =. Theta + if (leftle.size() == 0 && rightle.size() == 0 && leftlewc.size() == 0 && rightlewc.size() ==0) { + Stream lseq = lefteq.stream(); //left.filter(x -> (x.getLhsType() instanceof PlaceholderType && x.getPairOp() == PairOperator.EQUALSDOT)); + Stream rseq = righteq.stream(); //right.filter(x -> (x.getLhsType() instanceof PlaceholderType && x.getPairOp() == PairOperator.EQUALSDOT)); + BinaryOperator> combiner = (x,y) -> { x.putAll(y); return x;}; + HashMap hm = rseq.reduce(new HashMap(), (x, y)-> { x.put(y.getLhsType(),y); return x; }, combiner); + lseq = lseq.filter(x -> !(hm.get(x.getLhsType()) == null));//NOCHMALS UEBERPRUEFEN!!!! + lseq = lseq.filter(x -> !x.equals(hm.get(x.getLhsType()))); //Elemente die gleich sind muessen nicht verglichen werden + Optional si = lseq.map(x -> compareEq(x, hm.get(x.getLhsType()))).reduce((x,y)-> { if (x == y) return x; else return 0; } ); + if (!si.isPresent()) return 0; + else return si.get(); + } + //Fall 1 und 4 + if (lefteq.size() >= 1 && righteq.size() >= 1 && (leftlewc.size() > 0 || rightlewc.size() > 0)) { + if (lefteq.iterator().next().getLhsType().getName().equals("D")) + System.out.print(""); + //Set varsleft = lefteq.stream().map(x -> (PlaceholderType)x.getLhsType()).collect(Collectors.toCollection(HashSet::new)); + //Set varsright = righteq.stream().map(x -> (PlaceholderType)x.getLhsType()).collect(Collectors.toCollection(HashSet::new)); + //filtern des Paares a = Theta, das durch a <. Thata' generiert wurde (nur im Fall 1 relevant) andere Substitutioen werden rausgefiltert + lefteq.removeIf(x -> (x.getBasePair()!=null) && !(x.getLhsType().getName().equals(x.getBasePair().getLhsType().getName()) + ||x.getLhsType().getName().equals(x.getBasePair().getRhsType().getName())));//removeIf(x -> !varsright.contains(x.getLhsType())); + righteq.removeIf(x -> (x.getBasePair()!=null) && !(x.getLhsType().getName().equals(x.getBasePair().getLhsType().getName()) + ||x.getLhsType().getName().equals(x.getBasePair().getRhsType().getName())));//.removeIf(x -> !varsleft.contains(x.getLhsType())); + UnifyPair lseq = lefteq.iterator().next(); + UnifyPair rseq = righteq.iterator().next(); + if (lseq.getRhsType().getName().equals("Object")) { + if (rseq.getRhsType().getName().equals("Object")) return 0; + else return 1; + } + else { + if (rseq.getRhsType().getName().equals("Object")) return -1; + } + if (leftlewc.size() == rightlewc.size()) { + //TODO: Hier wird bei Wildcards nicht das richtige compare aufgerufen PL 18-04-20 + Pair> int_Unifier = compare(lseq.getRhsType(), rseq.getRhsType()); + Unifier uni = new Unifier(); + int_Unifier.getValue().get().forEach(x -> uni.add((PlaceholderType) x.getLhsType(), x.getRhsType())); + if (!lseq.getRhsType().getName().equals(rseq.getRhsType().getName()) + || leftlewc.size() == 0 || rightlewc.size() == 0) return int_Unifier.getKey(); + else { + Set lsleuni = leftlewc.stream().map(x -> uni.apply(x)).collect(Collectors.toCollection(HashSet::new)); + Set rsleuni = rightlewc.stream().map(x -> uni.apply(x)).collect(Collectors.toCollection(HashSet::new)); + BinaryOperator> combiner = (x,y) -> { x.putAll(y); return x;}; + + HashMap hm; + Optional si; + //1. Fall + if (leftlewc.iterator().next().getLhsType() instanceof PlaceholderType) { + hm = rsleuni.stream().reduce(new HashMap(), (x, y)-> { x.put(y.getLhsType(),y); return x; }, combiner); + Stream lslewcstr = lsleuni.stream().filter(x -> !(hm.get(x.getLhsType()) == null)); + si = lslewcstr.map(x -> fc.compare(x.getRhsType(), hm.get(x.getLhsType()).getRhsType(), PairOperator.SMALLERDOTWC)).reduce((x,y)-> { if (x == y) return x; else return 0; } ); + } + //4. Fall + else { + hm = rsleuni.stream().reduce(new HashMap(), (x, y)-> { x.put(y.getRhsType(),y); return x; }, combiner); + Stream lslewcstr = lsleuni.stream().filter(x -> !(hm.get(x.getRhsType()) == null)); + si = lslewcstr.map(x -> fc.compare(x.getLhsType(), hm.get(x.getRhsType()).getLhsType(), PairOperator.SMALLERDOTWC)).reduce((x,y)-> { if (x == y) return x; else return 0; } ); + } + if (!si.isPresent()) return 0; + else return si.get(); + } + } else { + if (leftlewc.size() > 0) { + Set subst; + subst = leftlewc.stream().map(x -> { + if (x.getLhsType() instanceof PlaceholderType) { + return new UnifyPair(x.getLhsType(), x.getRhsType(), PairOperator.EQUALSDOT); + } + else { + return new UnifyPair(x.getRhsType(), x.getLhsType(), PairOperator.EQUALSDOT); + }}).collect(Collectors.toCollection(HashSet::new)); + Unifier uni = new Unifier(); + lseq = uni.apply(lseq); + } + else { + Set subst; + subst = rightlewc.stream().map(x -> { + if (x.getLhsType() instanceof PlaceholderType) { + return new UnifyPair(x.getLhsType(), x.getRhsType(), PairOperator.EQUALSDOT); + } + else { + return new UnifyPair(x.getRhsType(), x.getLhsType(), PairOperator.EQUALSDOT); + }}).collect(Collectors.toCollection(HashSet::new)); + Unifier uni = new Unifier(); + subst.stream().forEach(x -> uni.add((PlaceholderType) x.getLhsType(), x.getRhsType())); + rseq = uni.apply(rseq); + } + return compareEq(lseq, rseq); + } + } + return 0; + } +} + diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/Pair.java b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/Pair.java new file mode 100644 index 00000000..de05c97d --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/Pair.java @@ -0,0 +1,25 @@ +package de.dhbwstuttgart.typeinference.unify.model; + +import java.util.Optional; + +public class Pair { + private final T key; + private final T1 value; + + public Pair(T a, T1 b) { + this.value = b; + this.key = a; + } + + public Optional getValue() { + return Optional.of(value); + } + + public T getKey() { + return key; + } + + public String toString() { + return "(" + key.toString() + "," + "," + value.toString() + ")\n"; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/PairOperator.java b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/PairOperator.java new file mode 100644 index 00000000..ea323c79 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/PairOperator.java @@ -0,0 +1,49 @@ +package de.dhbwstuttgart.typeinference.unify.model; + +/** + * Operators of pairs of the unification. + * @author Florian Steurer + */ +public enum PairOperator { + /** + * The smaller operator (T < P) is used to express a subtyping relation between + * T and P for example in the finite closure. It is necessarily true. + */ + SMALLER, + + /** + * The smallerdot operator (T <. P) is used to express a subtyping relation between + * of T and P in a CONSTRAINT during the unification. It is not necessarily true. + */ + SMALLERDOT, + + /** + * The smallernedot operator for arguments (T / ... with the Supertype Number + */ + SMALLERNEQDOT, + + /** + * The smallerdot operator for arguments (T <.? P) is used to express that + * T is an element of smArg(P) (or P is an element of grArg(T)) in a CONSTRAINT + * during the unification. It is not necessarily true. + */ + SMALLERDOTWC, + + /** + * The equalsdot operator (T =. P) is used to express that two types during the unification + * should be equal. It is not necessarily true. + */ + EQUALSDOT; + + @Override + public String toString() { + switch (this) { + case SMALLER: return "<"; + case SMALLERDOT: return "<."; + case SMALLERNEQDOT: return " EXISTING_PLACEHOLDERS = new ArrayList(); + + /** + * Prefix of auto-generated placeholder names. + */ + protected static String nextName = "gen_"; + + /** + * Random number generator used to generate fresh placeholder name. + */ + protected static Random rnd = new Random(43558747548978L); + + /** + * True if this object was auto-generated, false if this object was user-generated. + */ + private final boolean IsGenerated; + + + /** + * isWildcardable gibt an, ob ein Wildcardtyp dem PlaceholderType zugeordnet werden darf + */ + private boolean wildcardable = true; + + /** + * is innerType gibt an, ob der Type des PlaceholderType innerhalb eines Typkonstruktorsverwendet wird + */ + private boolean innerType = false; + + /** + * variance shows the variance of the pair + * -1: contravariant + * 1 covariant + * 0 invariant + * PL 2018-03-21 + */ + private int variance = 0; + + /** + * Creates a new placeholder type with the specified name. + */ + public PlaceholderType(String name) { + super(name, new TypeParams()); + EXISTING_PLACEHOLDERS.add(name); // Add to list of existing placeholder names + IsGenerated = false; // This type is user generated + } + + /** + * Creates a new placeholdertype + * @param isGenerated true if this placeholder is auto-generated, false if it is user-generated. + */ + protected PlaceholderType(String name, boolean isGenerated) { + super(name, new TypeParams()); + EXISTING_PLACEHOLDERS.add(name); // Add to list of existing placeholder names + IsGenerated = isGenerated; + } + + public UnifyType accept(UnifyTypeVisitor visitor, T ht) { + return visitor.visit(this, ht); + } + + /** + * Creates a fresh placeholder type with a name that does so far not exist. + * A user could later instantiate a type using the same name that is equivalent to this type. + * @return A fresh placeholder type. + */ + public synchronized static PlaceholderType freshPlaceholder() { + String name = nextName + (char) (rnd.nextInt(22) + 97); // Returns random char between 'a' and 'z' + // Add random chars while the name is in use. + while(EXISTING_PLACEHOLDERS.contains(name)) { + name += (char) (rnd.nextInt(22) + 97); // Returns random char between 'a' and 'z' + } + return new PlaceholderType(name, true); + } + + + /** + * True if this placeholder is auto-generated, false if it is user-generated. + */ + public boolean isGenerated() { + return IsGenerated; + } + + public void setVariance(int v) { + variance = v; + } + + public int getVariance() { + return variance; + } + + public void reversVariance() { + if (variance == 1) { + setVariance(-1); + } else { + if (variance == -1) { + setVariance(1); + }} + } + + public Boolean isWildcardable() { + return wildcardable; + } + public void disableWildcardtable() { + wildcardable = false; + } + + public void enableWildcardtable() { + wildcardable = true; + } + + public void setWildcardtable(Boolean wildcardable) { + this.wildcardable = wildcardable; + } + + public Boolean isInnerType() { + return innerType; + } + + public void setInnerType(Boolean innerType) { + this.innerType = innerType; + } + + @Override + Set smArg(IFiniteClosure fc, Set fBounded) { + return fc.smArg(this, fBounded); + } + + @Override + Set grArg(IFiniteClosure fc, Set fBounded) { + return fc.grArg(this, fBounded); + } + + @Override + public UnifyType setTypeParams(TypeParams newTp) { + return this; // Placeholders never have params. + } + + @Override + public int hashCode() { + return typeName.hashCode(); + } + + @Override + UnifyType apply(Unifier unif) { + if(unif.hasSubstitute(this)) { + UnifyType ret = unif.getSubstitute(this); + //PL 2018-05-17 Auskommentierung muesste korrekt sein, + //bereits in JavaTXComplier Variancen gesetzt werden. + //ret.accept(new distributeVariance(), this.getVariance()); + return ret; + } + return this; + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof PlaceholderType)) + return false; + + return ((PlaceholderType) obj).getName().equals(typeName); + } + + + @Override + public Collection getInvolvedPlaceholderTypes() { + ArrayList ret = new ArrayList<>(); + ret.add(this); + return ret; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/ReferenceType.java b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/ReferenceType.java new file mode 100644 index 00000000..62465b1a --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/ReferenceType.java @@ -0,0 +1,100 @@ +package de.dhbwstuttgart.typeinference.unify.model; + +import java.util.HashMap; +import java.util.Set; + +import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; +import de.dhbwstuttgart.typeinference.unify.interfaces.UnifyTypeVisitor; + +/** + * A reference type e.q. Integer or List. + * @author Florian Steurer + * + */ +public class ReferenceType extends UnifyType { + + /** + * The buffered hashCode + */ + private final int hashCode; + + /** + * gibt an, ob der ReferenceType eine generische Typvariable ist + */ + private final boolean genericTypeVar; + + + public UnifyType accept(UnifyTypeVisitor visitor, T ht) { + return visitor.visit(this, ht); + } + + public ReferenceType(String name, Boolean genericTypeVar) { + super(name, new TypeParams()); + hashCode = 31 + 17 * typeName.hashCode() + 17 * typeParams.hashCode(); + this.genericTypeVar = genericTypeVar; + } + + public ReferenceType(String name, UnifyType... params) { + super(name, new TypeParams(params)); + hashCode = 31 + 17 * typeName.hashCode() + 17 * typeParams.hashCode(); + genericTypeVar = false; + } + + public ReferenceType(String name, TypeParams params) { + super(name, params); + hashCode = 31 + 17 * typeName.hashCode() + 17 * typeParams.hashCode(); + genericTypeVar = false; + } + + public boolean isGenTypeVar () { + return genericTypeVar; + } + + @Override + Set smArg(IFiniteClosure fc, Set fBounded) { + return fc.smArg(this, fBounded); + } + + @Override + Set grArg(IFiniteClosure fc, Set fBounded) { + return fc.grArg(this, fBounded); + } + + @Override + UnifyType apply(Unifier unif) { + TypeParams newParams = typeParams.apply(unif); + + if(newParams.hashCode() == typeParams.hashCode() && newParams.equals(typeParams)) + return this; + + return new ReferenceType(typeName, newParams); + } + + @Override + public UnifyType setTypeParams(TypeParams newTp) { + if(newTp.hashCode() == typeParams.hashCode() && newTp.equals(typeParams)) + return this; // reduced the amount of objects created + return new ReferenceType(typeName, newTp); + } + + @Override + public int hashCode() { + return hashCode; + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof ReferenceType)) + return false; + + if(obj.hashCode() != this.hashCode()) + return false; + + ReferenceType other = (ReferenceType) obj; + + if(!other.getName().equals(typeName)) + return false; + + return other.getTypeParams().equals(typeParams); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/SuperType.java b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/SuperType.java new file mode 100644 index 00000000..50b8dcf7 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/SuperType.java @@ -0,0 +1,88 @@ +package de.dhbwstuttgart.typeinference.unify.model; + +import java.util.HashMap; +import java.util.Set; + +import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; +import de.dhbwstuttgart.typeinference.unify.interfaces.UnifyTypeVisitor; + +/** + * A super wildcard type e.g. ? super Integer. + * @author Florian Steurer + */ +public final class SuperType extends WildcardType { + + public UnifyType accept(UnifyTypeVisitor visitor, T ht) { + return visitor.visit(this, ht); + } + + /** + * Creates a new instance "? extends superedType" + * @param superedType The type that is supered e.g. Integer in "? super Integer" + */ + public SuperType(UnifyType superedType) { + super("? super " + superedType.getName(), superedType); + } + + /** + * The type that is supered e.g. Integer in "? super Integer" + */ + public UnifyType getSuperedType() { + return wildcardedType; + } + + @Override + public String toString() { + return "? super " + wildcardedType; + } + + /** + * Sets the type parameters of the wildcarded type and returns a new supertype that supers that type. + */ + @Override + public UnifyType setTypeParams(TypeParams newTp) { + UnifyType newType = wildcardedType.setTypeParams(newTp); + if(newType == wildcardedType) + return this; // Reduced the amount of objects created + return new SuperType(wildcardedType.setTypeParams(newTp)); + } + + @Override + Set smArg(IFiniteClosure fc, Set fBounded) { + return fc.smArg(this, fBounded); + } + + @Override + Set grArg(IFiniteClosure fc, Set fBounded) { + return fc.grArg(this, fBounded); + } + + @Override + UnifyType apply(Unifier unif) { + UnifyType newType = wildcardedType.apply(unif); + if(newType.hashCode() == wildcardedType.hashCode() && newType.equals(wildcardedType)) + return this; // Reduced the amount of objects created + return new SuperType(newType); + } + + @Override + public int hashCode() { + /* + * It is important that the prime that is added is different to the prime added in hashCode() of ExtendsType. + * Otherwise ? extends T and ? super T have the same hashCode() for every Type T. + */ + return wildcardedType.hashCode() + 3917; + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof SuperType)) + return false; + + if(obj.hashCode() != this.hashCode()) + return false; + + SuperType other = (SuperType) obj; + return other.getSuperedType().equals(wildcardedType); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/TypeParams.java b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/TypeParams.java new file mode 100644 index 00000000..f70cccb0 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/TypeParams.java @@ -0,0 +1,191 @@ +package de.dhbwstuttgart.typeinference.unify.model; + +import java.util.*; + + +/** + * The generic or non-generic parameters of a type e.g. for List + * @author Florian Steurer + */ +public final class TypeParams implements Iterable{ + /** + * The array which backs the type parameters. + */ + private final UnifyType[] typeParams; + + /** + * Hashcode calculation is expensive and must be cached. + */ + private final int hashCode; + + /** + * Creates a new set of type parameters. + * @param types The type parameters. + */ + public TypeParams(List types){ + typeParams = new UnifyType[types.size()]; + for(int i=0;i x instanceof PlaceholderType); + } + + /** + * Returns the number of the type parameters in this object. + * @return number of type parameters, always positive (including 0). + */ + public int size() { + return typeParams.length; + } + + /** + * Returns true if this object has size() of zero, false otherwise. + */ + public boolean empty() { + return typeParams.length == 0; + } + + /** + * Applies a unifier to every parameter in this object. + * @param unif The applied unifier. + * @return A new type parameter object, where the unifier was applied to every parameter. + */ + public TypeParams apply(Unifier unif) { + UnifyType[] newParams = new UnifyType[typeParams.length]; + + // If true, a type was modified and a new typeparams object has to be created. + // Otherwise it is enough to return this object, since it is immutable + // This reduced the needed TypeParams-Instances for the lambda14-Test from + // 130.000 to 30.000 without a decrease in speed. + boolean isNew = false; + + for(int i = 0; i < typeParams.length; i++) { + UnifyType newType = typeParams[i].apply(unif); + newParams[i] = newType; + if(!isNew && (newType.hashCode() != typeParams[i].hashCode() || !newType.equals(typeParams[i]))) + isNew = true; + } + + if(!isNew) + return this; + return new TypeParams(newParams); + } + + /** + * True if the PlaceholderType t is a parameter of this object, or if any parameter + * contains t (arbitrary depth of recursion), false otherwise. + */ + public boolean occurs(PlaceholderType t) { + for(UnifyType p : typeParams) + if(p instanceof PlaceholderType) {//PL 2018-01-31 dangeling else Problem { ... } eingefuegt. + if(p.equals(t)) + return true; + } + else { + if(p.getTypeParams().occurs(t)) + return true; } + return false; + } + + /** + * Returns the i-th parameter of this object. + */ + public UnifyType get(int i) { + return typeParams[i]; + } + + /** + * Returns the parameters of this object. + * PL 2018-03-17 + */ + public UnifyType[] get() { + return typeParams; + } + + /** + * Sets the the type t as the i-th parameter and returns a new object + * that equals this object, except for the i-th type. + */ + public TypeParams set(UnifyType t, int idx) { + // Reduce the creation of new objects for less memory + // Reduced the needed instances of TypeParams in the lambda14-Test from + // 150.000 to 130.000 + if(t.hashCode() == typeParams[idx].hashCode() && t.equals(typeParams[idx])) + return this; + UnifyType[] newparams = Arrays.copyOf(typeParams, typeParams.length); + newparams[idx] = t; + return new TypeParams(newparams); + } + + @Override + public Iterator iterator() { + return Arrays.stream(typeParams).iterator(); + } + + @Override + public int hashCode() { + return hashCode; + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof TypeParams)) + return false; + + if(obj.hashCode() != this.hashCode()) + return false; + + TypeParams other = (TypeParams) obj; + + if(other.size() != this.size()) + return false; + + for(int i = 0; i < this.size(); i++){ + //if(this.get(i) == null) + //System.out.print("s"); + } + for(int i = 0; i < this.size(); i++) + if(!(this.get(i).equals(other.get(i)))) + return false; + + return true; + } + + @Override + public String toString() { + String res = ""; + for(UnifyType t : typeParams) + res += t + ","; + return "<" + res.substring(0, res.length()-1) + ">"; + } + + public Collection getInvolvedPlaceholderTypes() { + ArrayList ret = new ArrayList<>(); + for(UnifyType t : typeParams){ + ret.addAll(t.getInvolvedPlaceholderTypes()); + } + return ret; + } +} + diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/Unifier.java b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/Unifier.java new file mode 100644 index 00000000..8cfac643 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/Unifier.java @@ -0,0 +1,189 @@ +package de.dhbwstuttgart.typeinference.unify.model; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map.Entry; +import java.util.Set; +import java.util.function.Function; + +/** + * A set of substitutions (s -> t) that is an applicable function to types and pairs. + * @author Florian Steurer + */ +public class Unifier implements Function, Iterable> { + + /** + * The set of substitutions that unify a type-term + */ + private HashMap substitutions = new HashMap<>(); + + /** + * Creates a new instance with a single substitution (source -> target). + * @param The type that is replaced + * @param The type that replaces + */ + public Unifier(PlaceholderType source, UnifyType target) { + substitutions.put(source, target); + } + + /** + * Identity function as an "unifier". + */ + protected Unifier() { + + } + + /** + * Creates an unifier that is the identity function (thus has no substitutions). + */ + public static Unifier identity() { + return new Unifier(); + } + + /** + * Adds a substitution to the unifier from (source -> target) + * @param The type that is replaced + * @param The type that replaces + */ + public void add(PlaceholderType source, UnifyType target) { + Unifier tempU = new Unifier(source, target); + // Every new substitution must be applied to previously added substitutions + // otherwise the unifier needs to be applied multiple times to unify two terms + for(PlaceholderType pt : substitutions.keySet()) + substitutions.put(pt, substitutions.get(pt).apply(tempU)); + substitutions.put(source, target); + } + + @Override + public UnifyType apply(UnifyType t) { + return t.apply(this); + } + + /** + * Applies the unifier to the two terms of the pair. + * @return A new pair where the left and right-hand side are applied + */ + public UnifyPair apply(UnifyPair p) { + UnifyType newLhs = this.apply(p.getLhsType()); + UnifyType newRhs = this.apply(p.getRhsType()); + return new UnifyPair(newLhs, newRhs, p.getPairOp()); + } + + /** + * Applies the unifier to the two terms of the pair. + * works only for single subsitution + * @return A new pair where the left and right-hand side are applied + */ + public UnifyPair apply(UnifyPair thisAsPair, UnifyPair p) { + UnifyType newLhs = this.apply(p.getLhsType()); + UnifyType newRhs = this.apply(p.getRhsType()); + //Varianceweitergabe wird nicht benoetigt. + //PlaceholderType lhsph = (PlaceholderType)thisAsPair.getLhsType(); + //if (lhsph.getVariance() != 0) { + // if (p.getLhsType().equals(lhsph)) { + // if (p.getRhsType() instanceof PlaceholderType) { + // ((PlaceholderType)p.getRhsType()).setVariance(lhsph.getVariance()); + // } + // } + // if (p.getRhsType().equals(lhsph)) { + // if (p.getLhsType() instanceof PlaceholderType) { + // ((PlaceholderType)p.getLhsType()).setVariance(lhsph.getVariance()); + // } + // } + //} + if (!(p.getLhsType().equals(newLhs)) || !(p.getRhsType().equals(newRhs))) {//Die Anwendung von this hat was veraendert PL 2018-04-01 + Set suniUnifyPair = new HashSet<>(); + suniUnifyPair.addAll(thisAsPair.getAllSubstitutions()); + suniUnifyPair.add(thisAsPair); + if (p.getLhsType() instanceof PlaceholderType //&& newLhs instanceof PlaceholderType entfernt PL 2018-04-13 + && p.getPairOp() == PairOperator.EQUALSDOT) { + suniUnifyPair.add(p); //p koennte auch subsitution sein + } + return new UnifyPair(newLhs, newRhs, p.getPairOp(), suniUnifyPair, p); + } + return new UnifyPair(newLhs, newRhs, p.getPairOp(), p.getSubstitution(), p.getBasePair(), p.getfBounded()); + } + + /** + * Applies the unifier to the left terms of the pair. + * @return A new pair where the left and right-hand side are applied + */ + public UnifyPair applyleft(UnifyPair p) { + return new UnifyPair(this.apply(p.getLhsType()), p.getRhsType(), p.getPairOp()); + } + + /** + * True if the typevariable t will be substituted if the unifier is applied. + * false otherwise. + */ + public boolean hasSubstitute(PlaceholderType t) { + return substitutions.containsKey(t); + } + + /** + * Returns the type that will replace the typevariable t if the unifier is applied. + */ + public UnifyType getSubstitute(PlaceholderType t) { + return substitutions.get(t); + } + + /** + * The number of substitutions in the unifier. If zero, this is the identity function. + */ + public int size() { + return substitutions.size(); + } + + /** + * Garantuees that if there is a substitutions (a -> b) in this unifier, + * a is not an element of the targetParams. Substitutions that do not + * satisfy this condition, are swapped. + */ + public void swapPlaceholderSubstitutions(Iterable targetParams) { + for(UnifyType tph : targetParams) { + if(!(tph instanceof PlaceholderType)) + continue; + // Swap a substitutions (a -> b) if a is an element of the target params. + if(substitutions.containsKey(tph)) { + if((substitutions.get(tph) instanceof PlaceholderType)) { + PlaceholderType newLhs = (PlaceholderType) substitutions.get(tph); + substitutions.remove(tph); + substitutions.put(newLhs, tph); + } + } + } + } + + public void swapPlaceholderSubstitutionsReverse(Iterable sourceParams) { + for(UnifyType tph : sourceParams) { + if(!(tph instanceof PlaceholderType)) + continue; + if(substitutions.containsValue(tph)) { + UnifyType key = substitutions.values().stream().filter(x -> x.equals(tph)).findAny().get(); + if(key instanceof PlaceholderType) { + PlaceholderType newLhs = (PlaceholderType) tph; + substitutions.remove(key); + substitutions.put(newLhs, key); + } + } + } + } + + @Override + public String toString() { + String result = "{ "; + for(Entry entry : substitutions.entrySet()) + result += "(" + entry.getKey() + " -> " + entry.getValue() + "), "; + if(!substitutions.isEmpty()) + result = result.substring(0, result.length()-2); + result += " }"; + return result; + } + + @Override + public Iterator> iterator() { + return substitutions.entrySet().iterator(); + } +} + diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/UnifyPair.java b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/UnifyPair.java new file mode 100644 index 00000000..497fd811 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/UnifyPair.java @@ -0,0 +1,247 @@ +package de.dhbwstuttgart.typeinference.unify.model; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.Set; + + +/** + * A pair which contains two types and an operator, e.q. (Integer <. a). + * @author Florian Steurer + */ +public class UnifyPair { + + /** + * The type on the left hand side of the pair. + */ + private final UnifyType lhs; + + /** + * The type on the right hand side of the pair. + */ + private final UnifyType rhs; + + /** + * The operator that determines the relation between the left and right hand side type. + */ + private PairOperator pairOp; + + private boolean undefinedPair = false; + + /** + * Unifier/substitute that generated this pair + * PL 2018-03-15 + */ + private Set substitution; + + /** + * Base on which the the unifier is applied + * PL 2018-03-15 + */ + private UnifyPair basePair; + + /** + * For pairs a <. Theta generated in the rule reduceTphSup + * to store the f-Bouned Elements to avoid endless recursion + * PL 2018-03-15 + */ + private Set fBounded = new HashSet<>(); + + private final int hashCode; + + /** + * Creates a new instance of the pair. + * @param lhs The type on the left hand side of the pair. + * @param rhs The type on the right hand side of the pair. + * @param op The operator that determines the relation between the left and right hand side type. + */ + public UnifyPair(UnifyType lhs, UnifyType rhs, PairOperator op) { + this.lhs = lhs; + this.rhs = rhs; + pairOp = op; + substitution = new HashSet<>(); + + // Caching hashcode + hashCode = 17 + 31 * lhs.hashCode() + 31 * rhs.hashCode() + 31 * pairOp.hashCode(); + } + + public UnifyPair(UnifyType lhs, UnifyType rhs, PairOperator op, Set uni, UnifyPair base) { + this.lhs = lhs; + this.rhs = rhs; + pairOp = op; + substitution = uni; + basePair = base; + + + // Caching hashcode + hashCode = 17 + 31 * lhs.hashCode() + 31 * rhs.hashCode() + 31 * pairOp.hashCode(); + } + + public UnifyPair(UnifyType lhs, UnifyType rhs, PairOperator op, Set uni, UnifyPair base, Set fBounded) { + this(lhs, rhs, op, uni, base); + + this.fBounded = fBounded; + } + + /** + * Returns the type on the left hand side of the pair. + */ + public UnifyType getLhsType() { + return lhs; + } + + /** + * Returns the type on the right hand side of the pair. + */ + public UnifyType getRhsType() { + return rhs; + } + + /** + * Returns the operator that determines the relation between the left and right hand side type. + */ + public PairOperator getPairOp() { + return pairOp; + } + + public void setPairOp(PairOperator po) { + pairOp = po; + } + + public void addSubstitutions(Set sup) { + substitution.addAll(sup); + } + + public void setUndefinedPair() { + undefinedPair = true; + } + public Set getSubstitution() { + return new HashSet<>(substitution); + } + + public UnifyPair getBasePair() { + return basePair; + } + public boolean isUndefinedPair() { + return undefinedPair; + } + + public Set getAllSubstitutions () { + Set ret = new HashSet<>(); + ret.addAll(new ArrayList<>(getSubstitution())); + if (basePair != null) { + ret.addAll(new ArrayList<>(basePair.getAllSubstitutions())); + } + return ret; + } + + public Set getThisAndAllBases () { + Set ret = getAllBases(); + ret.add(this); + return ret; + } + public Set getAllBases () { + Set ret = new HashSet<>(); + if (basePair != null) { + ret.add(getBasePair()); + ret.addAll(basePair.getAllBases()); + } + return ret; + } + + public UnifyPair getGroundBasePair () { + if (basePair == null) { + return this; + } + if (basePair.getBasePair() == null) { + return basePair; + } + else { + return basePair.getGroundBasePair(); + } + } + + /** + * wenn in einem Paar bestehend aus 2 Typvariablen eine nicht wildcardtable ist, + * so beide auf nicht wildcardtable setzen + */ + public void disableCondWildcards() { + if (lhs instanceof PlaceholderType && rhs instanceof PlaceholderType + && (!((PlaceholderType)lhs).isWildcardable() || !((PlaceholderType)rhs).isWildcardable())) + { + ((PlaceholderType)lhs).disableWildcardtable(); + ((PlaceholderType)rhs).disableWildcardtable(); + } + + } + + public Boolean wrongWildcard() { + return lhs.wrongWildcard() || rhs.wrongWildcard(); + } + + public Set getfBounded() { + return this.fBounded; + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof UnifyPair)) + return false; + + if(obj.hashCode() != this.hashCode()) + return false; + + UnifyPair other = (UnifyPair) obj; + + if (isUndefinedPair()) { + if (other.getBasePair() != basePair || (other.getBasePair() == null && basePair == null)) { + return false; + } + + if (!other.getBasePair().equals(basePair) || + !other.getAllSubstitutions().equals(getAllSubstitutions())) { + return false; + } + } + + + return other.getPairOp() == pairOp + && other.getLhsType().equals(lhs) + && other.getRhsType().equals(rhs); + } + + @Override + public int hashCode() { + return hashCode; + } + + @Override + public String toString() { + String ret = ""; + if (lhs instanceof PlaceholderType) { + ret = new Integer(((PlaceholderType)lhs).getVariance()).toString() + " " + + "WC: " + ((PlaceholderType)lhs).isWildcardable() + + ", IT: " + ((PlaceholderType)lhs).isInnerType(); + } + if (rhs instanceof PlaceholderType) { + ret = ret + ", " + new Integer(((PlaceholderType)rhs).getVariance()).toString() + " " + + "WC: " + ((PlaceholderType)rhs).isWildcardable() + + ", IT: " + ((PlaceholderType)rhs).isInnerType(); + } + return "(" + lhs + " " + pairOp + " " + rhs + ", " + ret + ")"; //+ ", [" + getfBounded().toString()+ "])"; + } + + /* + public List getInvolvedPlaceholderTypes() { + ArrayList ret = new ArrayList<>(); + ret.addAll(lhs.getInvolvedPlaceholderTypes()); + ret.addAll(rhs.getInvolvedPlaceholderTypes()); + return ret; + } + */ +} + + diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/UnifyType.java b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/UnifyType.java new file mode 100644 index 00000000..8d253092 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/UnifyType.java @@ -0,0 +1,120 @@ +package de.dhbwstuttgart.typeinference.unify.model; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Set; + +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; +import de.dhbwstuttgart.typeinference.unify.interfaces.UnifyTypeVisitor; + +/** + * Represents a java type. + * @author Florian Steurer + */ +public abstract class UnifyType { + + /** + * The name of the type e.q. "Integer", "? extends Integer" or "List" for (List) + */ + protected final String typeName; + + /** + * The type parameters of the type. + */ + protected final TypeParams typeParams; + + /** + * Creates a new instance + * @param name Name of the type (e.q. List for List, Integer or ? extends Integer) + * @param typeParams Parameters of the type (e.q. for List) + */ + protected UnifyType(String name, TypeParams p) { + typeName = name; + typeParams = p; + } + + + abstract public UnifyType accept(UnifyTypeVisitor visitor, T ht); + + /** + * Returns the name of the type. + * @return The name e.q. List for List, Integer or ? extends Integer + */ + public String getName() { + return typeName; + } + + /** + * The parameters of the type. + * @return Parameters of the type, e.q. for List. + */ + public TypeParams getTypeParams() { + return typeParams; + } + + /** + * Returns a new type that equals this type except for the type parameters. + * @param newTp The type params of the new type. + * @return A new type object. + */ + public abstract UnifyType setTypeParams(TypeParams newTp); + + /** + * Implementation of the visitor-pattern. Returns the set of smArg + * by calling the most specific overload in the FC. + * @param fc The FC that is called. + * @return The set that is smArg(this) + */ + abstract Set smArg(IFiniteClosure fc, Set fBounded); + + /** + * Implementation of the visitor-pattern. Returns the set of grArg + * by calling the most specific overload in the FC. + * @param fc The FC that is called. + * @return The set that is grArg(this) + */ + abstract Set grArg(IFiniteClosure fc, Set fBounded); + + /** + * Applies a unifier to this object. + * @param unif The unifier + * @return A UnifyType, that may or may not be a new object, that has its subtypes substituted. + */ + abstract UnifyType apply(Unifier unif); + + @Override + public String toString() { + String params = ""; + if(typeParams.size() != 0) { + for(UnifyType param : typeParams) + params += param.toString() + ","; + params = "<" + params.substring(0, params.length()-1) + ">"; + } + + return typeName + params; + } + + public Collection getInvolvedPlaceholderTypes() { + ArrayList ret = new ArrayList<>(); + ret.addAll(typeParams.getInvolvedPlaceholderTypes()); + return ret; + } + + public Boolean wrongWildcard() {//default + return false; + } + + @Override + public int hashCode() { + return this.toString().hashCode(); + } + + @Override + public boolean equals(Object obj) { + if(obj == null)return false; + return this.toString().equals(obj.toString()); + } +} \ No newline at end of file diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/WildcardType.java b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/WildcardType.java new file mode 100644 index 00000000..ed706b26 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/WildcardType.java @@ -0,0 +1,72 @@ +package de.dhbwstuttgart.typeinference.unify.model; + +import java.util.ArrayList; +import java.util.Collection; + +/** + * A wildcard type that is either a ExtendsType or a SuperType. + * @author Florian Steurer + */ +public abstract class WildcardType extends UnifyType { + + /** + * The wildcarded type, e.q. Integer for ? extends Integer. Never a wildcard type itself. + */ + protected UnifyType wildcardedType; + + /** + * Creates a new instance. + * @param name The name of the type, e.q. ? extends Integer + * @param wildcardedType The wildcarded type, e.q. Integer for ? extends Integer. Never a wildcard type itself. + */ + protected WildcardType(String name, UnifyType wildcardedType) { + super(name, wildcardedType.getTypeParams()); + this.wildcardedType = wildcardedType; + } + + /** + * Returns the wildcarded type, e.q. Integer for ? extends Integer. + * @return The wildcarded type. Never a wildcard type itself. + */ + public UnifyType getWildcardedType() { + return wildcardedType; + } + + /** + * Returns the type parameters of the WILDCARDED TYPE. + */ + @Override + public TypeParams getTypeParams() { + return wildcardedType.getTypeParams(); + } + + @Override + public Boolean wrongWildcard () {//This is an error + return (wildcardedType instanceof WildcardType); + } + + @Override + public int hashCode() { + return wildcardedType.hashCode() + getName().hashCode() + 17; + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof WildcardType)) + return false; + + if(obj.hashCode() != this.hashCode()) + return false; + + WildcardType other = (WildcardType) obj; + return other.getWildcardedType().equals(wildcardedType); + } + + + @Override + public Collection getInvolvedPlaceholderTypes() { + ArrayList ret = new ArrayList<>(); + ret.addAll(wildcardedType.getInvolvedPlaceholderTypes()); + return ret; + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/hashKeyType.java b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/hashKeyType.java new file mode 100644 index 00000000..dedfcd86 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/model/hashKeyType.java @@ -0,0 +1,25 @@ +package de.dhbwstuttgart.typeinference.unify.model; + +public class hashKeyType { + UnifyType realType; + + hashKeyType(UnifyType realType) { + this.realType= realType; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof hashKeyType) { + return realType.equals(((hashKeyType)obj).realType); + } + else + { + return false; + } + } + + @Override + public int hashCode() { + return realType.hashCode(); + } +} diff --git a/app/src/main/java/de/dhbwstuttgart/typeinference/unify/visitUnifyTypeVisitor.java b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/visitUnifyTypeVisitor.java new file mode 100644 index 00000000..9ea3dc59 --- /dev/null +++ b/app/src/main/java/de/dhbwstuttgart/typeinference/unify/visitUnifyTypeVisitor.java @@ -0,0 +1,47 @@ +package de.dhbwstuttgart.typeinference.unify; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.HashMap; +import java.util.stream.Collectors; + +import de.dhbwstuttgart.typeinference.unify.interfaces.UnifyTypeVisitor; +import de.dhbwstuttgart.typeinference.unify.model.ExtendsType; +import de.dhbwstuttgart.typeinference.unify.model.FunNType; +import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType; +import de.dhbwstuttgart.typeinference.unify.model.ReferenceType; +import de.dhbwstuttgart.typeinference.unify.model.SuperType; +import de.dhbwstuttgart.typeinference.unify.model.TypeParams; + +public class visitUnifyTypeVisitor implements UnifyTypeVisitor { + + public ReferenceType visit(ReferenceType refty, T ht) { + return new ReferenceType(refty.getName(), + new TypeParams( + Arrays.stream(refty.getTypeParams().get()) + .map(x -> x.accept(this, ht)) + .collect(Collectors.toCollection(ArrayList::new)))); + } + + public PlaceholderType visit(PlaceholderType phty, T ht) { + return phty; + } + + public FunNType visit(FunNType funnty, T ht) { + return FunNType.getFunNType( + new TypeParams( + Arrays.stream(funnty.getTypeParams().get()) + .map(x -> x.accept(this, ht)) + .collect(Collectors.toCollection(ArrayList::new))) + ); + } + + public SuperType visit(SuperType suty, T ht) { + return new SuperType(suty.getWildcardedType().accept(this, ht)); + } + + public ExtendsType visit(ExtendsType extty, T ht) { + return new ExtendsType(extty.getWildcardedType().accept(this, ht)); + } +} diff --git a/app/src/test/java/AllgemeinTest.java b/app/src/test/java/AllgemeinTest.java new file mode 100644 index 00000000..46203361 --- /dev/null +++ b/app/src/test/java/AllgemeinTest.java @@ -0,0 +1,72 @@ + + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Field; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Arrays; + +import org.junit.BeforeClass; +import org.junit.Test; + +import com.google.common.collect.Lists; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class AllgemeinTest { + + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + + @Test + public void test() throws Exception { + //String className = "GenTest"; + //String className = "Overloading_Generics"; + //String className = "Generics"; + //String className = "OverloadingMain"; + //String className = "OverrideMain"; + //String className = "OverrideMainRet"; + //String className = "FCTest1"; + //String className = "FCTest2"; + //String className = "Pair"; + //String className = "FCTest3"; + //String className = "Var"; + //String className = "Put"; + //String className = "Twice"; + //String className = "TestSubTypless"; + //String className = "addList"; + //String className = "M"; + //String className = "Wildcard_Andi"; + //String className = "Box"; + //String className = "Box_Main"; + //String className = "wildcardPair"; + String className = "VectorConstAdd"; + //PL 2019-10-24: genutzt fuer unterschiedliche Tests + path = System.getProperty("user.dir")+"/resources/AllgemeinTest/" + className + ".jav"; + //path = System.getProperty("user.dir")+"/src/test/resources/AllgemeinTest/Overloading_Generics.jav"; + //path = System.getProperty("user.dir")+"/src/test/resources/bytecode/javFiles/mathStrucInteger.jav"; + //compiler = new JavaTXCompiler(Lists.newArrayList(new File(System.getProperty("user.dir")+"/src/test/resources/AllgemeinTest/Overloading_Generics.jav"))); + ///* + compiler = new JavaTXCompiler( + Lists.newArrayList(new File(path)), + Lists.newArrayList(new File(System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"))); + //*/ + compiler.generateBytecode(System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass(className); + //classToTest = loader.loadClass("Overloading_Generics"); + //instanceOfClass = classToTest.getDeclaredConstructor().newInstance("A"); + //classToTest = loader.loadClass("Overloading_Generics1"); + //instanceOfClass = classToTest.getDeclaredConstructor(Object.class).newInstance("B"); + } + +} diff --git a/app/src/test/java/astfactory/ASTFactoryTest.java b/app/src/test/java/astfactory/ASTFactoryTest.java new file mode 100644 index 00000000..6285cf0a --- /dev/null +++ b/app/src/test/java/astfactory/ASTFactoryTest.java @@ -0,0 +1,34 @@ +package astfactory; + +//import javafx.collections.ObservableList; +import de.dhbwstuttgart.syntaxtree.ClassOrInterface; +import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; +import de.dhbwstuttgart.syntaxtree.type.GenericRefType; +import org.junit.Test; + +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.util.Arrays; +import java.util.HashMap; + +import static org.junit.Assert.*; + +public class ASTFactoryTest extends HashMap{ + @Test + public void test(){ + System.out.println((this.getClass().getGenericSuperclass())); + Type[] arguments = ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments(); + System.out.println(Arrays.toString(arguments)); + System.out.println(((TypeVariable)arguments[1]).getGenericDeclaration()); + } + + public static class GenericFieldTest{ + public G testField; + } + @Test + public void genericFieldTest(){ + ClassOrInterface test = ASTFactory.createClass(GenericFieldTest.class); + assertTrue(test.getFieldDecl().get(0).getType() instanceof GenericRefType); + } +} \ No newline at end of file diff --git a/app/src/test/java/bytecode/BinaryTest.java b/app/src/test/java/bytecode/BinaryTest.java new file mode 100644 index 00000000..a2396106 --- /dev/null +++ b/app/src/test/java/bytecode/BinaryTest.java @@ -0,0 +1,50 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class BinaryTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/BinaryInMeth.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("BinaryInMeth"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void test() throws Exception { + Method m2 = classToTest.getDeclaredMethod("m2", Integer.class,Integer.class); + Integer res = (Integer) m2.invoke(instanceOfClass, 2,3); + assertEquals(new Integer(6), res); + } + + @Test + public void testM3() throws Exception { + Method m3 = classToTest.getDeclaredMethod("m3", Integer.class); + Integer res = (Integer) m3.invoke(instanceOfClass, 2); + assertEquals(new Integer(4), res); + } + +} diff --git a/app/src/test/java/bytecode/ClassGenLamTest.java b/app/src/test/java/bytecode/ClassGenLamTest.java new file mode 100644 index 00000000..3fc81e64 --- /dev/null +++ b/app/src/test/java/bytecode/ClassGenLamTest.java @@ -0,0 +1,37 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class ClassGenLamTest { + + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @Test + public void generateBC() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/ClassGenLam.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("ClassGenLam"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + +} diff --git a/app/src/test/java/bytecode/FacTest.java b/app/src/test/java/bytecode/FacTest.java new file mode 100644 index 00000000..7f5c1b97 --- /dev/null +++ b/app/src/test/java/bytecode/FacTest.java @@ -0,0 +1,44 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class FacTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/Fac.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Fac"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testInteger() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method getFac = classToTest.getDeclaredMethod("getFac", Integer.class); + Integer result = (Integer) getFac.invoke(instanceOfClass,3); + assertEquals(result, new Integer(6)); + } + +} diff --git a/app/src/test/java/bytecode/FacultyTest.java b/app/src/test/java/bytecode/FacultyTest.java new file mode 100644 index 00000000..10207262 --- /dev/null +++ b/app/src/test/java/bytecode/FacultyTest.java @@ -0,0 +1,58 @@ +package bytecode; + +import static org.junit.Assert.assertEquals; + +import java.io.File; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class FacultyTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @Test + public void generateBC() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/Faculty.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Faculty"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + + Method getFact = classToTest.getDeclaredMethod("getFact", Integer.class); +// Field fact = classToTest.getDeclaredField("fact"); +// Class lambda = m.invoke(instanceOfClass).getClass(); +// Class lambda = fact.getType(); +// System.out.println(fact.getType().getName()); +// Method apply = lambda.getMethod("apply", Object.class); +// System.out.println(lambda.getMethods()[0]); +// System.out.println(instanceOfClass.toString()); +// // Damit man auf die Methode zugreifen kann +// apply.setAccessible(true); + // Field value +// Object fieldVal = fact.get(instanceOfClass); + Integer i = 3; +// Method applyFromField = fieldVal.getClass().getDeclaredMethod("apply", Object.class); +// applyFromField.setAccessible(true); +// Integer result = (Integer) apply.invoke(lambda,i); + Integer result = (Integer) getFact.invoke(instanceOfClass,i); + + assertEquals(new Integer(6), result); + } + + +} diff --git a/app/src/test/java/bytecode/FieldTest.java b/app/src/test/java/bytecode/FieldTest.java new file mode 100644 index 00000000..e0b98ff0 --- /dev/null +++ b/app/src/test/java/bytecode/FieldTest.java @@ -0,0 +1,43 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Field; + +import org.junit.BeforeClass; +import org.junit.Test; +import java.net.URL; +import java.net.URLClassLoader; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class FieldTest { + + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/Field.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Field"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void test() { + Field[] fields = classToTest.getFields(); + assertEquals(1, fields.length); + } + +} diff --git a/app/src/test/java/bytecode/FieldTph2Test.java b/app/src/test/java/bytecode/FieldTph2Test.java new file mode 100644 index 00000000..509e00f8 --- /dev/null +++ b/app/src/test/java/bytecode/FieldTph2Test.java @@ -0,0 +1,52 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class FieldTph2Test { + + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/FieldTph2.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("FieldTph2"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void test() throws Exception { + Field a = classToTest.getDeclaredField("a"); + a.setAccessible(true); + + Method m2 = classToTest.getDeclaredMethod("m2", Object.class); + m2.invoke(instanceOfClass, 1); + + Method m = classToTest.getDeclaredMethod("m", Object.class); + Object result = m.invoke(instanceOfClass, 1); + + assertEquals(1,result); + } + +} diff --git a/app/src/test/java/bytecode/FieldTphConsMethTest.java b/app/src/test/java/bytecode/FieldTphConsMethTest.java new file mode 100644 index 00000000..3d5dbe7a --- /dev/null +++ b/app/src/test/java/bytecode/FieldTphConsMethTest.java @@ -0,0 +1,50 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class FieldTphConsMethTest { + + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/FieldTphConsMeth.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("FieldTphConsMeth"); + } + + @Test + public void test() throws Exception { + instanceOfClass = classToTest.getConstructor(Object.class).newInstance("C"); + Field a = classToTest.getDeclaredField("a"); + a.setAccessible(true); + + Method m = classToTest.getDeclaredMethod("id", Object.class); + Object result = m.invoke(instanceOfClass, 42); + + assertEquals(42,result); + assertEquals("C", a.get(instanceOfClass)); + } + +} diff --git a/app/src/test/java/bytecode/FieldTphMMethTest.java b/app/src/test/java/bytecode/FieldTphMMethTest.java new file mode 100644 index 00000000..ae04383b --- /dev/null +++ b/app/src/test/java/bytecode/FieldTphMMethTest.java @@ -0,0 +1,66 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class FieldTphMMethTest { + + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + private static Object instanceOfClass2; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/FieldTphMMeth.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("FieldTphMMeth"); + instanceOfClass = classToTest.getConstructor(Object.class,Object.class,Boolean.class).newInstance("C",42,true); + instanceOfClass2 = classToTest.getConstructor(Object.class,Object.class,Boolean.class).newInstance("C",42,false); + } + + @Test + public void testM() throws Exception { + + Method m = classToTest.getDeclaredMethod("m", Object.class,Object.class,Boolean.class); + Object result = m.invoke(instanceOfClass, "C",42,false); + + assertEquals(42,result); + } + + @Test + public void testWithTrue() throws Exception { + Field a = classToTest.getDeclaredField("a"); + a.setAccessible(true); + + assertEquals("C", a.get(instanceOfClass)); + + } + + @Test + public void testWithFalse() throws Exception { + Field a = classToTest.getDeclaredField("a"); + a.setAccessible(true); + + assertEquals(42, a.get(instanceOfClass2)); + } + +} diff --git a/app/src/test/java/bytecode/GenTest.java b/app/src/test/java/bytecode/GenTest.java new file mode 100644 index 00000000..a830aac0 --- /dev/null +++ b/app/src/test/java/bytecode/GenTest.java @@ -0,0 +1,30 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class GenTest { + + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static String pathToClassFile; + + @Test + public void generateBC() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/Gen.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); + } + +} diff --git a/app/src/test/java/bytecode/GreaterEqualTest.java b/app/src/test/java/bytecode/GreaterEqualTest.java new file mode 100644 index 00000000..bbc7d844 --- /dev/null +++ b/app/src/test/java/bytecode/GreaterEqualTest.java @@ -0,0 +1,140 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class GreaterEqualTest { + + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/GreaterEqual.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); + loader = new URLClassLoader(new URL[] {new URL("File://"+pathToClassFile)}); + classToTest = loader.loadClass("GreaterEqual"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testName() { + assertEquals("GreaterEqual", classToTest.getName()); + } + @Test + public void testIntegers() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Integer.class, Integer.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 7, 5); + assertTrue(result); + } + + @Test + public void testIntegers2() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Integer.class, Integer.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 5, 7); + assertFalse(result); + } + + @Test + public void testEqIntegers() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Integer.class, Integer.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 5, 5); + assertTrue(result); + } + + @Test + public void testLongs() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Long.class, Long.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 10L,7L); + assertTrue(result); + } + + @Test + public void testFloats() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Float.class, Float.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 5F,7F); + assertFalse(result); + } + + @Test + public void testDoubles() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Double.class, Double.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 5.0,7.0); + assertFalse(result); + } + + @Test + public void testLongInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Long.class, Integer.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 15L,7); + assertTrue(result); + } + + @Test + public void testFloatInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Float.class, Integer.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 5F,7); + assertFalse(result); + } + + @Test + public void testDoubleInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Double.class, Integer.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 25.0,17); + assertTrue(result); + } + + @Test + public void testFloatLong() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Float.class, Long.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 75F,70L); + assertTrue(result); + } + + @Test + public void testDoubleLong() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Double.class, Long.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 5.0,7L); + assertFalse(result); + } + + @Test + public void testEqDoubleFloat() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Double.class, Float.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 7.0,7F); + assertTrue(result); + } + + @Test + public void testDoubleFloat() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Double.class, Float.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 15.0,7F); + assertTrue(result); + } + + @Test + public void testDoubleFloat3() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Double.class, Float.class); + Boolean result = (Boolean) gE.invoke(instanceOfClass, 9.0,17F); + assertFalse(result); + } + +} diff --git a/app/src/test/java/bytecode/GreaterThanTest.java b/app/src/test/java/bytecode/GreaterThanTest.java new file mode 100644 index 00000000..001ebbc9 --- /dev/null +++ b/app/src/test/java/bytecode/GreaterThanTest.java @@ -0,0 +1,139 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class GreaterThanTest { + + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/GreaterThan.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); + loader = new URLClassLoader(new URL[] {new URL("File://"+pathToClassFile)}); + classToTest = loader.loadClass("GreaterThan"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testName() { + assertEquals("GreaterThan", classToTest.getName()); + } + + public void testIntegers() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Integer.class, Integer.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 7, 5); + assertTrue(result); + } + + @Test + public void testIntegers2() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Integer.class, Integer.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 5, 7); + assertFalse(result); + } + + @Test + public void testEqIntegers() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Integer.class, Integer.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 5, 5); + assertFalse(result); + } + + @Test + public void testLongs() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Long.class, Long.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 10L,7L); + assertTrue(result); + }@Test + + public void testFloats() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Float.class, Float.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 5F,7F); + assertFalse(result); + } + + @Test + public void testDoubles() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Double.class, Double.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 5.0,7.0); + assertFalse(result); + } + + @Test + public void testLongInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Long.class, Integer.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 15L,7); + assertTrue(result); + } + + @Test + public void testFloatInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Float.class, Integer.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 5F,7); + assertFalse(result); + } + + @Test + public void testDoubleInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Double.class, Integer.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 25.0,17); + assertTrue(result); + } + + @Test + public void testFloatLong() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Float.class, Long.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 75F,70L); + assertTrue(result); + } + + @Test + public void testDoubleLong() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Double.class, Long.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 5.0,7L); + assertFalse(result); + } + + @Test + public void testEqDoubleFloat() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Double.class, Float.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 7.0,7F); + assertFalse(result); + } + + @Test + public void testDoubleFloat() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Double.class, Float.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 15.0,7F); + assertTrue(result); + } + + @Test + public void testDoubleFloat3() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gT = classToTest.getDeclaredMethod("gT", Double.class, Float.class); + Boolean result = (Boolean) gT.invoke(instanceOfClass, 9.0,17F); + assertFalse(result); + } + +} diff --git a/app/src/test/java/bytecode/IdTest.java b/app/src/test/java/bytecode/IdTest.java new file mode 100644 index 00000000..6e252aed --- /dev/null +++ b/app/src/test/java/bytecode/IdTest.java @@ -0,0 +1,39 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Field; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; + + +import de.dhbwstuttgart.core.JavaTXCompiler; +import org.junit.Test; + +public class IdTest { + + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + + @Test + public void test() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/Id.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Id"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + +} diff --git a/app/src/test/java/bytecode/InfTest.java b/app/src/test/java/bytecode/InfTest.java new file mode 100644 index 00000000..cc6a7a25 --- /dev/null +++ b/app/src/test/java/bytecode/InfTest.java @@ -0,0 +1,37 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class InfTest { + + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @Test + public void generateBC() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/Inf.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Inf"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + +} diff --git a/app/src/test/java/bytecode/InheritTest.java b/app/src/test/java/bytecode/InheritTest.java new file mode 100644 index 00000000..74db5b85 --- /dev/null +++ b/app/src/test/java/bytecode/InheritTest.java @@ -0,0 +1,193 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Field; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Stack; +import java.util.Vector; +import java.util.stream.Collectors; + +import org.junit.BeforeClass; +import org.junit.Test; + +import com.google.common.collect.Lists; + +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericGenratorResultForSourceFile; +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.typeinference.result.ResultSet; + +public class InheritTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static Class classToTestAA, classToTestBB, classToTestCC, classToTestDD; + private static String pathToClassFile = System.getProperty("user.dir")+"/resources/bytecode/javFiles/";; + //private static String pathToClassFile1 = System.getProperty("user.dir") + "/resources/testBytecode/generatedBC/"; + private static Object instanceOfClass; + private static Object instanceOfClassAA, instanceOfClassBB, instanceOfClassCC, instanceOfClassDD; + private static HashMap, Method> hm = new HashMap<>(); + private static List typeinferenceResult; + private static List simplifyResultsForAllSourceFiles; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/AA.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + List typeinferenceResult = compiler.typeInference(); + List simplifyResultsForAllSourceFiles = compiler.getGeneratedGenericResultsForAllSourceFiles(typeinferenceResult); + compiler.generateBytecode(new File(pathToClassFile),typeinferenceResult,simplifyResultsForAllSourceFiles); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTestAA = loader.loadClass("AA"); + instanceOfClassAA = classToTestAA.getDeclaredConstructor().newInstance(); + + + + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/BB.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + typeinferenceResult = compiler.typeInference(); + simplifyResultsForAllSourceFiles = compiler.getGeneratedGenericResultsForAllSourceFiles(typeinferenceResult); + compiler.generateBytecode(new File(pathToClassFile),typeinferenceResult,simplifyResultsForAllSourceFiles); + classToTestBB = loader.loadClass("BB"); + instanceOfClassBB = classToTestBB.getDeclaredConstructor().newInstance(); + + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/CC.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + typeinferenceResult = compiler.typeInference(); + simplifyResultsForAllSourceFiles = compiler.getGeneratedGenericResultsForAllSourceFiles(typeinferenceResult); + compiler.generateBytecode(new File(pathToClassFile),typeinferenceResult,simplifyResultsForAllSourceFiles); + classToTestCC = loader.loadClass("CC"); + instanceOfClassCC = classToTestCC.getDeclaredConstructor().newInstance(); + + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/DD.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + typeinferenceResult = compiler.typeInference(); + simplifyResultsForAllSourceFiles = compiler.getGeneratedGenericResultsForAllSourceFiles(typeinferenceResult); + compiler.generateBytecode(new File(pathToClassFile),typeinferenceResult,simplifyResultsForAllSourceFiles); + classToTestDD = loader.loadClass("DD"); + instanceOfClassDD = classToTestDD.getDeclaredConstructor().newInstance(); + + + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/Inherit.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + typeinferenceResult = compiler.typeInference(); + simplifyResultsForAllSourceFiles = compiler.getGeneratedGenericResultsForAllSourceFiles(typeinferenceResult); + compiler.generateBytecode(new File(pathToClassFile),typeinferenceResult,simplifyResultsForAllSourceFiles); + classToTest = loader.loadClass("Inherit"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testInheritClassName() { + assertEquals("Inherit", classToTest.getName()); + } + + + @Test + public void testAAName() { + assertEquals("AA", classToTestAA.getName()); + } + + @Test + public void testBBName() { + assertEquals("BB", classToTestBB.getName()); + } + + @Test + public void testCCName() { + assertEquals("CC", classToTestCC.getName()); + } + + @Test + public void testDDName() { + assertEquals("DD", classToTestDD.getName()); + } + + @Test + public void testmainAA() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, MalformedURLException, ClassNotFoundException, NoSuchFieldException { + Method m = classToTestAA.getDeclaredMethod("m", Integer.class); + assertEquals(m.invoke(instanceOfClassAA, 5), "AA"); + Method main = classToTest.getDeclaredMethod("main", classToTestAA, Integer.class); + assertEquals(main.invoke(instanceOfClass, instanceOfClassAA, 5), "AA"); + } + + @Test + public void testmainBB() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, MalformedURLException, ClassNotFoundException, NoSuchFieldException { + Method m = classToTestAA.getDeclaredMethod("m", Integer.class); + assertEquals(m.invoke(instanceOfClassBB, 5), "AA"); + Method main = classToTest.getDeclaredMethod("main", classToTestAA, Integer.class); + assertEquals(main.invoke(instanceOfClass, instanceOfClassBB, 5), "AA"); + } + + @Test + public void testmainCC() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, MalformedURLException, ClassNotFoundException, NoSuchFieldException { + Method m = classToTestCC.getDeclaredMethod("m", Integer.class); + assertEquals(m.invoke(instanceOfClassCC, 5), "CC"); + Method main = classToTest.getDeclaredMethod("main", classToTestCC, Integer.class); + assertEquals(main.invoke(instanceOfClass, instanceOfClassCC, 5), "CC"); + } + + @Test + public void testmainDD() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, MalformedURLException, ClassNotFoundException, NoSuchFieldException { + Method m = classToTestCC.getDeclaredMethod("m", Integer.class); + assertEquals(m.invoke(instanceOfClassDD, 5), "CC"); + Method main = classToTest.getDeclaredMethod("main", classToTestCC, Integer.class); + assertEquals(main.invoke(instanceOfClass, instanceOfClassDD, 5), "CC"); + } + + @Test + public void testmainVectorAA() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, MalformedURLException, ClassNotFoundException, NoSuchFieldException { + Method m = classToTestAA.getDeclaredMethod("m", Integer.class); + assertEquals(m.invoke(instanceOfClassAA, 5), "AA"); + Vector v = new Vector<>(); + v.add(instanceOfClassAA); + Method main = classToTest.getDeclaredMethod("main", Vector.class, Integer.class); + assertEquals(main.invoke(instanceOfClass, v, 5), "AA"); + } + + @Test + public void testmainVectorBB() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, MalformedURLException, ClassNotFoundException, NoSuchFieldException { + Method m = classToTestAA.getDeclaredMethod("m", Integer.class); + assertEquals(m.invoke(instanceOfClassBB, 5), "AA"); + Vector v = new Vector<>(); + v.add(instanceOfClassBB); + Method main = classToTest.getDeclaredMethod("main", Vector.class, Integer.class); + assertEquals(main.invoke(instanceOfClass, v, 5), "AA"); + } + + @Test + public void testmainVectorCC() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, MalformedURLException, ClassNotFoundException, NoSuchFieldException { + Method m = classToTestCC.getDeclaredMethod("m", Integer.class); + assertEquals(m.invoke(instanceOfClassCC, 5), "CC"); + Vector v = new Vector<>(); + v.add(instanceOfClassCC); + Method main = classToTest.getDeclaredMethod("main", Vector.class, Integer.class); + assertEquals(main.invoke(instanceOfClass, v, 5), "CC"); + } + + @Test + public void testmainVectorDD() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, MalformedURLException, ClassNotFoundException, NoSuchFieldException { + Method m = classToTestCC.getDeclaredMethod("m", Integer.class); + assertEquals(m.invoke(instanceOfClassDD, 5), "CC"); + Vector v = new Vector<>(); + v.add(instanceOfClassDD); + Method main = classToTest.getDeclaredMethod("main", Vector.class, Integer.class); + assertEquals(main.invoke(instanceOfClass, v, 5), "CC"); + } +} diff --git a/app/src/test/java/bytecode/InheritTest2.java b/app/src/test/java/bytecode/InheritTest2.java new file mode 100644 index 00000000..4d0c5d6c --- /dev/null +++ b/app/src/test/java/bytecode/InheritTest2.java @@ -0,0 +1,211 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Field; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Stack; +import java.util.Vector; +import java.util.stream.Collectors; + +import org.junit.BeforeClass; +import org.junit.Test; + +import com.google.common.collect.Lists; + +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericGenratorResultForSourceFile; +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.typeinference.result.ResultSet; + +public class InheritTest2 { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static Class classToTestAA, classToTestBB, classToTestCC, classToTestDD; + private static String pathToClassFile = System.getProperty("user.dir")+"/resources/bytecode/javFiles/";; + //private static String pathToClassFile1 = System.getProperty("user.dir") + "/resources/testBytecode/generatedBC/"; + private static Object instanceOfClass; + private static Object instanceOfClassAA, instanceOfClassBB, instanceOfClassCC, instanceOfClassDD; + private static HashMap, Method> hm = new HashMap<>(); + private static List typeinferenceResult; + private static List simplifyResultsForAllSourceFiles; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/AA.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + List typeinferenceResult = compiler.typeInference(); + List simplifyResultsForAllSourceFiles = compiler.getGeneratedGenericResultsForAllSourceFiles(typeinferenceResult); + compiler.generateBytecode(new File(pathToClassFile),typeinferenceResult,simplifyResultsForAllSourceFiles); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTestAA = loader.loadClass("AA"); + instanceOfClassAA = classToTestAA.getDeclaredConstructor().newInstance(); + + + + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/BB.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + typeinferenceResult = compiler.typeInference(); + simplifyResultsForAllSourceFiles = compiler.getGeneratedGenericResultsForAllSourceFiles(typeinferenceResult); + compiler.generateBytecode(new File(pathToClassFile),typeinferenceResult,simplifyResultsForAllSourceFiles); + classToTestBB = loader.loadClass("BB"); + instanceOfClassBB = classToTestBB.getDeclaredConstructor().newInstance(); + + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/CC.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + typeinferenceResult = compiler.typeInference(); + simplifyResultsForAllSourceFiles = compiler.getGeneratedGenericResultsForAllSourceFiles(typeinferenceResult); + compiler.generateBytecode(new File(pathToClassFile),typeinferenceResult,simplifyResultsForAllSourceFiles); + classToTestCC = loader.loadClass("CC"); + instanceOfClassCC = classToTestCC.getDeclaredConstructor().newInstance(); + + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/DD.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + typeinferenceResult = compiler.typeInference(); + simplifyResultsForAllSourceFiles = compiler.getGeneratedGenericResultsForAllSourceFiles(typeinferenceResult); + compiler.generateBytecode(new File(pathToClassFile),typeinferenceResult,simplifyResultsForAllSourceFiles); + classToTestDD = loader.loadClass("DD"); + instanceOfClassDD = classToTestDD.getDeclaredConstructor().newInstance(); + + + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/Inherit2.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + typeinferenceResult = compiler.typeInference(); + simplifyResultsForAllSourceFiles = compiler.getGeneratedGenericResultsForAllSourceFiles(typeinferenceResult); + compiler.generateBytecode(new File(pathToClassFile),typeinferenceResult,simplifyResultsForAllSourceFiles); + classToTest = loader.loadClass("Inherit2"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testInheritClassName() { + assertEquals("Inherit2", classToTest.getName()); + } + + + @Test + public void testAAName() { + assertEquals("AA", classToTestAA.getName()); + } + + @Test + public void testBBName() { + assertEquals("BB", classToTestBB.getName()); + } + + @Test + public void testCCName() { + assertEquals("CC", classToTestCC.getName()); + } + + @Test + public void testDDName() { + assertEquals("DD", classToTestDD.getName()); + } + + @Test + public void testmainAA() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, MalformedURLException, ClassNotFoundException, NoSuchFieldException { + Method m2 = classToTestAA.getDeclaredMethod("m2", classToTestAA); + assertEquals(m2.invoke(instanceOfClassAA, instanceOfClassAA), "AA"); + Method main = classToTest.getDeclaredMethod("main", classToTestAA); + assertEquals(main.invoke(instanceOfClass, instanceOfClassAA), "AA"); + } + + @Test + public void testmainBB() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, MalformedURLException, ClassNotFoundException, NoSuchFieldException { + Method m2 = classToTestAA.getDeclaredMethod("m2", classToTestAA); + assertEquals(m2.invoke(instanceOfClassAA, instanceOfClassAA), "AA"); + Method main = classToTest.getDeclaredMethod("main", classToTestAA); + assertEquals(main.invoke(instanceOfClass, instanceOfClassBB), "AA"); + } + + @Test + public void testmainCC() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, MalformedURLException, ClassNotFoundException, NoSuchFieldException { + Method m2 = classToTestCC.getDeclaredMethod("m2", classToTestCC); + assertEquals(m2.invoke(instanceOfClassCC, instanceOfClassCC), "CC"); + Method main = classToTest.getDeclaredMethod("main", classToTestCC); + assertEquals(main.invoke(instanceOfClass, instanceOfClassCC), "CC"); + } + + @Test + public void testmainDD() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, MalformedURLException, ClassNotFoundException, NoSuchFieldException { + Method m2 = classToTestCC.getDeclaredMethod("m2", classToTestCC); + assertEquals(m2.invoke(instanceOfClassCC, instanceOfClassCC), "CC"); + Method main = classToTest.getDeclaredMethod("main", classToTestCC); + assertEquals(main.invoke(instanceOfClass, instanceOfClassDD), "CC"); + } + + + //PL 2020-05-12: Die folgenden Test funktionieren erst, wenn Generics im Bytecode implementiert sind + @Test + public void testmainVectorAA() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, MalformedURLException, ClassNotFoundException, NoSuchFieldException { + Method m2 = classToTestAA.getDeclaredMethod("m2", classToTestAA); + assertEquals(m2.invoke(instanceOfClassAA, instanceOfClassAA), "AA"); + Vector v = new Vector<>(); + v.add(instanceOfClassAA); + Method main = classToTest.getDeclaredMethod("main", Vector.class); + try { + assertEquals(main.invoke(instanceOfClass, v), "AA"); + } + catch (java.lang.reflect.InvocationTargetException e) { + testmainVectorCC(); + } + } + + @Test + public void testmainVectorBB() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, MalformedURLException, ClassNotFoundException, NoSuchFieldException { + Method m2 = classToTestAA.getDeclaredMethod("m2", classToTestAA); + assertEquals(m2.invoke(instanceOfClassAA, instanceOfClassAA), "AA"); + Vector v = new Vector<>(); + v.add(instanceOfClassBB); + Method main = classToTest.getDeclaredMethod("main", Vector.class); + try { + assertEquals(main.invoke(instanceOfClass, v), "AA"); + } + catch (java.lang.reflect.InvocationTargetException e) { + testmainVectorCC(); + } + } + + @Test + public void testmainVectorCC() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, MalformedURLException, ClassNotFoundException, NoSuchFieldException { + Method m2 = classToTestCC.getDeclaredMethod("m2", classToTestCC); + assertEquals(m2.invoke(instanceOfClassCC, instanceOfClassCC), "CC"); + Vector v = new Vector<>(); + v.add(instanceOfClassCC); + Method main = classToTest.getDeclaredMethod("main", Vector.class); + String erg; + assertEquals(erg= (String) main.invoke(instanceOfClass, v), + erg.equals("CC")? "CC": "AA"); + } + + @Test + public void testmainVectorDD() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, MalformedURLException, ClassNotFoundException, NoSuchFieldException { + Method m2 = classToTestCC.getDeclaredMethod("m2", classToTestCC); + assertEquals(m2.invoke(instanceOfClassCC, instanceOfClassCC), "CC"); + Vector v = new Vector<>(); + v.add(instanceOfClassDD); + Method main = classToTest.getDeclaredMethod("main", Vector.class); + String erg; + assertEquals(erg= (String) main.invoke(instanceOfClass, v), + erg.equals("CC")? "CC": "AA"); + } + + +} diff --git a/app/src/test/java/bytecode/KompTphTest.java b/app/src/test/java/bytecode/KompTphTest.java new file mode 100644 index 00000000..0ecaed01 --- /dev/null +++ b/app/src/test/java/bytecode/KompTphTest.java @@ -0,0 +1,37 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class KompTphTest { + + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @Test + public void generateBC() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/KompTph.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("KompTph"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + +} diff --git a/app/src/test/java/bytecode/LambdaCapturetest.java b/app/src/test/java/bytecode/LambdaCapturetest.java new file mode 100644 index 00000000..f3f5e341 --- /dev/null +++ b/app/src/test/java/bytecode/LambdaCapturetest.java @@ -0,0 +1,43 @@ +/** + * + */ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +/** + * @author fayez + * + */ +public class LambdaCapturetest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @Test + public void generateBC() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/LambdaCapture.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("LambdaCapture"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + +} diff --git a/app/src/test/java/bytecode/LambdaTest.java b/app/src/test/java/bytecode/LambdaTest.java new file mode 100644 index 00000000..79665697 --- /dev/null +++ b/app/src/test/java/bytecode/LambdaTest.java @@ -0,0 +1,50 @@ +package bytecode; + +import static org.junit.Assert.assertEquals; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class LambdaTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @Test + public void generateBC() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/Lambda.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Lambda"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + + Method m = classToTest.getDeclaredMethod("m"); + Class lambda = m.invoke(instanceOfClass).getClass(); + Method apply = lambda.getMethod("apply", Object.class); + + // Damit man auf die Methode zugreifen kann + apply.setAccessible(true); + + Integer i = 77; + System.out.println(m.invoke(instanceOfClass).toString()); + Integer result = (Integer) apply.invoke(m.invoke(instanceOfClass), i); + + assertEquals(i, result); + } + + +} diff --git a/app/src/test/java/bytecode/LambdaVoidTest.java b/app/src/test/java/bytecode/LambdaVoidTest.java new file mode 100644 index 00000000..e2c09204 --- /dev/null +++ b/app/src/test/java/bytecode/LambdaVoidTest.java @@ -0,0 +1,47 @@ +package bytecode; + +import static org.junit.Assert.assertEquals; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class LambdaVoidTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @Test + public void generateBC() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/Lambda.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Lambda"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + + Method m = classToTest.getDeclaredMethod("m"); + Class lambda = m.invoke(instanceOfClass).getClass(); + Method apply = lambda.getMethod("apply", Object.class); + + // Damit man auf die Methode zugreifen kann + apply.setAccessible(true); + + Integer i = 77; + apply.invoke(m.invoke(instanceOfClass), i); + } + + +} diff --git a/app/src/test/java/bytecode/LessEqualTest.java b/app/src/test/java/bytecode/LessEqualTest.java new file mode 100644 index 00000000..ce2cc46c --- /dev/null +++ b/app/src/test/java/bytecode/LessEqualTest.java @@ -0,0 +1,133 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class LessEqualTest { + + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/LessEqual.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("LessEqual"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testName() { + assertEquals("LessEqual", classToTest.getName()); + } + + @Test + public void testIntegers() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Integer.class, Integer.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 5,7); + assertTrue(result); + } + + @Test + public void testEqualIntegers() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Integer.class, Integer.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 5,5); + assertTrue(result); + } + + @Test + public void testLongs() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Long.class, Long.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 5L,7L); + assertTrue(result); + }@Test + + public void testFloats() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Float.class, Float.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 5F,7F); + assertTrue(result); + } + + @Test + public void testDoubles() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Double.class, Double.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 5.0,7.0); + assertTrue(result); + } + + @Test + public void testLongInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Long.class, Integer.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 5L,7); + assertTrue(result); + } + + @Test + public void testFloatInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Float.class, Integer.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 5F,7); + assertTrue(result); + } + + @Test + public void testDoubleInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Double.class, Integer.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 5.0,7); + assertTrue(result); + } + + @Test + public void testFloatLong() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Float.class, Long.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 5F,7L); + assertTrue(result); + } + + @Test + public void testDoubleLong() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Double.class, Long.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 5.0,7L); + assertTrue(result); + } + + @Test + public void testEqDoubleFloat() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Double.class, Float.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 7.0,7F); + assertTrue(result); + } + + @Test + public void testDoubleFloat() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Double.class, Float.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 5.0,7F); + assertTrue(result); + } + + @Test + public void testDoubleFloat3() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Double.class, Float.class); + Boolean result = (Boolean) lessEqual.invoke(instanceOfClass, 9.0,7F); + assertFalse(result); + } + +} diff --git a/app/src/test/java/bytecode/LessThanTest.java b/app/src/test/java/bytecode/LessThanTest.java new file mode 100644 index 00000000..bdc6b8bd --- /dev/null +++ b/app/src/test/java/bytecode/LessThanTest.java @@ -0,0 +1,141 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class LessThanTest { + + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/LessThan.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("LessThan"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testClassName() { + assertEquals("LessThan", classToTest.getName()); + } + + @Test + public void testLessThanInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Integer.class,Integer.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 5, 7); + assertTrue(result); + } + + @Test + public void testLessThanInt2() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Integer.class, Integer.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 7, 5); + assertFalse(result); + } + + @Test + public void testLessThanInt3() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Integer.class, Integer.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 5, 5); + assertFalse(result); + } + + @Test + public void testLessThanLong() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Long.class,Long.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 5L, 7L); + assertTrue(result); + } + + @Test + public void testLessThanLong2() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Long.class, Long.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 7L, 5L); + assertFalse(result); + } + + @Test + public void testLessThanLong3() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Long.class, Long.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 5L, 5L); + assertFalse(result); + } + + @Test + public void testLessThanFloat() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Float.class, Float.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 7F, 5F); + assertFalse(result); + } + + @Test + public void testLessThanDouble() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Double.class, Double.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 7.0, 5.0); + assertFalse(result); + } + + @Test + public void testLessThanLongInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Long.class, Integer.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 7L, 5); + assertFalse(result); + } + + @Test + public void testLessThanFloatInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Float.class, Integer.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 7F, 5); + assertFalse(result); + } + + @Test + public void testLessThanDoubleInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Double.class, Integer.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 7.0, 5); + assertFalse(result); + } + + @Test + public void testLessThanFloatLong() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Float.class, Long.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 7F, 5L); + assertFalse(result); + } + + @Test + public void testLessThanDoubleLong() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Double.class, Long.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 7.0, 5L); + assertFalse(result); + } + + @Test + public void testLessThanDoubleFloat() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Double.class, Float.class); + Boolean result = (Boolean) lessThan.invoke(instanceOfClass, 7.0, 5F); + assertFalse(result); + } + +} diff --git a/app/src/test/java/bytecode/MatrixOpTest.java b/app/src/test/java/bytecode/MatrixOpTest.java new file mode 100644 index 00000000..01c12372 --- /dev/null +++ b/app/src/test/java/bytecode/MatrixOpTest.java @@ -0,0 +1,102 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Vector; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class MatrixOpTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass_m1; + private static Object instanceOfClass_m2; + private static Object instanceOfClass_m3; + + @Test + public void test() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException, IOException, InstantiationException, NoSuchFieldException { + path = System.getProperty("user.dir") + "/resources/bytecode/javFiles/MatrixOP.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir") + "/resources/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); + loader = new URLClassLoader(new URL[]{new URL("file://" + pathToClassFile)}); + classToTest = loader.loadClass("MatrixOP"); + + Vector> vv = new Vector>(); + Vector v1 = new Vector(); + v1.addElement(2); + v1.addElement(2); + Vector v2 = new Vector(); + v2.addElement(3); + v2.addElement(3); + //Matrix m1 = new Matrix(); + //m1.addElement(v1); + //m1.addElement(v2); + vv.addElement(v1); + vv.addElement(v2); + + instanceOfClass_m1 = classToTest.getDeclaredConstructor(Vector.class).newInstance(vv); //Matrix m1 = new Matrix(vv); + + Vector> vv1 = new Vector>(); + Vector v3 = new Vector(); + v3.addElement(2); + v3.addElement(2); + Vector v4 = new Vector(); + v4.addElement(3); + v4.addElement(3); + //Matrix m2 = new Matrix(); + //m2.addElement(v3); + //m2.addElement(v4); + vv1.addElement(v3); + vv1.addElement(v4); + + instanceOfClass_m2 = classToTest.getDeclaredConstructor(Vector.class).newInstance(vv1);//Matrix m2 = new Matrix(vv1); + + + //Matrix m3 = m1.mul(vv1); +// Method mul = classToTest.getDeclaredMethod("mul", Vector.class); +// Object result = mul.invoke(instanceOfClass_m1, instanceOfClass_m2); + Field mul = classToTest.getField("mul"); + mul.setAccessible(true); + + Class lambda = mul.get(instanceOfClass_m1).getClass(); + Method apply = lambda.getMethod("apply", Object.class, Object.class); + // Damit man auf die Methode zugreifen kann + apply.setAccessible(true); + + Object result = apply.invoke(mul.get(instanceOfClass_m1), instanceOfClass_m1, instanceOfClass_m2); + System.out.println(instanceOfClass_m1.toString() + " * " + instanceOfClass_m2.toString() + " = " + result.toString()); + + Vector> res = new Vector>(); + Vector v5 = new Vector(); + v5.addElement(10); + v5.addElement(10); + Vector v6 = new Vector(); + v6.addElement(15); + v6.addElement(15); + //Matrix m2 = new Matrix(); + //m2.addElement(v3); + //m2.addElement(v4); + res.addElement(v5); + res.addElement(v6); + instanceOfClass_m3 = classToTest.getDeclaredConstructor(Vector.class).newInstance(res); + assertEquals(result, instanceOfClass_m3); + + } + +} diff --git a/app/src/test/java/bytecode/MatrixTest.java b/app/src/test/java/bytecode/MatrixTest.java new file mode 100755 index 00000000..0689f490 --- /dev/null +++ b/app/src/test/java/bytecode/MatrixTest.java @@ -0,0 +1,90 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Vector; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class MatrixTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass_m1; + private static Object instanceOfClass_m2; + private static Object instanceOfClass_m3; + + @Test + public void test() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException, IOException, InstantiationException { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/Matrix.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Matrix"); + + Vector> vv = new Vector>(); + Vector v1 = new Vector (); + v1.addElement(2); + v1.addElement(2); + Vector v2 = new Vector (); + v2.addElement(3); + v2.addElement(3); + //Matrix m1 = new Matrix(); + //m1.addElement(v1); + //m1.addElement(v2); + vv.addElement(v1); + vv.addElement(v2); + instanceOfClass_m1 = classToTest.getDeclaredConstructor(Vector.class).newInstance(vv); //Matrix m1 = new Matrix(vv); + + Vector> vv1 = new Vector>(); + Vector v3 = new Vector (); + v3.addElement(2); + v3.addElement(2); + Vector v4 = new Vector (); + v4.addElement(3); + v4.addElement(3); + //Matrix m2 = new Matrix(); + //m2.addElement(v3); + //m2.addElement(v4); + vv1.addElement(v3); + vv1.addElement(v4); + instanceOfClass_m2 = classToTest.getDeclaredConstructor(Vector.class).newInstance(vv1);//Matrix m2 = new Matrix(vv1); + + + + //Matrix m3 = m1.mul(vv1); + Method mul = classToTest.getDeclaredMethod("mul", Vector.class); + Object result = mul.invoke(instanceOfClass_m1, instanceOfClass_m2); + System.out.println(instanceOfClass_m1.toString() + " * " + instanceOfClass_m2.toString() + " = " + result.toString()); + + Vector> res = new Vector>(); + Vector v5 = new Vector (); + v5.addElement(10); + v5.addElement(10); + Vector v6 = new Vector (); + v6.addElement(15); + v6.addElement(15); + //Matrix m2 = new Matrix(); + //m2.addElement(v3); + //m2.addElement(v4); + res.addElement(v5); + res.addElement(v6); + instanceOfClass_m3 = classToTest.getDeclaredConstructor(Vector.class).newInstance(res); + assertEquals(result, instanceOfClass_m3); + } + +} diff --git a/app/src/test/java/bytecode/MergeTest.java b/app/src/test/java/bytecode/MergeTest.java new file mode 100644 index 00000000..b0bc9a89 --- /dev/null +++ b/app/src/test/java/bytecode/MergeTest.java @@ -0,0 +1,41 @@ +package bytecode; + + +import static org.junit.Assert.assertEquals; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class MergeTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + + @Test + public void generateBC() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/Merge.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"); +// pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; +// loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); +// classToTest = loader.loadClass("Merge"); + //instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + + //Method m = classToTest.getDeclaredMethod("m"); + //Object result = m.invoke(instanceOfClass); + + //assertEquals(result.getClass(), loader.loadClass("Apply")); + } +} diff --git a/app/src/test/java/bytecode/OLFun2Test.java b/app/src/test/java/bytecode/OLFun2Test.java new file mode 100644 index 00000000..6ec8701b --- /dev/null +++ b/app/src/test/java/bytecode/OLFun2Test.java @@ -0,0 +1,69 @@ +package bytecode; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.function.Function; + +import general.TestCleanUp; +import org.junit.*; +import de.dhbwstuttgart.core.JavaTXCompiler; +import static org.junit.Assert.*; + +/** + * //ToDo Etienne: Beschreiben + * + * @since Studienarbeit Type Erasure + * @author etiennezink + */ +public class OLFun2Test { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static Class classFun1IntInt; + private static Class classFun1DoubleDouble; + private static Class classFun1StringString; + + private static String generatedByteCodeDirectory = System.getProperty("user.dir") + "/src/test/resources/testBytecode/generatedBC/"; + + //ToDo Etienne: Nach Anpassung des Bytecode die Tests hinzufügen + //ToDo Etienne: Aufruf von m testen + @BeforeClass + public static void setUp() throws Exception { + path = System.getProperty("user.dir")+"/src/test/resources/bytecode/javFiles/OLFun2.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(generatedByteCodeDirectory); + loader = new URLClassLoader(new URL[] {new URL("file://"+generatedByteCodeDirectory)}); + classToTest = loader.loadClass("OLFun2"); + classFun1IntInt = loader.loadClass("Fun1$$Ljava$lang$Integer$_$Ljava$lang$Integer$_$"); + classFun1DoubleDouble = loader.loadClass("Fun1$$Ljava$lang$Double$_$Ljava$lang$Double$_$"); + classFun1StringString = loader.loadClass("Fun1$$Ljava$lang$String$_$Ljava$lang$String$_$"); + } + + @Test + public void mExistsWithInteger() throws Exception{ + Method m = classToTest.getDeclaredMethod("m", classFun1IntInt); + assertNotNull(m); + } + + @Test + public void mExistsWithDouble() throws Exception{ + Method m = classToTest.getDeclaredMethod("m", classFun1DoubleDouble); + assertNotNull(m); + } + + @Test + public void mExistsWithString() throws Exception{ + Method m = classToTest.getDeclaredMethod("m", classFun1StringString); + assertNotNull(m); + } + + //@AfterClass + public static void cleanUp(){ + TestCleanUp.cleanUpDirectory(new File(generatedByteCodeDirectory), f -> f.getName().contains(".class")); + } +} diff --git a/app/src/test/java/bytecode/OLFunTest.java b/app/src/test/java/bytecode/OLFunTest.java new file mode 100644 index 00000000..d1910e07 --- /dev/null +++ b/app/src/test/java/bytecode/OLFunTest.java @@ -0,0 +1,68 @@ +package bytecode; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import general.TestCleanUp; +import org.junit.*; +import de.dhbwstuttgart.core.JavaTXCompiler; +import static org.junit.Assert.*; + +/** + * //ToDo Etienne: Beschreiben + * + * @since Studienarbeit Type Erasure + * @author etiennezink + */ +public class OLFunTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static Class classFun1IntInt; + private static Class classFun1DoubleDouble; + private static Class classFun1StringString; + + private static String generatedByteCodeDirectory = System.getProperty("user.dir") + "/src/test/resources/testBytecode/generatedBC/"; + + //ToDo Etienne: Nach Anpassung des Bytecode die Tests hinzufügen + //ToDo Etienne: Aufruf von m testen + @BeforeClass + public static void setUp() throws Exception { + path = System.getProperty("user.dir")+"/src/test/resources/bytecode/javFiles/OLFun.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(generatedByteCodeDirectory); + loader = new URLClassLoader(new URL[] {new URL("file://"+generatedByteCodeDirectory)}); + classToTest = loader.loadClass("OLFun"); + classFun1IntInt = loader.loadClass("Fun1$$Ljava$lang$Integer$_$Ljava$lang$Integer$_$"); + classFun1DoubleDouble = loader.loadClass("Fun1$$Ljava$lang$Double$_$Ljava$lang$Double$_$"); + classFun1StringString = loader.loadClass("Fun1$$Ljava$lang$String$_$Ljava$lang$String$_$"); + } + + @Test + public void mExistsWithInteger() throws Exception{ + Method m = classToTest.getDeclaredMethod("m", classFun1IntInt ,Integer.class); + assertNotNull(m); + } + + @Test + public void mExistsWithDouble() throws Exception{ + Method m = classToTest.getDeclaredMethod("m", classFun1DoubleDouble ,Double.class); + assertNotNull(m); + } + + @Test + public void mExistsWithString() throws Exception{ + Method m = classToTest.getDeclaredMethod("m", classFun1StringString ,String.class); + assertNotNull(m); + } + + //@AfterClass + public static void cleanUp(){ + TestCleanUp.cleanUpDirectory(new File(generatedByteCodeDirectory), f -> f.getName().contains(".class")); + } +} diff --git a/app/src/test/java/bytecode/OLTest.java b/app/src/test/java/bytecode/OLTest.java new file mode 100644 index 00000000..7cf2508f --- /dev/null +++ b/app/src/test/java/bytecode/OLTest.java @@ -0,0 +1,97 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.List; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericGenratorResultForSourceFile; +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.typeinference.result.ResultSet; + +public class OLTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static Class classToTest1; + private static String pathToClassFile; + private static Object instanceOfClass; + private static Object instanceOfClass1; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/OL.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + List typeinferenceResult = compiler.typeInference(); + List simplifyResultsForAllSourceFiles = compiler.getGeneratedGenericResultsForAllSourceFiles(typeinferenceResult); + compiler.generateBytecode(new File(pathToClassFile),typeinferenceResult,simplifyResultsForAllSourceFiles); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("OL"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + classToTest1 = loader.loadClass("OLMain"); + instanceOfClass1 = classToTest1.getDeclaredConstructor().newInstance(); + } + + @Test + public void testOLClassName() { + assertEquals("OL", classToTest.getName()); + } + + @Test + public void testmInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("m", Integer.class); + Integer result = (Integer) m.invoke(instanceOfClass, 5); + assertEquals(new Integer(10), result); + } + + @Test + public void testmDouble() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("m", Double.class); + Double result = (Double) m.invoke(instanceOfClass, 5.0); + assertEquals(new Double(10.0), result); + } + + @Test + public void testmString() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("m", String.class); + String result = (String) m.invoke(instanceOfClass, "xxx"); + assertEquals("xxxxxx", result); + } + + @Test + public void testOLMainClassName() { + assertEquals("OLMain", classToTest1.getName()); + } + + @Test + public void testmainInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method main = classToTest1.getDeclaredMethod("main", Integer.class); + Integer result = (Integer) main.invoke(instanceOfClass1, 5); + assertEquals(new Integer(10), result); + } + + @Test + public void testmainDouble() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method main = classToTest1.getDeclaredMethod("main", Double.class); + Double result = (Double) main.invoke(instanceOfClass1, 5.0); + assertEquals(new Double(10.0), result); + } + + @Test + public void testmainString() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method main = classToTest1.getDeclaredMethod("main", String.class); + String result = (String) main.invoke(instanceOfClass1, "xxx"); + assertEquals("xxxxxx", result); + } +} diff --git a/app/src/test/java/bytecode/OpTest.java b/app/src/test/java/bytecode/OpTest.java new file mode 100644 index 00000000..ce4d77df --- /dev/null +++ b/app/src/test/java/bytecode/OpTest.java @@ -0,0 +1,61 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.objectweb.asm.Opcodes; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class OpTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/Op.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Op"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testAddString() throws NoSuchMethodException, SecurityException, IllegalAccessException, + IllegalArgumentException, InvocationTargetException, InstantiationException { + + Method m = classToTest.getDeclaredMethod("m", String.class,String.class); + + String result = (String) m.invoke(instanceOfClass, "Byte","Code"); + + assertEquals("ByteCode", result); + } + + @Test + public void testAddInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, + IllegalArgumentException, InvocationTargetException, InstantiationException { + + Method m = classToTest.getDeclaredMethod("m", Integer.class,Integer.class); + + Integer result = (Integer) m.invoke(instanceOfClass, 7,3); + + assertEquals(new Integer(10), result); + } + + +} diff --git a/app/src/test/java/bytecode/OverloadingSortingTest.java b/app/src/test/java/bytecode/OverloadingSortingTest.java new file mode 100644 index 00000000..c64f1f2a --- /dev/null +++ b/app/src/test/java/bytecode/OverloadingSortingTest.java @@ -0,0 +1,51 @@ +package bytecode; + +import de.dhbwstuttgart.core.JavaTXCompiler; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import static org.junit.Assert.assertEquals; + +public class OverloadingSortingTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + private static Class classOL2; + private static Object instanceOfClassOL2; + + @Test + public void generateBC() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/Sorting.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); +// loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); +// classToTest = loader.loadClass("Sorting"); +// instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + +// @Test +// public void test() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { +// Method meth = classToTest.getDeclaredMethod("merge", classToTest); +// } +// +// @Test +// public void test2() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { +// Method meth = classToTest.getDeclaredMethod("test", classOL2); +// String res = (String) meth.invoke(instanceOfClass, instanceOfClassOL2); +// assertEquals("Overloading2", res); +// } + +} diff --git a/app/src/test/java/bytecode/OverloadingTest.java b/app/src/test/java/bytecode/OverloadingTest.java new file mode 100644 index 00000000..f93f0166 --- /dev/null +++ b/app/src/test/java/bytecode/OverloadingTest.java @@ -0,0 +1,57 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class OverloadingTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + private static Class classOL2; + private static Object instanceOfClassOL2; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/Overloading.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Overloading"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + + classOL2 = loader.loadClass("Overloading2"); + instanceOfClassOL2 = classOL2.getDeclaredConstructor().newInstance(); + } + + @Test + public void test() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method meth = classToTest.getDeclaredMethod("test", classToTest); + String res = (String) meth.invoke(instanceOfClass, instanceOfClass); + assertEquals("Overloading", res); + } + + @Test + public void test2() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method meth = classToTest.getDeclaredMethod("test", classOL2); + String res = (String) meth.invoke(instanceOfClass, instanceOfClassOL2); + assertEquals("Overloading2", res); + } + +} diff --git a/app/src/test/java/bytecode/PlusTest.java b/app/src/test/java/bytecode/PlusTest.java new file mode 100644 index 00000000..a11d505e --- /dev/null +++ b/app/src/test/java/bytecode/PlusTest.java @@ -0,0 +1,53 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class PlusTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/Plus.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Plus"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testAddInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, + IllegalArgumentException, InvocationTargetException, InstantiationException { + Method addInt = classToTest.getDeclaredMethod("m", Integer.class,Integer.class); + Number result = (Number) addInt.invoke(instanceOfClass, 7,3); + assertEquals(10, result); + } + + @Test + public void testAddString() throws NoSuchMethodException, SecurityException, IllegalAccessException, + IllegalArgumentException, InvocationTargetException, InstantiationException { + Method addString = classToTest.getDeclaredMethod("m", String.class,String.class); + String result = (String) addString.invoke(instanceOfClass, "Byte","Code"); + assertEquals("ByteCode", result); + } + +} diff --git a/app/src/test/java/bytecode/PostIncTest.java b/app/src/test/java/bytecode/PostIncTest.java new file mode 100644 index 00000000..9ecabd23 --- /dev/null +++ b/app/src/test/java/bytecode/PostIncTest.java @@ -0,0 +1,65 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class PostIncTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/PostIncDec.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("PostIncDec"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testM1() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("m"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(new Integer(1), res); + } + + @Test + public void testM2() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("m2"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(new Integer(0), res); + } + + @Test + public void testD1() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("d"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(new Integer(-1), res); + } + + @Test + public void testD2() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("d2"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(new Integer(0), res); + } + +} diff --git a/app/src/test/java/bytecode/PreIncTest.java b/app/src/test/java/bytecode/PreIncTest.java new file mode 100644 index 00000000..3c30e27f --- /dev/null +++ b/app/src/test/java/bytecode/PreIncTest.java @@ -0,0 +1,65 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class PreIncTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/PreInc.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); + loader = new URLClassLoader(new URL[] {new URL("file://" + pathToClassFile)}); + classToTest = loader.loadClass("PreInc"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testM() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("m"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(new Integer(1), res); + } + + @Test + public void testM2() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("m2"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(new Integer(1), res); + } + + @Test + public void testD() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("d"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(new Integer(-1), res); + } + + @Test + public void testD2() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("d2"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(new Integer(-1), res); + } + +} diff --git a/app/src/test/java/bytecode/PutTest.java b/app/src/test/java/bytecode/PutTest.java new file mode 100644 index 00000000..cf3e83d3 --- /dev/null +++ b/app/src/test/java/bytecode/PutTest.java @@ -0,0 +1,86 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.List; +import java.util.Stack; +import java.util.Vector; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericGenratorResultForSourceFile; +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.typeinference.result.ResultSet; + +public class PutTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static Class classToTest1; + private static String pathToClassFile; + private static Object instanceOfClass; + private static Object instanceOfClass1; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/Put.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + List typeinferenceResult = compiler.typeInference(); + List simplifyResultsForAllSourceFiles = compiler.getGeneratedGenericResultsForAllSourceFiles(typeinferenceResult); + compiler.generateBytecode(new File(pathToClassFile),typeinferenceResult,simplifyResultsForAllSourceFiles); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Put"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testPutClassName() { + assertEquals("Put", classToTest.getName()); + } + + @Test + public void testPutElementVector() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("putElement", Object.class, Vector.class); + Vector v_invoke = new Vector<>(); + m.invoke(instanceOfClass, 5, v_invoke); + Vector v = new Vector<>(); + v.add(5); + assertEquals(v, v_invoke); + } + + @Test + public void testPutElementStack() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("putElement", Object.class, Stack.class); + Stack s_invoke = new Stack<>(); + m.invoke(instanceOfClass, 5, s_invoke); + assertEquals(new Integer(5), s_invoke.pop()); + } + + @Test + public void testMainVector() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("main", Object.class, Vector.class); + Vector v_invoke = new Vector<>(); + m.invoke(instanceOfClass, 6, v_invoke); + Vector v = new Vector<>(); + v.add(6); + assertEquals(v, v_invoke); + } + + @Test + public void testMainStack() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("main", Object.class, Stack.class); + Stack s_invoke = new Stack<>(); + m.invoke(instanceOfClass, 6, s_invoke); + assertEquals(new Integer(6), s_invoke.pop()); + } +} diff --git a/app/src/test/java/bytecode/RelOpsTest.java b/app/src/test/java/bytecode/RelOpsTest.java new file mode 100644 index 00000000..52774327 --- /dev/null +++ b/app/src/test/java/bytecode/RelOpsTest.java @@ -0,0 +1,44 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class RelOpsTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/RelOps.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("RelOps"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void test() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("m", Integer.class,Integer.class); + Boolean result = (Boolean) m.invoke(instanceOfClass, 7,3); + assertFalse(result); + } + +} diff --git a/app/src/test/java/bytecode/SimpleCycleTest.java b/app/src/test/java/bytecode/SimpleCycleTest.java new file mode 100644 index 00000000..45a63e44 --- /dev/null +++ b/app/src/test/java/bytecode/SimpleCycleTest.java @@ -0,0 +1,38 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class SimpleCycleTest { + + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @Test + public void generateGen() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/SimpleCycle.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("SimpleCycle"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + +} diff --git a/app/src/test/java/bytecode/SortingTest.java b/app/src/test/java/bytecode/SortingTest.java new file mode 100644 index 00000000..9220bb81 --- /dev/null +++ b/app/src/test/java/bytecode/SortingTest.java @@ -0,0 +1,52 @@ +package bytecode; + +import static org.junit.Assert.assertEquals; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class SortingTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @Test + public void generateBC() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/Sorting.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Sorting"); + /* + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + + Method m = classToTest.getDeclaredMethod("m"); + Class lambda = m.invoke(instanceOfClass).getClass(); + Method apply = lambda.getMethod("apply", Object.class); + + // Damit man auf die Methode zugreifen kann + apply.setAccessible(true); + + Integer i = 77; + + Integer result = (Integer) apply.invoke(m.invoke(instanceOfClass), i); + + assertEquals(77, result); + */ + } + + +} diff --git a/app/src/test/java/bytecode/SubMatTest.java b/app/src/test/java/bytecode/SubMatTest.java new file mode 100644 index 00000000..e3988697 --- /dev/null +++ b/app/src/test/java/bytecode/SubMatTest.java @@ -0,0 +1,27 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.IOException; + +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class SubMatTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static String pathToClassFile; + + @Test + public void test() throws ClassNotFoundException, IOException { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/SubMatrix.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); + } + +} diff --git a/app/src/test/java/bytecode/Tph2Test.java b/app/src/test/java/bytecode/Tph2Test.java new file mode 100644 index 00000000..a6acf5b2 --- /dev/null +++ b/app/src/test/java/bytecode/Tph2Test.java @@ -0,0 +1,69 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class Tph2Test { + + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/Tph2.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Tph2"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void test1() throws Exception { + Method m = classToTest.getDeclaredMethod("m", Object.class, Object.class); + Object result = m.invoke(instanceOfClass, 1,2); + + assertEquals(1,result); + } + + @Test + public void test2() throws Exception { + Method m = classToTest.getDeclaredMethod("m", Object.class, Object.class); + Object result = m.invoke(instanceOfClass, "sss",2); + + assertEquals("sss",result); + } + + @Test + public void test3() throws Exception { + Method m = classToTest.getDeclaredMethod("m2", Object.class, Object.class); + Object result = m.invoke(instanceOfClass, 1,2); + + assertEquals(2,result); + } + + @Test + public void test4() throws Exception { + Method m = classToTest.getDeclaredMethod("m2", Object.class, Object.class); + Object result = m.invoke(instanceOfClass, 1,"xxx"); + + assertEquals("xxx",result); + } + +} diff --git a/app/src/test/java/bytecode/Tph3Test.java b/app/src/test/java/bytecode/Tph3Test.java new file mode 100644 index 00000000..ba76e3c0 --- /dev/null +++ b/app/src/test/java/bytecode/Tph3Test.java @@ -0,0 +1,31 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class Tph3Test { + + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static String pathToClassFile; + + @Test + public void generateBC() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/Tph3.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); + } + +} diff --git a/app/src/test/java/bytecode/Tph5Test.java b/app/src/test/java/bytecode/Tph5Test.java new file mode 100644 index 00000000..de028469 --- /dev/null +++ b/app/src/test/java/bytecode/Tph5Test.java @@ -0,0 +1,45 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class Tph5Test { + + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/Tph5.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Tph5"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void test() throws Exception { +// Method m = classToTest.getDeclaredMethod("m", Object.class, Object.class, Object.class); + Method m = classToTest.getDeclaredMethod("m", Object.class, Object.class); +// Object result = m.invoke(instanceOfClass, "xx",2,3); + + //assertEquals(2,result); + } +} diff --git a/app/src/test/java/bytecode/Tph6Test.java b/app/src/test/java/bytecode/Tph6Test.java new file mode 100644 index 00000000..39580320 --- /dev/null +++ b/app/src/test/java/bytecode/Tph6Test.java @@ -0,0 +1,45 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class Tph6Test { + + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/Tph6.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Tph6"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void test() throws Exception { +// Method m = classToTest.getDeclaredMethod("m", Object.class, Object.class, Object.class); + Method m = classToTest.getDeclaredMethod("m", Object.class, Object.class); +// Object result = m.invoke(instanceOfClass, "xx",2,3); + + //assertEquals(2,result); + } +} diff --git a/app/src/test/java/bytecode/TphTest.java b/app/src/test/java/bytecode/TphTest.java new file mode 100644 index 00000000..6effa069 --- /dev/null +++ b/app/src/test/java/bytecode/TphTest.java @@ -0,0 +1,69 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class TphTest { + + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/Tph.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Tph"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void test1() throws Exception { + Method m = classToTest.getDeclaredMethod("m", Object.class, Object.class); + Object result = m.invoke(instanceOfClass, 1,2); + + assertEquals(1,result); + } + + @Test + public void test2() throws Exception { + Method m = classToTest.getDeclaredMethod("m", Object.class, Object.class); + Object result = m.invoke(instanceOfClass, 1, "sss"); + + assertEquals(1,result); + } + + @Test + public void test3() throws Exception { + Method m = classToTest.getDeclaredMethod("m2", Object.class); + Object result = m.invoke(instanceOfClass, 2); + + assertEquals(2,result); + } + + @Test + public void test4() throws Exception { + Method m = classToTest.getDeclaredMethod("m2", Object.class); + Object result = m.invoke(instanceOfClass,"xxx"); + + assertEquals("xxx",result); + } + +} diff --git a/app/src/test/java/bytecode/TypedIDTest.java b/app/src/test/java/bytecode/TypedIDTest.java new file mode 100644 index 00000000..99a9995f --- /dev/null +++ b/app/src/test/java/bytecode/TypedIDTest.java @@ -0,0 +1,38 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Field; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class TypedIDTest { + + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + + @Test + public void test() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/TypedID.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("TypedID"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + +} diff --git a/app/src/test/java/bytecode/VectorAddTest.java b/app/src/test/java/bytecode/VectorAddTest.java new file mode 100644 index 00000000..120bd7a0 --- /dev/null +++ b/app/src/test/java/bytecode/VectorAddTest.java @@ -0,0 +1,38 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Vector; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class VectorAddTest { + + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @Test + public void test() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/VectorAdd.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("VectorAdd"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + +} diff --git a/app/src/test/java/bytecode/VectorSuperTest.java b/app/src/test/java/bytecode/VectorSuperTest.java new file mode 100644 index 00000000..e7015b51 --- /dev/null +++ b/app/src/test/java/bytecode/VectorSuperTest.java @@ -0,0 +1,45 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Vector; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class VectorSuperTest { + + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/VectorSuper.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("VectorSuper"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void test1() throws Exception { + Method m = classToTest.getDeclaredMethod("m", Vector.class); + //Object result = m.invoke(instanceOfClass, 1); + + //assertEquals(1,result); + } +} diff --git a/app/src/test/java/bytecode/WhileTest.java b/app/src/test/java/bytecode/WhileTest.java new file mode 100644 index 00000000..2adaff4a --- /dev/null +++ b/app/src/test/java/bytecode/WhileTest.java @@ -0,0 +1,58 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class WhileTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/While.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + compiler.generateBytecode(pathToClassFile); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("While"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void test() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("m", Integer.class); + Integer result = (Integer) m.invoke(instanceOfClass, 0); + assertEquals(new Integer(2), result); + } + + @Test + public void testDouble() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("m", Double.class); + Double result = (Double) m.invoke(instanceOfClass, 0.0); + assertEquals(new Double(2.0), result); + } + + @Test + public void testLong() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("m", Long.class); + Long result = (Long) m.invoke(instanceOfClass, 0l); + assertEquals(new Long(2l), result); + } + +} diff --git a/app/src/test/java/bytecode/YTest.java b/app/src/test/java/bytecode/YTest.java new file mode 100644 index 00000000..bb78a204 --- /dev/null +++ b/app/src/test/java/bytecode/YTest.java @@ -0,0 +1,52 @@ +package bytecode; + +import static org.junit.Assert.assertEquals; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class YTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @Test + public void generateBC() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/Y.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Y"); + /* + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + + Method m = classToTest.getDeclaredMethod("m"); + Class lambda = m.invoke(instanceOfClass).getClass(); + Method apply = lambda.getMethod("apply", Object.class); + + // Damit man auf die Methode zugreifen kann + apply.setAccessible(true); + + Integer i = 77; + + Integer result = (Integer) apply.invoke(m.invoke(instanceOfClass), i); + + assertEquals(77, result); + */ + } + + +} diff --git a/app/src/test/java/bytecode/applyLambdaTest.java b/app/src/test/java/bytecode/applyLambdaTest.java new file mode 100644 index 00000000..ada25547 --- /dev/null +++ b/app/src/test/java/bytecode/applyLambdaTest.java @@ -0,0 +1,40 @@ + +package bytecode; + +import static org.junit.Assert.assertEquals; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class applyLambdaTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + @Test + public void generateBC() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/applyLambda.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("applyLambda"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + + Method m = classToTest.getDeclaredMethod("m"); + Object result = m.invoke(instanceOfClass); + + assertEquals(result.getClass(), loader.loadClass("Apply")); + } +} diff --git a/app/src/test/java/bytecode/mathStrucIntegerTest.java b/app/src/test/java/bytecode/mathStrucIntegerTest.java new file mode 100644 index 00000000..ee614db4 --- /dev/null +++ b/app/src/test/java/bytecode/mathStrucIntegerTest.java @@ -0,0 +1,38 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Field; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class mathStrucIntegerTest { + + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + + @Test + public void test() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/mathStrucInteger.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("mathStrucInteger"); + //instanceOfClass = classToTest.getDeclaredConstructor(Integer.class).newInstance("A"); + } + +} diff --git a/app/src/test/java/bytecode/mathStrucMatrixOPTest.java.txt b/app/src/test/java/bytecode/mathStrucMatrixOPTest.java.txt new file mode 100644 index 00000000..50bb30ad --- /dev/null +++ b/app/src/test/java/bytecode/mathStrucMatrixOPTest.java.txt @@ -0,0 +1,40 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Field; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class mathStrucMatrixOPTest { + + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + + @Test + public void test() throws Exception { + //PL 2019-10-24: laeuft nicht durch deshalb ersetzt + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/mathStrucMatrixOp.jav"; + //path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/mathStrucInteger.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("mathStrucMatrixOP"); + instanceOfClass = classToTest.getDeclaredConstructor(Object.class).newInstance("A"); + } + +} diff --git a/app/src/test/java/bytecode/mathStrucTest.java b/app/src/test/java/bytecode/mathStrucTest.java new file mode 100644 index 00000000..d472b403 --- /dev/null +++ b/app/src/test/java/bytecode/mathStrucTest.java @@ -0,0 +1,38 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Field; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class mathStrucTest { + + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + + @Test + public void test() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/mathStruc.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("mathStruc"); + instanceOfClass = classToTest.getDeclaredConstructor(Object.class).newInstance("A"); + } + +} diff --git a/app/src/test/java/bytecode/mathStrucVectorAddTest.java.txt b/app/src/test/java/bytecode/mathStrucVectorAddTest.java.txt new file mode 100644 index 00000000..61130cf1 --- /dev/null +++ b/app/src/test/java/bytecode/mathStrucVectorAddTest.java.txt @@ -0,0 +1,38 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Field; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.BeforeClass; +import org.junit.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class mathStrucVectorAddTest { + + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static String pathToClassFile; + private static Object instanceOfClass; + + + @Test + public void test() throws Exception { + path = System.getProperty("user.dir")+"/resources/bytecode/javFiles/mathStrucVector.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"); + pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("mathStrucVector"); + //instanceOfClass = classToTest.getDeclaredConstructor(Integer.class).newInstance("A"); + } + +} diff --git a/app/src/test/java/constraintSimplify/FamilyOfGenerics.java b/app/src/test/java/constraintSimplify/FamilyOfGenerics.java new file mode 100644 index 00000000..e5c9ad13 --- /dev/null +++ b/app/src/test/java/constraintSimplify/FamilyOfGenerics.java @@ -0,0 +1,68 @@ +package constraintSimplify; + +import de.dhbwstuttgart.bytecode.TPHExtractor; +import de.dhbwstuttgart.bytecode.insertGenerics.PositionFinder; +import de.dhbwstuttgart.bytecode.genericsGenerator.GeneratedGenericsFinder; +import de.dhbwstuttgart.parser.NullToken; +import de.dhbwstuttgart.parser.scope.JavaClassName; +import de.dhbwstuttgart.syntaxtree.*; +import de.dhbwstuttgart.syntaxtree.statement.Block; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.result.ResultSet; +import org.junit.Test; + +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; + +public class FamilyOfGenerics { + + @Test + public void generateBC() throws Exception { + SourceFile sf = generateAST(); + PositionFinder.getPositionOfTPH(sf, null); + TPHExtractor tphExtractor = new TPHExtractor(); + List results = new ArrayList(); + GeneratedGenericsFinder generatedGenericsFinder = new GeneratedGenericsFinder(sf, results); + } + + public static SourceFile generateAST(){ + ArrayList classes = new ArrayList<>(); + ArrayList fields = new ArrayList<>(); + ArrayList methods = new ArrayList<>(); + + fields.add(generateField("fld1")); + String[] paramNames = {"a"}; + methods.add(generateMethod("testMethode", paramNames)); + + classes.add(new ClassOrInterface(Modifier.PUBLIC, new JavaClassName("Test"), fields, Optional.empty(), methods, + new ArrayList<>(), generateEmptyGenericDeclList(), + new RefType(new JavaClassName("java.lang.Object"), new NullToken()), + false, new ArrayList<>(), new NullToken())); + + return new SourceFile("Test.jav", classes, new HashSet<>()); + } + + public static Method generateMethod(String methodName, String[] paramNames){ + ArrayList parameters = new ArrayList<>(); + for(String str: paramNames) { + FormalParameter fp = new FormalParameter(str, TypePlaceholder.fresh(new NullToken()), new NullToken()); + parameters.add(fp); + + } + ParameterList parameterList = new ParameterList(parameters, new NullToken()); + return new Method(Modifier.PUBLIC, methodName, TypePlaceholder.fresh(new NullToken()), parameterList, + new Block(new ArrayList<>(), new NullToken()), generateEmptyGenericDeclList(), new NullToken()); + } + + public static GenericDeclarationList generateEmptyGenericDeclList(){ + return new GenericDeclarationList(new ArrayList<>(), new NullToken()); + } + + public static Field generateField(String fieldName) { + return new Field(fieldName, TypePlaceholder.fresh(new NullToken()), Modifier.PUBLIC, new NullToken()); + } +} diff --git a/app/src/test/java/finiteClosure/SuperInterfacesTest.java b/app/src/test/java/finiteClosure/SuperInterfacesTest.java new file mode 100644 index 00000000..d74215b7 --- /dev/null +++ b/app/src/test/java/finiteClosure/SuperInterfacesTest.java @@ -0,0 +1,46 @@ +package finiteClosure; + +import de.dhbwstuttgart.parser.SyntaxTreeGenerator.FCGenerator; +import de.dhbwstuttgart.syntaxtree.ClassOrInterface; +import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class SuperInterfacesTest { + @Test + public void test() throws ClassNotFoundException { + Collection classes = new ArrayList<>(); + classes.add(ASTFactory.createClass(TestClass.class)); + System.out.println(FCGenerator.toFC(classes, ClassLoader.getSystemClassLoader())); + } + + @Test + public void testGeneric() throws ClassNotFoundException { + Collection classes = new ArrayList<>(); + classes.add(ASTFactory.createClass(TestClassGeneric.class)); + System.out.println(FCGenerator.toFC(classes, ClassLoader.getSystemClassLoader())); + } +} + +class TestClass implements Test2, Test3{ + +} + +class TestClassGeneric implements Test4{ + +} + +interface Test2 { + +} + +interface Test3{ + +} + +interface Test4{ + +} \ No newline at end of file diff --git a/app/src/test/java/general/TestCleanUp.java b/app/src/test/java/general/TestCleanUp.java new file mode 100644 index 00000000..f1b82cc8 --- /dev/null +++ b/app/src/test/java/general/TestCleanUp.java @@ -0,0 +1,14 @@ +package general; + +import java.io.File; +import java.io.FileFilter; + +public class TestCleanUp { + + public static void cleanUpDirectory(File directory, FileFilter fileFilter){ + if(!directory.isDirectory()) throw new RuntimeException("Directory for bytecode generation is wrong!"); + for (File file: directory.listFiles(fileFilter)) { + file.delete(); + } + } +} diff --git a/app/src/test/java/insertGenerics/FamilyOfGeneratedGenericsTest.java b/app/src/test/java/insertGenerics/FamilyOfGeneratedGenericsTest.java new file mode 100644 index 00000000..53122862 --- /dev/null +++ b/app/src/test/java/insertGenerics/FamilyOfGeneratedGenericsTest.java @@ -0,0 +1,228 @@ +/* +package insertGenerics; + +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; +import de.dhbwstuttgart.bytecode.insertGenerics.*; +import de.dhbwstuttgart.bytecode.utilities.MethodAndTPH; +import junit.framework.TestCase; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +public class FamilyOfGeneratedGenericsTest extends TestCase { + + public void testIdentityMethod(){ + */ +/* + Example method: + A id(B i) return i; + gives constraint: B <. A and A <. Object, which are method constraints + *//* + + + List inputConstraints = new ArrayList<>(); + inputConstraints.add(new TPHConstraint("B", "A", TPHConstraint.Relation.EXTENDS)); + + HashMap> tphPositions = new HashMap<>(); + PairTphMethod meth1 = new PairTphMethod(PositionFinder.Position.METHOD, "m1"); + tphPositions.put("A", meth1); + tphPositions.put("B", meth1); + + List classConstraints = FamilyOfGeneratedGenerics.getClassConstraints(inputConstraints, tphPositions); + assertTrue(classConstraints.isEmpty()); + + */ +/* + MethodConstraints should be the same as the input constraint + *//* + +// List methodConstraints = FamilyOfGeneratedGenerics.getMethodConstraints(inputConstraints, new ArrayList(), tphPositions); +// assertTrue(methodConstraints.size() == 2); +// assertTrue(methodConstraints.get(0).getLeft().equals("B")); +// assertTrue(methodConstraints.get(0).getRight().equals("A")); + } + + public void testClassField(){ + */ +/* + class Example{ + A f; + B fReturn(){ + return f; + } + } + gives constraint: A <. B and B <. Object which are class constraints + *//* + + + List inputConstraints = new ArrayList<>(); + inputConstraints.add(new TPHConstraint("A", "B", TPHConstraint.Relation.EXTENDS)); + + HashMap> tphPositions = new HashMap<>(); + PairTphMethod posOfA = new PairTphMethod<>(PositionFinder.Position.FIELD, null); + tphPositions.put("A", posOfA); + PairTphMethod posOfB = new PairTphMethod<>(PositionFinder.Position.METHOD, "fReturn"); + tphPositions.put("B", posOfB); + + */ +/* + ClassConstraints should not be the same as the input constraint + *//* + + List classConstraints = FamilyOfGeneratedGenerics.getClassConstraints(inputConstraints, tphPositions); + System.out.println(classConstraints); + assertTrue(classConstraints.size() == 2); + //assertTrue(classConstraints.get(0).getLeft().equals("A")); + //assertTrue(classConstraints.get(0).getRight().equals("B")); +// HashMap> methodConstraintsWithPosition = FamilyOfGeneratedGenerics.getMethodConstraintsWithPosition(inputConstraints,classConstraints,tphPositions,) + } + + public void testSecondLineOfClassConstraints() { + */ +/* + class Example() { + A a; + B b = a; + C anyMethod() { + F f; + return f; + } + D otherMethod(E e) { + this.b = e; + e = this.a; + return e; + } + } + *//* + + + List inputConstraints = new ArrayList<>(); + inputConstraints.add(new TPHConstraint("A", "B", TPHConstraint.Relation.EXTENDS)); + inputConstraints.add(new TPHConstraint("F", "C", TPHConstraint.Relation.EXTENDS)); + inputConstraints.add(new TPHConstraint("E", "B", TPHConstraint.Relation.EXTENDS)); + inputConstraints.add(new TPHConstraint("A", "E", TPHConstraint.Relation.EXTENDS)); + inputConstraints.add(new TPHConstraint("E", "D", TPHConstraint.Relation.EXTENDS)); + + HashMap> tphPositions = new HashMap<>(); + PairTphMethod posOfA = new PairTphMethod<>(PositionFinder.Position.FIELD, null); + PairTphMethod posOfB = new PairTphMethod<>(PositionFinder.Position.FIELD, null); + PairTphMethod posOfC = new PairTphMethod<>(PositionFinder.Position.METHOD, "anyMethod"); + PairTphMethod posOfD = new PairTphMethod<>(PositionFinder.Position.METHOD, "otherMethod"); + PairTphMethod posOfE = new PairTphMethod<>(PositionFinder.Position.METHOD, "otherMethod"); + PairTphMethod posOfF = new PairTphMethod<>(PositionFinder.Position.METHOD, "anyMethod"); + + tphPositions.put("A", posOfA); + tphPositions.put("B", posOfB); + tphPositions.put("C", posOfC); + tphPositions.put("F", posOfF); + tphPositions.put("D", posOfD); + tphPositions.put("E", posOfE); + + List classConstraints = FamilyOfGeneratedGenerics.getClassConstraints(inputConstraints, tphPositions); + System.out.println(classConstraints); +// List methodConstraints = FamilyOfGeneratedGenerics.getMethodConstraints(inputConstraints, classConstraints, tphPositions); +// System.out.println(methodConstraints); + assertFalse(classConstraints.isEmpty()); + assertTrue(classConstraints.size() == 6); +// assertFalse(methodConstraints.isEmpty()); +// assertTrue(methodConstraints.size() == 2); + + } + + public void testTPHsAndGenerics() { + */ +/* + class TPHsAndGenerics { + Fun1 id = x -> x; + C id2 (D x) { + return id.apply(x); + } + E m(F a, G b){ + var c = m2(a,b); + return a; + } + H m2(I a, J b){ + return b; + } + } + *//* + + + List inputConstraints = new ArrayList<>(); + inputConstraints.add(new TPHConstraint("A","B", TPHConstraint.Relation.EXTENDS)); + inputConstraints.add(new TPHConstraint("B","C", TPHConstraint.Relation.EXTENDS)); + inputConstraints.add(new TPHConstraint("D","A", TPHConstraint.Relation.EXTENDS)); + inputConstraints.add(new TPHConstraint("F","E", TPHConstraint.Relation.EXTENDS)); + inputConstraints.add(new TPHConstraint("F","I", TPHConstraint.Relation.EXTENDS)); + inputConstraints.add(new TPHConstraint("G","J", TPHConstraint.Relation.EXTENDS)); + inputConstraints.add(new TPHConstraint("J","H", TPHConstraint.Relation.EXTENDS)); + + HashMap> tphPositions = new HashMap<>(); + PairTphMethod posOfA = new PairTphMethod<>(PositionFinder.Position.FIELD, null); + PairTphMethod posOfB = new PairTphMethod<>(PositionFinder.Position.FIELD, null); + PairTphMethod posOfC = new PairTphMethod<>(PositionFinder.Position.METHOD, "id2"); + PairTphMethod posOfD = new PairTphMethod<>(PositionFinder.Position.METHOD, "id2"); + PairTphMethod posOfE = new PairTphMethod<>(PositionFinder.Position.METHOD, "m"); + PairTphMethod posOfF = new PairTphMethod<>(PositionFinder.Position.METHOD, "m"); + PairTphMethod posOfG = new PairTphMethod<>(PositionFinder.Position.METHOD, "m"); + PairTphMethod posOfH = new PairTphMethod<>(PositionFinder.Position.METHOD, "m2"); + PairTphMethod posOfI = new PairTphMethod<>(PositionFinder.Position.METHOD, "m2"); + PairTphMethod posOfJ = new PairTphMethod<>(PositionFinder.Position.METHOD, "m2"); + + tphPositions.put("A", posOfA); + tphPositions.put("B", posOfB); + tphPositions.put("C", posOfC); + tphPositions.put("D", posOfD); + tphPositions.put("E", posOfE); + tphPositions.put("F", posOfF); + tphPositions.put("G", posOfG); + tphPositions.put("H", posOfH); + tphPositions.put("I", posOfI); + tphPositions.put("J", posOfJ); + + List classConstraints = FamilyOfGeneratedGenerics.getClassConstraints(inputConstraints, tphPositions); + System.out.println(classConstraints); +// List methodConstraints = FamilyOfGeneratedGenerics.getMethodConstraints(inputConstraints, classConstraints, tphPositions); +// System.out.println(methodConstraints); + + assertFalse(classConstraints.isEmpty()); + assertTrue(classConstraints.size() == 3); +// assertFalse(methodConstraints.isEmpty()); +// assertTrue(methodConstraints.size()==9); + } + + + public void testPositionConverter() { + HashMap allTphsOld = new HashMap<>(); + List listOfMethodsAndTphs = new ArrayList<>(); + allTphsOld.put("A", true); + allTphsOld.put("B", false); + MethodAndTPH m1 = new MethodAndTPH("m1"); + m1.getTphs().add("A"); + MethodAndTPH bla = new MethodAndTPH("bla"); + MethodAndTPH blubb = new MethodAndTPH("blubb"); +// blubb.getTphs().add("A"); + listOfMethodsAndTphs.add(bla); + listOfMethodsAndTphs.add(blubb); + listOfMethodsAndTphs.add(m1); + + + + HashMap>> allTphsNew = FamilyOfGeneratedGenerics.positionConverter(allTphsOld, listOfMethodsAndTphs); + System.out.println(allTphsNew); + //was tun wenn zwei (oder mehr) Methoden gleiches TPH enthalten? + //ist dies möglich oder werden die TPHs immer verschieden initialisiert und dann erst am Ende gemappt? + //überarbeiten oder lassen? + + + assertTrue(allTphsNew.get("A").fst.equals(PositionFinder.Position.METHOD)); + assertTrue(allTphsNew.get("B").fst.equals(PositionFinder.Position.FIELD)); + } + + + public void testFirstTransitiveSubtypeForMethodTypes(){ + + } + +}*/ diff --git a/app/src/test/java/insertGenerics/TestAny.java b/app/src/test/java/insertGenerics/TestAny.java new file mode 100644 index 00000000..5865e16b --- /dev/null +++ b/app/src/test/java/insertGenerics/TestAny.java @@ -0,0 +1,112 @@ +package insertGenerics; + +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericGenratorResultForSourceFile; +import de.dhbwstuttgart.bytecode.insertGenerics.ClassConstraint; +import de.dhbwstuttgart.bytecode.insertGenerics.FamilyOfGeneratedGenerics; +import de.dhbwstuttgart.bytecode.insertGenerics.MethodConstraint; +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter; +import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter; +import de.dhbwstuttgart.typedeployment.TypeInsert; +import de.dhbwstuttgart.typedeployment.TypeInsertFactory; +import de.dhbwstuttgart.typeinference.result.ResultSet; + +import org.junit.BeforeClass; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class TestAny { + + public static final String rootDirectory = System.getProperty("user.dir")+"/resources/insertGenericsJav/"; + + @BeforeClass + public static void resetNamesOfTypePlaceholder() { + de.dhbwstuttgart.syntaxtree.factory.NameGenerator.reset(); + } + + @Test + public void ggFinder() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"TestAny.jav")); + } + + private static class TestResultSet{ + + } + + public TestResultSet execute(File fileToTest) throws IOException, ClassNotFoundException { + JavaTXCompiler compiler = new JavaTXCompiler(fileToTest); + for(File f : compiler.sourceFiles.keySet()){ + SourceFile sf = compiler.sourceFiles.get(f); + } + List results = compiler.typeInference(); + List simplifyResultsForAllSourceFiles = compiler.getGeneratedGenericResultsForAllSourceFiles(results); + + List classConstraintsTest = new ArrayList<>(); + classConstraintsTest.add(new ClassConstraint("N", "O", Relation.EXTENDS)); + classConstraintsTest.add(new ClassConstraint("N", "U", Relation.EXTENDS)); + classConstraintsTest.add(new ClassConstraint("U", "O", Relation.EXTENDS)); + classConstraintsTest.add(new ClassConstraint("O", "java/lang/Object", Relation.EXTENDS)); + HashMap> methodConstraintsWithPositionTest = new HashMap<>(); + Set lmc; + lmc = new HashSet<>(); + lmc.add(new MethodConstraint("R", "java/lang/Object", Relation.EXTENDS)); + methodConstraintsWithPositionTest.put("TPH RanyMethod()", lmc); + lmc = new HashSet<>(); + methodConstraintsWithPositionTest.put("TPH UotherMethod(TPH U)", lmc); + + FamilyOfGeneratedGenerics fogg = compiler.fogg; + Set computedClassCons = new HashSet<>(fogg.classConstraints); + Set expectedClassCons = new HashSet<>(classConstraintsTest); + + assertEquals(expectedClassCons, computedClassCons); + + HashMap> methodConstraintsWithPositionComputed = new HashMap<>(); + fogg.methodConstraintsWithPosition.forEach((s, l) -> methodConstraintsWithPositionComputed.put(s,new HashSet<>(l))); + + assertEquals(methodConstraintsWithPositionTest, methodConstraintsWithPositionComputed); + + //compiler.generateBytecode(rootDirectory+"xxx.class", results, simplifyResultsForAllSourceFiles); + for(File f : compiler.sourceFiles.keySet()){ + SourceFile sf = compiler.sourceFiles.get(f); + System.out.println(ASTTypePrinter.print(sf)); + System.out.println(ASTPrinter.print(sf)); + //List results = compiler.typeInference(); PL 2017-10-03 vor die For-Schleife gezogen + assert results.size()>0; + Set insertedTypes = new HashSet<>(); + for(ResultSet resultSet : results){ + Set result = TypeInsertFactory.createTypeInsertPoints(sf, resultSet, results, simplifyResultsForAllSourceFiles); + assert result.size()>0; + String content = readFile(f.getPath(), StandardCharsets.UTF_8); + for(TypeInsert tip : result){ + insertedTypes.add(tip.insert(content)); + } + } + for(String s : insertedTypes){ + System.out.println(s); + } + } + return new TestResultSet(); + } + + static String readFile(String path, Charset encoding) + throws IOException + { + byte[] encoded = Files.readAllBytes(Paths.get(path)); + return new String(encoded, encoding); + } +} diff --git a/app/src/test/java/insertGenerics/TestClassField.java b/app/src/test/java/insertGenerics/TestClassField.java new file mode 100644 index 00000000..4f03ceb0 --- /dev/null +++ b/app/src/test/java/insertGenerics/TestClassField.java @@ -0,0 +1,79 @@ +package insertGenerics; + +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericGenratorResultForSourceFile; +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter; +import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter; +import de.dhbwstuttgart.typedeployment.TypeInsert; +import de.dhbwstuttgart.typedeployment.TypeInsertFactory; +import de.dhbwstuttgart.typeinference.result.ResultSet; + +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class TestClassField { + + public static final String rootDirectory = System.getProperty("user.dir")+"/resources/insertGenericsJav/"; + + @BeforeClass + public static void resetNamesOfTypePlaceholder() { + de.dhbwstuttgart.syntaxtree.factory.NameGenerator.reset(); + } + + @Test + public void ggFinder() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"TestClassField.jav")); + } + + private static class TestResultSet{ + + } + + public TestResultSet execute(File fileToTest) throws IOException, ClassNotFoundException { + JavaTXCompiler compiler = new JavaTXCompiler(fileToTest); + for(File f : compiler.sourceFiles.keySet()){ + SourceFile sf = compiler.sourceFiles.get(f); + } + List results = compiler.typeInference(); + List simplifyResultsForAllSourceFiles = compiler.getGeneratedGenericResultsForAllSourceFiles(results); + //compiler.generateBytecode(rootDirectory+"xxx.class", results, simplifyResultsForAllSourceFiles); + for(File f : compiler.sourceFiles.keySet()){ + SourceFile sf = compiler.sourceFiles.get(f); + System.out.println(ASTTypePrinter.print(sf)); + System.out.println(ASTPrinter.print(sf)); + //List results = compiler.typeInference(); PL 2017-10-03 vor die For-Schleife gezogen + assert results.size()>0; + Set insertedTypes = new HashSet<>(); + for(ResultSet resultSet : results){ + Set result = TypeInsertFactory.createTypeInsertPoints(sf, resultSet, results, simplifyResultsForAllSourceFiles); + assert result.size()>0; + String content = readFile(f.getPath(), StandardCharsets.UTF_8); + for(TypeInsert tip : result){ + insertedTypes.add(tip.insert(content)); + } + } + for(String s : insertedTypes){ + System.out.println(s); + } + } + return new TestResultSet(); + } + + static String readFile(String path, Charset encoding) + throws IOException + { + byte[] encoded = Files.readAllBytes(Paths.get(path)); + return new String(encoded, encoding); + } +} diff --git a/app/src/test/java/insertGenerics/TestContraVariant.java b/app/src/test/java/insertGenerics/TestContraVariant.java new file mode 100644 index 00000000..3e04a6ae --- /dev/null +++ b/app/src/test/java/insertGenerics/TestContraVariant.java @@ -0,0 +1,112 @@ +package insertGenerics; + +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericGenratorResultForSourceFile; +import de.dhbwstuttgart.bytecode.insertGenerics.ClassConstraint; +import de.dhbwstuttgart.bytecode.insertGenerics.FamilyOfGeneratedGenerics; +import de.dhbwstuttgart.bytecode.insertGenerics.MethodConstraint; +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter; +import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter; +import de.dhbwstuttgart.typedeployment.TypeInsert; +import de.dhbwstuttgart.typedeployment.TypeInsertFactory; +import de.dhbwstuttgart.typeinference.result.ResultSet; + +import org.junit.BeforeClass; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class TestContraVariant { + + public static final String rootDirectory = System.getProperty("user.dir")+"/resources/insertGenericsJav/"; + + @BeforeClass + public static void resetNamesOfTypePlaceholder() { + de.dhbwstuttgart.syntaxtree.factory.NameGenerator.reset(); + } + + @Test + public void ggFinder() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"TestContraVariant.jav")); + } + + private static class TestResultSet{ + + } + + public TestResultSet execute(File fileToTest) throws IOException, ClassNotFoundException { + JavaTXCompiler compiler = new JavaTXCompiler(fileToTest); + for(File f : compiler.sourceFiles.keySet()){ + SourceFile sf = compiler.sourceFiles.get(f); + } + List results = compiler.typeInference(); + List simplifyResultsForAllSourceFiles = compiler.getGeneratedGenericResultsForAllSourceFiles(results); + + List classConstraintsTest = new ArrayList<>(); + HashMap> methodConstraintsWithPositionTest = new HashMap<>(); + Set lmc; + lmc = new HashSet<>(); + lmc.add(new MethodConstraint("R", "O", Relation.EXTENDS)); + lmc.add(new MethodConstraint("O", "java/lang/Object", Relation.EXTENDS)); + methodConstraintsWithPositionTest.put("TPH Rm(TPH O)", lmc); + lmc = new HashSet<>(); + //lmc.add(new MethodConstraint("S", "O", Relation.EXTENDS)); + lmc.add(new MethodConstraint("S", "java/lang/Object", Relation.EXTENDS)); + lmc.add(new MethodConstraint("R", "java/lang/Object", Relation.EXTENDS)); + methodConstraintsWithPositionTest.put("TPH Rmain(TPH S)", lmc); + + FamilyOfGeneratedGenerics fogg = compiler.fogg; + Set computedClassCons = new HashSet<>(fogg.classConstraints); + Set expectedClassCons = new HashSet<>(classConstraintsTest); + + assertEquals(expectedClassCons, computedClassCons); + + HashMap> methodConstraintsWithPositionComputed = new HashMap<>(); + fogg.methodConstraintsWithPosition.forEach((s, l) -> methodConstraintsWithPositionComputed.put(s,new HashSet<>(l))); + + assertEquals(methodConstraintsWithPositionTest, methodConstraintsWithPositionComputed); + + //compiler.generateBytecode(rootDirectory+"xxx.class", results, simplifyResultsForAllSourceFiles); + for(File f : compiler.sourceFiles.keySet()){ + SourceFile sf = compiler.sourceFiles.get(f); + System.out.println(ASTTypePrinter.print(sf)); + System.out.println(ASTPrinter.print(sf)); + //List results = compiler.typeInference(); PL 2017-10-03 vor die For-Schleife gezogen + assert results.size()>0; + Set insertedTypes = new HashSet<>(); + for(ResultSet resultSet : results){ + Set result = TypeInsertFactory.createTypeInsertPoints(sf, resultSet, results, simplifyResultsForAllSourceFiles); + assert result.size()>0; + String content = readFile(f.getPath(), StandardCharsets.UTF_8); + for(TypeInsert tip : result){ + insertedTypes.add(tip.insert(content)); + } + } + for(String s : insertedTypes){ + System.out.println(s); + } + } + return new TestResultSet(); + } + + static String readFile(String path, Charset encoding) + throws IOException + { + byte[] encoded = Files.readAllBytes(Paths.get(path)); + return new String(encoded, encoding); + } +} diff --git a/app/src/test/java/insertGenerics/TestExample42.java b/app/src/test/java/insertGenerics/TestExample42.java new file mode 100644 index 00000000..a052bacf --- /dev/null +++ b/app/src/test/java/insertGenerics/TestExample42.java @@ -0,0 +1,62 @@ +package insertGenerics; + +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; +import de.dhbwstuttgart.bytecode.insertGenerics.*; +import org.junit.Test; +import static org.junit.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +public class TestExample42 { + public List fillConstraintsList() { + List cs = new ArrayList<>(); + cs.add(new TPHConstraint("M", "N", Relation.EXTENDS)); + cs.add(new TPHConstraint("N", "Z", Relation.EXTENDS)); + cs.add(new TPHConstraint("Q", "K", Relation.EXTENDS)); + cs.add(new TPHConstraint("K", "P", Relation.EXTENDS)); + cs.add(new TPHConstraint("W", "M", Relation.EXTENDS)); + cs.add(new TPHConstraint("Z", "V", Relation.EXTENDS)); + return cs; + } + + public HashMap> fillPosOfTphs() { + HashMap> posOfTphs = new HashMap<>(); + + // TPHs "U" und "L" auskommentiert, da nach Vorgaben L zu Z umbenannt und U als void interpretiert wird + PairTphMethod posOfK = new PairTphMethod<>(PositionFinder.Position.FIELD, null); +// PairTphMethod posOfL = new PairTphMethod<>(PositionFinder.Position.METHOD, "id"); + PairTphMethod posOfM = new PairTphMethod<>(PositionFinder.Position.METHOD, "id"); + PairTphMethod posOfN = new PairTphMethod<>(PositionFinder.Position.METHOD, "id"); + PairTphMethod posOfP = new PairTphMethod<>(PositionFinder.Position.METHOD, "setA"); + PairTphMethod posOfQ = new PairTphMethod<>(PositionFinder.Position.METHOD, "setA"); +// PairTphMethod posOfU = new PairTphMethod<>(PositionFinder.Position.METHOD, "m"); + PairTphMethod posOfV = new PairTphMethod<>(PositionFinder.Position.METHOD, "m"); + PairTphMethod posOfW = new PairTphMethod<>(PositionFinder.Position.METHOD, "m"); + PairTphMethod posOfZ = new PairTphMethod<>(PositionFinder.Position.METHOD, "m"); + + posOfTphs.put("K", posOfK); +// posOfTphs.put("L", posOfL); + posOfTphs.put("M", posOfM); + posOfTphs.put("N", posOfN); + posOfTphs.put("P", posOfP); + posOfTphs.put("Q", posOfQ); +// posOfTphs.put("U", posOfU); + posOfTphs.put("V", posOfV); + posOfTphs.put("W", posOfW); + posOfTphs.put("Z", posOfZ); + return posOfTphs; + } + + @Test + public void genericTest() { +// List classConstraints = FamilyOfGeneratedGenerics.getClassConstraints(fillConstraintsList(),fillPosOfTphs()); +// System.out.println("ClassConstraints: " + classConstraints); +// List methodConstraints = FamilyOfGeneratedGenerics.getMethodConstraints(fillConstraintsList(),classConstraints,fillPosOfTphs()); +// System.out.println("MethodConstraints: " + methodConstraints); + + List testCons; + } +} diff --git a/app/src/test/java/insertGenerics/TestExample42_allInOneMethod.java b/app/src/test/java/insertGenerics/TestExample42_allInOneMethod.java new file mode 100644 index 00000000..f3fe7213 --- /dev/null +++ b/app/src/test/java/insertGenerics/TestExample42_allInOneMethod.java @@ -0,0 +1,61 @@ +package insertGenerics; + +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; +import de.dhbwstuttgart.bytecode.insertGenerics.*; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +public class TestExample42_allInOneMethod { + public List fillConstraintsList() { + List cs = new ArrayList<>(); + cs.add(new TPHConstraint("M", "N", Relation.EXTENDS)); + cs.add(new TPHConstraint("N", "Z", Relation.EXTENDS)); + cs.add(new TPHConstraint("Q", "K", Relation.EXTENDS)); + cs.add(new TPHConstraint("K", "P", Relation.EXTENDS)); + cs.add(new TPHConstraint("W", "M", Relation.EXTENDS)); + cs.add(new TPHConstraint("Z", "V", Relation.EXTENDS)); + return cs; + } + + public HashMap> fillPosOfTphs() { + HashMap> posOfTphs = new HashMap<>(); + + // TPHs "U" und "L" auskommentiert, da nach Vorgaben L zu Z umbenannt und U als void interpretiert wird + PairTphMethod posOfK = new PairTphMethod<>(PositionFinder.Position.FIELD, null); +// PairTphMethod posOfL = new PairTphMethod<>(PositionFinder.Position.METHOD, "sameMethod"); + PairTphMethod posOfM = new PairTphMethod<>(PositionFinder.Position.METHOD, "sameMethod"); + PairTphMethod posOfN = new PairTphMethod<>(PositionFinder.Position.METHOD, "sameMethod"); + PairTphMethod posOfP = new PairTphMethod<>(PositionFinder.Position.METHOD, "sameMethod"); + PairTphMethod posOfQ = new PairTphMethod<>(PositionFinder.Position.METHOD, "sameMethod"); +// PairTphMethod posOfU = new PairTphMethod<>(PositionFinder.Position.METHOD, "sameMethod"); + PairTphMethod posOfV = new PairTphMethod<>(PositionFinder.Position.METHOD, "sameMethod"); + PairTphMethod posOfW = new PairTphMethod<>(PositionFinder.Position.METHOD, "sameMethod"); + PairTphMethod posOfZ = new PairTphMethod<>(PositionFinder.Position.METHOD, "sameMethod"); + + posOfTphs.put("K", posOfK); +// posOfTphs.put("L", posOfL); + posOfTphs.put("M", posOfM); + posOfTphs.put("N", posOfN); + posOfTphs.put("P", posOfP); + posOfTphs.put("Q", posOfQ); +// posOfTphs.put("U", posOfU); + posOfTphs.put("V", posOfV); + posOfTphs.put("W", posOfW); + posOfTphs.put("Z", posOfZ); + return posOfTphs; + } + + @Test + public void genericTest() { +// List classConstraints = FamilyOfGeneratedGenerics.getClassConstraints(fillConstraintsList(),fillPosOfTphs()); +// System.out.println("ClassConstraints: " + classConstraints); +// List methodConstraints = FamilyOfGeneratedGenerics.getMethodConstraints(fillConstraintsList(),classConstraints,fillPosOfTphs(),); +// System.out.println("MethodConstraints: " + methodConstraints); + + List testCons; + } +} diff --git a/app/src/test/java/insertGenerics/TestGGFinder.java b/app/src/test/java/insertGenerics/TestGGFinder.java new file mode 100644 index 00000000..cc4fdcc6 --- /dev/null +++ b/app/src/test/java/insertGenerics/TestGGFinder.java @@ -0,0 +1,99 @@ +package insertGenerics; + +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericGenratorResultForSourceFile; +import de.dhbwstuttgart.bytecode.insertGenerics.ClassConstraint; +import de.dhbwstuttgart.bytecode.insertGenerics.FamilyOfGeneratedGenerics; +import de.dhbwstuttgart.bytecode.insertGenerics.MethodConstraint; +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter; +import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter; +import de.dhbwstuttgart.typedeployment.TypeInsert; +import de.dhbwstuttgart.typedeployment.TypeInsertFactory; +import de.dhbwstuttgart.typeinference.result.ResultSet; + +import org.junit.BeforeClass; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class TestGGFinder { + + private static final String rootDirectory = System.getProperty("user.dir")+"/resources/insertGenericsJav/"; + private String pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + private static ClassLoader loader; + private static Class classToTest; + private static Object instanceOfClass; + private static String className = "TestGGFinder"; + + @BeforeClass + public static void resetNamesOfTypePlaceholder() { + de.dhbwstuttgart.syntaxtree.factory.NameGenerator.reset(); + } + + @Test + public void ggFinder() throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { + execute(new File(rootDirectory+className+".jav")); + } + + private static class TestResultSet{ + + } + + public TestResultSet execute(File fileToTest) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { + JavaTXCompiler compiler = new JavaTXCompiler(fileToTest); + List results = compiler.typeInference(); + List simplifyResultsForAllSourceFiles = compiler.getGeneratedGenericResultsForAllSourceFiles(results); + + List classConstraintsTest = new ArrayList<>(); + classConstraintsTest.add(new ClassConstraint("S", "java/lang/Object", Relation.EXTENDS)); + HashMap> methodConstraintsWithPositionTest = new HashMap<>(); + Set lmc; + lmc = new HashSet<>(); + lmc.add(new MethodConstraint("P", "AC", Relation.EXTENDS)); + lmc.add(new MethodConstraint("AC", "java/lang/Object", Relation.EXTENDS)); + methodConstraintsWithPositionTest.put("TPH ACid(TPH P)", lmc); + lmc = new HashSet<>(); + lmc.add(new MethodConstraint("T", "S", Relation.EXTENDS)); + methodConstraintsWithPositionTest.put("TPH SsetA(TPH T)", lmc); + lmc = new HashSet<>(); + lmc.add(new MethodConstraint("AC", "Y", Relation.EXTENDS)); + lmc.add(new MethodConstraint("Z", "P", Relation.EXTENDS)); + lmc.add(new MethodConstraint("P", "AC", Relation.EXTENDS)); + lmc.add(new MethodConstraint("Y", "java/lang/Object", Relation.EXTENDS)); + methodConstraintsWithPositionTest.put("voidm(TPH YTPH Z)", lmc); + + FamilyOfGeneratedGenerics fogg = compiler.fogg; + Set computedClassCons = new HashSet<>(fogg.classConstraints); + Set expectedClassCons = new HashSet<>(classConstraintsTest); + + assertEquals(expectedClassCons, computedClassCons); + + HashMap> methodConstraintsWithPositionComputed = new HashMap<>(); + fogg.methodConstraintsWithPosition.forEach((s, l) -> methodConstraintsWithPositionComputed.put(s,new HashSet<>(l))); + + assertEquals(methodConstraintsWithPositionTest, methodConstraintsWithPositionComputed); + + compiler.generateBytecode(new File(pathToClassFile), results, simplifyResultsForAllSourceFiles); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass(className); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + return new TestResultSet(); + } +} diff --git a/app/src/test/java/insertGenerics/TestLocalVarLambda.java b/app/src/test/java/insertGenerics/TestLocalVarLambda.java new file mode 100644 index 00000000..8fc87a82 --- /dev/null +++ b/app/src/test/java/insertGenerics/TestLocalVarLambda.java @@ -0,0 +1,112 @@ +package insertGenerics; + +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericGenratorResultForSourceFile; +import de.dhbwstuttgart.bytecode.insertGenerics.ClassConstraint; +import de.dhbwstuttgart.bytecode.insertGenerics.FamilyOfGeneratedGenerics; +import de.dhbwstuttgart.bytecode.insertGenerics.MethodConstraint; +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter; +import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter; +import de.dhbwstuttgart.typedeployment.TypeInsert; +import de.dhbwstuttgart.typedeployment.TypeInsertFactory; +import de.dhbwstuttgart.typeinference.result.ResultSet; + +import org.junit.BeforeClass; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class TestLocalVarLambda { + + private static final String rootDirectory = System.getProperty("user.dir")+"/resources/insertGenericsJav/"; + private String pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + private static ClassLoader loader; + private static Class classToTest; + private static Object instanceOfClass; + private static String className = "TestLocalVarLambda"; + + @BeforeClass + public static void resetNamesOfTypePlaceholder() { + de.dhbwstuttgart.syntaxtree.factory.NameGenerator.reset(); + } + + @Test + public void ggFinder() throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { + execute(new File(rootDirectory+className+".jav")); + } + + private static class TestResultSet{ + + } + + public TestResultSet execute(File fileToTest) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { + JavaTXCompiler compiler = new JavaTXCompiler(fileToTest); + List results = compiler.typeInference(); + List simplifyResultsForAllSourceFiles = compiler.getGeneratedGenericResultsForAllSourceFiles(results); + + List classConstraintsTest = new ArrayList<>(); + HashMap> methodConstraintsWithPositionTest = new HashMap<>(); + + FamilyOfGeneratedGenerics fogg = compiler.fogg; + + Set lmc; + lmc = new HashSet<>(); + + if (fogg.allConstraints.contains((new MethodConstraint("O", "ALU", Relation.EXTENDS)))) { + lmc.add(new MethodConstraint("O", "ALU", Relation.EXTENDS)); + lmc.add(new MethodConstraint("DIU", "java/lang/Object", Relation.EXTENDS)); + lmc.add(new MethodConstraint("ALU", "DIU", Relation.EXTENDS)); + lmc.add(new MethodConstraint("SY", "java/lang/Object", Relation.EXTENDS)); + methodConstraintsWithPositionTest.put("TPH DIUm(TPH O)", lmc); + } + else if (fogg.allConstraints.contains((new MethodConstraint("O", "DIV", Relation.EXTENDS)))) { + lmc.add(new MethodConstraint("O", "DIV", Relation.EXTENDS)); + lmc.add(new MethodConstraint("N", "java/lang/Object", Relation.EXTENDS)); + lmc.add(new MethodConstraint("DIV", "N", Relation.EXTENDS)); + lmc.add(new MethodConstraint("SY", "java/lang/Object", Relation.EXTENDS)); + methodConstraintsWithPositionTest.put("TPH Nm(TPH O)", lmc); + } + else + { + lmc.add(new MethodConstraint("O", "DIU", Relation.EXTENDS)); + lmc.add(new MethodConstraint("N", "java/lang/Object", Relation.EXTENDS)); + lmc.add(new MethodConstraint("DIU", "N", Relation.EXTENDS)); + lmc.add(new MethodConstraint("SY", "java/lang/Object", Relation.EXTENDS)); + methodConstraintsWithPositionTest.put("TPH Nm(TPH O)", lmc); + } + + + Set computedClassCons = new HashSet<>(fogg.classConstraints); + Set expectedClassCons = new HashSet<>(classConstraintsTest); + + assertEquals(expectedClassCons, computedClassCons); + + HashMap> methodConstraintsWithPositionComputed = new HashMap<>(); + fogg.methodConstraintsWithPosition.forEach((s, l) -> methodConstraintsWithPositionComputed.put(s,new HashSet<>(l))); + + assertEquals(methodConstraintsWithPositionTest, methodConstraintsWithPositionComputed); + + compiler.generateBytecode(new File(pathToClassFile), results, simplifyResultsForAllSourceFiles); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass(className); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + return new TestResultSet(); + } +} diff --git a/app/src/test/java/insertGenerics/TestMutualRecursion.java b/app/src/test/java/insertGenerics/TestMutualRecursion.java new file mode 100644 index 00000000..a1345f6b --- /dev/null +++ b/app/src/test/java/insertGenerics/TestMutualRecursion.java @@ -0,0 +1,126 @@ +package insertGenerics; + +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericGenratorResultForSourceFile; +import de.dhbwstuttgart.bytecode.insertGenerics.ClassConstraint; +import de.dhbwstuttgart.bytecode.insertGenerics.FamilyOfGeneratedGenerics; +import de.dhbwstuttgart.bytecode.insertGenerics.MethodConstraint; +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter; +import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter; +import de.dhbwstuttgart.typedeployment.TypeInsert; +import de.dhbwstuttgart.typedeployment.TypeInsertFactory; +import de.dhbwstuttgart.typeinference.result.ResultSet; + +import org.junit.BeforeClass; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class TestMutualRecursion { + + private static final String rootDirectory = System.getProperty("user.dir")+"/resources/insertGenericsJav/"; + private String pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + private static ClassLoader loader; + private static Class classToTest; + private static Object instanceOfClass; + private static String className; + + @BeforeClass + public static void resetNamesOfTypePlaceholder() { + de.dhbwstuttgart.syntaxtree.factory.NameGenerator.reset(); + } + + @Test + public void TestMutualRecursion1() throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { + className = "TestMutualRecursion"; + JavaTXCompiler compiler = new JavaTXCompiler(new File(rootDirectory+className+".jav")); + List results = compiler.typeInference(); + List simplifyResultsForAllSourceFiles = compiler.getGeneratedGenericResultsForAllSourceFiles(results); + + + List classConstraintsTest = new ArrayList<>(); + classConstraintsTest.add(new ClassConstraint("N", "java/lang/Object", Relation.EXTENDS)); + HashMap> methodConstraintsWithPositionTest = new HashMap<>(); + Set lmc; + lmc = new HashSet<>(); + lmc.add(new MethodConstraint("P", "Q", Relation.EXTENDS)); + lmc.add(new MethodConstraint("Q", "java/lang/Object", Relation.EXTENDS)); + lmc.add(new MethodConstraint("AL", "java/lang/Object", Relation.EXTENDS)); + methodConstraintsWithPositionTest.put("TPH ALid(TPH P)", lmc); + lmc = new HashSet<>(); + lmc.add(new MethodConstraint("AL", "java/lang/Object", Relation.EXTENDS)); + lmc.add(new MethodConstraint("Z", "java/lang/Object", Relation.EXTENDS)); + methodConstraintsWithPositionTest.put("TPH ALm(TPH ALTPH Z)", lmc); + lmc = new HashSet<>(); + lmc.add(new MethodConstraint("AG", "java/lang/Object", Relation.EXTENDS)); + lmc.add(new MethodConstraint("AH", "java/lang/Object", Relation.EXTENDS)); + lmc.add(new MethodConstraint("AL", "java/lang/Object", Relation.EXTENDS)); + methodConstraintsWithPositionTest.put("TPH ALmain(TPH AGTPH AH)", lmc); + + FamilyOfGeneratedGenerics fogg = compiler.fogg; + Set computedClassCons = new HashSet<>(fogg.classConstraints); + Set expectedClassCons = new HashSet<>(classConstraintsTest); + + assertEquals(expectedClassCons, computedClassCons); + + HashMap> methodConstraintsWithPositionComputed = new HashMap<>(); + fogg.methodConstraintsWithPosition.forEach((s, l) -> methodConstraintsWithPositionComputed.put(s,new HashSet<>(l))); + + assertEquals(methodConstraintsWithPositionTest, methodConstraintsWithPositionComputed); + + compiler.generateBytecode(new File(pathToClassFile), results, simplifyResultsForAllSourceFiles); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass(className); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void TestMutualRecursionWithField() throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { + className = "TestMutualRecursionWithField"; + execute(new File(rootDirectory+className+".jav")); + } + + @Test + public void TestMutualRecursionWithField2() throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { + className = "TestMutualRecursionWithField2"; + execute(new File(rootDirectory+className+".jav")); + } + + @Test + public void TestMutualRecursionWithField3() throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { + className = "TestMutualRecursionWithField3"; + execute(new File(rootDirectory+className+".jav")); + } + + private static class TestResultSet{ + + } + + public TestResultSet execute(File fileToTest) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { + JavaTXCompiler compiler = new JavaTXCompiler(fileToTest); + List results = compiler.typeInference(); + List simplifyResultsForAllSourceFiles = compiler.getGeneratedGenericResultsForAllSourceFiles(results); + compiler.generateBytecode(new File(pathToClassFile), results, simplifyResultsForAllSourceFiles); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass(className); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + return new TestResultSet(); + } +} diff --git a/app/src/test/java/insertGenerics/TestReturnVar.java b/app/src/test/java/insertGenerics/TestReturnVar.java new file mode 100644 index 00000000..6c66cc73 --- /dev/null +++ b/app/src/test/java/insertGenerics/TestReturnVar.java @@ -0,0 +1,79 @@ +package insertGenerics; + +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericGenratorResultForSourceFile; +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter; +import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter; +import de.dhbwstuttgart.typedeployment.TypeInsert; +import de.dhbwstuttgart.typedeployment.TypeInsertFactory; +import de.dhbwstuttgart.typeinference.result.ResultSet; + +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class TestReturnVar { + + public static final String rootDirectory = System.getProperty("user.dir")+"/resources/insertGenericsJav/"; + + @BeforeClass + public static void resetNamesOfTypePlaceholder() { + de.dhbwstuttgart.syntaxtree.factory.NameGenerator.reset(); + } + + @Test + public void ggFinder() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"TestReturnVar.jav")); + } + + private static class TestResultSet{ + + } + + public TestResultSet execute(File fileToTest) throws IOException, ClassNotFoundException { + JavaTXCompiler compiler = new JavaTXCompiler(fileToTest); + for(File f : compiler.sourceFiles.keySet()){ + SourceFile sf = compiler.sourceFiles.get(f); + } + List results = compiler.typeInference(); + List simplifyResultsForAllSourceFiles = compiler.getGeneratedGenericResultsForAllSourceFiles(results); + //compiler.generateBytecode(rootDirectory+"xxx.class", results, simplifyResultsForAllSourceFiles); + for(File f : compiler.sourceFiles.keySet()){ + SourceFile sf = compiler.sourceFiles.get(f); + System.out.println(ASTTypePrinter.print(sf)); + System.out.println(ASTPrinter.print(sf)); + //List results = compiler.typeInference(); PL 2017-10-03 vor die For-Schleife gezogen + assert results.size()>0; + Set insertedTypes = new HashSet<>(); + for(ResultSet resultSet : results){ + Set result = TypeInsertFactory.createTypeInsertPoints(sf, resultSet, results, simplifyResultsForAllSourceFiles); + assert result.size()>0; + String content = readFile(f.getPath(), StandardCharsets.UTF_8); + for(TypeInsert tip : result){ + insertedTypes.add(tip.insert(content)); + } + } + for(String s : insertedTypes){ + System.out.println(s); + } + } + return new TestResultSet(); + } + + static String readFile(String path, Charset encoding) + throws IOException + { + byte[] encoded = Files.readAllBytes(Paths.get(path)); + return new String(encoded, encoding); + } +} diff --git a/app/src/test/java/insertGenerics/TestSecondLineOfClassConstraints.java b/app/src/test/java/insertGenerics/TestSecondLineOfClassConstraints.java new file mode 100644 index 00000000..73a72ed4 --- /dev/null +++ b/app/src/test/java/insertGenerics/TestSecondLineOfClassConstraints.java @@ -0,0 +1,79 @@ +package insertGenerics; + +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericGenratorResultForSourceFile; +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter; +import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter; +import de.dhbwstuttgart.typedeployment.TypeInsert; +import de.dhbwstuttgart.typedeployment.TypeInsertFactory; +import de.dhbwstuttgart.typeinference.result.ResultSet; + +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class TestSecondLineOfClassConstraints { + + public static final String rootDirectory = System.getProperty("user.dir")+"/resources/insertGenericsJav/"; + + @BeforeClass + public static void resetNamesOfTypePlaceholder() { + de.dhbwstuttgart.syntaxtree.factory.NameGenerator.reset(); + } + + @Test + public void ggFinder() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"TestSecondLineOfClassConstraints.jav")); + } + + private static class TestResultSet{ + + } + + public TestResultSet execute(File fileToTest) throws IOException, ClassNotFoundException { + JavaTXCompiler compiler = new JavaTXCompiler(fileToTest); + for(File f : compiler.sourceFiles.keySet()){ + SourceFile sf = compiler.sourceFiles.get(f); + } + List results = compiler.typeInference(); + List simplifyResultsForAllSourceFiles = compiler.getGeneratedGenericResultsForAllSourceFiles(results); + //compiler.generateBytecode(rootDirectory+"xxx.class", results, simplifyResultsForAllSourceFiles); + for(File f : compiler.sourceFiles.keySet()){ + SourceFile sf = compiler.sourceFiles.get(f); + System.out.println(ASTTypePrinter.print(sf)); + System.out.println(ASTPrinter.print(sf)); + //List results = compiler.typeInference(); PL 2017-10-03 vor die For-Schleife gezogen + assert results.size()>0; + Set insertedTypes = new HashSet<>(); + for(ResultSet resultSet : results){ + Set result = TypeInsertFactory.createTypeInsertPoints(sf, resultSet, results, simplifyResultsForAllSourceFiles); + assert result.size()>0; + String content = readFile(f.getPath(), StandardCharsets.UTF_8); + for(TypeInsert tip : result){ + insertedTypes.add(tip.insert(content)); + } + } + for(String s : insertedTypes){ + System.out.println(s); + } + } + return new TestResultSet(); + } + + static String readFile(String path, Charset encoding) + throws IOException + { + byte[] encoded = Files.readAllBytes(Paths.get(path)); + return new String(encoded, encoding); + } +} diff --git a/app/src/test/java/insertGenerics/TestTPHsAndGenerics.java b/app/src/test/java/insertGenerics/TestTPHsAndGenerics.java new file mode 100644 index 00000000..17318b84 --- /dev/null +++ b/app/src/test/java/insertGenerics/TestTPHsAndGenerics.java @@ -0,0 +1,154 @@ +package insertGenerics; + + import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericGenratorResultForSourceFile; +import de.dhbwstuttgart.bytecode.insertGenerics.ClassConstraint; +import de.dhbwstuttgart.bytecode.insertGenerics.FamilyOfGeneratedGenerics; +import de.dhbwstuttgart.bytecode.insertGenerics.MethodConstraint; +import de.dhbwstuttgart.core.JavaTXCompiler; + import de.dhbwstuttgart.syntaxtree.SourceFile; + import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter; + import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter; + import de.dhbwstuttgart.typedeployment.TypeInsert; + import de.dhbwstuttgart.typedeployment.TypeInsertFactory; + import de.dhbwstuttgart.typeinference.result.ResultSet; + +import org.junit.BeforeClass; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +import java.io.File; + import java.io.IOException; + import java.lang.reflect.InvocationTargetException; + import java.net.URL; + import java.net.URLClassLoader; + import java.nio.charset.Charset; + import java.nio.charset.StandardCharsets; + import java.nio.file.Files; + import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; + import java.util.List; + import java.util.Set; + + +public class TestTPHsAndGenerics { + + private static final String rootDirectory = System.getProperty("user.dir")+"/resources/insertGenericsJav/"; + private String pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + private static ClassLoader loader; + private static Class classToTest; + private static Object instanceOfClass; + private static String className = "TestTPHsAndGenerics"; + + @BeforeClass + public static void resetNamesOfTypePlaceholder() { + de.dhbwstuttgart.syntaxtree.factory.NameGenerator.reset(); + } + + @Test + public void ggFinder() throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { + execute(new File(rootDirectory+className+".jav")); + } + + private static class TestResultSet{ + + } + + public TestResultSet execute(File fileToTest) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { + JavaTXCompiler compiler = new JavaTXCompiler(fileToTest); + List results = compiler.typeInference(); + List simplifyResultsForAllSourceFiles = compiler.getGeneratedGenericResultsForAllSourceFiles(results); + + List classConstraintsTest = new ArrayList<>(); + HashMap> methodConstraintsWithPositionTest = new HashMap<>(); + + FamilyOfGeneratedGenerics fogg = compiler.fogg; + + Set lmc; + lmc = new HashSet<>(); + + if (fogg.allConstraints.contains((new MethodConstraint("DZP", "ETW", Relation.EXTENDS)))) { + classConstraintsTest.add(new ClassConstraint("UD", "DZP", Relation.EXTENDS)); + classConstraintsTest.add(new ClassConstraint("DZP", "ETW", Relation.EXTENDS)); + classConstraintsTest.add(new ClassConstraint("ETW", "java/lang/Object", Relation.EXTENDS)); + + lmc.add(new MethodConstraint("AI", "AE", Relation.EXTENDS)); + lmc.add(new MethodConstraint("AD", "AI", Relation.EXTENDS)); + //lmc.add(new MethodConstraint("AB", "AM", Relation.EXTENDS)); + lmc.add(new MethodConstraint("AE", "java/lang/Object", Relation.EXTENDS)); + lmc.add(new MethodConstraint("AB", "java/lang/Object", Relation.EXTENDS)); + methodConstraintsWithPositionTest.put("TPH ABm(TPH ABTPH AD)", lmc); + lmc = new HashSet<>(); + lmc.add(new MethodConstraint("V", "UD", Relation.EXTENDS)); + methodConstraintsWithPositionTest.put("TPH ETWid2(TPH V)", lmc); + lmc = new HashSet<>(); + lmc.add(new MethodConstraint("AM", "java/lang/Object", Relation.EXTENDS)); + lmc.add(new MethodConstraint("AI", "java/lang/Object", Relation.EXTENDS)); + methodConstraintsWithPositionTest.put("TPH AIm2(TPH AMTPH AI)", lmc); + } else { + if (fogg.allConstraints.contains((new MethodConstraint("DZP", "U", Relation.EXTENDS)))) { + classConstraintsTest.add(new ClassConstraint("ETW", "DZP", Relation.EXTENDS)); + classConstraintsTest.add(new ClassConstraint("DZP", "U", Relation.EXTENDS)); + classConstraintsTest.add(new ClassConstraint("U", "java/lang/Object", Relation.EXTENDS)); + + lmc.add(new MethodConstraint("AI", "AE", Relation.EXTENDS)); + lmc.add(new MethodConstraint("AD", "AI", Relation.EXTENDS)); + //lmc.add(new MethodConstraint("AB", "AM", Relation.EXTENDS)); + lmc.add(new MethodConstraint("AE", "java/lang/Object", Relation.EXTENDS)); + lmc.add(new MethodConstraint("AB", "java/lang/Object", Relation.EXTENDS)); + methodConstraintsWithPositionTest.put("TPH ABm(TPH ABTPH AD)", lmc); + lmc = new HashSet<>(); + lmc.add(new MethodConstraint("V", "ETW", Relation.EXTENDS)); + methodConstraintsWithPositionTest.put("TPH Uid2(TPH V)", lmc); + lmc = new HashSet<>(); + lmc.add(new MethodConstraint("AM", "java/lang/Object", Relation.EXTENDS)); + lmc.add(new MethodConstraint("AI", "java/lang/Object", Relation.EXTENDS)); + methodConstraintsWithPositionTest.put("TPH AIm2(TPH AMTPH AI)", lmc); + } else { + if (fogg.allConstraints.contains((new MethodConstraint("EIM", "FEA", Relation.EXTENDS)))) { + classConstraintsTest.add(new ClassConstraint("VK", "EIM", Relation.EXTENDS)); + classConstraintsTest.add(new ClassConstraint("EIM", "FEA", Relation.EXTENDS)); + classConstraintsTest.add(new ClassConstraint("FEA", "java/lang/Object", Relation.EXTENDS)); + + lmc.add(new MethodConstraint("AI", "AE", Relation.EXTENDS)); + lmc.add(new MethodConstraint("AD", "AI", Relation.EXTENDS)); + //lmc.add(new MethodConstraint("AB", "AM", Relation.EXTENDS)); + lmc.add(new MethodConstraint("AE", "java/lang/Object", Relation.EXTENDS)); + lmc.add(new MethodConstraint("AB", "java/lang/Object", Relation.EXTENDS)); + methodConstraintsWithPositionTest.put("TPH ABm(TPH ABTPH AD)", lmc); + lmc = new HashSet<>(); + lmc.add(new MethodConstraint("V", "VK", Relation.EXTENDS)); + methodConstraintsWithPositionTest.put("TPH FEAid2(TPH V)", lmc); + lmc = new HashSet<>(); + lmc.add(new MethodConstraint("AM", "java/lang/Object", Relation.EXTENDS)); + lmc.add(new MethodConstraint("AI", "java/lang/Object", Relation.EXTENDS)); + methodConstraintsWithPositionTest.put("TPH AIm2(TPH AMTPH AI)", lmc); + } + } + + } + + + Set computedClassCons = new HashSet<>(fogg.classConstraints); + Set expectedClassCons = new HashSet<>(classConstraintsTest); + + assertEquals(expectedClassCons, computedClassCons); + + HashMap> methodConstraintsWithPositionComputed = new HashMap<>(); + fogg.methodConstraintsWithPosition.forEach((s, l) -> methodConstraintsWithPositionComputed.put(s,new HashSet<>(l))); + + assertEquals(methodConstraintsWithPositionTest, methodConstraintsWithPositionComputed); + + /* + compiler.generateBytecode(new File(pathToClassFile), results, simplifyResultsForAllSourceFiles); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass(className); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + */ + return new TestResultSet(); + + } + } diff --git a/app/src/test/java/insertGenerics/TestTPHsAndGenerics2.java b/app/src/test/java/insertGenerics/TestTPHsAndGenerics2.java new file mode 100644 index 00000000..cd24b974 --- /dev/null +++ b/app/src/test/java/insertGenerics/TestTPHsAndGenerics2.java @@ -0,0 +1,79 @@ +package insertGenerics; + +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericGenratorResultForSourceFile; +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter; +import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter; +import de.dhbwstuttgart.typedeployment.TypeInsert; +import de.dhbwstuttgart.typedeployment.TypeInsertFactory; +import de.dhbwstuttgart.typeinference.result.ResultSet; + +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class TestTPHsAndGenerics2 { + + public static final String rootDirectory = System.getProperty("user.dir")+"/resources/insertGenericsJav/"; + + @BeforeClass + public static void resetNamesOfTypePlaceholder() { + de.dhbwstuttgart.syntaxtree.factory.NameGenerator.reset(); + } + + @Test + public void ggFinder() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"TestTPHSAndGenerics2.jav")); + } + + private static class TestResultSet{ + + } + + public TestResultSet execute(File fileToTest) throws IOException, ClassNotFoundException { + JavaTXCompiler compiler = new JavaTXCompiler(fileToTest); + for(File f : compiler.sourceFiles.keySet()){ + SourceFile sf = compiler.sourceFiles.get(f); + } + List results = compiler.typeInference(); + List simplifyResultsForAllSourceFiles = compiler.getGeneratedGenericResultsForAllSourceFiles(results); + //compiler.generateBytecode(rootDirectory+"xxx.class", results, simplifyResultsForAllSourceFiles); + for(File f : compiler.sourceFiles.keySet()){ + SourceFile sf = compiler.sourceFiles.get(f); + System.out.println(ASTTypePrinter.print(sf)); + System.out.println(ASTPrinter.print(sf)); + //List results = compiler.typeInference(); PL 2017-10-03 vor die For-Schleife gezogen + assert results.size()>0; + Set insertedTypes = new HashSet<>(); + for(ResultSet resultSet : results){ + Set result = TypeInsertFactory.createTypeInsertPoints(sf, resultSet, results, simplifyResultsForAllSourceFiles); + assert result.size()>0; + String content = readFile(f.getPath(), StandardCharsets.UTF_8); + for(TypeInsert tip : result){ + insertedTypes.add(tip.insert(content)); + } + } + for(String s : insertedTypes){ + System.out.println(s); + } + } + return new TestResultSet(); + } + + static String readFile(String path, Charset encoding) + throws IOException + { + byte[] encoded = Files.readAllBytes(Paths.get(path)); + return new String(encoded, encoding); + } +} diff --git a/app/src/test/java/insertGenerics/TestThreeArgs.java b/app/src/test/java/insertGenerics/TestThreeArgs.java new file mode 100644 index 00000000..a7c0c09e --- /dev/null +++ b/app/src/test/java/insertGenerics/TestThreeArgs.java @@ -0,0 +1,99 @@ +package insertGenerics; + +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericGenratorResultForSourceFile; +import de.dhbwstuttgart.bytecode.insertGenerics.ClassConstraint; +import de.dhbwstuttgart.bytecode.insertGenerics.FamilyOfGeneratedGenerics; +import de.dhbwstuttgart.bytecode.insertGenerics.MethodConstraint; +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter; +import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter; +import de.dhbwstuttgart.typedeployment.TypeInsert; +import de.dhbwstuttgart.typedeployment.TypeInsertFactory; +import de.dhbwstuttgart.typeinference.result.ResultSet; + +import org.junit.BeforeClass; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class TestThreeArgs { + + private static final String rootDirectory = System.getProperty("user.dir")+"/resources/insertGenericsJav/"; + private String pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + private static ClassLoader loader; + private static Class classToTest; + private static Object instanceOfClass; + private static String className = "TestThreeArgs"; + + @BeforeClass + public static void resetNamesOfTypePlaceholder() { + de.dhbwstuttgart.syntaxtree.factory.NameGenerator.reset(); + } + + @Test + public void ggFinder() throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { + execute(new File(rootDirectory+className+".jav")); + } + + private static class TestResultSet{ + + } + + public TestResultSet execute(File fileToTest) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { + JavaTXCompiler compiler = new JavaTXCompiler(fileToTest); + List results = compiler.typeInference(); + List simplifyResultsForAllSourceFiles = compiler.getGeneratedGenericResultsForAllSourceFiles(results); + + List classConstraintsTest = new ArrayList<>(); + classConstraintsTest.add(new ClassConstraint("N", "java/lang/Object", Relation.EXTENDS)); + HashMap> methodConstraintsWithPositionTest = new HashMap<>(); + Set lmc; + lmc = new HashSet<>(); + lmc.add(new MethodConstraint("P", "AF", Relation.EXTENDS)); + lmc.add(new MethodConstraint("Q", "java/lang/Object", Relation.EXTENDS)); + lmc.add(new MethodConstraint("AF", "java/lang/Object", Relation.EXTENDS)); + methodConstraintsWithPositionTest.put("TPH AFid(TPH P)", lmc); + lmc = new HashSet<>(); + lmc.add(new MethodConstraint("AF", "W", Relation.EXTENDS)); + lmc.add(new MethodConstraint("AB", "P", Relation.EXTENDS)); + lmc.add(new MethodConstraint("P", "AF", Relation.EXTENDS)); + lmc.add(new MethodConstraint("AC", "java/lang/Object", Relation.EXTENDS)); + lmc.add(new MethodConstraint("W", "java/lang/Object", Relation.EXTENDS)); + methodConstraintsWithPositionTest.put("TPH Wm(TPH WTPH ABTPH AC)", lmc); + + FamilyOfGeneratedGenerics fogg = compiler.fogg; + Set computedClassCons = new HashSet<>(fogg.classConstraints); + Set expectedClassCons = new HashSet<>(classConstraintsTest); + + assertEquals(expectedClassCons, computedClassCons); + + HashMap> methodConstraintsWithPositionComputed = new HashMap<>(); + fogg.methodConstraintsWithPosition.forEach((s, l) -> methodConstraintsWithPositionComputed.put(s,new HashSet<>(l))); + + assertEquals(methodConstraintsWithPositionTest, methodConstraintsWithPositionComputed); + + compiler.generateBytecode(new File(pathToClassFile), results, simplifyResultsForAllSourceFiles); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass(className); + //liefert Fehler, da Variable "a" nicht initialisiert ist. + //instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + return new TestResultSet(); + } +} diff --git a/app/src/test/java/insertGenerics/TestTransitiveClosure.java b/app/src/test/java/insertGenerics/TestTransitiveClosure.java new file mode 100644 index 00000000..4eaf0527 --- /dev/null +++ b/app/src/test/java/insertGenerics/TestTransitiveClosure.java @@ -0,0 +1,28 @@ +package insertGenerics; + +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; +import de.dhbwstuttgart.bytecode.insertGenerics.FamilyOfGeneratedGenerics; +import org.junit.Test; +import static org.junit.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.List; + +public class TestTransitiveClosure { + public List fillList() { + List list = new ArrayList<>(); + list.add(new TPHConstraint("A", "B", Relation.EXTENDS)); + list.add(new TPHConstraint("B", "C", Relation.EXTENDS)); + list.add(new TPHConstraint("C", "D", Relation.EXTENDS)); + + return list; + } + + @Test + public void genericTest() { + //List testCons = FamilyOfGeneratedGenerics.buildTransitiveClosure(fillList()); + //System.out.println(testCons); + + } +} diff --git a/app/src/test/java/insertGenerics/TestTwoArgs.java b/app/src/test/java/insertGenerics/TestTwoArgs.java new file mode 100644 index 00000000..b21bb99b --- /dev/null +++ b/app/src/test/java/insertGenerics/TestTwoArgs.java @@ -0,0 +1,111 @@ +package insertGenerics; + +import static org.junit.Assert.*; + +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericGenratorResultForSourceFile; +import de.dhbwstuttgart.bytecode.insertGenerics.ClassConstraint; +import de.dhbwstuttgart.bytecode.insertGenerics.FamilyOfGeneratedGenerics; +import de.dhbwstuttgart.bytecode.insertGenerics.MethodConstraint; +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter; +import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter; +import de.dhbwstuttgart.typedeployment.TypeInsert; +import de.dhbwstuttgart.typedeployment.TypeInsertFactory; +import de.dhbwstuttgart.typeinference.result.ResultSet; + +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class TestTwoArgs { + + private static final String rootDirectory = System.getProperty("user.dir")+"/resources/insertGenericsJav/"; + private String pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + private static ClassLoader loader; + private static Class classToTest; + private static Object instanceOfClass; + private static String className = "TestTwoArgs"; + + @BeforeClass + public static void resetNamesOfTypePlaceholder() { + de.dhbwstuttgart.syntaxtree.factory.NameGenerator.reset(); + } + + @Test + public void ggFinder() throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { + execute(new File(rootDirectory+className+".jav")); + } + + private static class TestResultSet{ + + } + + public TestResultSet execute(File fileToTest) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { + JavaTXCompiler compiler = new JavaTXCompiler(fileToTest); + List results = compiler.typeInference(); + List simplifyResultsForAllSourceFiles = compiler.getGeneratedGenericResultsForAllSourceFiles(results); + + List classConstraintsTest = new ArrayList<>(); + classConstraintsTest.add(new ClassConstraint("AP", "Z", Relation.EXTENDS)); + classConstraintsTest.add(new ClassConstraint("Z", "P", Relation.EXTENDS)); + classConstraintsTest.add(new ClassConstraint("P", "AL", Relation.EXTENDS)); + classConstraintsTest.add(new ClassConstraint("AL", "AF", Relation.EXTENDS)); + classConstraintsTest.add(new ClassConstraint("AF", "java/lang/Object", Relation.EXTENDS)); + HashMap> methodConstraintsWithPositionTest = new HashMap<>(); + Set lmc; + lmc = new HashSet<>(); + lmc.add(new MethodConstraint("P", "AL", Relation.EXTENDS)); + lmc.add(new MethodConstraint("AL", "java/lang/Object", Relation.EXTENDS)); + methodConstraintsWithPositionTest.put("TPH ALid(TPH P)", lmc); + lmc = new HashSet<>(); + lmc.add(new MethodConstraint("AL", "AF", Relation.EXTENDS)); + lmc.add(new MethodConstraint("Z", "P", Relation.EXTENDS)); + lmc.add(new MethodConstraint("P", "AL", Relation.EXTENDS)); + lmc.add(new MethodConstraint("AF", "java/lang/Object", Relation.EXTENDS)); + methodConstraintsWithPositionTest.put("TPH AFm(TPH AFTPH Z)", lmc); + lmc = new HashSet<>(); + lmc.add(new MethodConstraint("T", "AP", Relation.EXTENDS)); + methodConstraintsWithPositionTest.put("TPH APsetA(TPH T)", lmc); + lmc = new HashSet<>(); + lmc.add(new MethodConstraint("AG", "P", Relation.EXTENDS)); + lmc.add(new MethodConstraint("AH", "T", Relation.EXTENDS)); + lmc.add(new MethodConstraint("T", "AP", Relation.EXTENDS)); + lmc.add(new MethodConstraint("AL", "AF", Relation.EXTENDS)); + lmc.add(new MethodConstraint("P", "AL", Relation.EXTENDS)); + methodConstraintsWithPositionTest.put("TPH AFmain(TPH AGTPH AH)", lmc); + + FamilyOfGeneratedGenerics fogg = compiler.fogg; + Set computedClassCons = new HashSet<>(fogg.classConstraints); + Set expectedClassCons = new HashSet<>(classConstraintsTest); + + assertEquals(expectedClassCons, computedClassCons); + + HashMap> methodConstraintsWithPositionComputed = new HashMap<>(); + fogg.methodConstraintsWithPosition.forEach((s, l) -> methodConstraintsWithPositionComputed.put(s,new HashSet<>(l))); + + assertEquals(methodConstraintsWithPositionTest, methodConstraintsWithPositionComputed); + + compiler.generateBytecode(new File(pathToClassFile), results, simplifyResultsForAllSourceFiles); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass(className); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + return new TestResultSet(); + } +} diff --git a/app/src/test/java/insertGenerics/TestTwoArgs2.java b/app/src/test/java/insertGenerics/TestTwoArgs2.java new file mode 100644 index 00000000..f9168a20 --- /dev/null +++ b/app/src/test/java/insertGenerics/TestTwoArgs2.java @@ -0,0 +1,105 @@ +package insertGenerics; + +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericGenratorResultForSourceFile; +import de.dhbwstuttgart.bytecode.insertGenerics.ClassConstraint; +import de.dhbwstuttgart.bytecode.insertGenerics.FamilyOfGeneratedGenerics; +import de.dhbwstuttgart.bytecode.insertGenerics.MethodConstraint; +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter; +import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter; +import de.dhbwstuttgart.typedeployment.TypeInsert; +import de.dhbwstuttgart.typedeployment.TypeInsertFactory; +import de.dhbwstuttgart.typeinference.result.ResultSet; + +import org.junit.BeforeClass; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class TestTwoArgs2 { + + private static final String rootDirectory = System.getProperty("user.dir")+"/resources/insertGenericsJav/"; + private String pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + private static ClassLoader loader; + private static Class classToTest; + private static Object instanceOfClass; + private static String className = "TestTwoArgs2"; + + @BeforeClass + public static void resetNamesOfTypePlaceholder() { + de.dhbwstuttgart.syntaxtree.factory.NameGenerator.reset(); + } + + @Test + public void ggFinder() throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { + execute(new File(rootDirectory+className+".jav")); + } + + private static class TestResultSet{ + + } + + public TestResultSet execute(File fileToTest) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { + JavaTXCompiler compiler = new JavaTXCompiler(fileToTest); + List results = compiler.typeInference(); + List simplifyResultsForAllSourceFiles = compiler.getGeneratedGenericResultsForAllSourceFiles(results); + + List classConstraintsTest = new ArrayList<>(); + classConstraintsTest.add(new ClassConstraint("N", "java/lang/Object", Relation.EXTENDS)); + HashMap> methodConstraintsWithPositionTest = new HashMap<>(); + Set lmc; + lmc = new HashSet<>(); + lmc.add(new MethodConstraint("AG", "AA", Relation.EXTENDS)); + lmc.add(new MethodConstraint("U", "P", Relation.EXTENDS)); + lmc.add(new MethodConstraint("P", "AG", Relation.EXTENDS)); + lmc.add(new MethodConstraint("AA", "java/lang/Object", Relation.EXTENDS)); + methodConstraintsWithPositionTest.put("TPH AAm(TPH AATPH U)", lmc); + lmc = new HashSet<>(); + lmc.add(new MethodConstraint("AB", "P", Relation.EXTENDS)); + lmc.add(new MethodConstraint("AC", "U", Relation.EXTENDS)); + lmc.add(new MethodConstraint("AB", "AA", Relation.EXTENDS)); + lmc.add(new MethodConstraint("AA", "U", Relation.EXTENDS)); + lmc.add(new MethodConstraint("AG", "AA", Relation.EXTENDS)); + lmc.add(new MethodConstraint("U", "AA", Relation.EXTENDS)); + lmc.add(new MethodConstraint("P", "AG", Relation.EXTENDS)); + methodConstraintsWithPositionTest.put("TPH AAmain(TPH ABTPH AC)", lmc); + lmc = new HashSet<>(); + lmc.add(new MethodConstraint("P", "AG", Relation.EXTENDS)); + lmc.add(new MethodConstraint("AG", "java/lang/Object", Relation.EXTENDS)); + methodConstraintsWithPositionTest.put("TPH AGid(TPH P)", lmc); + + FamilyOfGeneratedGenerics fogg = compiler.fogg; + Set computedClassCons = new HashSet<>(fogg.classConstraints); + Set expectedClassCons = new HashSet<>(classConstraintsTest); + + assertEquals(expectedClassCons, computedClassCons); + + HashMap> methodConstraintsWithPositionComputed = new HashMap<>(); + fogg.methodConstraintsWithPosition.forEach((s, l) -> methodConstraintsWithPositionComputed.put(s,new HashSet<>(l))); + + assertEquals(methodConstraintsWithPositionTest, methodConstraintsWithPositionComputed); + + compiler.generateBytecode(new File(pathToClassFile), results, simplifyResultsForAllSourceFiles); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass(className); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + return new TestResultSet(); + } +} diff --git a/app/src/test/java/insertGenerics/TestTwoCalls.java b/app/src/test/java/insertGenerics/TestTwoCalls.java new file mode 100644 index 00000000..e5331fca --- /dev/null +++ b/app/src/test/java/insertGenerics/TestTwoCalls.java @@ -0,0 +1,95 @@ +package insertGenerics; + +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericGenratorResultForSourceFile; +import de.dhbwstuttgart.bytecode.insertGenerics.ClassConstraint; +import de.dhbwstuttgart.bytecode.insertGenerics.FamilyOfGeneratedGenerics; +import de.dhbwstuttgart.bytecode.insertGenerics.MethodConstraint; +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter; +import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter; +import de.dhbwstuttgart.typedeployment.TypeInsert; +import de.dhbwstuttgart.typedeployment.TypeInsertFactory; +import de.dhbwstuttgart.typeinference.result.ResultSet; + +import org.junit.BeforeClass; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class TestTwoCalls { + + private static final String rootDirectory = System.getProperty("user.dir")+"/resources/insertGenericsJav/"; + private String pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + private static ClassLoader loader; + private static Class classToTest; + private static Object instanceOfClass; + private static String className = "TestTwoCalls"; + + @BeforeClass + public static void resetNamesOfTypePlaceholder() { + de.dhbwstuttgart.syntaxtree.factory.NameGenerator.reset(); + } + + @Test + public void ggFinder() throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { + execute(new File(rootDirectory+className+".jav")); + } + + private static class TestResultSet{ + + } + + public TestResultSet execute(File fileToTest) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { + JavaTXCompiler compiler = new JavaTXCompiler(fileToTest); + List results = compiler.typeInference(); + List simplifyResultsForAllSourceFiles = compiler.getGeneratedGenericResultsForAllSourceFiles(results); + + List classConstraintsTest = new ArrayList<>(); + HashMap> methodConstraintsWithPositionTest = new HashMap<>(); + Set lmc; + lmc = new HashSet<>(); + lmc.add(new MethodConstraint("O", "R", Relation.EXTENDS)); + lmc.add(new MethodConstraint("R", "java/lang/Object", Relation.EXTENDS)); + methodConstraintsWithPositionTest.put("TPH Rid(TPH O)", lmc); + lmc = new HashSet<>(); + lmc.add(new MethodConstraint("T", "O", Relation.EXTENDS)); + lmc.add(new MethodConstraint("O", "R", Relation.EXTENDS)); + lmc.add(new MethodConstraint("R", "java/lang/Object", Relation.EXTENDS)); + lmc.add(new MethodConstraint("S", "java/lang/Object", Relation.EXTENDS)); + methodConstraintsWithPositionTest.put("TPH Rmain(TPH STPH T)", lmc); + + FamilyOfGeneratedGenerics fogg = compiler.fogg; + Set computedClassCons = new HashSet<>(fogg.classConstraints); + Set expectedClassCons = new HashSet<>(classConstraintsTest); + + assertEquals(expectedClassCons, computedClassCons); + + HashMap> methodConstraintsWithPositionComputed = new HashMap<>(); + fogg.methodConstraintsWithPosition.forEach((s, l) -> methodConstraintsWithPositionComputed.put(s,new HashSet<>(l))); + + assertEquals(methodConstraintsWithPositionTest, methodConstraintsWithPositionComputed); + + compiler.generateBytecode(new File(pathToClassFile), results, simplifyResultsForAllSourceFiles); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass(className); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + return new TestResultSet(); + } +} diff --git a/app/src/test/java/insertGenerics/TestVector.java b/app/src/test/java/insertGenerics/TestVector.java new file mode 100644 index 00000000..b8e42c21 --- /dev/null +++ b/app/src/test/java/insertGenerics/TestVector.java @@ -0,0 +1,92 @@ +package insertGenerics; + +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericGenratorResultForSourceFile; +import de.dhbwstuttgart.bytecode.insertGenerics.ClassConstraint; +import de.dhbwstuttgart.bytecode.insertGenerics.FamilyOfGeneratedGenerics; +import de.dhbwstuttgart.bytecode.insertGenerics.MethodConstraint; +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter; +import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter; +import de.dhbwstuttgart.typedeployment.TypeInsert; +import de.dhbwstuttgart.typedeployment.TypeInsertFactory; +import de.dhbwstuttgart.typeinference.result.ResultSet; + +import org.junit.BeforeClass; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class TestVector { + + private static final String rootDirectory = System.getProperty("user.dir")+"/resources/insertGenericsJav/"; + private String pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + private static ClassLoader loader; + private static Class classToTest; + private static Object instanceOfClass; + private static String className = "TestVector"; + + @BeforeClass + public static void resetNamesOfTypePlaceholder() { + de.dhbwstuttgart.syntaxtree.factory.NameGenerator.reset(); + } + + @Test + public void ggFinder() throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { + execute(new File(rootDirectory+className+".jav")); + } + + private static class TestResultSet{ + + } + + public TestResultSet execute(File fileToTest) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { + JavaTXCompiler compiler = new JavaTXCompiler(fileToTest); + List results = compiler.typeInference(); + List simplifyResultsForAllSourceFiles = compiler.getGeneratedGenericResultsForAllSourceFiles(results); + + List classConstraintsTest = new ArrayList<>(); + HashMap> methodConstraintsWithPositionTest = new HashMap<>(); + Set lmc; + lmc = new HashSet<>(); + lmc.add(new MethodConstraint("T", "W", Relation.EXTENDS)); + lmc.add(new MethodConstraint("W", "ZU", Relation.EXTENDS)); + lmc.add(new MethodConstraint("ZU", "java/lang/Object", Relation.EXTENDS)); + methodConstraintsWithPositionTest.put("voidm(java/util/Vectorjava/util/Vector)", lmc); + lmc = new HashSet<>(); + lmc.add(new MethodConstraint("W", "java/lang/Object", Relation.EXTENDS)); + methodConstraintsWithPositionTest.put("TPH Wid(TPH W)", lmc); + + FamilyOfGeneratedGenerics fogg = compiler.fogg; + Set computedClassCons = new HashSet<>(fogg.classConstraints); + Set expectedClassCons = new HashSet<>(classConstraintsTest); + + assertEquals(expectedClassCons, computedClassCons); + + HashMap> methodConstraintsWithPositionComputed = new HashMap<>(); + fogg.methodConstraintsWithPosition.forEach((s, l) -> methodConstraintsWithPositionComputed.put(s,new HashSet<>(l))); + + assertEquals(methodConstraintsWithPositionTest, methodConstraintsWithPositionComputed); + compiler.generateBytecode(new File(pathToClassFile), results, simplifyResultsForAllSourceFiles); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass(className); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + return new TestResultSet(); + } +} diff --git a/app/src/test/java/insertGenerics/TestVectorArg.java b/app/src/test/java/insertGenerics/TestVectorArg.java new file mode 100644 index 00000000..ff1a1b99 --- /dev/null +++ b/app/src/test/java/insertGenerics/TestVectorArg.java @@ -0,0 +1,92 @@ +package insertGenerics; + +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericGenratorResultForSourceFile; +import de.dhbwstuttgart.bytecode.insertGenerics.ClassConstraint; +import de.dhbwstuttgart.bytecode.insertGenerics.FamilyOfGeneratedGenerics; +import de.dhbwstuttgart.bytecode.insertGenerics.MethodConstraint; +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter; +import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter; +import de.dhbwstuttgart.typedeployment.TypeInsert; +import de.dhbwstuttgart.typedeployment.TypeInsertFactory; +import de.dhbwstuttgart.typeinference.result.ResultSet; + +import org.junit.BeforeClass; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class TestVectorArg { + + private static final String rootDirectory = System.getProperty("user.dir")+"/resources/insertGenericsJav/"; + private String pathToClassFile = System.getProperty("user.dir")+"/resources/testBytecode/generatedBC/"; + private static ClassLoader loader; + private static Class classToTest; + private static Object instanceOfClass; + private static String className = "TestVectorArg"; + + @BeforeClass + public static void resetNamesOfTypePlaceholder() { + de.dhbwstuttgart.syntaxtree.factory.NameGenerator.reset(); + } + + @Test + public void ggFinder() throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { + execute(new File(rootDirectory+className+".jav")); + } + + private static class TestResultSet{ + + } + + public TestResultSet execute(File fileToTest) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { + JavaTXCompiler compiler = new JavaTXCompiler(fileToTest); + List results = compiler.typeInference(); + List simplifyResultsForAllSourceFiles = compiler.getGeneratedGenericResultsForAllSourceFiles(results); + + List classConstraintsTest = new ArrayList<>(); + HashMap> methodConstraintsWithPositionTest = new HashMap<>(); + Set lmc; + lmc = new HashSet<>(); + lmc.add(new MethodConstraint("T", "W", Relation.EXTENDS)); + lmc.add(new MethodConstraint("W", "ZU", Relation.EXTENDS)); + lmc.add(new MethodConstraint("ZU", "java/lang/Object", Relation.EXTENDS)); + methodConstraintsWithPositionTest.put("voidm(java/util/Vectorjava/util/Vector)", lmc); + lmc = new HashSet<>(); + lmc.add(new MethodConstraint("W", "java/lang/Object", Relation.EXTENDS)); + methodConstraintsWithPositionTest.put("TPH Wid(TPH W)", lmc); + + FamilyOfGeneratedGenerics fogg = compiler.fogg; + Set computedClassCons = new HashSet<>(fogg.classConstraints); + Set expectedClassCons = new HashSet<>(classConstraintsTest); + + //assertEquals(expectedClassCons, computedClassCons); + + HashMap> methodConstraintsWithPositionComputed = new HashMap<>(); + fogg.methodConstraintsWithPosition.forEach((s, l) -> methodConstraintsWithPositionComputed.put(s,new HashSet<>(l))); + + //assertEquals(methodConstraintsWithPositionTest, methodConstraintsWithPositionComputed); + compiler.generateBytecode(new File(pathToClassFile), results, simplifyResultsForAllSourceFiles); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass(className); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + return new TestResultSet(); + } +} diff --git a/app/src/test/java/insertGenerics/TestVoidMeth.java b/app/src/test/java/insertGenerics/TestVoidMeth.java new file mode 100644 index 00000000..3b4c1984 --- /dev/null +++ b/app/src/test/java/insertGenerics/TestVoidMeth.java @@ -0,0 +1,79 @@ +package insertGenerics; + +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericGenratorResultForSourceFile; +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter; +import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter; +import de.dhbwstuttgart.typedeployment.TypeInsert; +import de.dhbwstuttgart.typedeployment.TypeInsertFactory; +import de.dhbwstuttgart.typeinference.result.ResultSet; + +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class TestVoidMeth { + + public static final String rootDirectory = System.getProperty("user.dir")+"/resources/insertGenericsJav/"; + + @BeforeClass + public static void resetNamesOfTypePlaceholder() { + de.dhbwstuttgart.syntaxtree.factory.NameGenerator.reset(); + } + + @Test + public void ggFinder() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"TestVoidMeth.jav")); + } + + private static class TestResultSet{ + + } + + public TestResultSet execute(File fileToTest) throws IOException, ClassNotFoundException { + JavaTXCompiler compiler = new JavaTXCompiler(fileToTest); + for(File f : compiler.sourceFiles.keySet()){ + SourceFile sf = compiler.sourceFiles.get(f); + } + List results = compiler.typeInference(); + List simplifyResultsForAllSourceFiles = compiler.getGeneratedGenericResultsForAllSourceFiles(results); + //compiler.generateBytecode(rootDirectory+"xxx.class", results, simplifyResultsForAllSourceFiles); + for(File f : compiler.sourceFiles.keySet()){ + SourceFile sf = compiler.sourceFiles.get(f); + System.out.println(ASTTypePrinter.print(sf)); + System.out.println(ASTPrinter.print(sf)); + //List results = compiler.typeInference(); PL 2017-10-03 vor die For-Schleife gezogen + assert results.size()>0; + Set insertedTypes = new HashSet<>(); + for(ResultSet resultSet : results){ + Set result = TypeInsertFactory.createTypeInsertPoints(sf, resultSet, results, simplifyResultsForAllSourceFiles); + assert result.size()>0; + String content = readFile(f.getPath(), StandardCharsets.UTF_8); + for(TypeInsert tip : result){ + insertedTypes.add(tip.insert(content)); + } + } + for(String s : insertedTypes){ + System.out.println(s); + } + } + return new TestResultSet(); + } + + static String readFile(String path, Charset encoding) + throws IOException + { + byte[] encoded = Files.readAllBytes(Paths.get(path)); + return new String(encoded, encoding); + } +} diff --git a/app/src/test/java/log4jTesting.xml b/app/src/test/java/log4jTesting.xml new file mode 100755 index 00000000..dc30c245 --- /dev/null +++ b/app/src/test/java/log4jTesting.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/test/java/packages/Bytecode.java b/app/src/test/java/packages/Bytecode.java new file mode 100644 index 00000000..48a21f9b --- /dev/null +++ b/app/src/test/java/packages/Bytecode.java @@ -0,0 +1,52 @@ +package packages; + +import de.dhbwstuttgart.core.JavaTXCompiler; +import junit.framework.TestCase; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.net.URL; +import java.net.URLClassLoader; + +public class Bytecode extends TestCase { + + public static final String rootDirectory = System.getProperty("user.dir")+"/resources/javFiles/packageTest/"; + @Test + public void testSetPackageNameInBytecode() throws Exception { + JavaTXCompiler compiler = new JavaTXCompiler(new File(rootDirectory+"de/test/TestClass.jav")); + compiler.typeInference(); + File f = new File(rootDirectory + "de/test/TestClass.class"); + if(f.exists() && !f.isDirectory()) { + f.delete(); + } + compiler.generateBytecode(); + f = new File(rootDirectory + "de/test/TestClass.class"); + assertTrue(f.exists()); + + + URLClassLoader loader = new URLClassLoader(new URL[]{new URL("file://" + rootDirectory)}); + Class classToTest = loader.loadClass("de.test.TestClass"); + Object instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testSetPackageNameInBytecodeAndOutputFolder() throws Exception { + JavaTXCompiler compiler = new JavaTXCompiler(new File(rootDirectory+"de/test/TestClass.jav")); + compiler.typeInference(); + File f = new File(rootDirectory + "de/test/output/de/test/TestClass.class"); + if(f.exists() && !f.isDirectory()) { + f.delete(); + } + compiler.generateBytecode(rootDirectory + "de/test/output/"); + f = new File(rootDirectory + "de/test/output/de/test/TestClass.class"); + assertTrue(f.exists()); + + URLClassLoader loader = new URLClassLoader(new URL[]{new URL("file://" + rootDirectory + "de/test/output/")}); + Class classToTest = loader.loadClass("de.test.TestClass"); + Object instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + +} diff --git a/app/src/test/java/packages/CheckPackageFolder.java b/app/src/test/java/packages/CheckPackageFolder.java new file mode 100644 index 00000000..cb9a6231 --- /dev/null +++ b/app/src/test/java/packages/CheckPackageFolder.java @@ -0,0 +1,80 @@ +package packages; + +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import junit.framework.TestCase; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import java.io.File; +import java.io.IOException; +import java.util.Arrays; + +public class CheckPackageFolder extends TestCase { + + public static final String rootDirectory = System.getProperty("user.dir")+"/resources/javFiles/packageTest/de/test/"; + + @Test + public void testCorrectFolder1FileWithWrongPackageName() throws IOException, ClassNotFoundException { + JavaTXCompiler compiler = new JavaTXCompiler(new File(rootDirectory+"packageNameTestWrongPackage.jav")); + compiler.typeInference(); + File f = new File(rootDirectory + "TestClass.class"); + if(f.exists() && !f.isDirectory()) { + f.delete(); + } + compiler.generateBytecode(); + f = new File(rootDirectory + "TestClass.class"); + assertTrue(f.exists()); //Es ist erlaubt falsche package Namen zu verwenden. Warnung wäre optional + } + + @Test + public void testCorrectFolder1File() throws IOException, ClassNotFoundException { + JavaTXCompiler compiler = new JavaTXCompiler(new File(rootDirectory+"TestClass.jav")); + compiler.typeInference(); + File f = new File(rootDirectory + "TestClass.class"); + if(f.exists() && !f.isDirectory()) { + f.delete(); + } + compiler.generateBytecode(); + f = new File(rootDirectory + "TestClass.class"); + assertTrue(f.exists()); //Es ist erlaubt falsche package Namen zu verwenden. Warnung wäre optional + } + + @Test + public void testCorrectFolder1FileAndOutputDirectory() throws IOException, ClassNotFoundException { + JavaTXCompiler compiler = new JavaTXCompiler(new File(rootDirectory+"TestClass.jav")); + compiler.typeInference(); + File f = new File(rootDirectory + "output/de/test/TestClass.class"); + if(f.exists() && !f.isDirectory()) { + f.delete(); + } + compiler.generateBytecode(rootDirectory+"output/"); + f = new File(rootDirectory + "output/de/test/TestClass.class"); + assertTrue(f.exists()); //Es ist erlaubt falsche package Namen zu verwenden. Warnung wäre optional + } + + /* + * Dieser Test wird übersprungen, da der Bytecode-Generator nicht mit zwei Eingabedateien gleichzeitig umgehen kann + @Test + public void testCorrectFolder2Files() throws IOException, ClassNotFoundException { + JavaTXCompiler compiler = new JavaTXCompiler(Arrays.asList( + new File(rootDirectory+"subpackage1/Test1.jav"), + new File(rootDirectory+"subpackage2/Test2.jav") + )); + compiler.typeInference(); + File f = new File(rootDirectory + "subpackage1/Test1.class"); + if(f.exists() && !f.isDirectory()) { + f.delete(); + } + File f2 = new File(rootDirectory + "subpackage2/Test2.class"); + if(f.exists() && !f.isDirectory()) { + f.delete(); + } + compiler.generateBytecode(); + f = new File(rootDirectory + "subpackage1/Test1.class"); + f2 = new File(rootDirectory + "subpackage2/Test2.class"); + assertTrue(f.exists()); + assertTrue(f2.exists()); + } + */ +} diff --git a/app/src/test/java/packages/ConsoleInterfaceTest.java b/app/src/test/java/packages/ConsoleInterfaceTest.java new file mode 100644 index 00000000..658455af --- /dev/null +++ b/app/src/test/java/packages/ConsoleInterfaceTest.java @@ -0,0 +1,133 @@ +package packages; + +import de.dhbwstuttgart.core.ConsoleInterface; +import de.dhbwstuttgart.core.JavaTXCompiler; +import junit.framework.TestCase; +import org.junit.Test; + +import java.io.File; +import java.net.URL; +import java.net.URLClassLoader; + +public class ConsoleInterfaceTest extends TestCase { + + public static final String rootDirectory = System.getProperty("user.dir")+"/resources/javFiles/packageTest/"; + + @Test + public void testCompileSingleJavFile() throws Exception { + File f = new File(rootDirectory + "de/test/TestClass.class"); + if(f.exists() && !f.isDirectory()) { + f.delete(); + } + + ConsoleInterface.main(new String[]{rootDirectory + "de/test/TestClass.jav"}); + + f = new File(rootDirectory + "de/test/TestClass.class"); + assertTrue(f.exists()); + } + + @Test + public void testCompileSingleJavFileWithOutputDirectory() throws Exception { + File f = new File(rootDirectory + "de/test/output/de/test/TestClass.class"); + if(f.exists() && !f.isDirectory()) { + f.delete(); + } + + ConsoleInterface.main(new String[]{"-d", rootDirectory + "de/test/output/" ,rootDirectory + "de/test/TestClass.jav"}); + + f = new File(rootDirectory + "de/test/output/de/test/TestClass.class"); + assertTrue(f.exists()); + } + + @Test + public void testCpNotEndsWithSlash() throws Exception { + JavaTXCompiler compiler = new JavaTXCompiler(new File(rootDirectory+"/de/test/ToImport.jav")); + compiler.typeInference(); + compiler.generateBytecode(rootDirectory + "output/"); + File f = new File(rootDirectory + "output/de/test/ToImport.class"); + assertTrue(f.exists()); + + f = new File(rootDirectory + "de/test/ImportTest.class"); + if(f.exists() && !f.isDirectory()) { + f.delete(); + } + + ConsoleInterface.main(new String[]{"-cp", rootDirectory + "de/test/output" , rootDirectory + "de/test/ImportTest.jav"}); + + f = new File(rootDirectory + "de/test/ImportTest.class"); + assertTrue(f.exists()); + } + + @Test + public void testOutputDirNotEndsWithSlash() throws Exception { + File f = new File(rootDirectory + "de/test/output/de/test/TestClass.class"); + if(f.exists() && !f.isDirectory()) { + f.delete(); + } + + ConsoleInterface.main(new String[]{"-d", rootDirectory + "de/test/output" ,rootDirectory + "de/test/TestClass.jav"}); + + f = new File(rootDirectory + "de/test/output/de/test/TestClass.class"); + assertTrue(f.exists()); + } + + @Test + public void testCompileSingleJavFileWithClassPath() throws Exception { + JavaTXCompiler compiler = new JavaTXCompiler(new File(rootDirectory+"/de/test/ToImport.jav")); + compiler.typeInference(); + compiler.generateBytecode(rootDirectory + "output/"); + File f = new File(rootDirectory + "output/de/test/ToImport.class"); + assertTrue(f.exists()); + + f = new File(rootDirectory + "de/test/ImportTest.class"); + if(f.exists() && !f.isDirectory()) { + f.delete(); + } + + ConsoleInterface.main(new String[]{"-cp", rootDirectory + "de/test/output/" ,rootDirectory + "de/test/ImportTest.jav"}); + + f = new File(rootDirectory + "de/test/ImportTest.class"); + assertTrue(f.exists()); + } + + @Test + public void testCompileSingleJavFileWithMultipleClassPath() throws Exception { + JavaTXCompiler compiler = new JavaTXCompiler(new File(rootDirectory+"/de/test/ToImport.jav")); + compiler.typeInference(); + compiler.generateBytecode(rootDirectory + "output/"); + File f = new File(rootDirectory + "output/de/test/ToImport.class"); + assertTrue(f.exists()); + + f = new File(rootDirectory + "de/test/ImportTest.class"); + if(f.exists() && !f.isDirectory()) { + f.delete(); + } + + ConsoleInterface.main(new String[]{"-cp", rootDirectory + "de/test/output/:"+rootDirectory+"de", + rootDirectory + "de/test/ImportTest.jav"}); + + f = new File(rootDirectory + "de/test/ImportTest.class"); + assertTrue(f.exists()); + } + + @Test + public void testCompileSingleJavFileWithClassPathAndOutputDir() throws Exception { + JavaTXCompiler compiler = new JavaTXCompiler(new File(rootDirectory+"/de/test/ToImport.jav")); + compiler.typeInference(); + compiler.generateBytecode(rootDirectory + "output/"); + File f = new File(rootDirectory + "output/de/test/ToImport.class"); + assertTrue(f.exists()); + + f = new File(rootDirectory + "de/test/output/de/test/ImportTest.class"); + if(f.exists() && !f.isDirectory()) { + f.delete(); + } + + ConsoleInterface.main(new String[]{"-cp", rootDirectory + "de/test/output/", + "-d"+rootDirectory + "de/test/output/" ,rootDirectory + "de/test/ImportTest.jav"}); + + f = new File(rootDirectory + "de/test/output/de/test/ImportTest.class"); + assertTrue(f.exists()); + } + +} diff --git a/app/src/test/java/packages/ImportTest.java b/app/src/test/java/packages/ImportTest.java new file mode 100644 index 00000000..c6fc6e2e --- /dev/null +++ b/app/src/test/java/packages/ImportTest.java @@ -0,0 +1,108 @@ +package packages; + +import com.google.common.collect.Lists; +import de.dhbwstuttgart.core.JavaTXCompiler; +import junit.framework.TestCase; +import org.junit.Before; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.net.URL; + +public class ImportTest extends TestCase { + + public static final String rootDirectory = System.getProperty("user.dir")+"/resources/javFiles/packageTest/de/test/"; + + + public ImportTest() throws ClassNotFoundException, IOException { + /* + Generate ToImport class in rootDirectory and in output-Directory + */ + JavaTXCompiler compiler = new JavaTXCompiler(new File(rootDirectory+"ToImport.jav")); + compiler.typeInference(); + compiler.generateBytecode(rootDirectory + "output/"); + File f = new File(rootDirectory + "output/de/test/ToImport.class"); + assertTrue(f.exists()); + + compiler = new JavaTXCompiler(new File(rootDirectory+"ToImport.jav")); + compiler.typeInference(); + compiler.generateBytecode(); + f = new File(rootDirectory + "ToImport.class"); + assertTrue(f.exists()); + + compiler = new JavaTXCompiler(new File(rootDirectory+"subpackage1/ToImport2.jav")); + compiler.typeInference(); + compiler.generateBytecode(rootDirectory + "output/"); + f = new File(rootDirectory + "output/de/test/subpackage1/ToImport2.class"); + assertTrue(f.exists()); + + compiler = new JavaTXCompiler(new File(rootDirectory+"subpackage2/ToImport3.jav")); + compiler.typeInference(); + compiler.generateBytecode(rootDirectory + "output/"); + f = new File(rootDirectory + "output/de/test/subpackage2/ToImport3.class"); + assertTrue(f.exists()); + } + + @Test + public void testSetPackageNameInBytecodeAndOutputFolder() throws IOException, ClassNotFoundException { + JavaTXCompiler compiler = new JavaTXCompiler( + Lists.newArrayList(new File(rootDirectory+"ImportTest.jav")), + Lists.newArrayList(new File(rootDirectory+"output/"))); + compiler.typeInference(); + File f = new File(rootDirectory + "output/de/test/ImportTest.class"); + if(f.exists() && !f.isDirectory()) { + f.delete(); + } + compiler.generateBytecode(rootDirectory + "output/"); + f = new File(rootDirectory + "output/de/test/ImportTest.class"); + assertTrue(f.exists()); + } + + @Test + public void testSetPackageNameInBytecodeAndStandardOutputFolder() throws IOException, ClassNotFoundException { + JavaTXCompiler compiler = new JavaTXCompiler( + Lists.newArrayList(new File(rootDirectory+"ImportTest.jav")), + Lists.newArrayList(new File(rootDirectory+"output/"))); + compiler.typeInference(); + File f = new File(rootDirectory + "ImportTest.class"); + if(f.exists() && !f.isDirectory()) { + f.delete(); + } + compiler.generateBytecode(); + f = new File(rootDirectory + "ImportTest.class"); + assertTrue(f.exists()); + } + + + @Test + public void testImportTwoClasses() throws IOException, ClassNotFoundException { + JavaTXCompiler compiler = new JavaTXCompiler( + Lists.newArrayList(new File(rootDirectory+"ImportTest2.jav")), + Lists.newArrayList(new File(rootDirectory+"output/"))); + compiler.typeInference(); + File f = new File(rootDirectory + "ImportTest2.class"); + if(f.exists() && !f.isDirectory()) { + f.delete(); + } + compiler.generateBytecode(); + f = new File(rootDirectory + "ImportTest2.class"); + assertTrue(f.exists()); + } + + @Test + public void testImportDefaultPackage() throws IOException, ClassNotFoundException { + JavaTXCompiler compiler = new JavaTXCompiler( + Lists.newArrayList(new File(rootDirectory+"ImportTestDefault.jav"))); + compiler.typeInference(); + File f = new File(rootDirectory + "ImportTestDefault.class"); + if(f.exists() && !f.isDirectory()) { + f.delete(); + } + compiler.generateBytecode(); + f = new File(rootDirectory + "ImportTestDefault.class"); + assertTrue(f.exists()); + } + + +} diff --git a/app/src/test/java/packages/LoadDefaultPackageClassesTest.java b/app/src/test/java/packages/LoadDefaultPackageClassesTest.java new file mode 100644 index 00000000..49f33385 --- /dev/null +++ b/app/src/test/java/packages/LoadDefaultPackageClassesTest.java @@ -0,0 +1,55 @@ +package packages; + +import com.google.common.collect.Lists; +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.environment.CompilationEnvironment; +import junit.framework.TestCase; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.net.URLClassLoader; + +public class LoadDefaultPackageClassesTest extends TestCase { + + public static final String rootDirectory = System.getProperty("user.dir")+"/resources/javFiles/packageTest/"; + + + public LoadDefaultPackageClassesTest() throws ClassNotFoundException, IOException { + /* + Generate ToImport class in rootDirectory and in output-Directory + */ + JavaTXCompiler compiler = new JavaTXCompiler( + Lists.newArrayList(new File(rootDirectory+"Gen.jav")), + Lists.newArrayList(new File(rootDirectory+"/de/test/output/"))); + compiler.typeInference(); + compiler.generateBytecode(); + File f = new File(rootDirectory + "Gen.class"); + assertTrue(f.exists()); + } + + public void testLoadGenClass() throws IOException, ClassNotFoundException { + CompilationEnvironment.loadDefaultPackageClasses(new File( rootDirectory + "Test.jav"), ClassLoader.getSystemClassLoader()); + } + + public void testURLClassLoader() throws IOException, ClassNotFoundException { + URLClassLoader cl = new URLClassLoader(new URL[]{new URL("file://"+rootDirectory)}, ClassLoader.getSystemClassLoader()); + cl.loadClass("Gen"); + } +/* + public void testE2E() throws IOException, ClassNotFoundException { + JavaTXCompiler compiler = new JavaTXCompiler(new File(rootDirectory+"OL.jav")); + compiler.typeInference(); + compiler.generateBytecode(); + File f = new File(rootDirectory + "OL.class"); + assertTrue(f.exists()); + + compiler = new JavaTXCompiler(new File(rootDirectory+"OLMain.jav")); + compiler.typeInference(); + compiler.generateBytecode(); + f = new File(rootDirectory + "OLMain.class"); + assertTrue(f.exists()); + } + */ +} diff --git a/app/src/test/java/packages/OLOneFileTest.java b/app/src/test/java/packages/OLOneFileTest.java new file mode 100644 index 00000000..6e91fef7 --- /dev/null +++ b/app/src/test/java/packages/OLOneFileTest.java @@ -0,0 +1,133 @@ +package packages; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.List; + +import org.junit.BeforeClass; +import org.junit.Test; + +import com.google.common.collect.Lists; + +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericGenratorResultForSourceFile; +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.typeinference.result.ResultSet; + +public class OLOneFileTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static Class classToTest1; + private static Class classToTest2; + private static String pathToClassFile; + private static Object instanceOfClass; + private static Object instanceOfClass1; + private static Object instanceOfClass2; + + public static final String rootDirectory = System.getProperty("user.dir")+"/resources/javFiles/packageTest/"; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + path = rootDirectory +"OLOneFile.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler( + Lists.newArrayList(fileToTest), + Lists.newArrayList(new File(rootDirectory+"de/test/output/"))); + pathToClassFile = System.getProperty("user.dir")+"/resources/javFiles/packageTest/"; + List typeinferenceResult = compiler.typeInference(); + List simplifyResultsForAllSourceFiles = compiler.getGeneratedGenericResultsForAllSourceFiles(typeinferenceResult); + compiler.generateBytecode(new File(pathToClassFile),typeinferenceResult,simplifyResultsForAllSourceFiles); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("OLOneFile"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + classToTest1 = loader.loadClass("OLextendsOneFile"); + instanceOfClass1 = classToTest1.getDeclaredConstructor().newInstance(); + classToTest2 = loader.loadClass("OLMainOneFile"); + instanceOfClass2 = classToTest2.getDeclaredConstructor().newInstance(); + } + + @Test + public void testOLClassName() { + assertEquals("OLOneFile", classToTest.getName()); + } + + @Test + public void testmInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("m2", Integer.class); + Integer result = (Integer) m.invoke(instanceOfClass, 5); + assertEquals(new Integer(10), result); + } + + @Test + public void testmDouble() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("m2", Double.class); + Double result = (Double) m.invoke(instanceOfClass, 5.0); + assertEquals(new Double(10.0), result); + } + + @Test + public void testmString() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("m2", String.class); + String result = (String) m.invoke(instanceOfClass, "xxx"); + assertEquals("xxxxxx", result); + } + + @Test + public void testOLextendsClassName() { + assertEquals("OLextendsOneFile", classToTest1.getName()); + } + + @Test + public void testextendsInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method main = classToTest1.getMethod("m2", Integer.class); + Integer result = (Integer) main.invoke(instanceOfClass1, 5); + assertEquals(new Integer(10), result); + } + + @Test + public void testextendsDouble() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method main = classToTest1.getMethod("m2", Double.class); + Double result = (Double) main.invoke(instanceOfClass1, 5.0); + assertEquals(new Double(10.0), result); + } + + @Test + public void testextendsString() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method main = classToTest1.getMethod("m2", String.class); + String result = (String) main.invoke(instanceOfClass1, "xxx"); + assertEquals("xxxxxx", result); + } + + @Test + public void testOLMainClassName() { + assertEquals("OLMainOneFile", classToTest2.getName()); + } + + @Test + public void testmainInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method main = classToTest2.getDeclaredMethod("main", Integer.class); + Integer result = (Integer) main.invoke(instanceOfClass2, 5); + assertEquals(new Integer(10), result); + } + + @Test + public void testmainDouble() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method main = classToTest2.getDeclaredMethod("main", Double.class); + Double result = (Double) main.invoke(instanceOfClass2, 5.0); + assertEquals(new Double(10.0), result); + } + + @Test + public void testmainString() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method main = classToTest2.getDeclaredMethod("main", String.class); + String result = (String) main.invoke(instanceOfClass2, "xxx"); + assertEquals("xxxxxx", result); + } +} diff --git a/app/src/test/java/packages/OLTest.java b/app/src/test/java/packages/OLTest.java new file mode 100644 index 00000000..ea3f9c1b --- /dev/null +++ b/app/src/test/java/packages/OLTest.java @@ -0,0 +1,147 @@ +package packages; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.List; + +import org.junit.BeforeClass; +import org.junit.Test; + +import com.google.common.collect.Lists; + +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericGenratorResultForSourceFile; +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.typeinference.result.ResultSet; + +public class OLTest { + private static String path; + private static File fileToTest; + private static JavaTXCompiler compiler; + private static ClassLoader loader; + private static Class classToTest; + private static Class classToTest1; + private static Class classToTest2; + private static String pathToClassFile; + private static Object instanceOfClass; + private static Object instanceOfClass1; + private static Object instanceOfClass2; + + public static final String rootDirectory = System.getProperty("user.dir")+"/resources/javFiles/packageTest"; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + JavaTXCompiler compiler = new JavaTXCompiler(new File(rootDirectory+"/de/test/OL.jav")); + compiler.typeInference(); + compiler.generateBytecode(rootDirectory + "/de/test/output/"); + loader = new URLClassLoader(new URL[] {new URL("file://"+ rootDirectory + "/de/test/output/")}); + classToTest = loader.loadClass("de.test.OL"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + + path = System.getProperty("user.dir")+"/resources/javFiles/packageTest/OLextends.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler( + Lists.newArrayList(new File(rootDirectory+"/OLextends.jav")), + Lists.newArrayList(new File(rootDirectory+"/de/test/output/"))); + //compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/resources/javFiles/packageTest/"; + compiler.generateBytecode(pathToClassFile); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile), new URL("file://"+ rootDirectory + "/de/test/output/")}); + classToTest1 = loader.loadClass("OLextends"); + instanceOfClass1 = classToTest1.getDeclaredConstructor().newInstance(); + + path = System.getProperty("user.dir")+"/resources/javFiles/packageTest/OLMain.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler( + Lists.newArrayList(new File(rootDirectory+"/OLMain.jav")), + Lists.newArrayList(new File(rootDirectory+"/de/test/output/"))); + //compiler = new JavaTXCompiler(fileToTest); + pathToClassFile = System.getProperty("user.dir")+"/resources/javFiles/packageTest/"; + compiler.generateBytecode(pathToClassFile); + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile), new URL("file://"+ rootDirectory + "/de/test/output/")}); + classToTest2 = loader.loadClass("OLMain"); + instanceOfClass2 = classToTest2.getDeclaredConstructor().newInstance(); + } + + @Test + public void testOLClassName() { + assertEquals("de.test.OL", classToTest.getName()); + } + + @Test + public void testmInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("m", Integer.class); + Integer result = (Integer) m.invoke(instanceOfClass, 5); + assertEquals(new Integer(10), result); + } + + @Test + public void testmDouble() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("m", Double.class); + Double result = (Double) m.invoke(instanceOfClass, 5.0); + assertEquals(new Double(10.0), result); + } + + @Test + public void testmString() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method m = classToTest.getDeclaredMethod("m", String.class); + String result = (String) m.invoke(instanceOfClass, "xxx"); + assertEquals("xxxxxx", result); + } + + @Test + public void testOLextendsClassName() { + assertEquals("OLextends", classToTest1.getName()); + } + + @Test + public void testextendsInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method main = classToTest1.getMethod("m", Integer.class); + Integer result = (Integer) main.invoke(instanceOfClass1, 5); + assertEquals(new Integer(10), result); + } + + @Test + public void testextendsDouble() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method main = classToTest1.getMethod("m", Double.class); + Double result = (Double) main.invoke(instanceOfClass1, 5.0); + assertEquals(new Double(10.0), result); + } + + @Test + public void testextendsString() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method main = classToTest1.getMethod("m", String.class); + String result = (String) main.invoke(instanceOfClass1, "xxx"); + assertEquals("xxxxxx", result); + } + + @Test + public void testOLMainClassName() { + assertEquals("OLMain", classToTest2.getName()); + } + + @Test + public void testmainInt() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method main = classToTest2.getDeclaredMethod("main", Integer.class); + Integer result = (Integer) main.invoke(instanceOfClass2, 5); + assertEquals(new Integer(10), result); + } + + @Test + public void testmainDouble() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method main = classToTest2.getDeclaredMethod("main", Double.class); + Double result = (Double) main.invoke(instanceOfClass2, 5.0); + assertEquals(new Double(10.0), result); + } + + @Test + public void testmainString() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method main = classToTest2.getDeclaredMethod("main", String.class); + String result = (String) main.invoke(instanceOfClass2, "xxx"); + assertEquals("xxxxxx", result); + } +} diff --git a/app/src/test/java/packages/ParsePackageName.java b/app/src/test/java/packages/ParsePackageName.java new file mode 100644 index 00000000..ba5abac7 --- /dev/null +++ b/app/src/test/java/packages/ParsePackageName.java @@ -0,0 +1,21 @@ +package packages; + +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; + +public class ParsePackageName { + + public static final String rootDirectory = System.getProperty("user.dir")+"/resources/javFiles/packageTest/de/test/"; + @Test + public void parsePackage() throws IOException, ClassNotFoundException { + JavaTXCompiler compiler = new JavaTXCompiler(new File(rootDirectory+"TestClass.jav")); + for(File f : compiler.sourceFiles.keySet()){ + SourceFile sf = compiler.sourceFiles.get(f); + assert sf.getPkgName().equals("de.test"); + } + } +} diff --git a/app/src/test/java/packages/mathStrucMatrixOPTest.java.txt b/app/src/test/java/packages/mathStrucMatrixOPTest.java.txt new file mode 100644 index 00000000..c9c24969 --- /dev/null +++ b/app/src/test/java/packages/mathStrucMatrixOPTest.java.txt @@ -0,0 +1,51 @@ +package packages; + +import com.google.common.collect.Lists; +import de.dhbwstuttgart.core.JavaTXCompiler; +import junit.framework.TestCase; +import org.junit.Before; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.net.URL; + +public class mathStrucMatrixOPTest extends TestCase { + + public static final String rootDirectory = System.getProperty("user.dir")+"/resources/javFiles/packageTest/de/test/"; + + + public mathStrucMatrixOPTest() throws ClassNotFoundException, IOException { + /* + Generate ToImport class in rootDirectory and in output-Directory + */ + /* PL 2020-01-07 kann z.Zt. nicht erzeugt werden (siehe Bug 170, http://bugzilla.ba-horb.de/show_bug.cgi?id=170) + JavaTXCompiler compiler = new JavaTXCompiler(new File(rootDirectory+"mathStruc.jav")); + compiler.typeInference(); + compiler.generateBytecode(rootDirectory + "output/"); + File f = new File(rootDirectory + "output/de/test/mathStruc.class"); + assertTrue(f.exists()); +*/ + JavaTXCompiler compiler = new JavaTXCompiler(new File(rootDirectory+"MatrixOP.jav")); + compiler.typeInference(); + compiler.generateBytecode(rootDirectory + "output/"); + File f = new File(rootDirectory + "output/de/test/MatrixOP.class"); + assertTrue(f.exists()); + + } + + @Test + public void testSetPackageNameInBytecodeAndOutputFolder() throws IOException, ClassNotFoundException { + JavaTXCompiler compiler = new JavaTXCompiler( + Lists.newArrayList(new File(rootDirectory+"mathStrucMatrixOP.jav")), + Lists.newArrayList(new File(rootDirectory+"output/"))); + compiler.typeInference(); + File f = new File(rootDirectory + "output/de/test/mathStrucMatrixOP.class"); + if(f.exists() && !f.isDirectory()) { + f.delete(); + } + compiler.generateBytecode(rootDirectory + "output/"); + f = new File(rootDirectory + "output/de/test/mathStrucMatrixOP.class"); + assertTrue(f.exists()); + } +} diff --git a/app/src/test/java/packages/mathStrucVectorTest.java b/app/src/test/java/packages/mathStrucVectorTest.java new file mode 100644 index 00000000..0d299d7b --- /dev/null +++ b/app/src/test/java/packages/mathStrucVectorTest.java @@ -0,0 +1,54 @@ +package packages; + +import com.google.common.collect.Lists; +import de.dhbwstuttgart.core.JavaTXCompiler; +import junit.framework.TestCase; +import org.junit.Before; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.net.URL; + +public class mathStrucVectorTest extends TestCase { + + public static final String rootDirectory = System.getProperty("user.dir")+"/resources/javFiles/packageTest/de/test/"; + + + public mathStrucVectorTest() throws ClassNotFoundException, IOException { + /* + Generate ToImport class in rootDirectory and in output-Directory + */ + +/* PL 2020-01-07 kann z.Zt. nicht erzeugt werden (siehe Bug 170, http://bugzilla.ba-horb.de/show_bug.cgi?id=170) + JavaTXCompiler compiler = new JavaTXCompiler(new File(rootDirectory+"mathStruc.jav")); + compiler.typeInference(); + compiler.generateBytecode(rootDirectory + "output/"); + File f = new File(rootDirectory + "output/de/test/mathStruc.class"); + assertTrue(f.exists()); + */ + JavaTXCompiler compiler = new JavaTXCompiler(new File(rootDirectory+"vectorAdd.jav")); + compiler.typeInference(); + compiler.generateBytecode(rootDirectory + "output/"); + File f = new File(rootDirectory + "output/de/test/vectorAdd.class"); + assertTrue(f.exists()); + + } + + @Test + public void testSetPackageNameInBytecodeAndOutputFolder() throws IOException, ClassNotFoundException { + JavaTXCompiler compiler = new JavaTXCompiler( + Lists.newArrayList(new File(rootDirectory+"mathStrucVector.jav")), + Lists.newArrayList(new File(rootDirectory+"output/"))); + compiler.typeInference(); + File f = new File(rootDirectory + "output/de/test/mathStrucVector.class"); + if(f.exists() && !f.isDirectory()) { + f.delete(); + } + compiler.generateBytecode(rootDirectory + "output/"); + f = new File(rootDirectory + "output/de/test/mathStrucVector.class"); + assertTrue(f.exists()); + } + + +} diff --git a/app/src/test/java/parser/AntlrTest.jav b/app/src/test/java/parser/AntlrTest.jav new file mode 100644 index 00000000..31ab067d --- /dev/null +++ b/app/src/test/java/parser/AntlrTest.jav @@ -0,0 +1,6 @@ +class Test{ +method(){ + if(true)i++; + if(true)i--; + else i++; +}} \ No newline at end of file diff --git a/app/src/test/java/parser/BoundedParameter.jav b/app/src/test/java/parser/BoundedParameter.jav new file mode 100644 index 00000000..6d7518a9 --- /dev/null +++ b/app/src/test/java/parser/BoundedParameter.jav @@ -0,0 +1,3 @@ +class Matrix{ + String op = "String"; +} diff --git a/app/src/test/java/parser/CastTest.jav b/app/src/test/java/parser/CastTest.jav new file mode 100644 index 00000000..86ca7519 --- /dev/null +++ b/app/src/test/java/parser/CastTest.jav @@ -0,0 +1,8 @@ + +class CastTest{ +void methode(){ + Object a; + String b; + a = (Object) b; +} +} \ No newline at end of file diff --git a/app/src/test/java/parser/ExtendsTest.jav b/app/src/test/java/parser/ExtendsTest.jav new file mode 100644 index 00000000..9103f463 --- /dev/null +++ b/app/src/test/java/parser/ExtendsTest.jav @@ -0,0 +1,4 @@ +class C1 extends Object +{ + m(para) { return para; } +} \ No newline at end of file diff --git a/app/src/test/java/parser/FeatherWeightJava.jav b/app/src/test/java/parser/FeatherWeightJava.jav new file mode 100644 index 00000000..e607b12a --- /dev/null +++ b/app/src/test/java/parser/FeatherWeightJava.jav @@ -0,0 +1,11 @@ + +class FeatherWeightJava { + mt4(a,b,c) { return a.add(b).sub(c) ; } + + mt1(a) {return a; } + + mt2(a) {return a.f; } + + mt3(a) {return a.add(); } +} + diff --git a/app/src/test/java/parser/FieldInitializationTest.jav b/app/src/test/java/parser/FieldInitializationTest.jav new file mode 100644 index 00000000..f7818cc3 --- /dev/null +++ b/app/src/test/java/parser/FieldInitializationTest.jav @@ -0,0 +1,3 @@ +class FieldInitializationTest{ + var var = "hallo"; +} \ No newline at end of file diff --git a/app/src/test/java/parser/FieldVarTest.jav b/app/src/test/java/parser/FieldVarTest.jav new file mode 100644 index 00000000..6e897824 --- /dev/null +++ b/app/src/test/java/parser/FieldVarTest.jav @@ -0,0 +1,5 @@ +package test; + +class Test{ +Typ a; +} \ No newline at end of file diff --git a/app/src/test/java/parser/GeneralParserTest.java b/app/src/test/java/parser/GeneralParserTest.java new file mode 100644 index 00000000..4e7d9868 --- /dev/null +++ b/app/src/test/java/parser/GeneralParserTest.java @@ -0,0 +1,55 @@ +package parser; + +import static org.junit.Assert.*; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.parser.JavaTXParser; + +import org.junit.Test; + + +/** + * Dieser Test pr�ft nur, ob .java-Dateien fehlerfrei geparst werden. + * Der dabei erstellte Syntaxbaum wird nicht kontrolliert. + * @author janulrich + * + */ +public class GeneralParserTest{ + private static final String rootDirectory = System.getProperty("user.dir")+"/test/parser/"; + + @Test + public void run(){ + + + List filenames = new ArrayList(); + /* + filenames.add("NewTest.jav"); + filenames.add("FieldInitializationTest.jav"); + filenames.add("ImportTest.jav"); + filenames.add("CastTest.jav"); + filenames.add("StatementsTest.jav"); + //filenames.add("Methods.jav"); + filenames.add("ImportTestGeneric.jav"); + filenames.add("CastTest.jav"); + //filenames.add("BoundedParameter.jav"); + //filenames.add("GenericFieldVarTest.jav"); + filenames.add("FieldVarTest.jav"); + filenames.add("StructuralTypes.jav"); + */ +// filenames.add("ExtendsTest.jav"); + filenames.add("PackageNameTest.jav"); + try{ + new JavaTXCompiler(filenames.stream().map(s -> new File(rootDirectory + s)).collect(Collectors.toList())); + }catch(Exception exc){ + exc.printStackTrace(); + fail(); + } + assertTrue("Tests durchlaufen",filenames.size()>0); + } + +} diff --git a/app/src/test/java/parser/GenericFieldVarTest.jav b/app/src/test/java/parser/GenericFieldVarTest.jav new file mode 100644 index 00000000..a47b41eb --- /dev/null +++ b/app/src/test/java/parser/GenericFieldVarTest.jav @@ -0,0 +1,3 @@ +class Test{ + A var; +} diff --git a/app/src/test/java/parser/ImportTest.jav b/app/src/test/java/parser/ImportTest.jav new file mode 100644 index 00000000..2de55cee --- /dev/null +++ b/app/src/test/java/parser/ImportTest.jav @@ -0,0 +1,4 @@ +import java.util.*; + +class ImportTest{ +} \ No newline at end of file diff --git a/app/src/test/java/parser/ImportTest2.jav b/app/src/test/java/parser/ImportTest2.jav new file mode 100644 index 00000000..3492e31c --- /dev/null +++ b/app/src/test/java/parser/ImportTest2.jav @@ -0,0 +1,4 @@ +import java.util.ArrayList; + +class ImportTest{ +} \ No newline at end of file diff --git a/app/src/test/java/parser/ImportTestGeneric.jav b/app/src/test/java/parser/ImportTestGeneric.jav new file mode 100644 index 00000000..094f4c5e --- /dev/null +++ b/app/src/test/java/parser/ImportTestGeneric.jav @@ -0,0 +1,5 @@ +import java.util.List; + +class ImportTest{ + List test; +} \ No newline at end of file diff --git a/app/src/test/java/parser/NewTest.jav b/app/src/test/java/parser/NewTest.jav new file mode 100644 index 00000000..992a2e8d --- /dev/null +++ b/app/src/test/java/parser/NewTest.jav @@ -0,0 +1,5 @@ + +class NewTest { +main() { return new NewTest<>().mt(new NewTest(1) , new NewTest(2) , new +NewTest(3)); } +} \ No newline at end of file diff --git a/app/src/test/java/parser/OpratorTest.jav b/app/src/test/java/parser/OpratorTest.jav new file mode 100644 index 00000000..2764adf4 --- /dev/null +++ b/app/src/test/java/parser/OpratorTest.jav @@ -0,0 +1,12 @@ +import java.lang.Integer; + +class OpratorTest { + m(Integer a, Integer b) { + c = a+b; +// d = a-b; +// e = a*b; +// f = a/b; + + return c; + } +} \ No newline at end of file diff --git a/app/src/test/java/parser/PackageNameTest.jav b/app/src/test/java/parser/PackageNameTest.jav new file mode 100644 index 00000000..53c889b7 --- /dev/null +++ b/app/src/test/java/parser/PackageNameTest.jav @@ -0,0 +1,9 @@ +import java.lang.Integer; +import java.lang.Comparable; + +class PackageNameTest{ +java.lang.Integer test(a){return a;} + +Comparable test2(a){return a;} + +} \ No newline at end of file diff --git a/app/src/test/java/parser/StatementsTest.jav b/app/src/test/java/parser/StatementsTest.jav new file mode 100644 index 00000000..891dff12 --- /dev/null +++ b/app/src/test/java/parser/StatementsTest.jav @@ -0,0 +1,8 @@ +class Statements{ + +public void methodeTest(){ + methodeTest(); + return null; +} + +} diff --git a/app/src/test/java/parser/StructuralTypes.jav b/app/src/test/java/parser/StructuralTypes.jav new file mode 100644 index 00000000..b3c210c8 --- /dev/null +++ b/app/src/test/java/parser/StructuralTypes.jav @@ -0,0 +1,5 @@ + +class A { + mt(x, y, z) { return x.sub(y).add(z); } +} + diff --git a/app/src/test/java/parser/WhileTest.jav b/app/src/test/java/parser/WhileTest.jav new file mode 100644 index 00000000..2ce192bd --- /dev/null +++ b/app/src/test/java/parser/WhileTest.jav @@ -0,0 +1,14 @@ +class WhileTest{ + void methode(){ + Boolean test; + do{ + test=test; + }while(test); + + + while(test){ + test = test; + } + return; + } +} \ No newline at end of file diff --git a/app/src/test/java/targetast/ASTToTypedTargetAST.java b/app/src/test/java/targetast/ASTToTypedTargetAST.java new file mode 100644 index 00000000..94b56bd4 --- /dev/null +++ b/app/src/test/java/targetast/ASTToTypedTargetAST.java @@ -0,0 +1,88 @@ +package targetast; + +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.parser.NullToken; +import de.dhbwstuttgart.parser.scope.JavaClassName; +import de.dhbwstuttgart.syntaxtree.*; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.target.ByteArrayClassLoader; +import de.dhbwstuttgart.target.generate.ASTToTargetAST; +import de.dhbwstuttgart.target.tree.TargetClass; +import de.dhbwstuttgart.typeinference.result.ResultSet; +import org.junit.Test; + +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; + +import static org.junit.Assert.*; + +public class ASTToTypedTargetAST { + + @Test + public void emptyClass(){ + ClassOrInterface emptyClass = new ClassOrInterface(0, new JavaClassName("EmptyClass"), new ArrayList<>(), java.util.Optional.empty(), new ArrayList<>(), new ArrayList<>(), new GenericDeclarationList(new ArrayList<>(), new NullToken()), + new RefType(new JavaClassName("Object"), new NullToken()), false, new ArrayList<>(), new NullToken()); + ResultSet emptyResultSet = new ResultSet(new HashSet<>()); + TargetClass emptyTargetClass = new ASTToTargetAST(List.of(emptyResultSet)).convert(emptyClass); + assert emptyTargetClass.getName().equals("EmptyClass"); + assert emptyTargetClass.methods().size() == 0; + assert emptyTargetClass.fields().size() == 0; + } + + @Test + public void overloading() throws Exception { + var file = Path.of(System.getProperty("user.dir"), "/src/test/resources/bytecode/javFiles/Overloading.jav").toFile(); + var compiler = new JavaTXCompiler(file); + var resultSet = compiler.typeInference(); + var converter = new ASTToTargetAST(resultSet); + var classes = compiler.sourceFiles.get(file).getClasses(); + + var classLoader = new ByteArrayClassLoader(); + var overloading = TestCodegen.generateClass(converter.convert(classes.get(0)), classLoader); + var overloading2 = TestCodegen.generateClass(converter.convert(classes.get(1)), classLoader); + + var test1 = overloading.getDeclaredMethod("test", overloading); + test1.setAccessible(true); + var test2 = overloading.getDeclaredMethod("test", overloading2); + test2.setAccessible(true); + Object overloadingInstance = overloading.getDeclaredConstructor().newInstance(); + Object overloading2Instance = overloading2.getDeclaredConstructor().newInstance(); + assertEquals(test1.invoke(overloadingInstance, overloadingInstance), "Overloading"); + assertEquals(test2.invoke(overloadingInstance, overloading2Instance), "Overloading2"); + } + + @Test + public void tphsAndGenerics() throws Exception { + var file = Path.of(System.getProperty("user.dir"), "/src/test/resources/bytecode/javFiles/Tph2.jav").toFile(); + var compiler = new JavaTXCompiler(file); + var resultSet = compiler.typeInference(); + var converter = new ASTToTargetAST(resultSet); + var classes = compiler.sourceFiles.get(file).getClasses(); + + var tphAndGenerics = TestCodegen.generateClass(converter.convert(classes.get(0)), new ByteArrayClassLoader()); + } + + @Test + public void cycles() throws Exception { + var file = Path.of(System.getProperty("user.dir"), "/src/test/resources/bytecode/javFiles/Cycle.jav").toFile(); + var compiler = new JavaTXCompiler(file); + var resultSet = compiler.typeInference(); + var converter = new ASTToTargetAST(resultSet); + var classes = compiler.sourceFiles.get(file).getClasses(); + + var cycle = TestCodegen.generateClass(converter.convert(classes.get(0)), new ByteArrayClassLoader()); + } + + @Test + public void infimum() throws Exception { + var file = Path.of(System.getProperty("user.dir"), "/src/test/resources/bytecode/javFiles/Infimum.jav").toFile(); + var compiler = new JavaTXCompiler(file); + var resultSet = compiler.typeInference(); + var converter = new ASTToTargetAST(resultSet); + var classes = compiler.sourceFiles.get(file).getClasses(); + + var infimum = TestCodegen.generateClass(converter.convert(classes.get(0)), new ByteArrayClassLoader()); + } +} diff --git a/app/src/test/java/targetast/Fun1$$.java b/app/src/test/java/targetast/Fun1$$.java new file mode 100644 index 00000000..882112f2 --- /dev/null +++ b/app/src/test/java/targetast/Fun1$$.java @@ -0,0 +1,3 @@ +public interface Fun1$$ { + public R apply(T t); +} diff --git a/app/src/test/java/targetast/GreaterEqualTest.java b/app/src/test/java/targetast/GreaterEqualTest.java new file mode 100644 index 00000000..2a4c6b0d --- /dev/null +++ b/app/src/test/java/targetast/GreaterEqualTest.java @@ -0,0 +1,135 @@ +package targetast; + +import de.dhbwstuttgart.target.ByteArrayClassLoader; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class GreaterEqualTest { + static Class classToTest; + static Object instance; + + @BeforeClass + public static void beforeClass() throws Exception { + var classFiles = TestCodegen.generateClassFiles("GreaterEqual.jav", new ByteArrayClassLoader()); + classToTest = classFiles.get("GreaterEqual"); + instance = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testIntegers() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Integer.class, Integer.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 7, 5); + assertTrue(result); + } + + @Test + public void testIntegers2() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Integer.class, Integer.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 5, 7); + assertFalse(result); + } + + @Test + public void testEqIntegers() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Integer.class, Integer.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 5, 5); + assertTrue(result); + } + + @Test + public void testLongs() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Method gE = classToTest.getDeclaredMethod("gE", Long.class, Long.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 10L, 7L); + assertTrue(result); + } + + @Test + public void testFloats() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Float.class, Float.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 5F, 7F); + assertFalse(result); + } + + @Test + public void testDoubles() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Double.class, Double.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 5.0, 7.0); + assertFalse(result); + } + + @Test + public void testLongInt() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Long.class, Integer.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 15L, 7); + assertTrue(result); + } + + @Test + public void testFloatInt() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Float.class, Integer.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 5F, 7); + assertFalse(result); + } + + @Test + public void testDoubleInt() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Double.class, Integer.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 25.0, 17); + assertTrue(result); + } + + @Test + public void testFloatLong() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Float.class, Long.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 75F, 70L); + assertTrue(result); + } + + @Test + public void testDoubleLong() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Double.class, Long.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 5.0, 7L); + assertFalse(result); + } + + @Test + public void testEqDoubleFloat() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Double.class, Float.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 7.0, 7F); + assertTrue(result); + } + + @Test + public void testDoubleFloat() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Double.class, Float.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 15.0, 7F); + assertTrue(result); + } + + @Test + public void testDoubleFloat3() throws Exception { + Method gE = classToTest.getDeclaredMethod("gE", Double.class, Float.class); + gE.setAccessible(true); + Boolean result = (Boolean) gE.invoke(instance, 9.0, 17F); + assertFalse(result); + } +} diff --git a/app/src/test/java/targetast/GreaterThanTest.java b/app/src/test/java/targetast/GreaterThanTest.java new file mode 100644 index 00000000..3d7ce1cf --- /dev/null +++ b/app/src/test/java/targetast/GreaterThanTest.java @@ -0,0 +1,133 @@ +package targetast; + +import de.dhbwstuttgart.target.ByteArrayClassLoader; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.lang.reflect.Method; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class GreaterThanTest { + static Class classToTest; + static Object instance; + + @BeforeClass + public static void beforeClass() throws Exception { + var classFiles = TestCodegen.generateClassFiles("GreaterThan.jav", new ByteArrayClassLoader()); + classToTest = classFiles.get("GreaterThan"); + instance = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testIntegers() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Integer.class, Integer.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 7, 5); + assertTrue(result); + } + + @Test + public void testIntegers2() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Integer.class, Integer.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 5, 7); + assertFalse(result); + } + + @Test + public void testEqIntegers() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Integer.class, Integer.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 5, 5); + assertFalse(result); + } + + @Test + public void testLongs() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Long.class, Long.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 10L,7L); + assertTrue(result); + }@Test + + public void testFloats() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Float.class, Float.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 5F,7F); + assertFalse(result); + } + + @Test + public void testDoubles() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Double.class, Double.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 5.0,7.0); + assertFalse(result); + } + + @Test + public void testLongInt() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Long.class, Integer.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 15L,7); + assertTrue(result); + } + + @Test + public void testFloatInt() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Float.class, Integer.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 5F,7); + assertFalse(result); + } + + @Test + public void testDoubleInt() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Double.class, Integer.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 25.0,17); + assertTrue(result); + } + + @Test + public void testFloatLong() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Float.class, Long.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 75F,70L); + assertTrue(result); + } + + @Test + public void testDoubleLong() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Double.class, Long.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 5.0,7L); + assertFalse(result); + } + + @Test + public void testEqDoubleFloat() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Double.class, Float.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 7.0,7F); + assertFalse(result); + } + + @Test + public void testDoubleFloat() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Double.class, Float.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 15.0,7F); + assertTrue(result); + } + + @Test + public void testDoubleFloat3() throws Exception { + Method gT = classToTest.getDeclaredMethod("gT", Double.class, Float.class); + gT.setAccessible(true); + Boolean result = (Boolean) gT.invoke(instance, 9.0,17F); + assertFalse(result); + } +} diff --git a/app/src/test/java/targetast/InheritTest.java b/app/src/test/java/targetast/InheritTest.java new file mode 100644 index 00000000..7c99cc66 --- /dev/null +++ b/app/src/test/java/targetast/InheritTest.java @@ -0,0 +1,103 @@ +package targetast; + +import de.dhbwstuttgart.target.ByteArrayClassLoader; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.lang.reflect.Method; +import java.util.Vector; + +import static org.junit.Assert.assertEquals; + +public class InheritTest { + private static Class classToTest, classToTestAA, classToTestBB, classToTestCC, classToTestDD; + private static Object instanceOfClass, instanceOfClassAA, instanceOfClassBB, instanceOfClassCC, instanceOfClassDD; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + var classLoader = new ByteArrayClassLoader(); + classToTest = TestCodegen.generateClassFiles("Inherit.jav", classLoader).get("Inherit"); + classToTestAA = TestCodegen.generateClassFiles("AA.jav", classLoader).get("AA"); + classToTestBB = TestCodegen.generateClassFiles("BB.jav", classLoader).get("BB"); + classToTestCC = TestCodegen.generateClassFiles("CC.jav", classLoader).get("CC"); + classToTestDD = TestCodegen.generateClassFiles("DD.jav", classLoader).get("DD"); + + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + instanceOfClassAA = classToTestAA.getDeclaredConstructor().newInstance(); + instanceOfClassBB = classToTestBB.getDeclaredConstructor().newInstance(); + instanceOfClassCC = classToTestCC.getDeclaredConstructor().newInstance(); + instanceOfClassDD = classToTestDD.getDeclaredConstructor().newInstance(); + } + + @Test + public void testmainAA() throws Exception { + Method m = classToTestAA.getDeclaredMethod("m", Integer.class); + assertEquals(m.invoke(instanceOfClassAA, 5), "AA"); + Method main = classToTest.getDeclaredMethod("main", classToTestAA, Integer.class); + assertEquals(main.invoke(instanceOfClass, instanceOfClassAA, 5), "AA"); + } + + @Test + public void testmainBB() throws Exception { + Method m = classToTestAA.getDeclaredMethod("m", Integer.class); + assertEquals(m.invoke(instanceOfClassBB, 5), "AA"); + Method main = classToTest.getDeclaredMethod("main", classToTestAA, Integer.class); + assertEquals(main.invoke(instanceOfClass, instanceOfClassBB, 5), "AA"); + } + + @Test + public void testmainCC() throws Exception { + Method m = classToTestCC.getDeclaredMethod("m", Integer.class); + assertEquals(m.invoke(instanceOfClassCC, 5), "CC"); + Method main = classToTest.getDeclaredMethod("main", classToTestCC, Integer.class); + assertEquals(main.invoke(instanceOfClass, instanceOfClassCC, 5), "CC"); + } + + @Test + public void testmainDD() throws Exception { + Method m = classToTestCC.getDeclaredMethod("m", Integer.class); + assertEquals(m.invoke(instanceOfClassDD, 5), "CC"); + Method main = classToTest.getDeclaredMethod("main", classToTestCC, Integer.class); + assertEquals(main.invoke(instanceOfClass, instanceOfClassDD, 5), "CC"); + } + + @Test + public void testmainVectorAA() throws Exception { + Method m = classToTestAA.getDeclaredMethod("m", Integer.class); + assertEquals(m.invoke(instanceOfClassAA, 5), "AA"); + Vector v = new Vector<>(); + v.add(instanceOfClassAA); + Method main = classToTest.getDeclaredMethod("main", Vector.class, Integer.class); + assertEquals(main.invoke(instanceOfClass, v, 5), "AA"); + } + + @Test + public void testmainVectorBB() throws Exception { + Method m = classToTestAA.getDeclaredMethod("m", Integer.class); + assertEquals(m.invoke(instanceOfClassBB, 5), "AA"); + Vector v = new Vector<>(); + v.add(instanceOfClassBB); + Method main = classToTest.getDeclaredMethod("main", Vector.class, Integer.class); + assertEquals(main.invoke(instanceOfClass, v, 5), "AA"); + } + + @Test + public void testmainVectorCC() throws Exception { + Method m = classToTestCC.getDeclaredMethod("m", Integer.class); + assertEquals(m.invoke(instanceOfClassCC, 5), "CC"); + Vector v = new Vector<>(); + v.add(instanceOfClassCC); + Method main = classToTest.getDeclaredMethod("main", Vector.class, Integer.class); + assertEquals(main.invoke(instanceOfClass, v, 5), "CC"); + } + + @Test + public void testmainVectorDD() throws Exception { + Method m = classToTestCC.getDeclaredMethod("m", Integer.class); + assertEquals(m.invoke(instanceOfClassDD, 5), "CC"); + Vector v = new Vector<>(); + v.add(instanceOfClassDD); + Method main = classToTest.getDeclaredMethod("main", Vector.class, Integer.class); + assertEquals(main.invoke(instanceOfClass, v, 5), "CC"); + } +} diff --git a/app/src/test/java/targetast/InheritTest2.java b/app/src/test/java/targetast/InheritTest2.java new file mode 100644 index 00000000..c4c48ed5 --- /dev/null +++ b/app/src/test/java/targetast/InheritTest2.java @@ -0,0 +1,119 @@ +package targetast; + +import de.dhbwstuttgart.target.ByteArrayClassLoader; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.lang.reflect.Method; +import java.util.Vector; + +import static org.junit.Assert.assertEquals; + +public class InheritTest2 { + private static Class classToTest, classToTestAA, classToTestBB, classToTestCC, classToTestDD; + private static Object instanceOfClass, instanceOfClassAA, instanceOfClassBB, instanceOfClassCC, instanceOfClassDD; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + var classLoader = new ByteArrayClassLoader(); + classToTest = TestCodegen.generateClassFiles("Inherit2.jav", classLoader).get("Inherit2"); + classToTestAA = TestCodegen.generateClassFiles("AA.jav", classLoader).get("AA"); + classToTestBB = TestCodegen.generateClassFiles("BB.jav", classLoader).get("BB"); + classToTestCC = TestCodegen.generateClassFiles("CC.jav", classLoader).get("CC"); + classToTestDD = TestCodegen.generateClassFiles("DD.jav", classLoader).get("DD"); + + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + instanceOfClassAA = classToTestAA.getDeclaredConstructor().newInstance(); + instanceOfClassBB = classToTestBB.getDeclaredConstructor().newInstance(); + instanceOfClassCC = classToTestCC.getDeclaredConstructor().newInstance(); + instanceOfClassDD = classToTestDD.getDeclaredConstructor().newInstance(); + } + + @Test + public void testmainAA() throws Exception { + Method m2 = classToTestAA.getDeclaredMethod("m2", classToTestAA); + assertEquals(m2.invoke(instanceOfClassAA, instanceOfClassAA), "AA"); + Method main = classToTest.getDeclaredMethod("main", classToTestAA); + assertEquals(main.invoke(instanceOfClass, instanceOfClassAA), "AA"); + } + + @Test + public void testmainBB() throws Exception { + Method m2 = classToTestAA.getDeclaredMethod("m2", classToTestAA); + assertEquals(m2.invoke(instanceOfClassAA, instanceOfClassAA), "AA"); + Method main = classToTest.getDeclaredMethod("main", classToTestAA); + assertEquals(main.invoke(instanceOfClass, instanceOfClassBB), "AA"); + } + + @Test + public void testmainCC() throws Exception { + Method m2 = classToTestCC.getDeclaredMethod("m2", classToTestCC); + assertEquals(m2.invoke(instanceOfClassCC, instanceOfClassCC), "CC"); + Method main = classToTest.getDeclaredMethod("main", classToTestCC); + assertEquals(main.invoke(instanceOfClass, instanceOfClassCC), "CC"); + } + + @Test + public void testmainDD() throws Exception { + Method m2 = classToTestCC.getDeclaredMethod("m2", classToTestCC); + assertEquals(m2.invoke(instanceOfClassCC, instanceOfClassCC), "CC"); + Method main = classToTest.getDeclaredMethod("main", classToTestCC); + assertEquals(main.invoke(instanceOfClass, instanceOfClassDD), "CC"); + } + + + //PL 2020-05-12: Die folgenden Test funktionieren erst, wenn Generics im Bytecode implementiert sind + @Test + public void testmainVectorAA() throws Exception { + Method m2 = classToTestAA.getDeclaredMethod("m2", classToTestAA); + assertEquals(m2.invoke(instanceOfClassAA, instanceOfClassAA), "AA"); + Vector v = new Vector<>(); + v.add(instanceOfClassAA); + Method main = classToTest.getDeclaredMethod("main", Vector.class); + try { + assertEquals(main.invoke(instanceOfClass, v), "AA"); + } + catch (java.lang.reflect.InvocationTargetException e) { + testmainVectorCC(); + } + } + + @Test + public void testmainVectorBB() throws Exception { + Method m2 = classToTestAA.getDeclaredMethod("m2", classToTestAA); + assertEquals(m2.invoke(instanceOfClassAA, instanceOfClassAA), "AA"); + Vector v = new Vector<>(); + v.add(instanceOfClassBB); + Method main = classToTest.getDeclaredMethod("main", Vector.class); + try { + assertEquals(main.invoke(instanceOfClass, v), "AA"); + } + catch (java.lang.reflect.InvocationTargetException e) { + testmainVectorCC(); + } + } + + @Test + public void testmainVectorCC() throws Exception { + Method m2 = classToTestCC.getDeclaredMethod("m2", classToTestCC); + assertEquals(m2.invoke(instanceOfClassCC, instanceOfClassCC), "CC"); + Vector v = new Vector<>(); + v.add(instanceOfClassCC); + Method main = classToTest.getDeclaredMethod("main", Vector.class); + String erg; + assertEquals(erg= (String) main.invoke(instanceOfClass, v), + erg.equals("CC")? "CC": "AA"); + } + + @Test + public void testmainVectorDD() throws Exception { + Method m2 = classToTestCC.getDeclaredMethod("m2", classToTestCC); + assertEquals(m2.invoke(instanceOfClassCC, instanceOfClassCC), "CC"); + Vector v = new Vector<>(); + v.add(instanceOfClassDD); + Method main = classToTest.getDeclaredMethod("main", Vector.class); + String erg; + assertEquals(erg= (String) main.invoke(instanceOfClass, v), + erg.equals("CC")? "CC": "AA"); + } +} diff --git a/app/src/test/java/targetast/LessEqualTest.java b/app/src/test/java/targetast/LessEqualTest.java new file mode 100644 index 00000000..617a3f0b --- /dev/null +++ b/app/src/test/java/targetast/LessEqualTest.java @@ -0,0 +1,112 @@ +package targetast; + +import de.dhbwstuttgart.target.ByteArrayClassLoader; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.lang.reflect.Method; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class LessEqualTest { + static Class classToTest; + static Object instance; + + @BeforeClass + public static void beforeClass() throws Exception { + var classFiles = TestCodegen.generateClassFiles("LessEqual.jav", new ByteArrayClassLoader()); + classToTest = classFiles.get("LessEqual"); + instance = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testIntegers() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Integer.class, Integer.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 5,7); + assertTrue(result); + } + + @Test + public void testEqualIntegers() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Integer.class, Integer.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 5,5); + assertTrue(result); + } + + @Test + public void testLongs() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Long.class, Long.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 5L,7L); + assertTrue(result); + }@Test + + public void testFloats() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Float.class, Float.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 5F,7F); + assertTrue(result); + } + + @Test + public void testDoubles() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Double.class, Double.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 5.0,7.0); + assertTrue(result); + } + + @Test + public void testLongInt() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Long.class, Integer.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 5L,7); + assertTrue(result); + } + + @Test + public void testFloatInt() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Float.class, Integer.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 5F,7); + assertTrue(result); + } + + @Test + public void testDoubleInt() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Double.class, Integer.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 5.0,7); + assertTrue(result); + } + + @Test + public void testFloatLong() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Float.class, Long.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 5F,7L); + assertTrue(result); + } + + @Test + public void testDoubleLong() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Double.class, Long.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 5.0,7L); + assertTrue(result); + } + + @Test + public void testEqDoubleFloat() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Double.class, Float.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 7.0,7F); + assertTrue(result); + } + + @Test + public void testDoubleFloat() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Double.class, Float.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 5.0,7F); + assertTrue(result); + } + + @Test + public void testDoubleFloat3() throws Exception { + Method lessEqual = classToTest.getDeclaredMethod("lessEqual", Double.class, Float.class); + Boolean result = (Boolean) lessEqual.invoke(instance, 9.0,7F); + assertFalse(result); + } +} diff --git a/app/src/test/java/targetast/LessThanTest.java b/app/src/test/java/targetast/LessThanTest.java new file mode 100644 index 00000000..3ed46908 --- /dev/null +++ b/app/src/test/java/targetast/LessThanTest.java @@ -0,0 +1,120 @@ +package targetast; + +import de.dhbwstuttgart.target.ByteArrayClassLoader; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.lang.reflect.Method; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class LessThanTest { + static Class classToTest; + static Object instance; + + @BeforeClass + public static void beforeClass() throws Exception { + var classFiles = TestCodegen.generateClassFiles("LessThan.jav", new ByteArrayClassLoader()); + classToTest = classFiles.get("LessThan"); + instance = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testLessThanInt() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Integer.class,Integer.class); + Boolean result = (Boolean) lessThan.invoke(instance, 5, 7); + assertTrue(result); + } + + @Test + public void testLessThanInt2() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Integer.class, Integer.class); + Boolean result = (Boolean) lessThan.invoke(instance, 7, 5); + assertFalse(result); + } + + @Test + public void testLessThanInt3() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Integer.class, Integer.class); + Boolean result = (Boolean) lessThan.invoke(instance, 5, 5); + assertFalse(result); + } + + @Test + public void testLessThanLong() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Long.class,Long.class); + Boolean result = (Boolean) lessThan.invoke(instance, 5L, 7L); + assertTrue(result); + } + + @Test + public void testLessThanLong2() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Long.class, Long.class); + Boolean result = (Boolean) lessThan.invoke(instance, 7L, 5L); + assertFalse(result); + } + + @Test + public void testLessThanLong3() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Long.class, Long.class); + Boolean result = (Boolean) lessThan.invoke(instance, 5L, 5L); + assertFalse(result); + } + + @Test + public void testLessThanFloat() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Float.class, Float.class); + Boolean result = (Boolean) lessThan.invoke(instance, 7F, 5F); + assertFalse(result); + } + + @Test + public void testLessThanDouble() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Double.class, Double.class); + Boolean result = (Boolean) lessThan.invoke(instance, 7.0, 5.0); + assertFalse(result); + } + + @Test + public void testLessThanLongInt() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Long.class, Integer.class); + Boolean result = (Boolean) lessThan.invoke(instance, 7L, 5); + assertFalse(result); + } + + @Test + public void testLessThanFloatInt() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Float.class, Integer.class); + Boolean result = (Boolean) lessThan.invoke(instance, 7F, 5); + assertFalse(result); + } + + @Test + public void testLessThanDoubleInt() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Double.class, Integer.class); + Boolean result = (Boolean) lessThan.invoke(instance, 7.0, 5); + assertFalse(result); + } + + @Test + public void testLessThanFloatLong() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Float.class, Long.class); + Boolean result = (Boolean) lessThan.invoke(instance, 7F, 5L); + assertFalse(result); + } + + @Test + public void testLessThanDoubleLong() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Double.class, Long.class); + Boolean result = (Boolean) lessThan.invoke(instance, 7.0, 5L); + assertFalse(result); + } + + @Test + public void testLessThanDoubleFloat() throws Exception { + Method lessThan = classToTest.getDeclaredMethod("lessThan", Double.class, Float.class); + Boolean result = (Boolean) lessThan.invoke(instance, 7.0, 5F); + assertFalse(result); + } +} diff --git a/app/src/test/java/targetast/OLTest.java b/app/src/test/java/targetast/OLTest.java new file mode 100644 index 00000000..30957a09 --- /dev/null +++ b/app/src/test/java/targetast/OLTest.java @@ -0,0 +1,72 @@ +package targetast; + +import de.dhbwstuttgart.target.ByteArrayClassLoader; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.lang.reflect.Method; + +import static org.junit.Assert.assertEquals; + +public class OLTest { + private static Class classToTest; + private static Class classToTest1; + private static Object instanceOfClass; + private static Object instanceOfClass1; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + var classFiles = TestCodegen.generateClassFiles("OL.jav", new ByteArrayClassLoader()); + classToTest = classFiles.get("OL"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + classToTest1 = classFiles.get("OLMain"); + instanceOfClass1 = classToTest1.getDeclaredConstructor().newInstance(); + } + + @Test + public void testmInt() throws Exception { + Method m = classToTest.getDeclaredMethod("m", Integer.class); + Integer result = (Integer) m.invoke(instanceOfClass, 5); + assertEquals(new Integer(10), result); + } + + @Test + public void testmDouble() throws Exception { + Method m = classToTest.getDeclaredMethod("m", Double.class); + Double result = (Double) m.invoke(instanceOfClass, 5.0); + assertEquals(new Double(10.0), result); + } + + @Test + public void testmString() throws Exception { + Method m = classToTest.getDeclaredMethod("m", String.class); + String result = (String) m.invoke(instanceOfClass, "xxx"); + assertEquals("xxxxxx", result); + } + + @Test + public void testOLMainClassName() { + assertEquals("OLMain", classToTest1.getName()); + } + + @Test + public void testmainInt() throws Exception { + Method main = classToTest1.getDeclaredMethod("main", Integer.class); + Integer result = (Integer) main.invoke(instanceOfClass1, 5); + assertEquals(Integer.valueOf(10), result); + } + + @Test + public void testmainDouble() throws Exception { + Method main = classToTest1.getDeclaredMethod("main", Double.class); + Double result = (Double) main.invoke(instanceOfClass1, 5.0); + assertEquals(Double.valueOf(10.0), result); + } + + @Test + public void testmainString() throws Exception { + Method main = classToTest1.getDeclaredMethod("main", String.class); + String result = (String) main.invoke(instanceOfClass1, "xxx"); + assertEquals("xxxxxx", result); + } +} diff --git a/app/src/test/java/targetast/PostIncTest.java b/app/src/test/java/targetast/PostIncTest.java new file mode 100644 index 00000000..9fbbb965 --- /dev/null +++ b/app/src/test/java/targetast/PostIncTest.java @@ -0,0 +1,50 @@ +package targetast; + +import de.dhbwstuttgart.target.ByteArrayClassLoader; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.lang.reflect.Method; + +import static org.junit.Assert.assertEquals; + +public class PostIncTest { + private static Class classToTest; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + var classFiles = TestCodegen.generateClassFiles("PostIncDec.jav", new ByteArrayClassLoader()); + classToTest = classFiles.get("PostIncDec"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testM1() throws Exception { + Method m = classToTest.getDeclaredMethod("m"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(Integer.valueOf(1), res); + } + + @Test + public void testM2() throws Exception { + Method m = classToTest.getDeclaredMethod("m2"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(Integer.valueOf(0), res); + } + + @Test + public void testD1() throws Exception { + Method m = classToTest.getDeclaredMethod("d"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(Integer.valueOf(-1), res); + } + + @Test + public void testD2() throws Exception { + Method m = classToTest.getDeclaredMethod("d2"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(Integer.valueOf(0), res); + } + +} diff --git a/app/src/test/java/targetast/PreIncTest.java b/app/src/test/java/targetast/PreIncTest.java new file mode 100644 index 00000000..a48cea2c --- /dev/null +++ b/app/src/test/java/targetast/PreIncTest.java @@ -0,0 +1,50 @@ +package targetast; + +import de.dhbwstuttgart.target.ByteArrayClassLoader; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.lang.reflect.Method; + +import static org.junit.Assert.assertEquals; + +public class PreIncTest { + private static Class classToTest; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + var classFiles = TestCodegen.generateClassFiles("PreInc.jav", new ByteArrayClassLoader()); + classToTest = classFiles.get("PreInc"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testM() throws Exception { + Method m = classToTest.getDeclaredMethod("m"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(Integer.valueOf(1), res); + } + + @Test + public void testM2() throws Exception { + Method m = classToTest.getDeclaredMethod("m2"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(Integer.valueOf(1), res); + } + + @Test + public void testD() throws Exception { + Method m = classToTest.getDeclaredMethod("d"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(Integer.valueOf(-1), res); + } + + @Test + public void testD2() throws Exception { + Method m = classToTest.getDeclaredMethod("d2"); + Integer res = (Integer) m.invoke(instanceOfClass); + assertEquals(Integer.valueOf(-1), res); + } + +} diff --git a/app/src/test/java/targetast/PutTest.java b/app/src/test/java/targetast/PutTest.java new file mode 100644 index 00000000..a67ad03a --- /dev/null +++ b/app/src/test/java/targetast/PutTest.java @@ -0,0 +1,59 @@ +package targetast; + +import de.dhbwstuttgart.target.ByteArrayClassLoader; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.lang.reflect.Method; +import java.util.Stack; +import java.util.Vector; + +import static org.junit.Assert.assertEquals; + +public class PutTest { + private static Class classToTest; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + var classFiles = TestCodegen.generateClassFiles("Put.jav", new ByteArrayClassLoader()); + classToTest = classFiles.get("Put"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void testPutElementVector() throws Exception { + Method m = classToTest.getDeclaredMethod("putElement", Object.class, Vector.class); + Vector v_invoke = new Vector<>(); + m.invoke(instanceOfClass, 5, v_invoke); + Vector v = new Vector<>(); + v.add(5); + assertEquals(v, v_invoke); + } + + @Test + public void testPutElementStack() throws Exception { + Method m = classToTest.getDeclaredMethod("putElement", Object.class, Stack.class); + Stack s_invoke = new Stack<>(); + m.invoke(instanceOfClass, 5, s_invoke); + assertEquals(new Integer(5), s_invoke.pop()); + } + + @Test + public void testMainVector() throws Exception { + Method m = classToTest.getDeclaredMethod("main", Object.class, Vector.class); + Vector v_invoke = new Vector<>(); + m.invoke(instanceOfClass, 6, v_invoke); + Vector v = new Vector<>(); + v.add(6); + assertEquals(v, v_invoke); + } + + @Test + public void testMainStack() throws Exception { + Method m = classToTest.getDeclaredMethod("main", Object.class, Stack.class); + Stack s_invoke = new Stack<>(); + m.invoke(instanceOfClass, 6, s_invoke); + assertEquals(new Integer(6), s_invoke.pop()); + } +} diff --git a/app/src/test/java/targetast/TestCodegen.java b/app/src/test/java/targetast/TestCodegen.java new file mode 100644 index 00000000..46c4c834 --- /dev/null +++ b/app/src/test/java/targetast/TestCodegen.java @@ -0,0 +1,351 @@ +package targetast; + +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.target.ByteArrayClassLoader; +import de.dhbwstuttgart.target.bytecode.Codegen; +import de.dhbwstuttgart.target.generate.ASTToTargetAST; +import de.dhbwstuttgart.target.tree.MethodParameter; +import de.dhbwstuttgart.target.tree.TargetClass; +import de.dhbwstuttgart.target.tree.expression.*; +import de.dhbwstuttgart.target.tree.type.TargetFunNType; +import de.dhbwstuttgart.target.tree.type.TargetRefType; +import de.dhbwstuttgart.target.tree.type.TargetType; +import org.junit.Test; +import static org.junit.Assert.*; +import org.objectweb.asm.Opcodes; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + + +public class TestCodegen { + + public static Class generateClass(TargetClass clazz, ByteArrayClassLoader classLoader) throws IOException { + var codegen = new Codegen(clazz); + var bytes = codegen.generate(); + var path = Path.of(System.getProperty("user.dir"), "src/test/resources/target/"); + Files.createDirectories(path); + Files.write(path.resolve(clazz.qualifiedName() + ".class"), bytes, StandardOpenOption.CREATE); + return classLoader.loadClass(bytes); + } + + public static Map> generateClassFiles(String filename, ByteArrayClassLoader classLoader) throws IOException, ClassNotFoundException { + var file = Path.of(System.getProperty("user.dir"), "/src/test/resources/bytecode/javFiles/", filename).toFile(); + var compiler = new JavaTXCompiler(file); + var resultSet = compiler.typeInference(); + var sourceFile = compiler.sourceFiles.get(file); + var converter = new ASTToTargetAST(resultSet, sourceFile, classLoader); + var classes = compiler.sourceFiles.get(file).getClasses(); + + return classes.stream().map(cli -> { + try { + return generateClass(converter.convert(cli), classLoader); + } catch (IOException exception) { + throw new RuntimeException(exception); + } + }).collect(Collectors.toMap(Class::getName, Function.identity())); + } + + @Test + public void testEmptyClass() throws Exception { + var clazz = new TargetClass(Opcodes.ACC_PUBLIC, "Empty"); + clazz.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "main", List.of(), null, new TargetBlock(List.of())); + generateClass(clazz, new ByteArrayClassLoader()).getDeclaredMethod("main").invoke(null); + } + + @Test + public void testArithmetic() throws Exception { + var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "Arithmetic"); + + targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "add", + List.of(new MethodParameter(TargetType.Integer, "a"), new MethodParameter(TargetType.Integer, "b")), + TargetType.Integer, + new TargetBlock(List.of(new TargetReturn( + new TargetBinaryOp.Add(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "a"), new TargetLocalVar(TargetType.Integer, "b"))) + )) + ); + targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "sub", + List.of(new MethodParameter(TargetType.Integer, "a"), new MethodParameter(TargetType.Integer, "b")), + TargetType.Integer, + new TargetBlock(List.of(new TargetReturn( + new TargetBinaryOp.Sub(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "a"), new TargetLocalVar(TargetType.Integer, "b"))) + )) + ); + targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "div", + List.of(new MethodParameter(TargetType.Integer, "a"), new MethodParameter(TargetType.Integer, "b")), + TargetType.Integer, + new TargetBlock(List.of(new TargetReturn( + new TargetBinaryOp.Div(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "a"), new TargetLocalVar(TargetType.Integer, "b"))) + )) + ); + targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "mul", + List.of(new MethodParameter(TargetType.Integer, "a"), new MethodParameter(TargetType.Integer, "b")), + TargetType.Integer, + new TargetBlock(List.of(new TargetReturn( + new TargetBinaryOp.Mul(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "a"), new TargetLocalVar(TargetType.Integer, "b"))) + )) + ); + targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "rem", + List.of(new MethodParameter(TargetType.Integer, "a"), new MethodParameter(TargetType.Integer, "b")), + TargetType.Integer, + new TargetBlock(List.of(new TargetReturn( + new TargetBinaryOp.Rem(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "a"), new TargetLocalVar(TargetType.Integer, "b"))) + )) + ); + + + var clazz = generateClass(targetClass, new ByteArrayClassLoader()); + assertEquals(clazz.getDeclaredMethod("add", Integer.class, Integer.class).invoke(null, 10, 10), 20); + assertEquals(clazz.getDeclaredMethod("sub", Integer.class, Integer.class).invoke(null, 20, 10), 10); + assertEquals(clazz.getDeclaredMethod("div", Integer.class, Integer.class).invoke(null, 20, 10), 2); + assertEquals(clazz.getDeclaredMethod("mul", Integer.class, Integer.class).invoke(null, 20, 10), 200); + assertEquals(clazz.getDeclaredMethod("rem", Integer.class, Integer.class).invoke(null, 10, 3), 1); + } + + @Test + public void testUnary() throws Exception { + var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "Unary"); + + targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "not", + List.of(new MethodParameter(TargetType.Integer, "a")), + TargetType.Integer, + new TargetBlock(List.of(new TargetReturn( + new TargetUnaryOp.Not(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "a"))) + )) + ); + targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "neg", + List.of(new MethodParameter(TargetType.Integer, "a")), + TargetType.Integer, + new TargetBlock(List.of(new TargetReturn( + new TargetUnaryOp.Negate(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "a"))) + )) + ); + targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "add", + List.of(new MethodParameter(TargetType.Integer, "a")), + TargetType.Integer, + new TargetBlock(List.of(new TargetReturn( + new TargetUnaryOp.Add(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "a"))) + )) + ); + + var clazz = generateClass(targetClass, new ByteArrayClassLoader()); + assertEquals(clazz.getDeclaredMethod("not", Integer.class).invoke(null, 10), -11); + assertEquals(clazz.getDeclaredMethod("neg", Integer.class).invoke(null, 10), -10); + assertEquals(clazz.getDeclaredMethod("add", Integer.class).invoke(null, 10), 10); + + } + + @Test + public void testConditional() throws Exception { + var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "Conditional"); + + targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "and", + List.of(new MethodParameter(TargetType.Boolean, "a"), new MethodParameter(TargetType.Boolean, "b")), + TargetType.Boolean, + new TargetBlock(List.of(new TargetReturn( + new TargetBinaryOp.And(TargetType.Boolean, new TargetLocalVar(TargetType.Boolean, "a"), new TargetLocalVar(TargetType.Boolean, "b"))) + )) + ); + targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "or", + List.of(new MethodParameter(TargetType.Boolean, "a"), new MethodParameter(TargetType.Boolean, "b")), + TargetType.Boolean, + new TargetBlock(List.of(new TargetReturn( + new TargetBinaryOp.Or(TargetType.Boolean, new TargetLocalVar(TargetType.Boolean, "a"), new TargetLocalVar(TargetType.Boolean, "b"))) + )) + ); + + var clazz = generateClass(targetClass, new ByteArrayClassLoader()); + var and = clazz.getDeclaredMethod("and", Boolean.class, Boolean.class); + var or = clazz.getDeclaredMethod("or", Boolean.class, Boolean.class); + assertEquals(and.invoke(null, true, false), false); + assertEquals(and.invoke(null, true, true), true); + assertEquals(or.invoke(null, false, false), false); + assertEquals(or.invoke(null, true, false), true); + } + + // When adding two numbers and the return type is Long it needs to convert both values to Long + @Test + public void testArithmeticConvert() throws Exception { + var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "ArithmeticConvert"); + targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "add", List.of(), TargetType.Long, + new TargetBlock(List.of(new TargetReturn( + new TargetBinaryOp.Add(TargetType.Long, new TargetLiteral.CharLiteral((char)10), new TargetLiteral.LongLiteral((long)20)) + ))) + ); + var clazz = generateClass(targetClass, new ByteArrayClassLoader()); + assertEquals(clazz.getDeclaredMethod("add").invoke(null), (long)30); + } + + @Test + public void testMethodCall() throws Exception { + var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "HelloWorld"); + targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "helloWorld", List.of(), null, + new TargetBlock(List.of(new TargetMethodCall(null, + new TargetFieldVar( + new TargetRefType("java.io.PrintStream"), + new TargetRefType("java.lang.System"), + true, + new TargetClassName(new TargetRefType("java.lang.System")), + "out" + ), + List.of(new TargetLiteral.StringLiteral("Hello World!")), + new TargetRefType("java.io.PrintStream"), + "println", + false, false + ))) + ); + + var clazz = generateClass(targetClass, new ByteArrayClassLoader()); + clazz.getDeclaredMethod("helloWorld").invoke(null); + } + + @Test + public void testIfStatement() throws Exception { + var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "IfStmt"); + targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "ifStmt", + List.of(new MethodParameter(TargetType.Integer, "val")), + TargetType.Integer, + new TargetBlock(List.of(new TargetIf( + new TargetBinaryOp.Equal(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "val"), new TargetLiteral.IntLiteral(10)), + new TargetReturn(new TargetLiteral.IntLiteral(1)), + new TargetIf( + new TargetBinaryOp.Less(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "val"), new TargetLiteral.IntLiteral(5)), + new TargetReturn(new TargetLiteral.IntLiteral(2)), + new TargetReturn(new TargetLiteral.IntLiteral(3)) + ) + ))) + ); + var clazz = generateClass(targetClass, new ByteArrayClassLoader()); + var ifStmt = clazz.getDeclaredMethod("ifStmt", Integer.class); + assertEquals(ifStmt.invoke(null, 10), 1); + assertEquals(ifStmt.invoke(null, 3), 2); + assertEquals(ifStmt.invoke(null, 20), 3); + } + + @Test + public void testFor() throws Exception { + var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "For"); + targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "forLoop", List.of(), TargetType.Integer, + new TargetBlock(List.of( + new TargetVarDecl(TargetType.Integer, "sum", new TargetLiteral.IntLiteral(0)), + new TargetFor( + new TargetVarDecl(TargetType.Integer, "i", new TargetLiteral.IntLiteral(0)), + new TargetBinaryOp.Less(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "i"), new TargetLiteral.IntLiteral(10)), + new TargetAssign(TargetType.Integer, + new TargetLocalVar(TargetType.Integer, "i"), + new TargetBinaryOp.Add(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "i"), new TargetLiteral.IntLiteral(1))), + new TargetBlock(List.of( + new TargetAssign(TargetType.Integer, + new TargetLocalVar(TargetType.Integer, "sum"), + new TargetBinaryOp.Add(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "sum"), new TargetLocalVar(TargetType.Integer, "i")) + ) + )) + ), + new TargetReturn(new TargetLocalVar(TargetType.Integer, "sum")) + )) + ); + var clazz = generateClass(targetClass, new ByteArrayClassLoader()); + assertEquals(clazz.getDeclaredMethod("forLoop").invoke(null), 45); + } + + @Test + public void testWhile() throws Exception { + var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "While"); + targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "whileLoop", List.of(), TargetType.Integer, + new TargetBlock(List.of( + new TargetVarDecl(TargetType.Integer, "i", new TargetLiteral.IntLiteral(0)), + new TargetWhile( + new TargetBinaryOp.Less(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "i"), new TargetLiteral.IntLiteral(10)), + new TargetBlock(List.of( + new TargetAssign(TargetType.Integer, + new TargetLocalVar(TargetType.Integer, "i"), + new TargetBinaryOp.Add(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "i"), new TargetLiteral.IntLiteral(1)) + ) + )) + ), + new TargetReturn(new TargetLocalVar(TargetType.Integer, "i")) + )) + ); + var clazz = generateClass(targetClass, new ByteArrayClassLoader()); + assertEquals(clazz.getDeclaredMethod("whileLoop").invoke(null), 10); + } + + @Test + public void testNew() throws Exception { + var pointType = new TargetRefType("Point"); + var pointTarget = new TargetClass(Opcodes.ACC_PUBLIC, "Point"); + pointTarget.addField(Opcodes.ACC_PUBLIC, TargetType.Integer, "x"); + pointTarget.addField(Opcodes.ACC_PUBLIC, TargetType.Integer, "y"); + pointTarget.addConstructor(Opcodes.ACC_PUBLIC, + List.of(new MethodParameter(TargetType.Integer, "x"), new MethodParameter(TargetType.Integer, "y")), + new TargetBlock(List.of( + new TargetMethodCall(null, new TargetSuper(TargetType.Object), List.of(), TargetType.Object, "", false, false), + new TargetAssign(TargetType.Integer, + new TargetFieldVar(TargetType.Integer, pointType, false, new TargetThis(pointType), "x"), + new TargetLocalVar(TargetType.Integer, "x") + ), + new TargetAssign(TargetType.Integer, + new TargetFieldVar(TargetType.Integer, pointType, false, new TargetThis(pointType), "y"), + new TargetLocalVar(TargetType.Integer, "y") + ) + )) + ); + + var mainTarget = new TargetClass(Opcodes.ACC_PUBLIC, "New"); + mainTarget.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "makePoint", + List.of(new MethodParameter(TargetType.Integer, "x"), new MethodParameter(TargetType.Integer, "y")), pointType, + new TargetBlock(List.of( + new TargetReturn(new TargetNew(pointType, List.of( + new TargetLocalVar(TargetType.Integer, "x"), + new TargetLocalVar(TargetType.Integer, "y") + ))) + )) + ); + + var classLoader = new ByteArrayClassLoader(); + var pointClass = generateClass(pointTarget, classLoader); + var mainClass = generateClass(mainTarget, classLoader); + + var point = mainClass.getDeclaredMethod("makePoint", Integer.class, Integer.class).invoke(null, 10, 20); + assertEquals(point.getClass().getDeclaredField("x").get(point), 10); + assertEquals(point.getClass().getDeclaredField("y").get(point), 20); + } + + @Test + public void testLambda() throws Exception { + var classLoader = new ByteArrayClassLoader(); + var fun = classLoader.loadClass(Path.of(System.getProperty("user.dir"), "src/test/java/targetast/Fun1$$.class")); + var interfaceType = new TargetFunNType(1, List.of()); + + var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, "CGLambda"); + targetClass.addConstructor(Opcodes.ACC_PUBLIC, List.of(), new TargetBlock(List.of( + new TargetMethodCall(null, new TargetSuper(TargetType.Object), List.of(), TargetType.Object, "", false, false) + ))); + targetClass.addMethod(Opcodes.ACC_PUBLIC, "lambda", List.of(), TargetType.Integer, + new TargetBlock(List.of( + new TargetVarDecl(interfaceType, "by2", + new TargetLambdaExpression(interfaceType, List.of(), List.of(new MethodParameter(TargetType.Integer, "num")), TargetType.Integer, + new TargetBlock(List.of( + new TargetReturn(new TargetBinaryOp.Mul(TargetType.Integer, + new TargetLocalVar(TargetType.Integer, "num"), + new TargetLiteral.IntLiteral(2) + )) + ) + )) + ), + new TargetReturn(new TargetCast(TargetType.Integer, new TargetMethodCall(TargetType.Object, TargetType.Object, List.of(TargetType.Object), new TargetLocalVar(interfaceType, "by2"), List.of( + new TargetLiteral.IntLiteral(10) + ), interfaceType, "apply", false, true))) + )) + ); + var clazz = generateClass(targetClass, classLoader); + var instance = clazz.getConstructor().newInstance(); + assertEquals(clazz.getDeclaredMethod("lambda").invoke(instance), 20); + } +} diff --git a/app/src/test/java/targetast/TestComplete.java b/app/src/test/java/targetast/TestComplete.java new file mode 100644 index 00000000..cf8cdac8 --- /dev/null +++ b/app/src/test/java/targetast/TestComplete.java @@ -0,0 +1,468 @@ +package targetast; + +import de.dhbwstuttgart.target.ByteArrayClassLoader; +import org.junit.Ignore; +import org.junit.Test; + +import java.lang.reflect.Method; +import java.lang.reflect.TypeVariable; +import java.util.Arrays; +import java.util.Vector; + +import static org.junit.Assert.*; +import static targetast.TestCodegen.generateClassFiles; + +public class TestComplete { + + @Test + public void applyLambdaTest() throws Exception { + var classFiles = generateClassFiles("applyLambda.jav", new ByteArrayClassLoader()); + var applyLambda = classFiles.get("applyLambda"); + var instance = applyLambda.getDeclaredConstructor().newInstance(); + var m = applyLambda.getDeclaredMethod("m"); + var result = m.invoke(instance); + + assertEquals(result.getClass(), classFiles.get("Apply")); + } + + @Test + public void binaryTest() throws Exception { + var classFiles = generateClassFiles("BinaryInMeth.jav", new ByteArrayClassLoader()); + var binaryInMeth = classFiles.get("BinaryInMeth"); + var instance = binaryInMeth.getDeclaredConstructor().newInstance(); + + var m2 = binaryInMeth.getDeclaredMethod("m2", Integer.class, Integer.class); + var m3 = binaryInMeth.getDeclaredMethod("m3", Integer.class); + + assertEquals(6, m2.invoke(instance, 2, 3)); + assertEquals(4, m3.invoke(instance, 2)); + } + + @Test + public void classGenLamTest() throws Exception { + var classFiles = generateClassFiles("ClassGenLam.jav", new ByteArrayClassLoader()); + classFiles.get("ClassGenLam").getDeclaredConstructor().newInstance(); + } + + @Test + public void facTest() throws Exception { + var classFiles = generateClassFiles("Fac.jav", new ByteArrayClassLoader()); + var fac = classFiles.get("Fac"); + var instance = fac.getDeclaredConstructor().newInstance(); + + var getFac = fac.getDeclaredMethod("getFac", Integer.class); + assertEquals(6, getFac.invoke(instance, 3)); + } + + @Test + public void facultyTest() throws Exception { + var classFiles = generateClassFiles("Faculty.jav", new ByteArrayClassLoader()); + + var fac = classFiles.get("Faculty"); + var constructor = fac.getDeclaredConstructor(); + constructor.setAccessible(true); + var instance = constructor.newInstance(); + + var getFact = fac.getDeclaredMethod("getFact", Integer.class); + assertEquals(6, getFact.invoke(instance, 3)); + } + + @Test + public void fieldTest() throws Exception { + var classFiles = generateClassFiles("Field.jav", new ByteArrayClassLoader()); + var field = classFiles.get("Field"); + var instance = field.getDeclaredConstructor().newInstance(); + assertEquals(1, field.getFields().length); + } + + @Test + public void fieldTph2Test() throws Exception { + var classFiles = generateClassFiles("FieldTph2.jav", new ByteArrayClassLoader()); + var fieldtph2 = classFiles.get("FieldTph2"); + var instance = fieldtph2.getDeclaredConstructor().newInstance(); + + var a = fieldtph2.getDeclaredField("a"); + var m2 = fieldtph2.getDeclaredMethod("m2", Object.class); + m2.invoke(instance, 1); + + var m = fieldtph2.getDeclaredMethod("m", Object.class); + assertEquals(1, m.invoke(instance, 1)); + } + + @Test + public void fieldTphConsMethTest() throws Exception { + var classFiles = generateClassFiles("FieldTphConsMeth.jav", new ByteArrayClassLoader()); + var fieldTphConsMeth = classFiles.get("FieldTphConsMeth"); + + var ctor = fieldTphConsMeth.getDeclaredConstructor(Object.class); + var instance = ctor.newInstance("C"); + var a = fieldTphConsMeth.getDeclaredField("a"); + var id = fieldTphConsMeth.getDeclaredMethod("id", Object.class); + + assertEquals(42, id.invoke(instance, 42)); + assertEquals("C", a.get(instance)); + } + + @Test + public void fieldTphMMethTest() throws Exception { + var classFiles = generateClassFiles("FieldTphMMeth.jav", new ByteArrayClassLoader()); + var fieldTphMMeth = classFiles.get("FieldTphMMeth"); + var ctor = fieldTphMMeth.getDeclaredConstructor(Object.class, Object.class, Boolean.class); + + var instance1 = ctor.newInstance("C", 42, true); + var instance2 = ctor.newInstance("C", 42, false); + + var m = fieldTphMMeth.getDeclaredMethod("m", Object.class, Object.class, Boolean.class); + assertEquals(42, m.invoke(instance1, "C", 42, false)); + + var a = fieldTphMMeth.getDeclaredField("a"); + assertEquals("C", a.get(instance1)); + assertEquals(42, a.get(instance2)); + } + + @Test + public void genTest() throws Exception { + var classFiles = generateClassFiles("Gen.jav", new ByteArrayClassLoader()); + } + + @Test + public void idTest() throws Exception { + var classFiles = generateClassFiles("Id.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("Id").getDeclaredConstructor().newInstance(); + } + + @Test + public void infTest() throws Exception { + var classFiles = generateClassFiles("Inf.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("Inf").getDeclaredConstructor().newInstance(); + } + + @Test + public void kompTphTest() throws Exception { + var classFiles = generateClassFiles("KompTph.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("KompTph").getDeclaredConstructor().newInstance(); + } + + @Test + public void lambdaCaptureTest() throws Exception { + var classFiles = generateClassFiles("LambdaCapture.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("LambdaCapture").getDeclaredConstructor().newInstance(); + } + + @Test + public void lambdaTest() throws Exception { + var classFiles = generateClassFiles("Lambda.jav", new ByteArrayClassLoader()); + var classToTest = classFiles.get("Lambda"); + var instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + + var m = classToTest.getDeclaredMethod("m"); + var lambda = m.invoke(instanceOfClass).getClass(); + var apply = lambda.getMethod("apply", Object.class); + apply.setAccessible(true); + + var i = Integer.valueOf(77); + assertEquals(i, apply.invoke(m.invoke(instanceOfClass), i)); + } + + @Test + public void mathStrucInteger() throws Exception { + var classFiles = generateClassFiles("mathStrucInteger.jav", new ByteArrayClassLoader()); + var mathStrucInteger = classFiles.get("mathStrucInteger"); + mathStrucInteger.getDeclaredConstructor(Integer.class).newInstance(10); + } + + @Test + public void mathStruc() throws Exception { + var classFiles = generateClassFiles("mathStruc.jav", new ByteArrayClassLoader()); + var mathStruc = classFiles.get("mathStruc"); + mathStruc.getDeclaredConstructor(Object.class).newInstance("A"); + } + + @Test + public void matrixOpTest() throws Exception { + var classFiles = generateClassFiles("MatrixOP.jav", new ByteArrayClassLoader()); + var matrixOP = classFiles.get("MatrixOP"); + + Vector> vv = new Vector<>(); + Vector v1 = new Vector<>(); + v1.addElement(2); + v1.addElement(2); + Vector v2 = new Vector<>(); + v2.addElement(3); + v2.addElement(3); + vv.addElement(v1); + vv.addElement(v2); + + var instanceOfClass_m1 = matrixOP.getDeclaredConstructor(Vector.class).newInstance(vv); + + Vector> vv1 = new Vector<>(); + Vector v3 = new Vector<>(); + v3.addElement(2); + v3.addElement(2); + Vector v4 = new Vector<>(); + v4.addElement(3); + v4.addElement(3); + vv1.addElement(v3); + vv1.addElement(v4); + + var instanceOfClass_m2 = matrixOP.getDeclaredConstructor(Vector.class).newInstance(vv1);//Matrix m2 = new Matrix(vv1); + + var mul = matrixOP.getField("mul"); + mul.setAccessible(true); + + var lambda = mul.get(instanceOfClass_m1).getClass(); + var apply = lambda.getMethod("apply", Object.class, Object.class); + apply.setAccessible(true); + + var result = apply.invoke(mul.get(instanceOfClass_m1), instanceOfClass_m1, instanceOfClass_m2); + System.out.println(instanceOfClass_m1.toString() + " * " + instanceOfClass_m2.toString() + " = " + result.toString()); + + Vector> res = new Vector<>(); + Vector v5 = new Vector<>(); + v5.addElement(10); + v5.addElement(10); + Vector v6 = new Vector<>(); + v6.addElement(15); + v6.addElement(15); + res.addElement(v5); + res.addElement(v6); + + var instanceOfClass_m3 = matrixOP.getDeclaredConstructor(Vector.class).newInstance(res); + assertEquals(result, instanceOfClass_m3); + } + + @Ignore("Thread blocking for some reason") + @Test + public void matrixTest() throws Exception { + var classFiles = generateClassFiles("Matrix.jav", new ByteArrayClassLoader()); + var matrix = classFiles.get("Matrix"); + + Vector> vv = new Vector<>(); + Vector v1 = new Vector<> (); + v1.addElement(2); + v1.addElement(2); + Vector v2 = new Vector<> (); + v2.addElement(3); + v2.addElement(3); + vv.addElement(v1); + vv.addElement(v2); + + var instanceOfClass_m1 = matrix.getDeclaredConstructor(Vector.class).newInstance(vv); + + Vector> vv1 = new Vector<>(); + Vector v3 = new Vector<> (); + v3.addElement(2); + v3.addElement(2); + Vector v4 = new Vector<> (); + v4.addElement(3); + v4.addElement(3); + vv1.addElement(v3); + vv1.addElement(v4); + + var instanceOfClass_m2 = matrix.getDeclaredConstructor(Vector.class).newInstance(vv1); + + var mul = matrix.getDeclaredMethod("mul", Vector.class); + var result = mul.invoke(instanceOfClass_m1, instanceOfClass_m2); + System.out.println(instanceOfClass_m1.toString() + " * " + instanceOfClass_m2.toString() + " = " + result.toString()); + + Vector> res = new Vector<>(); + Vector v5 = new Vector<> (); + v5.addElement(10); + v5.addElement(10); + Vector v6 = new Vector<> (); + v6.addElement(15); + v6.addElement(15); + res.addElement(v5); + res.addElement(v6); + + var instanceOfClass_m3 = matrix.getDeclaredConstructor(Vector.class).newInstance(res); + assertEquals(result, instanceOfClass_m3); + } + + @Test + public void mergeTest() throws Exception { + var classFiles = generateClassFiles("Merge.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("Merge").getDeclaredConstructor().newInstance(); + } + + @Test + public void overloadingSortingTest() throws Exception { + var classFiles = generateClassFiles("Sorting.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("Sorting").getDeclaredConstructor().newInstance(); + } + + @Test + public void overloadingTest() throws Exception { + var classFiles = generateClassFiles("Overloading.jav", new ByteArrayClassLoader()); + var overloading = classFiles.get("Overloading"); + var overloading2 = classFiles.get("Overloading2"); + var instance1 = overloading.getDeclaredConstructor().newInstance(); + var instance2 = overloading2.getDeclaredConstructor().newInstance(); + + var m1 = overloading.getDeclaredMethod("test", overloading); + assertEquals("Overloading", m1.invoke(instance1, instance1)); + var m2 = overloading.getDeclaredMethod("test", overloading2); + assertEquals("Overloading2", m2.invoke(instance1, instance2)); + } + + @Test + public void plusTest() throws Exception { + var classFiles = generateClassFiles("Plus.jav", new ByteArrayClassLoader()); + var plus = classFiles.get("Plus"); + var instance = plus.getDeclaredConstructor().newInstance(); + + var addInt = plus.getDeclaredMethod("m", Integer.class, Integer.class); + assertEquals(10, addInt.invoke(instance, 7, 3)); + + var addString = plus.getDeclaredMethod("m", String.class, String.class); + assertEquals("ByteCode", addString.invoke(instance, "Byte", "Code")); + } + + @Test + public void relOpsTest() throws Exception { + var classFiles = generateClassFiles("RelOps.jav", new ByteArrayClassLoader()); + var relOps = classFiles.get("RelOps"); + var instance = relOps.getDeclaredConstructor().newInstance(); + + var m = relOps.getDeclaredMethod("m", Integer.class,Integer.class); + assertFalse((Boolean) m.invoke(instance, 7, 3)); + } + + @Test + public void simpleCyclesTest() throws Exception { + var classFiles = generateClassFiles("SimpleCycle.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("SimpleCycle").getDeclaredConstructor().newInstance(); + } + + @Test + public void subMatTest() throws Exception { + var classFiles = generateClassFiles("SubMatrix.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("SubMatrix").getDeclaredConstructor().newInstance(); + } + + @Test + public void tph2Test() throws Exception { + var classFiles = generateClassFiles("Tph2.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("Tph2").getDeclaredConstructor().newInstance(); + } + + @Test + public void tph3Test() throws Exception { + var classFiles = generateClassFiles("Tph3.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("Tph3").getDeclaredConstructor().newInstance(); + } + + @Test + public void tph4Test() throws Exception { + var classFiles = generateClassFiles("Tph4.jav", new ByteArrayClassLoader()); + var tph4 = classFiles.get("Tph4"); + var instance = tph4.getDeclaredConstructor().newInstance(); + } + + @Test + public void tph5Test() throws Exception { + var classFiles = generateClassFiles("Tph5.jav", new ByteArrayClassLoader()); + var tph5 = classFiles.get("Tph5"); + var instance = tph5.getDeclaredConstructor().newInstance(); + var m = tph5.getDeclaredMethod("m", Object.class, Object.class); + } + + @Test + public void tph6Test() throws Exception { + var classFiles = generateClassFiles("Tph6.jav", new ByteArrayClassLoader()); + var tph5 = classFiles.get("Tph6"); + var instance = tph5.getDeclaredConstructor().newInstance(); + var m = tph5.getDeclaredMethod("m", Object.class, Object.class); + } + + + @Test + public void Tph7Test() throws Exception { + var classFiles = TestCodegen.generateClassFiles("Tph7.jav", new ByteArrayClassLoader()); + var classToTest = classFiles.get("Tph7"); + var instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + + //public DZU m(DZL, DZM); + Method m = classToTest.getDeclaredMethod("m", Object.class, Object.class); + + //System.out.println(m.toString()); + + //Argumenttypes of the method m + var paraTypes = m.getGenericParameterTypes(); + + //Typeparameters of the method m + var typeParaTypes = m.getTypeParameters(); + + //Typeparameters are extracted from the argumenttypes + //Conditions for the extracted typeparameters are set + + //paraTypes[0] = DLZ + var boundFstArg = Arrays.stream(typeParaTypes) + .filter(x -> x.equals(paraTypes[0])).findFirst().get().getBounds(); + + //Bound of DLZ has to be Object + assertEquals(Object.class, Arrays.stream(boundFstArg).findFirst().get()); + + //paraTypes[0] = DZM + var boundSndArg = Arrays.stream(typeParaTypes) + .filter(x -> x.equals(paraTypes[1])).findFirst().get().getBounds(); + + //Bound of DZM has to be the return type of m + assertEquals(Arrays.stream(boundSndArg).findFirst().get(), m.getGenericReturnType()); + + //Bound of the bound of DZM + var boundBoundSndArg = Arrays.stream(typeParaTypes).filter(x -> x.equals(Arrays.stream(boundSndArg) + .findFirst().get())).findFirst().get().getBounds(); + + //boundBoundSndArg have to be a type variable (type of the local variable c) + assertEquals(true, Arrays.stream(boundBoundSndArg).findFirst().get() instanceof TypeVariable); + m.getGenericParameterTypes(); + + //public DZU m2(DZU); + Method m2 = classToTest.getDeclaredMethod("m2", Object.class); + + //Argumenttypes of the method m2 + var paraTypesm2 = m2.getGenericParameterTypes(); + + //Typeparameters of the method m2 + var typeParaTypesm2 = m2.getTypeParameters(); + + //Typeparameters are extracted from the argumenttypes + //Conditions for the extracted typeparameters are set + + //paraTypes[0] = DZU + var fstArgm2 = Arrays.stream(typeParaTypesm2) + .filter(x -> x.equals(paraTypesm2[0])).findFirst().get(); + + //Bound of DZU has to be Object + assertEquals(Object.class, Arrays.stream(fstArgm2.getBounds()).findFirst().get()); + + //DZU has to be the return type of m + assertEquals(fstArgm2, m2.getGenericReturnType()); + } + + + @Test + public void typedIdTest() throws Exception { + var classFiles = generateClassFiles("TypedID.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("TypedID").getDeclaredConstructor().newInstance(); + } + + @Test + public void vectorAddTest() throws Exception { + var classFiles = generateClassFiles("VectorAdd.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("VectorAdd").getDeclaredConstructor().newInstance(); + } + + @Test + public void vectorSuperTest() throws Exception { + var classFiles = generateClassFiles("VectorSuper.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("VectorSuper").getDeclaredConstructor().newInstance(); + } + + @Test + public void yTest() throws Exception { + var classFiles = generateClassFiles("Y.jav", new ByteArrayClassLoader()); + var instance = classFiles.get("Y").getDeclaredConstructor().newInstance(); + } +} diff --git a/app/src/test/java/targetast/TphTest.java b/app/src/test/java/targetast/TphTest.java new file mode 100644 index 00000000..c3f29c7f --- /dev/null +++ b/app/src/test/java/targetast/TphTest.java @@ -0,0 +1,114 @@ +package targetast; + +import de.dhbwstuttgart.target.ByteArrayClassLoader; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.lang.reflect.Method; +import java.lang.reflect.TypeVariable; +import java.util.Arrays; + +import static org.junit.Assert.assertEquals; + +public class TphTest { + + private static Class classToTest; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + var classFiles = TestCodegen.generateClassFiles("Tph.jav", new ByteArrayClassLoader()); + classToTest = classFiles.get("Tph"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void test1() throws Exception { + var classFiles = TestCodegen.generateClassFiles("Tph7.jav", new ByteArrayClassLoader()); + var classToTest = classFiles.get("Tph7"); + var instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + + //public DZU m(DZL, DZM); + Method m = classToTest.getDeclaredMethod("m", Object.class, Object.class); + + //System.out.println(m.toString()); + + //Argumenttypes of the method m + var paraTypes = m.getGenericParameterTypes(); + + //Typeparameters of the method m + var typeParaTypes = m.getTypeParameters(); + + //Typeparameters are extracted from the argumenttypes + //Conditions for the extracted typeparameters are set + + //paraTypes[0] = DLZ + var boundFstArg = Arrays.stream(typeParaTypes) + .filter(x -> x.equals(paraTypes[0])).findFirst().get().getBounds(); + + //Bound of DLZ has to be Object + assertEquals(Object.class, Arrays.stream(boundFstArg).findFirst().get()); + + //paraTypes[0] = DZM + var boundSndArg = Arrays.stream(typeParaTypes) + .filter(x -> x.equals(paraTypes[1])).findFirst().get().getBounds(); + + //Bound of DZM has to be the return type of m + assertEquals(Arrays.stream(boundSndArg).findFirst().get(), m.getGenericReturnType()); + + //Bound of the bound of DZM + var boundBoundSndArg = Arrays.stream(typeParaTypes).filter(x -> x.equals(Arrays.stream(boundSndArg) + .findFirst().get())).findFirst().get().getBounds(); + + //boundBoundSndArg have to be a type variable (type of the local variable c) + assertEquals(true, Arrays.stream(boundBoundSndArg).findFirst().get() instanceof TypeVariable); + m.getGenericParameterTypes(); + + //public DZU m2(DZU); + Method m2 = classToTest.getDeclaredMethod("m2", Object.class); + + //Argumenttypes of the method m2 + var paraTypesm2 = m2.getGenericParameterTypes(); + + //Typeparameters of the method m2 + var typeParaTypesm2 = m2.getTypeParameters(); + + //Typeparameters are extracted from the argumenttypes + //Conditions for the extracted typeparameters are set + + //paraTypes[0] = DZU + var fstArgm2 = Arrays.stream(typeParaTypesm2) + .filter(x -> x.equals(paraTypesm2[0])).findFirst().get(); + + //Bound of DZU has to be Object + assertEquals(Object.class, Arrays.stream(fstArgm2.getBounds()).findFirst().get()); + + //DZU has to be the return type of m + assertEquals(fstArgm2, m2.getGenericReturnType()); + } + + @Test + public void test2() throws Exception { + Method m = classToTest.getDeclaredMethod("m", Object.class, Object.class); + Object result = m.invoke(instanceOfClass, 1, "sss"); + + assertEquals(1,result); + } + + @Test + public void test3() throws Exception { + Method m = classToTest.getDeclaredMethod("m2", Object.class); + Object result = m.invoke(instanceOfClass, 2); + + assertEquals(2,result); + } + + @Test + public void test4() throws Exception { + Method m = classToTest.getDeclaredMethod("m2", Object.class); + Object result = m.invoke(instanceOfClass,"xxx"); + + assertEquals("xxx",result); + } + +} diff --git a/app/src/test/java/targetast/WhileTest.java b/app/src/test/java/targetast/WhileTest.java new file mode 100644 index 00000000..0321c90f --- /dev/null +++ b/app/src/test/java/targetast/WhileTest.java @@ -0,0 +1,43 @@ +package targetast; + +import de.dhbwstuttgart.target.ByteArrayClassLoader; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.lang.reflect.Method; + +import static org.junit.Assert.assertEquals; + +public class WhileTest { + private static Class classToTest; + private static Object instanceOfClass; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + var classFiles = TestCodegen.generateClassFiles("While.jav", new ByteArrayClassLoader()); + classToTest = classFiles.get("While"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void test() throws Exception { + Method m = classToTest.getDeclaredMethod("m", Integer.class); + Integer result = (Integer) m.invoke(instanceOfClass, 0); + assertEquals(Integer.valueOf(2), result); + } + + @Test + public void testDouble() throws Exception { + Method m = classToTest.getDeclaredMethod("m", Double.class); + Double result = (Double) m.invoke(instanceOfClass, 0.0); + assertEquals(Double.valueOf(2.0), result); + } + + @Test + public void testLong() throws Exception { + Method m = classToTest.getDeclaredMethod("m", Long.class); + Long result = (Long) m.invoke(instanceOfClass, 0l); + assertEquals(Long.valueOf(2l), result); + } + +} diff --git a/app/src/test/java/typeinference/JavaTXCompilerTest.java b/app/src/test/java/typeinference/JavaTXCompilerTest.java new file mode 100644 index 00000000..63570d95 --- /dev/null +++ b/app/src/test/java/typeinference/JavaTXCompilerTest.java @@ -0,0 +1,177 @@ +package typeinference; + +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericGenratorResultForSourceFile; +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter; +import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter; +import de.dhbwstuttgart.typedeployment.TypeInsert; +import de.dhbwstuttgart.typedeployment.TypeInsertFactory; +import de.dhbwstuttgart.typeinference.result.ResultSet; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class JavaTXCompilerTest { + + public static final String rootDirectory = System.getProperty("user.dir")+"/resources/javFiles/"; + @Test + public void finiteClosure() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"fc.jav")); + } + @Test + public void importTest() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Import.jav")); + } + @Test + public void fieldTest() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"FieldAccess.jav")); + } + @Test + public void lambda() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Lambda.jav")); + } + @Test + public void lambda2() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Lambda2.jav")); + } + @Test + public void lambda3() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Lambda3.jav")); + } + @Test + public void lambdaField() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"LambdaField.jav")); + } + @Test + public void mathStruc() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"mathStruc.jav")); + } + @Test + public void generics() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Generics.jav")); + } + @Test + public void genericsMethodCall() throws IOException, ClassNotFoundException { + TestResultSet result = execute(new File(rootDirectory+"MethodCallGenerics.jav")); + //TODO: Hier sollte der Rückgabetyp der Methode String sein + } + @Test + public void faculty() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Faculty.jav")); + } + @Test + public void facultyIf() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"FacultyIf.jav")); + } + @Test + public void facultyTyped() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"FacultyTyped.jav")); + } + @Test + public void matrix() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Matrix.jav")); + } + @Test + public void packageTests() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Package.jav")); + } + @Test + public void vector() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Vector.jav")); + } + @Test + public void lambdaRunnable() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"LambdaRunnable.jav")); + } + @Test + public void expressions() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Expressions.jav")); + } + @Test + public void addLong() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"AddLong.jav")); + } + @Test + public void fields() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Fields.jav")); + } + @Test + public void ifStatement() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"IfTest.jav")); + } + @Test + public void multipleSolutions() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Sorting.jav")); + } + @Test + public void listenerTest() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"ListenerOverload.jav")); + } + + private static class TestResultSet{ + + } + + public TestResultSet execute(File fileToTest) throws IOException, ClassNotFoundException { + //filesToTest.add(new File(rootDirectory+"fc.jav")); + //filesToTest.add(new File(rootDirectory+"Lambda.jav")); + //filesToTest.add(new File(rootDirectory+"Lambda2.jav")); + //filesToTest.add(new File(rootDirectory+"Lambda3.jav")); + //filesToTest.add(new File(rootDirectory+"Vector.jav")); + //filesToTest.add(new File(rootDirectory+"Generics.jav")); + //filesToTest.add(new File(rootDirectory+"MethodsEasy.jav")); + //filesToTest.add(new File(rootDirectory+"Matrix.jav")); + //filesToTest.add(new File(rootDirectory+"Import.jav")); + // //filesToTest.add(new File(rootDirectory+"Faculty.jav")); + // //filesToTest.add(new File(rootDirectory+"mathStruc.jav")); + // //filesToTest.add(new File(rootDirectory+"test.jav")); + JavaTXCompiler compiler = new JavaTXCompiler(fileToTest); + for(File f : compiler.sourceFiles.keySet()){ + SourceFile sf = compiler.sourceFiles.get(f); + System.out.println(ASTTypePrinter.print(sf)); + System.out.println(ASTPrinter.print(sf)); + } + List results = compiler.typeInference(); + List simplifyResultsForAllSourceFiles = compiler.getGeneratedGenericResultsForAllSourceFiles(results); + //compiler.generateBytecode(rootDirectory+"xxx.class", results, simplifyResultsForAllSourceFiles); + for(File f : compiler.sourceFiles.keySet()){ + SourceFile sf = compiler.sourceFiles.get(f); + System.out.println(ASTTypePrinter.print(sf)); + System.out.println(ASTPrinter.print(sf)); + //List results = compiler.typeInference(); PL 2017-10-03 vor die For-Schleife gezogen + assert results.size()>0; + Set insertedTypes = new HashSet<>(); + for(ResultSet resultSet : results){ + Set result = TypeInsertFactory.createTypeInsertPoints(sf, resultSet, results, simplifyResultsForAllSourceFiles); + assert result.size()>0; + String content = readFile(f.getPath(), StandardCharsets.UTF_8); + for(TypeInsert tip : result){ + insertedTypes.add(tip.insert(content)); + } + } + for(String s : insertedTypes){ + System.out.println(s); + } + } + return new TestResultSet(); + } + + static String readFile(String path, Charset encoding) + throws IOException + { + byte[] encoded = Files.readAllBytes(Paths.get(path)); + return new String(encoded, encoding); + } + +} + diff --git a/app/src/test/java/typeinference/Meth_GenTest.java b/app/src/test/java/typeinference/Meth_GenTest.java new file mode 100644 index 00000000..0eb4feab --- /dev/null +++ b/app/src/test/java/typeinference/Meth_GenTest.java @@ -0,0 +1,141 @@ +package typeinference; + +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericGenratorResultForSourceFile; +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter; +import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter; +import de.dhbwstuttgart.typedeployment.TypeInsert; +import de.dhbwstuttgart.typedeployment.TypeInsertFactory; +import de.dhbwstuttgart.typeinference.result.ResultSet; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class Meth_GenTest { + + public static final String rootDirectory = System.getProperty("user.dir")+"/resources/javFiles/"; +/* + @Test + public void finiteClosure() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"fc.jav")); + } + @Test + public void lambda() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Lambda.jav")); + } + @Test + public void lambda2() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Lambda2.jav")); + } + @Test + public void lambda3() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Lambda3.jav")); + } + @Test + public void mathStruc() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"mathStruc.jav")); + } + @Test + public void generics() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Generics.jav")); + } + + @Test + public void faculty() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Faculty.jav")); + } + + @Test + public void facultyTyped() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"FacultyTyped.jav")); + } +*/ + @Test + public void matrix() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Meth_Gen.jav")); + } +/* + @Test + public void vector() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Vector.jav")); + } + @Test + public void lambdaRunnable() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"LambdaRunnable.jav")); + } + @Test + public void expressions() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Expressions.jav")); + } + @Test + public void matrixFC() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"FC_Matrix.jav")); + } +*/ + private static class TestResultSet{ + + } + + public TestResultSet execute(File fileToTest) throws IOException, ClassNotFoundException { + //filesToTest.add(new File(rootDirectory+"fc.jav")); + //filesToTest.add(new File(rootDirectory+"Lambda.jav")); + //filesToTest.add(new File(rootDirectory+"Lambda2.jav")); + //filesToTest.add(new File(rootDirectory+"Lambda3.jav")); + //filesToTest.add(new File(rootDirectory+"Vector.jav")); + //filesToTest.add(new File(rootDirectory+"Generics.jav")); + //filesToTest.add(new File(rootDirectory+"MethodsEasy.jav")); + //filesToTest.add(new File(rootDirectory+"Matrix.jav")); + //filesToTest.add(new File(rootDirectory+"Import.jav")); + // //filesToTest.add(new File(rootDirectory+"Faculty.jav")); + // //filesToTest.add(new File(rootDirectory+"mathStruc.jav")); + // //filesToTest.add(new File(rootDirectory+"test.jav")); + JavaTXCompiler compiler = new JavaTXCompiler(fileToTest); + for(File f : compiler.sourceFiles.keySet()){ + SourceFile sf = compiler.sourceFiles.get(f); + System.out.println(ASTTypePrinter.print(sf)); + System.out.println(ASTPrinter.print(sf)); + } + List results = compiler.typeInference(); + List simplifyResultsForAllSourceFiles = compiler.getGeneratedGenericResultsForAllSourceFiles(results); + + for(File f : compiler.sourceFiles.keySet()){ + SourceFile sf = compiler.sourceFiles.get(f); + System.out.println(ASTTypePrinter.print(sf)); + System.out.println(ASTPrinter.print(sf)); + //List results = compiler.typeInference(); PL 2017-10-03 vor die For-Schleife gezogen + assert results.size()>0; + Set insertedTypes = new HashSet<>(); + for(ResultSet resultSet : results){ + Set result = TypeInsertFactory.createTypeInsertPoints(sf, resultSet, results, simplifyResultsForAllSourceFiles); + assert result.size()>0; + String content = readFile(f.getPath(), StandardCharsets.UTF_8); + for(TypeInsert tip : result){ + insertedTypes.add(tip.insert(content)); + } + } + for(String s : insertedTypes){ + System.out.println(s); + } + } + return new TestResultSet(); + } + + static String readFile(String path, Charset encoding) + throws IOException + { + byte[] encoded = Files.readAllBytes(Paths.get(path)); + return new String(encoded, encoding); + } + +} + diff --git a/app/src/test/java/typeinference/UnifyTest.java b/app/src/test/java/typeinference/UnifyTest.java new file mode 100644 index 00000000..366b010e --- /dev/null +++ b/app/src/test/java/typeinference/UnifyTest.java @@ -0,0 +1,167 @@ +package typeinference; + +import de.dhbwstuttgart.bytecode.genericsGeneratorTypes.GenericGenratorResultForSourceFile; +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter; +import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter; +import de.dhbwstuttgart.typedeployment.TypeInsert; +import de.dhbwstuttgart.typedeployment.TypeInsertFactory; +import de.dhbwstuttgart.typeinference.result.ResultSet; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class UnifyTest { + + public static final String rootDirectory = System.getProperty("user.dir")+"/resources/javFiles/"; +/* + @Test + public void finiteClosure() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"fc.jav")); + } + + @Test + public void lambda() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Lambda.jav")); + } + + */ + /* + @Test + public void vector() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Vector.jav")); + } + */ + + /* + @Test + public void lambda2() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Lambda2.jav")); + } + */ +/* + @Test + public void lambda3() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Lambda3.jav")); + } + + @Test + public void lambdafield() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"LambdaField.jav")); + } + + @Test + public void mathStruc() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"mathStruc.jav")); + } + @Test + public void generics() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Generics.jav")); + } +*/ +/* + @Test + public void faculty() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Faculty.jav")); + } +*/ +/* + @Test + public void facultyTyped() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"FacultyTyped.jav")); + } + */ + + @Test + public void matrix() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Matrix.jav")); + //JavaTXCompiler compiler = new JavaTXCompiler(new File(rootDirectory+"Matrix.jav")); + //compiler.generateBytecode(); + } + + +/* + @Test + public void vector() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Vector.jav")); + } + @Test + public void lambdaRunnable() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"LambdaRunnable.jav")); + } + @Test + public void expressions() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"Expressions.jav")); + } + @Test + public void matrixFC() throws IOException, ClassNotFoundException { + execute(new File(rootDirectory+"FC_Matrix.jav")); + } +*/ + private static class TestResultSet{ + + } + + public TestResultSet execute(File fileToTest) throws IOException, ClassNotFoundException { + //filesToTest.add(new File(rootDirectory+"fc.jav")); + //filesToTest.add(new File(rootDirectory+"Lambda.jav")); + //filesToTest.add(new File(rootDirectory+"Lambda2.jav")); + //filesToTest.add(new File(rootDirectory+"Lambda3.jav")); + //filesToTest.add(new File(rootDirectory+"Vector.jav")); + //filesToTest.add(new File(rootDirectory+"Generics.jav")); + //filesToTest.add(new File(rootDirectory+"MethodsEasy.jav")); + //filesToTest.add(new File(rootDirectory+"Matrix.jav")); + //filesToTest.add(new File(rootDirectory+"Import.jav")); + // //filesToTest.add(new File(rootDirectory+"Faculty.jav")); + // //filesToTest.add(new File(rootDirectory+"mathStruc.jav")); + // //filesToTest.add(new File(rootDirectory+"test.jav")); + JavaTXCompiler compiler = new JavaTXCompiler(fileToTest); + for(File f : compiler.sourceFiles.keySet()){ + SourceFile sf = compiler.sourceFiles.get(f); + System.out.println(ASTTypePrinter.print(sf)); + System.out.println(ASTPrinter.print(sf)); + } + List results = compiler.typeInference(); + List simplifyResultsForAllSourceFiles = compiler.getGeneratedGenericResultsForAllSourceFiles(results); + + for(File f : compiler.sourceFiles.keySet()){ + SourceFile sf = compiler.sourceFiles.get(f); + System.out.println(ASTTypePrinter.print(sf)); + System.out.println(ASTPrinter.print(sf)); + //List results = compiler.typeInference(); PL 2017-10-03 vor die For-Schleife gezogen + assert results.size()>0; + Set insertedTypes = new HashSet<>(); + for(ResultSet resultSet : results){ + Set result = TypeInsertFactory.createTypeInsertPoints(sf, resultSet, results, simplifyResultsForAllSourceFiles); + assert result.size()>0; + String content = readFile(f.getPath(), StandardCharsets.UTF_8); + for(TypeInsert tip : result){ + insertedTypes.add(tip.insert(content)); + } + } + for(String s : insertedTypes){ + System.out.println(s); + } + } + return new TestResultSet(); + } + + static String readFile(String path, Charset encoding) + throws IOException + { + byte[] encoded = Files.readAllBytes(Paths.get(path)); + return new String(encoded, encoding); + } + +} + diff --git a/app/src/test/java/visualisation/ToString.java b/app/src/test/java/visualisation/ToString.java new file mode 100644 index 00000000..00b8ddea --- /dev/null +++ b/app/src/test/java/visualisation/ToString.java @@ -0,0 +1,5 @@ +package visualisation; + +public class ToString { + +} diff --git a/app/src/test/resources/target/Test.java b/app/src/test/resources/target/Test.java new file mode 100644 index 00000000..f7e1a0bc --- /dev/null +++ b/app/src/test/resources/target/Test.java @@ -0,0 +1,9 @@ +public class Test { + public void lambda() { + Interface mul2 = (Integer a) -> a * 2; + } +} + +interface Interface { + R apply(T t); +} \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..f398c33c --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip +networkTimeout=10000 +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100755 index 00000000..65dcd68d --- /dev/null +++ b/gradlew @@ -0,0 +1,244 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 00000000..93e3f59f --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 00000000..8c9f438f --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,11 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * The settings file is used to specify which projects to include in your build. + * + * Detailed information about configuring a multi-project build in Gradle can be found + * in the user manual at https://docs.gradle.org/7.6/userguide/multi_project_builds.html + */ + +rootProject.name = "JavaTXCompiler" +include("app")